WP GDPR Compliance - Version 1.4.0

Version Description

Release date: June 8th, 2018 * Small front-end fixes. * Added missing translatable strings. * Fixed the text domain for some translatable strings. * Show enabled consents of user. * Small bugfix for admin redirects. * Added the ability to remove 'Consents' via the admin panel. * Added the option to wrap 'Consents' with

Download this release

Release Info

Developer donnyoexman
Plugin Icon 128x128 WP GDPR Compliance
Version 1.4.0
Comparing to
See all releases

Code changes from version 1.3.9 to 1.4.0

Includes/Action.php CHANGED
@@ -10,36 +10,56 @@ class Action {
10
  /** @var null */
11
  private static $instance = null;
12
 
13
- public function showAdminNotices() {
14
- if (isset($_REQUEST['notice'])) {
15
- $dismissible = true;
16
- $type = 'info';
17
- $message = '';
18
- switch ($_REQUEST['notice']) {
19
- case 'wpgdprc-consent-updated' :
20
- $type = 'success';
21
- $message = __('Consent has been updated successfully.', WP_GDPR_C_SLUG);
22
- break;
23
- case 'wpgdprc-consent-added' :
24
- $type = 'success';
25
- $message = __('Consent has been added successfully.', WP_GDPR_C_SLUG);
26
- break;
27
- case 'wpgdprc-consent-not-found' :
28
- $type = 'error';
29
- $message = __('Couldn\'t find this consent.', WP_GDPR_C_SLUG);
30
- break;
31
- }
32
- if (!empty($message)) {
33
- printf(
34
- '<div class="notice notice-%s %s"><p>%s</p></div>',
35
- $type,
36
- (($dismissible) ? 'is-dismissible' : ''),
37
- $message
38
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  }
40
  }
41
  }
42
 
 
 
 
 
 
 
43
  /**
44
  * Stop WordPress from sending anything but essential data during the update check
45
  * @param array $query
@@ -114,12 +134,12 @@ class Action {
114
  }
115
 
116
  public function addConsentBar() {
117
- $output = '<div class="wpgdprc wpgdprc-consent-bar">';
118
  $output .= '<div class="wpgdprc-consent-bar__container">';
119
  $output .= '<div class="wpgdprc-consent-bar__content">';
120
  $output .= '<div class="wpgdprc-consent-bar__column">';
121
  $output .= '<div class="wpgdprc-consent-bar__notice">';
122
- $output .= apply_filters('the_content', Consent::getBarExplanationText());
123
  $output .= '</div>';
124
  $output .= '</div>';
125
  $output .= '<div class="wpgdprc-consent-bar__column">';
@@ -141,6 +161,7 @@ class Action {
141
  }
142
 
143
  public function addConsentModal() {
 
144
  $consents = Consent::getInstance()->getList(array(
145
  'active' => array('value' => 1)
146
  ));
@@ -164,8 +185,8 @@ class Action {
164
  '<h3 class="wpgdprc-consent-modal__title">%s</h3>',
165
  Consent::getModalTitle()
166
  );
167
- $output .= apply_filters('the_content', Consent::getModalExplanationText());
168
- $output .= apply_filters('the_content', sprintf(
169
  '<strong>%s:</strong> %s',
170
  strtoupper(__('Note', WP_GDPR_C_SLUG)),
171
  __('These settings will only apply to the browser and device you are currently using.', WP_GDPR_C_SLUG)
@@ -178,12 +199,13 @@ class Action {
178
  $consent->getId()
179
  );
180
  $output .= sprintf('<h3 class="wpgdprc-consent-modal__title">%s</h3>', $consent->getTitle());
181
- $output .= apply_filters('the_content', $consent->getDescription());
182
  $output .= '<div class="wpgdprc-checkbox">';
183
  $output .= '<label>';
184
  $output .= sprintf(
185
- '<input type="checkbox" value="%d" tabindex="1" />',
186
- $consent->getId()
 
187
  );
188
  $output .= '<span class="wpgdprc-switch" aria-hidden="true">';
189
  $output .= '<span class="wpgdprc-switch-label">';
@@ -191,7 +213,8 @@ class Action {
191
  $output .= '<span class="wpgdprc-switch-switch"></span>';
192
  $output .= '</span>';
193
  $output .= '</span>';
194
- $output .= ' Enable</label>';
 
195
  $output .= '</div>';
196
  $output .= '</div>'; // .wpgdprc-consent-modal__description
197
  }
@@ -219,8 +242,8 @@ class Action {
219
  return;
220
  }
221
  $args = array(
222
- 'active' => array('value' => 1),
223
  'placement' => array('value' => 'head'),
 
224
  );
225
  if (!empty($consentIds)) {
226
  $args['ID'] = array(
@@ -238,8 +261,8 @@ class Action {
238
  return;
239
  }
240
  $args = array(
 
241
  'active' => array('value' => 1),
242
- 'placement' => array('value' => 'footer')
243
  );
244
  if (!empty($consentIds)) {
245
  $args['ID'] = array(
10
  /** @var null */
11
  private static $instance = null;
12
 
13
+ public function handleRedirects() {
14
+ global $pagenow;
15
+ if ($pagenow === 'tools.php' && isset($_REQUEST['page']) && $_REQUEST['page'] === str_replace('-', '_', WP_GDPR_C_SLUG)) {
16
+ $type = (isset($_REQUEST['type'])) ? esc_html($_REQUEST['type']) : false;
17
+ if ($type !== false) {
18
+ switch ($type) {
19
+ case 'consents' :
20
+ $action = (isset($_REQUEST['action'])) ? esc_html($_REQUEST['action']) : false;
21
+ switch ($action) {
22
+ case 'manage' :
23
+ $id = (isset($_REQUEST['id']) && is_numeric($_REQUEST['id'])) ? intval($_REQUEST['id']) : 0;
24
+ if (!empty($id) && !Consent::getInstance()->exists($id)) {
25
+ wp_safe_redirect(Helper::getPluginAdminUrl('consents', array('notice' => 'wpgdprc-consent-not-found')));
26
+ exit;
27
+ }
28
+ break;
29
+ case 'create' :
30
+ $consent = new Consent();
31
+ $consent->setSiteId(get_current_blog_id());
32
+ $id = $consent->save();
33
+ if (!empty($id)) {
34
+ wp_redirect(add_query_arg(
35
+ array('notice' => 'wpgdprc-consent-added'),
36
+ Consent::getActionUrl($id)
37
+ ));
38
+ }
39
+ break;
40
+ case 'delete' :
41
+ $id = (isset($_REQUEST['id']) && is_numeric($_REQUEST['id'])) ? intval($_REQUEST['id']) : 0;
42
+ if (!empty($id) && Consent::getInstance()->exists($id)) {
43
+ $result = Consent::getInstance()->delete($id);
44
+ if ($result !== false) {
45
+ wp_safe_redirect(Helper::getPluginAdminUrl('consents', array('notice' => 'wpgdprc-consent-removed')));
46
+ exit;
47
+ }
48
+ }
49
+ break;
50
+ }
51
+ break;
52
+ }
53
  }
54
  }
55
  }
56
 
57
+ public function showAdminNotices() {
58
+ if (!empty($_REQUEST['notice'])) {
59
+ Helper::showAdminNotice(esc_html($_REQUEST['notice']));
60
+ }
61
+ }
62
+
63
  /**
64
  * Stop WordPress from sending anything but essential data during the update check
65
  * @param array $query
134
  }
135
 
136
  public function addConsentBar() {
137
+ $output = '<div class="wpgdprc wpgdprc-consent-bar" style="display: none;">';
138
  $output .= '<div class="wpgdprc-consent-bar__container">';
139
  $output .= '<div class="wpgdprc-consent-bar__content">';
140
  $output .= '<div class="wpgdprc-consent-bar__column">';
141
  $output .= '<div class="wpgdprc-consent-bar__notice">';
142
+ $output .= apply_filters('wpgdprc_the_content', Consent::getBarExplanationText());
143
  $output .= '</div>';
144
  $output .= '</div>';
145
  $output .= '<div class="wpgdprc-consent-bar__column">';
161
  }
162
 
163
  public function addConsentModal() {
164
+ $consentIds = (array)Helper::getConsentIdsByCookie();
165
  $consents = Consent::getInstance()->getList(array(
166
  'active' => array('value' => 1)
167
  ));
185
  '<h3 class="wpgdprc-consent-modal__title">%s</h3>',
186
  Consent::getModalTitle()
187
  );
188
+ $output .= apply_filters('wpgdprc_the_content', Consent::getModalExplanationText());
189
+ $output .= apply_filters('wpgdprc_the_content', sprintf(
190
  '<strong>%s:</strong> %s',
191
  strtoupper(__('Note', WP_GDPR_C_SLUG)),
192
  __('These settings will only apply to the browser and device you are currently using.', WP_GDPR_C_SLUG)
199
  $consent->getId()
200
  );
201
  $output .= sprintf('<h3 class="wpgdprc-consent-modal__title">%s</h3>', $consent->getTitle());
202
+ $output .= apply_filters('wpgdprc_the_content', $consent->getDescription());
203
  $output .= '<div class="wpgdprc-checkbox">';
204
  $output .= '<label>';
205
  $output .= sprintf(
206
+ '<input type="checkbox" value="%d" tabindex="1" %s />',
207
+ $consent->getId(),
208
+ checked(true, in_array($consent->getId(), $consentIds), false)
209
  );
210
  $output .= '<span class="wpgdprc-switch" aria-hidden="true">';
211
  $output .= '<span class="wpgdprc-switch-label">';
213
  $output .= '<span class="wpgdprc-switch-switch"></span>';
214
  $output .= '</span>';
215
  $output .= '</span>';
216
+ $output .= __('Enable', WP_GDPR_C_SLUG);
217
+ $output .= '</label>';
218
  $output .= '</div>';
219
  $output .= '</div>'; // .wpgdprc-consent-modal__description
220
  }
242
  return;
243
  }
244
  $args = array(
 
245
  'placement' => array('value' => 'head'),
246
+ 'active' => array('value' => 1),
247
  );
248
  if (!empty($consentIds)) {
249
  $args['ID'] = array(
261
  return;
262
  }
263
  $args = array(
264
+ 'placement' => array('value' => 'footer'),
265
  'active' => array('value' => 1),
 
266
  );
267
  if (!empty($consentIds)) {
268
  $args['ID'] = array(
Includes/Consent.php CHANGED
@@ -19,6 +19,8 @@ class Consent {
19
  private $description = '';
20
  /** @var string */
21
  private $snippet = '';
 
 
22
  /** @var string */
23
  private $placement = '';
24
  /** @var string */
@@ -61,7 +63,7 @@ class Consent {
61
  public static function getModalExplanationText($insertPrivacyPolicyLink = true) {
62
  $output = get_option(WP_GDPR_C_PREFIX . '_settings_consents_modal_explanation_text');
63
  if (empty($output)) {
64
- $output = __('This site uses functional cookies and external scripts to improve your experience. Which cookies and scripts are used and how they impact your visit is specified on the left. You may change your settings at any time. Your choices will not impact your visit.', WP_GDPR_C_PREFIX);
65
  }
66
  $output = ($insertPrivacyPolicyLink === true) ? Integration::insertPrivacyPolicyLink($output) : $output;
67
  return apply_filters('wpgdprc_consents_modal_explanation_text', wp_kses($output, Helper::getAllowedHTMLTags()));
@@ -74,7 +76,7 @@ class Consent {
74
  public static function getBarExplanationText($insertPrivacyPolicyLink = true) {
75
  $output = get_option(WP_GDPR_C_PREFIX . '_settings_consents_bar_explanation_text');
76
  if (empty($output)) {
77
- $output = __('This site uses functional cookies and external scripts to improve your experience.', WP_GDPR_C_PREFIX);
78
  }
79
  $output = ($insertPrivacyPolicyLink === true) ? Integration::insertPrivacyPolicyLink($output) : $output;
80
  return apply_filters('wpgdprc_consents_bar_explanation_text', wp_kses($output, Helper::getAllowedHTMLTags()));
@@ -89,10 +91,14 @@ class Consent {
89
  if (!empty($consents)) {
90
  /** @var Consent $consent */
91
  foreach ($consents as $consent) {
92
- $output .= sprintf(
93
- '<script type="text/javascript">%s</script>',
94
- $consent->getSnippet()
95
- );
 
 
 
 
96
  }
97
  }
98
  return $output;
@@ -123,7 +129,7 @@ class Consent {
123
  public function getList($filters = array(), $limit = 0, $offset = 0) {
124
  global $wpdb;
125
  $output = array();
126
- $query = "SELECT * FROM `" . self::getDatabaseTableName() . "` WHERE 1";
127
  $query .= Helper::getQueryByFilters($filters);
128
  $query .= sprintf(" AND `site_id` = '%d'", get_current_blog_id());
129
  $query .= " ORDER BY `date_modified` DESC";
@@ -150,6 +156,7 @@ class Consent {
150
  $this->setTitle($row->title);
151
  $this->setDescription($row->description);
152
  $this->setSnippet($row->snippet);
 
153
  $this->setPlacement($row->placement);
154
  $this->setPlugins($row->plugins);
155
  $this->setActive($row->active);
@@ -190,11 +197,12 @@ class Consent {
190
  'title' => $this->getTitle(),
191
  'description' => $this->getDescription(),
192
  'snippet' => $this->getSnippet(),
 
193
  'placement' => $this->getPlacement(),
194
  'plugins' => $this->getPlugins(),
195
  'active' => $this->getActive(),
196
  );
197
- $dataTypes = array('%s', '%s', '%s', '%s', '%s', '%d');
198
  if ($this->exists($this->getId())) {
199
  $wpdb->update(
200
  self::getDatabaseTableName(),
@@ -207,7 +215,6 @@ class Consent {
207
  } else {
208
  $data['site_id'] = $this->getSiteId();
209
  $data['date_created'] = date_i18n('Y-m-d H:i:s');
210
- $data['active'] = 1;
211
  $dataTypes = array_merge($dataTypes, array('%d', '%s', '%d'));
212
  $result = $wpdb->insert(
213
  self::getDatabaseTableName(),
@@ -224,14 +231,42 @@ class Consent {
224
 
225
  /**
226
  * @param int $id
227
- * @return string
228
  */
229
- public static function getManageUrl($id = 0) {
230
- $args = array('action' => 'manage');
231
  if ((int)$id > 0) {
232
- $args['id'] = $id;
 
 
 
 
233
  }
234
- return Helper::getPluginAdminUrl('consents', $args);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  }
236
 
237
  /**
@@ -324,6 +359,20 @@ class Consent {
324
  $this->snippet = $snippet;
325
  }
326
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
327
  /**
328
  * @return string
329
  */
19
  private $description = '';
20
  /** @var string */
21
  private $snippet = '';
22
+ /** @var int */
23
+ private $wrap = 1;
24
  /** @var string */
25
  private $placement = '';
26
  /** @var string */
63
  public static function getModalExplanationText($insertPrivacyPolicyLink = true) {
64
  $output = get_option(WP_GDPR_C_PREFIX . '_settings_consents_modal_explanation_text');
65
  if (empty($output)) {
66
+ $output = __('This site uses functional cookies and external scripts to improve your experience. Which cookies and scripts are used and how they impact your visit is specified on the left. You may change your settings at any time. Your choices will not impact your visit.', WP_GDPR_C_SLUG);
67
  }
68
  $output = ($insertPrivacyPolicyLink === true) ? Integration::insertPrivacyPolicyLink($output) : $output;
69
  return apply_filters('wpgdprc_consents_modal_explanation_text', wp_kses($output, Helper::getAllowedHTMLTags()));
76
  public static function getBarExplanationText($insertPrivacyPolicyLink = true) {
77
  $output = get_option(WP_GDPR_C_PREFIX . '_settings_consents_bar_explanation_text');
78
  if (empty($output)) {
79
+ $output = __('This site uses functional cookies and external scripts to improve your experience.', WP_GDPR_C_SLUG);
80
  }
81
  $output = ($insertPrivacyPolicyLink === true) ? Integration::insertPrivacyPolicyLink($output) : $output;
82
  return apply_filters('wpgdprc_consents_bar_explanation_text', wp_kses($output, Helper::getAllowedHTMLTags()));
91
  if (!empty($consents)) {
92
  /** @var Consent $consent */
93
  foreach ($consents as $consent) {
94
+ if ($consent->getWrap()) {
95
+ $output .= sprintf(
96
+ '<script type="text/javascript">%s</script>',
97
+ $consent->getSnippet()
98
+ );
99
+ } else {
100
+ $output .= sprintf('%s', $consent->getSnippet());
101
+ }
102
  }
103
  }
104
  return $output;
129
  public function getList($filters = array(), $limit = 0, $offset = 0) {
130
  global $wpdb;
131
  $output = array();
132
+ $query = "SELECT * FROM `" . self::getDatabaseTableName() . "` WHERE 1";
133
  $query .= Helper::getQueryByFilters($filters);
134
  $query .= sprintf(" AND `site_id` = '%d'", get_current_blog_id());
135
  $query .= " ORDER BY `date_modified` DESC";
156
  $this->setTitle($row->title);
157
  $this->setDescription($row->description);
158
  $this->setSnippet($row->snippet);
159
+ $this->setWrap($row->wrap);
160
  $this->setPlacement($row->placement);
161
  $this->setPlugins($row->plugins);
162
  $this->setActive($row->active);
197
  'title' => $this->getTitle(),
198
  'description' => $this->getDescription(),
199
  'snippet' => $this->getSnippet(),
200
+ 'wrap' => $this->getWrap(),
201
  'placement' => $this->getPlacement(),
202
  'plugins' => $this->getPlugins(),
203
  'active' => $this->getActive(),
204
  );
205
+ $dataTypes = array('%s', '%s', '%s', '%d', '%s', '%s', '%d');
206
  if ($this->exists($this->getId())) {
207
  $wpdb->update(
208
  self::getDatabaseTableName(),
215
  } else {
216
  $data['site_id'] = $this->getSiteId();
217
  $data['date_created'] = date_i18n('Y-m-d H:i:s');
 
218
  $dataTypes = array_merge($dataTypes, array('%d', '%s', '%d'));
219
  $result = $wpdb->insert(
220
  self::getDatabaseTableName(),
231
 
232
  /**
233
  * @param int $id
234
+ * @return bool
235
  */
236
+ public function delete($id = 0) {
 
237
  if ((int)$id > 0) {
238
+ global $wpdb;
239
+ $result = $wpdb->delete(self::getDatabaseTableName(), array('ID' => $id), array('%d'));
240
+ if ($result !== false) {
241
+ return true;
242
+ }
243
  }
244
+ return false;
245
+ }
246
+
247
+ /**
248
+ * @param int $id
249
+ * @param string $action
250
+ * @return string
251
+ */
252
+ public static function getActionUrl($id = 0, $action = 'manage') {
253
+ return Helper::getPluginAdminUrl(
254
+ 'consents',
255
+ array(
256
+ 'action' => $action,
257
+ 'id' => $id,
258
+ )
259
+ );
260
+ }
261
+
262
+ /**
263
+ * @return array
264
+ */
265
+ public static function getPossibleCodeWraps() {
266
+ return array(
267
+ '1' => esc_html__('Wrap my code snippet with <script> tags', WP_GDPR_C_SLUG),
268
+ '0' => __('Do not wrap my code snippet', WP_GDPR_C_SLUG)
269
+ );
270
  }
271
 
272
  /**
359
  $this->snippet = $snippet;
360
  }
361
 
362
+ /**
363
+ * @return int
364
+ */
365
+ public function getWrap() {
366
+ return $this->wrap;
367
+ }
368
+
369
+ /**
370
+ * @param int $wrap
371
+ */
372
+ public function setWrap($wrap) {
373
+ $this->wrap = $wrap;
374
+ }
375
+
376
  /**
377
  * @return string
378
  */
Includes/Helper.php CHANGED
@@ -121,6 +121,40 @@ class Helper {
121
  return $output;
122
  }
123
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  /**
125
  * @param string $plugin
126
  * @return string
@@ -527,26 +561,6 @@ class Helper {
527
  dbDelta($query);
528
  }
529
 
530
- public static function createConsentsTables() {
531
- global $wpdb;
532
- require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
533
- $charsetCollate = $wpdb->get_charset_collate();
534
- $query = "CREATE TABLE IF NOT EXISTS `" . Consent::getDatabaseTableName() . "` (
535
- `ID` bigint(20) NOT NULL AUTO_INCREMENT,
536
- `site_id` bigint(20) NOT NULL,
537
- `title` text NOT NULL,
538
- `description` longtext NOT NULL,
539
- `snippet` longtext NOT NULL,
540
- `placement` varchar(20) NOT NULL,
541
- `plugins` longtext NOT NULL,
542
- `active` tinyint(1) DEFAULT '1' NOT NULL,
543
- `date_modified` timestamp DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
544
- `date_created` datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
545
- PRIMARY KEY (`ID`)
546
- ) $charsetCollate;";
547
- dbDelta($query);
548
- }
549
-
550
  /**
551
  * @param array $filters
552
  * @param bool $grouped
121
  return $output;
122
  }
123
 
124
+ /**
125
+ * @param string $notice
126
+ */
127
+ public static function showAdminNotice($notice = '') {
128
+ if (!empty($notice)) {
129
+ $type = 'success';
130
+ $dismissible = true;
131
+ $message = '';
132
+ switch ($notice) {
133
+ case 'wpgdprc-consent-updated' :
134
+ $message = __('Consent has been updated successfully.', WP_GDPR_C_SLUG);
135
+ break;
136
+ case 'wpgdprc-consent-added' :
137
+ $message = __('Consent has been added successfully.', WP_GDPR_C_SLUG);
138
+ break;
139
+ case 'wpgdprc-consent-removed' :
140
+ $message = __('Consent has been removed successfully.', WP_GDPR_C_SLUG);
141
+ break;
142
+ case 'wpgdprc-consent-not-found' :
143
+ $type = 'error';
144
+ $message = __('Couldn\'t find this consent.', WP_GDPR_C_SLUG);
145
+ break;
146
+ }
147
+ if (!empty($message)) {
148
+ printf(
149
+ '<div class="notice notice-%s %s"><p>%s</p></div>',
150
+ $type,
151
+ (($dismissible) ? 'is-dismissible' : ''),
152
+ $message
153
+ );
154
+ }
155
+ }
156
+ }
157
+
158
  /**
159
  * @param string $plugin
160
  * @return string
561
  dbDelta($query);
562
  }
563
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
564
  /**
565
  * @param array $filters
566
  * @param bool $grouped
Includes/Page.php CHANGED
@@ -164,7 +164,7 @@ class Page {
164
  foreach ($activatedPlugins as $key => $plugin) :
165
  $optionName = WP_GDPR_C_PREFIX . '_integrations_' . $plugin['id'];
166
  $checked = Helper::isEnabled($plugin['id']);
167
- $description = (!empty($plugin['description'])) ? apply_filters('the_content', $plugin['description']) : '';
168
  $notices = Helper::getNotices($plugin['id']);
169
  $options = Integration::getSupportedPluginOptions($plugin['id']);
170
  ?>
@@ -414,44 +414,24 @@ class Page {
414
  */
415
  private static function renderManageConsentPage($consentId = 0) {
416
  wp_enqueue_style('wpgdprc.admin.codemirror.css');
417
- wp_enqueue_script('wpgdprc.admin.codemirror.js');
418
- wp_enqueue_script('wpgdprc.admin.codemirror.matchbrackets.js');
419
- wp_enqueue_script('wpgdprc.admin.codemirror.comment.js');
420
- wp_enqueue_script('wpgdprc.admin.codemirror.javascript.js');
421
- if (!empty($consentId)) {
422
- if (Consent::getInstance()->exists($consentId)) {
423
- $consent = new Consent($consentId);
424
- } else {
425
- wp_redirect(Helper::getPluginAdminUrl('consents', array('notice' => 'wpgdprc-consent-not-found')));
426
- exit;
427
- }
428
- } else {
429
- $consent = new Consent();
430
- $consent->setSiteId(get_current_blog_id());
431
- }
432
  if (isset($_POST['submit']) && check_admin_referer('consent_create_or_update', 'consent_nonce')) {
433
  $active = (isset($_POST['active'])) ? 1 : 0;
434
  $title = (isset($_POST['title'])) ? esc_html($_POST['title']) : $consent->getTitle();
435
  $description = (isset($_POST['description'])) ? stripslashes(esc_html($_POST['description'])) : $consent->getDescription();
436
  $snippet = (isset($_POST['snippet'])) ? stripslashes($_POST['snippet']) : $consent->getSnippet();
 
437
  $placement = (isset($_POST['placement']) && array_key_exists($_POST['placement'], Consent::getPossiblePlacements())) ? esc_html($_POST['placement']) : $consent->getPlacement();
438
  $consent->setTitle($title);
439
  $consent->setDescription($description);
440
  $consent->setSnippet($snippet);
 
441
  $consent->setPlacement($placement);
442
  $consent->setActive($active);
443
  $id = $consent->save();
444
  if (!empty($id)) {
445
- wp_redirect(add_query_arg(
446
- array(
447
- 'notice' => sprintf(
448
- 'wpgdprc-consent-%s',
449
- (!empty($consentId) ? 'updated' : 'added')
450
- )
451
- ),
452
- Consent::getManageUrl($id)
453
- ));
454
- exit;
455
  }
456
  }
457
  ?>
@@ -488,16 +468,24 @@ class Page {
488
  <textarea name="snippet" id="wpgdprc_snippet" rows="10" autocomplete="false" autocorrect="false" autocapitalize="false" spellcheck="false"><?php echo htmlspecialchars($consent->getSnippet(), ENT_QUOTES, get_option('blog_charset')); ?></textarea>
489
  <div class="wpgdprc-information">
490
  <p><?php _e('Code snippets for Google Analytics, Facebook Pixel, etc.', WP_GDPR_C_SLUG); ?></p>
491
- <div class="wpgdprc-message wpgdprc-message--notice">
492
- <?php
 
 
 
 
 
 
 
493
  printf(
494
- '<p><strong>%s:</strong> %s</p>',
495
- strtoupper(__('Note', WP_GDPR_C_SLUG)),
496
- esc_html__('JavaScript only. Do not add any <script> tags to your snippet.', WP_GDPR_C_SLUG)
 
497
  );
498
- ?>
499
- </div>
500
- </div>
501
  </div>
502
  </div>
503
  <div class="wpgdprc-setting">
@@ -549,7 +537,7 @@ class Page {
549
  ?>
550
  <div class="wpgdprc-message wpgdprc-message--notice">
551
  <p><?php _e('Ask your visitors for permission to enable certain scripts for tracking or advertising purposes. Add a Consent for each type of script you are requesting permission for. Scripts will only be activated when permission is given.', WP_GDPR_C_SLUG); ?></p>
552
- <p><a class="button button-primary" href="<?php echo Helper::getPluginAdminUrl('consents', array('action' => 'manage')); ?>"><?php _ex('Add New', 'consent', WP_GDPR_C_SLUG); ?></a></p>
553
  </div>
554
  <?php if (!empty($consents)) : ?>
555
  <table class="wpgdprc-table">
@@ -558,9 +546,9 @@ class Page {
558
  <th scope="col" width="10%"><?php _e('Consent', WP_GDPR_C_SLUG); ?></th>
559
  <th scope="col" width="16%"><?php _e('Title', WP_GDPR_C_SLUG); ?></th>
560
  <th scope="col" width="12%"><?php _e('Placement', WP_GDPR_C_SLUG); ?></th>
561
- <th scope="col" width="22%"><?php _e('Modified at', WP_GDPR_C_SLUG); ?></th>
562
- <th scope="col" width="22%"><?php _e('Created at', WP_GDPR_C_SLUG); ?></th>
563
- <th scope="col" width="10%"><?php _e('Action', WP_GDPR_C_SLUG); ?></th>
564
  <th scope="col" width="8%"><?php _e('Active', WP_GDPR_C_SLUG); ?></th>
565
  </tr>
566
  </thead>
@@ -568,11 +556,35 @@ class Page {
568
  <?php foreach ($consents as $consent) : ?>
569
  <tr class="wpgdprc-table__row <?php echo (!$consent->getActive()) ? 'wpgdprc-table__row--expired' : ''; ?>">
570
  <td><?php printf('#%d', $consent->getId()); ?></td>
571
- <td><?php printf('<a href="%s">%s</a>', Consent::getManageUrl($consent->getId()), $consent->getTitle()); ?></td>
 
 
 
 
 
 
 
 
572
  <td><?php echo $consent->getPlacement(); ?></td>
573
  <td><?php echo $consent->getDateModified(); ?></td>
574
  <td><?php echo $consent->getDateCreated(); ?></td>
575
- <td><?php printf('<a href="%s">%s</a>', Consent::getManageUrl($consent->getId()), __('Edit', WP_GDPR_C_SLUG)); ?></td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
576
  <td><?php echo ($consent->getActive()) ? __('Yes', WP_GDPR_C_SLUG) : __('No', WP_GDPR_C_SLUG); ?></td>
577
  </tr>
578
  <?php endforeach; ?>
164
  foreach ($activatedPlugins as $key => $plugin) :
165
  $optionName = WP_GDPR_C_PREFIX . '_integrations_' . $plugin['id'];
166
  $checked = Helper::isEnabled($plugin['id']);
167
+ $description = (!empty($plugin['description'])) ? apply_filters('wpgdprc_the_content', $plugin['description']) : '';
168
  $notices = Helper::getNotices($plugin['id']);
169
  $options = Integration::getSupportedPluginOptions($plugin['id']);
170
  ?>
414
  */
415
  private static function renderManageConsentPage($consentId = 0) {
416
  wp_enqueue_style('wpgdprc.admin.codemirror.css');
417
+ wp_enqueue_script('wpgdprc.admin.codemirror.additional.js');
418
+ $consent = new Consent($consentId);
 
 
 
 
 
 
 
 
 
 
 
 
 
419
  if (isset($_POST['submit']) && check_admin_referer('consent_create_or_update', 'consent_nonce')) {
420
  $active = (isset($_POST['active'])) ? 1 : 0;
421
  $title = (isset($_POST['title'])) ? esc_html($_POST['title']) : $consent->getTitle();
422
  $description = (isset($_POST['description'])) ? stripslashes(esc_html($_POST['description'])) : $consent->getDescription();
423
  $snippet = (isset($_POST['snippet'])) ? stripslashes($_POST['snippet']) : $consent->getSnippet();
424
+ $wrap = (isset($_POST['wrap']) && array_key_exists($_POST['wrap'], Consent::getPossibleCodeWraps())) ? esc_html($_POST['wrap']) : $consent->getWrap();
425
  $placement = (isset($_POST['placement']) && array_key_exists($_POST['placement'], Consent::getPossiblePlacements())) ? esc_html($_POST['placement']) : $consent->getPlacement();
426
  $consent->setTitle($title);
427
  $consent->setDescription($description);
428
  $consent->setSnippet($snippet);
429
+ $consent->setWrap($wrap);
430
  $consent->setPlacement($placement);
431
  $consent->setActive($active);
432
  $id = $consent->save();
433
  if (!empty($id)) {
434
+ Helper::showAdminNotice('wpgdprc-consent-updated');
 
 
 
 
 
 
 
 
 
435
  }
436
  }
437
  ?>
468
  <textarea name="snippet" id="wpgdprc_snippet" rows="10" autocomplete="false" autocorrect="false" autocapitalize="false" spellcheck="false"><?php echo htmlspecialchars($consent->getSnippet(), ENT_QUOTES, get_option('blog_charset')); ?></textarea>
469
  <div class="wpgdprc-information">
470
  <p><?php _e('Code snippets for Google Analytics, Facebook Pixel, etc.', WP_GDPR_C_SLUG); ?></p>
471
+ </div>
472
+ </div>
473
+ </div>
474
+ <div class="wpgdprc-setting">
475
+ <label for="wpgdprc_code_wrap"><?php _e('Code Wrap', WP_GDPR_C_SLUG); ?></label>
476
+ <div class="wpgdprc-options">
477
+ <select name="wrap" id="wpgdprc_code_wrap">
478
+ <?php
479
+ foreach (Consent::getPossibleCodeWraps() as $value => $label) {
480
  printf(
481
+ '<option value="%s" %s>%s</option>',
482
+ $value,
483
+ selected($value, $consent->getWrap(), false),
484
+ $label
485
  );
486
+ }
487
+ ?>
488
+ </select>
489
  </div>
490
  </div>
491
  <div class="wpgdprc-setting">
537
  ?>
538
  <div class="wpgdprc-message wpgdprc-message--notice">
539
  <p><?php _e('Ask your visitors for permission to enable certain scripts for tracking or advertising purposes. Add a Consent for each type of script you are requesting permission for. Scripts will only be activated when permission is given.', WP_GDPR_C_SLUG); ?></p>
540
+ <p><a class="button button-primary" href="<?php echo Helper::getPluginAdminUrl('consents', array('action' => 'create')); ?>"><?php _ex('Add New', 'consent', WP_GDPR_C_SLUG); ?></a></p>
541
  </div>
542
  <?php if (!empty($consents)) : ?>
543
  <table class="wpgdprc-table">
546
  <th scope="col" width="10%"><?php _e('Consent', WP_GDPR_C_SLUG); ?></th>
547
  <th scope="col" width="16%"><?php _e('Title', WP_GDPR_C_SLUG); ?></th>
548
  <th scope="col" width="12%"><?php _e('Placement', WP_GDPR_C_SLUG); ?></th>
549
+ <th scope="col" width="20%"><?php _e('Modified at', WP_GDPR_C_SLUG); ?></th>
550
+ <th scope="col" width="20%"><?php _e('Created at', WP_GDPR_C_SLUG); ?></th>
551
+ <th scope="col" width="14%"><?php _e('Action', WP_GDPR_C_SLUG); ?></th>
552
  <th scope="col" width="8%"><?php _e('Active', WP_GDPR_C_SLUG); ?></th>
553
  </tr>
554
  </thead>
556
  <?php foreach ($consents as $consent) : ?>
557
  <tr class="wpgdprc-table__row <?php echo (!$consent->getActive()) ? 'wpgdprc-table__row--expired' : ''; ?>">
558
  <td><?php printf('#%d', $consent->getId()); ?></td>
559
+ <td>
560
+ <?php
561
+ printf(
562
+ '<a href="%s">%s</a>',
563
+ Consent::getActionUrl($consent->getId()),
564
+ ((!empty($consent->getTitle())) ? $consent->getTitle() : __('(no title)'))
565
+ );
566
+ ?>
567
+ </td>
568
  <td><?php echo $consent->getPlacement(); ?></td>
569
  <td><?php echo $consent->getDateModified(); ?></td>
570
  <td><?php echo $consent->getDateCreated(); ?></td>
571
+ <td>
572
+ <?php
573
+ printf(
574
+ '%s | %s',
575
+ sprintf(
576
+ '<a href="%s">%s</a>',
577
+ Consent::getActionUrl($consent->getId()),
578
+ __('Edit', WP_GDPR_C_SLUG)
579
+ ),
580
+ sprintf(
581
+ '<a href="%s">%s</a>',
582
+ Consent::getActionUrl($consent->getId(), 'delete'),
583
+ __('Remove', WP_GDPR_C_SLUG)
584
+ )
585
+ );
586
+ ?>
587
+ </td>
588
  <td><?php echo ($consent->getActive()) ? __('Yes', WP_GDPR_C_SLUG) : __('No', WP_GDPR_C_SLUG); ?></td>
589
  </tr>
590
  <?php endforeach; ?>
Includes/Shortcode.php CHANGED
@@ -28,7 +28,7 @@ class Shortcode {
28
 
29
  $output .= sprintf(
30
  '<div class="wpgdprc-message wpgdprc-message--notice">%s</div>',
31
- apply_filters('the_content', Integration::getDeleteRequestFormExplanationText())
32
  );
33
 
34
  // WordPress Users
28
 
29
  $output .= sprintf(
30
  '<div class="wpgdprc-message wpgdprc-message--notice">%s</div>',
31
+ apply_filters('wpgdprc_the_content', Integration::getDeleteRequestFormExplanationText())
32
  );
33
 
34
  // WordPress Users
assets/js/admin.js CHANGED
@@ -184,13 +184,10 @@
184
  var $snippet = document.getElementById('wpgdprc_snippet');
185
  if ($snippet !== null) {
186
  var editor = CodeMirror.fromTextArea($snippet, {
 
187
  lineNumbers: true,
188
  matchBrackets: true,
189
- // continueComments: 'Enter',
190
- indentUnit: 4,
191
- extraKeys: {
192
- 'Ctrl-Q': 'toggleComment'
193
- }
194
  });
195
  }
196
  });
184
  var $snippet = document.getElementById('wpgdprc_snippet');
185
  if ($snippet !== null) {
186
  var editor = CodeMirror.fromTextArea($snippet, {
187
+ mode: 'text/html',
188
  lineNumbers: true,
189
  matchBrackets: true,
190
+ indentUnit: 4
 
 
 
 
191
  });
192
  }
193
  });
assets/js/front.js CHANGED
@@ -114,6 +114,8 @@
114
  return;
115
  }
116
 
 
 
117
  var $button = $consentBar.querySelector('.wpgdprc-consent-bar__button');
118
  if ($button !== null) {
119
  $button.addEventListener('click', function (e) {
@@ -305,7 +307,9 @@
305
  };
306
 
307
  document.addEventListener('DOMContentLoaded', function () {
308
- initConsentBar();
 
 
309
  initConsentModal();
310
  initFormAccessRequest();
311
  initFormDeleteRequest();
114
  return;
115
  }
116
 
117
+ $consentBar.style.display = 'block';
118
+
119
  var $button = $consentBar.querySelector('.wpgdprc-consent-bar__button');
120
  if ($button !== null) {
121
  $button.addEventListener('click', function (e) {
307
  };
308
 
309
  document.addEventListener('DOMContentLoaded', function () {
310
+ if (_readCookie('wpgdprc-consent') === null) {
311
+ initConsentBar();
312
+ }
313
  initConsentModal();
314
  initFormAccessRequest();
315
  initFormDeleteRequest();
assets/vendor/codemirror/codemirror.additional.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(P){"use strict";function e(e){for(var t={},r=0;r<e.length;++r)t[e[r].toLowerCase()]=!0;return t}P.defineMode("css",function(e,t){var r=t.inline;t.propertyKeywords||(t=P.resolveMode("text/css"));var n,a,o=e.indentUnit,i=t.tokenHooks,l=t.documentTypes||{},s=t.mediaTypes||{},c=t.mediaFeatures||{},u=t.mediaValueKeywords||{},d=t.propertyKeywords||{},p=t.nonStandardPropertyKeywords||{},f=t.fontProperties||{},m=t.counterDescriptors||{},h=t.colorKeywords||{},g=t.valueKeywords||{},b=t.allowNested,k=t.lineComment,y=!0===t.supportsAtComponent;function v(e,t){return n=t,e}function w(a){return function(e,t){for(var r,n=!1;null!=(r=e.next());){if(r==a&&!n){")"==a&&e.backUp(1);break}n=!n&&"\\"==r}return(r==a||!n&&")"!=a)&&(t.tokenize=null),v("string","string")}}function x(e,t){return e.next(),e.match(/\s*[\"\')]/,!1)?t.tokenize=null:t.tokenize=w(")"),v(null,"(")}function z(e,t,r){this.type=e,this.indent=t,this.prev=r}function M(e,t,r,n){return e.context=new z(r,t.indentation()+(!1===n?0:o),e.context),r}function j(e){return e.context.prev&&(e.context=e.context.prev),e.context.type}function T(e,t,r){return C[r.context.type](e,t,r)}function S(e,t,r,n){for(var a=n||1;0<a;a--)r.context=r.context.prev;return T(e,t,r)}function A(e){var t=e.current().toLowerCase();a=g.hasOwnProperty(t)?"atom":h.hasOwnProperty(t)?"keyword":"variable"}var C={top:function(e,t,r){if("{"==e)return M(r,t,"block");if("}"==e&&r.context.prev)return j(r);if(y&&/@component/i.test(e))return M(r,t,"atComponentBlock");if(/^@(-moz-)?document$/i.test(e))return M(r,t,"documentTypes");if(/^@(media|supports|(-moz-)?document|import)$/i.test(e))return M(r,t,"atBlock");if(/^@(font-face|counter-style)/i.test(e))return r.stateArg=e,"restricted_atBlock_before";if(/^@(-(moz|ms|o|webkit)-)?keyframes$/i.test(e))return"keyframes";if(e&&"@"==e.charAt(0))return M(r,t,"at");if("hash"==e)a="builtin";else if("word"==e)a="tag";else{if("variable-definition"==e)return"maybeprop";if("interpolation"==e)return M(r,t,"interpolation");if(":"==e)return"pseudo";if(b&&"("==e)return M(r,t,"parens")}return r.context.type},block:function(e,t,r){if("word"==e){var n=t.current().toLowerCase();return d.hasOwnProperty(n)?(a="property","maybeprop"):p.hasOwnProperty(n)?(a="string-2","maybeprop"):b?(a=t.match(/^\s*:(?:\s|$)/,!1)?"property":"tag","block"):(a+=" error","maybeprop")}return"meta"==e?"block":b||"hash"!=e&&"qualifier"!=e?C.top(e,t,r):(a="error","block")},maybeprop:function(e,t,r){return":"==e?M(r,t,"prop"):T(e,t,r)},prop:function(e,t,r){if(";"==e)return j(r);if("{"==e&&b)return M(r,t,"propBlock");if("}"==e||"{"==e)return S(e,t,r);if("("==e)return M(r,t,"parens");if("hash"!=e||/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(t.current())){if("word"==e)A(t);else if("interpolation"==e)return M(r,t,"interpolation")}else a+=" error";return"prop"},propBlock:function(e,t,r){return"}"==e?j(r):"word"==e?(a="property","maybeprop"):r.context.type},parens:function(e,t,r){return"{"==e||"}"==e?S(e,t,r):")"==e?j(r):"("==e?M(r,t,"parens"):"interpolation"==e?M(r,t,"interpolation"):("word"==e&&A(t),"parens")},pseudo:function(e,t,r){return"meta"==e?"pseudo":"word"==e?(a="variable-3",r.context.type):T(e,t,r)},documentTypes:function(e,t,r){return"word"==e&&l.hasOwnProperty(t.current())?(a="tag",r.context.type):C.atBlock(e,t,r)},atBlock:function(e,t,r){if("("==e)return M(r,t,"atBlock_parens");if("}"==e||";"==e)return S(e,t,r);if("{"==e)return j(r)&&M(r,t,b?"block":"top");if("interpolation"==e)return M(r,t,"interpolation");if("word"==e){var n=t.current().toLowerCase();a="only"==n||"not"==n||"and"==n||"or"==n?"keyword":s.hasOwnProperty(n)?"attribute":c.hasOwnProperty(n)?"property":u.hasOwnProperty(n)?"keyword":d.hasOwnProperty(n)?"property":p.hasOwnProperty(n)?"string-2":g.hasOwnProperty(n)?"atom":h.hasOwnProperty(n)?"keyword":"error"}return r.context.type},atComponentBlock:function(e,t,r){return"}"==e?S(e,t,r):"{"==e?j(r)&&M(r,t,b?"block":"top",!1):("word"==e&&(a="error"),r.context.type)},atBlock_parens:function(e,t,r){return")"==e?j(r):"{"==e||"}"==e?S(e,t,r,2):C.atBlock(e,t,r)},restricted_atBlock_before:function(e,t,r){return"{"==e?M(r,t,"restricted_atBlock"):"word"==e&&"@counter-style"==r.stateArg?(a="variable","restricted_atBlock_before"):T(e,t,r)},restricted_atBlock:function(e,t,r){return"}"==e?(r.stateArg=null,j(r)):"word"==e?(a="@font-face"==r.stateArg&&!f.hasOwnProperty(t.current().toLowerCase())||"@counter-style"==r.stateArg&&!m.hasOwnProperty(t.current().toLowerCase())?"error":"property","maybeprop"):"restricted_atBlock"},keyframes:function(e,t,r){return"word"==e?(a="variable","keyframes"):"{"==e?M(r,t,"top"):T(e,t,r)},at:function(e,t,r){return";"==e?j(r):"{"==e||"}"==e?S(e,t,r):("word"==e?a="tag":"hash"==e&&(a="builtin"),"at")},interpolation:function(e,t,r){return"}"==e?j(r):"{"==e||";"==e?S(e,t,r):("word"==e?a="variable":"variable"!=e&&"("!=e&&")"!=e&&(a="error"),"interpolation")}};return{startState:function(e){return{tokenize:null,state:r?"block":"top",stateArg:null,context:new z(r?"block":"top",e||0,null)}},token:function(e,t){if(!t.tokenize&&e.eatSpace())return null;var r=(t.tokenize||function(e,t){var r=e.next();if(i[r]){var n=i[r](e,t);if(!1!==n)return n}return"@"==r?(e.eatWhile(/[\w\\\-]/),v("def",e.current())):"="==r||("~"==r||"|"==r)&&e.eat("=")?v(null,"compare"):'"'==r||"'"==r?(t.tokenize=w(r),t.tokenize(e,t)):"#"==r?(e.eatWhile(/[\w\\\-]/),v("atom","hash")):"!"==r?(e.match(/^\s*\w*/),v("keyword","important")):/\d/.test(r)||"."==r&&e.eat(/\d/)?(e.eatWhile(/[\w.%]/),v("number","unit")):"-"!==r?/[,+>*\/]/.test(r)?v(null,"select-op"):"."==r&&e.match(/^-?[_a-z][_a-z0-9-]*/i)?v("qualifier","qualifier"):/[:;{}\[\]\(\)]/.test(r)?v(null,r):("u"==r||"U"==r)&&e.match(/rl(-prefix)?\(/i)||("d"==r||"D"==r)&&e.match("omain(",!0,!0)||("r"==r||"R"==r)&&e.match("egexp(",!0,!0)?(e.backUp(1),t.tokenize=x,v("property","word")):/[\w\\\-]/.test(r)?(e.eatWhile(/[\w\\\-]/),v("property","word")):v(null,null):/[\d.]/.test(e.peek())?(e.eatWhile(/[\w.%]/),v("number","unit")):e.match(/^-[\w\\\-]+/)?(e.eatWhile(/[\w\\\-]/),e.match(/^\s*:/,!1)?v("variable-2","variable-definition"):v("variable-2","variable")):e.match(/^\w+-/)?v("meta","meta"):void 0})(e,t);return r&&"object"==typeof r&&(n=r[1],r=r[0]),a=r,"comment"!=n&&(t.state=C[t.state](n,e,t)),a},indent:function(e,t){var r=e.context,n=t&&t.charAt(0),a=r.indent;return"prop"!=r.type||"}"!=n&&")"!=n||(r=r.prev),r.prev&&("}"!=n||"block"!=r.type&&"top"!=r.type&&"interpolation"!=r.type&&"restricted_atBlock"!=r.type?(")"!=n||"parens"!=r.type&&"atBlock_parens"!=r.type)&&("{"!=n||"at"!=r.type&&"atBlock"!=r.type)||(a=Math.max(0,r.indent-o)):a=(r=r.prev).indent),a},electricChars:"}",blockCommentStart:"/*",blockCommentEnd:"*/",blockCommentContinue:" * ",lineComment:k,fold:"brace"}});var t=["domain","regexp","url","url-prefix"],r=e(t),n=["all","aural","braille","handheld","print","projection","screen","tty","tv","embossed"],a=e(n),o=["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid","orientation","device-pixel-ratio","min-device-pixel-ratio","max-device-pixel-ratio","pointer","any-pointer","hover","any-hover"],i=e(o),l=["landscape","portrait","none","coarse","fine","on-demand","hover","interlace","progressive"],s=e(l),c=["align-content","align-items","align-self","alignment-adjust","alignment-baseline","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","binding","bleed","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","caret-color","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","flow-from","flow-into","font","font-feature-settings","font-family","font-kerning","font-language-override","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-weight","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-gap","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-gap","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","justify-content","justify-items","justify-self","left","letter-spacing","line-break","line-height","line-stacking","line-stacking-ruby","line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","max-height","max-width","min-height","min-width","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","place-content","place-items","place-self","play-during","position","presentation-level","punctuation-trim","quotes","region-break-after","region-break-before","region-break-inside","region-fragment","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotation","rotation-point","ruby-align","ruby-overhang","ruby-position","ruby-span","shape-image-threshold","shape-inside","shape-margin","shape-outside","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-outline","text-overflow","text-shadow","text-size-adjust","text-space-collapse","text-transform","text-underline-position","text-wrap","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","user-select","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","z-index","clip-path","clip-rule","mask","enable-background","filter","flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","text-anchor","writing-mode"],u=e(c),d=["scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-color","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-3d-light-color","scrollbar-track-color","shape-inside","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","zoom"],p=e(d),f=e(["font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"]),m=e(["additive-symbols","fallback","negative","pad","prefix","range","speak-as","suffix","symbols","system"]),h=["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"],g=e(h),b=["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","auto-flow","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","color","color-burn","color-dodge","column","column-reverse","compact","condensed","contain","content","contents","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor","cursive","cyclic","darken","dashed","decimal","decimal-leading-zero","default","default-button","dense","destination-atop","destination-in","destination-out","destination-over","devanagari","difference","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","exclusion","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","flex","flex-end","flex-start","footnotes","forwards","from","geometricPrecision","georgian","graytext","grid","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hard-light","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","hue","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-grid","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","lighten","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","luminosity","malayalam","match","matrix","matrix3d","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","multiply","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","opacity","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row","row-resize","row-reverse","rtl","run-in","running","s-resize","sans-serif","saturation","scale","scale3d","scaleX","scaleY","scaleZ","screen","scroll","scrollbar","scroll-position","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","self-start","self-end","semi-condensed","semi-expanded","separate","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","soft-light","solid","somali","source-atop","source-in","source-out","source-over","space","space-around","space-between","space-evenly","spell-out","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","symbolic","symbols","system-ui","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","transform","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","unset","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","wrap","wrap-reverse","x-large","x-small","xor","xx-large","xx-small"],k=e(b),y=t.concat(n).concat(o).concat(l).concat(c).concat(d).concat(h).concat(b);function v(e,t){for(var r,n=!1;null!=(r=e.next());){if(n&&"/"==r){t.tokenize=null;break}n="*"==r}return["comment","comment"]}P.registerHelper("hintWords","css",y),P.defineMIME("text/css",{documentTypes:r,mediaTypes:a,mediaFeatures:i,mediaValueKeywords:s,propertyKeywords:u,nonStandardPropertyKeywords:p,fontProperties:f,counterDescriptors:m,colorKeywords:g,valueKeywords:k,tokenHooks:{"/":function(e,t){return!!e.eat("*")&&(t.tokenize=v)(e,t)}},name:"css"}),P.defineMIME("text/x-scss",{mediaTypes:a,mediaFeatures:i,mediaValueKeywords:s,propertyKeywords:u,nonStandardPropertyKeywords:p,colorKeywords:g,valueKeywords:k,fontProperties:f,allowNested:!0,lineComment:"//",tokenHooks:{"/":function(e,t){return e.eat("/")?(e.skipToEnd(),["comment","comment"]):e.eat("*")?(t.tokenize=v)(e,t):["operator","operator"]},":":function(e){return!!e.match(/\s*\{/,!1)&&[null,null]},$:function(e){return e.match(/^[\w-]+/),e.match(/^\s*:/,!1)?["variable-2","variable-definition"]:["variable-2","variable"]},"#":function(e){return!!e.eat("{")&&[null,"interpolation"]}},name:"css",helperType:"scss"}),P.defineMIME("text/x-less",{mediaTypes:a,mediaFeatures:i,mediaValueKeywords:s,propertyKeywords:u,nonStandardPropertyKeywords:p,colorKeywords:g,valueKeywords:k,fontProperties:f,allowNested:!0,lineComment:"//",tokenHooks:{"/":function(e,t){return e.eat("/")?(e.skipToEnd(),["comment","comment"]):e.eat("*")?(t.tokenize=v)(e,t):["operator","operator"]},"@":function(e){return e.eat("{")?[null,"interpolation"]:!e.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/i,!1)&&(e.eatWhile(/[\w\\\-]/),e.match(/^\s*:/,!1)?["variable-2","variable-definition"]:["variable-2","variable"])},"&":function(){return["atom","atom"]}},name:"css",helperType:"less"}),P.defineMIME("text/x-gss",{documentTypes:r,mediaTypes:a,mediaFeatures:i,propertyKeywords:u,nonStandardPropertyKeywords:p,fontProperties:f,counterDescriptors:m,colorKeywords:g,valueKeywords:k,supportsAtComponent:!0,tokenHooks:{"/":function(e,t){return!!e.eat("*")&&(t.tokenize=v)(e,t)}},name:"css",helperType:"gss"})}),function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror"),require("../xml/xml"),require("../javascript/javascript"),require("../css/css")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../xml/xml","../javascript/javascript","../css/css"],e):e(CodeMirror)}(function(m){"use strict";var a={script:[["lang",/(javascript|babel)/i,"javascript"],["type",/^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i,"javascript"],["type",/./,"text/plain"],[null,null,"javascript"]],style:[["lang",/^css$/i,"css"],["type",/^(text\/)?(x-)?(stylesheet|css)$/i,"css"],["type",/./,"text/plain"],[null,null,"css"]]};var o={};function h(e,t){var r,n=e.match(o[r=t]||(o[r]=new RegExp("\\s+"+r+"\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*")));return n?/^\s*(.*?)\s*$/.exec(n[2])[1]:""}function g(e,t){return new RegExp((t?"^":"")+"</s*"+e+"s*>","i")}function i(e,t){for(var r in e)for(var n=t[r]||(t[r]=[]),a=e[r],o=a.length-1;0<=o;o--)n.unshift(a[o])}m.defineMode("htmlmixed",function(u,e){var d=m.getMode(u,{name:"xml",htmlMode:!0,multilineTagIndentFactor:e.multilineTagIndentFactor,multilineTagIndentPastTag:e.multilineTagIndentPastTag}),p={},t=e&&e.tags,r=e&&e.scriptTypes;if(i(a,p),t&&i(t,p),r)for(var n=r.length-1;0<=n;n--)p.script.unshift(["type",r[n].matches,r[n].mode]);function f(e,t){var r,n=d.token(e,t.htmlState),a=/\btag\b/.test(n);if(a&&!/[<>\s\/]/.test(e.current())&&(r=t.htmlState.tagName&&t.htmlState.tagName.toLowerCase())&&p.hasOwnProperty(r))t.inTag=r+" ";else if(t.inTag&&a&&/>$/.test(e.current())){var o=/^([\S]+) (.*)/.exec(t.inTag);t.inTag=null;var i=">"==e.current()&&function(e,t){for(var r=0;r<e.length;r++){var n=e[r];if(!n[0]||n[1].test(h(t,n[0])))return n[2]}}(p[o[1]],o[2]),l=m.getMode(u,i),s=g(o[1],!0),c=g(o[1],!1);t.token=function(e,t){return e.match(s,!1)?(t.token=f,t.localState=t.localMode=null,null):(r=e,n=c,a=t.localMode.token(e,t.localState),o=r.current(),-1<(i=o.search(n))?r.backUp(o.length-i):o.match(/<\/?$/)&&(r.backUp(o.length),r.match(n,!1)||r.match(o)),a);var r,n,a,o,i},t.localMode=l,t.localState=m.startState(l,d.indent(t.htmlState,""))}else t.inTag&&(t.inTag+=e.current(),e.eol()&&(t.inTag+=" "));return n}return{startState:function(){return{token:f,inTag:null,localMode:null,localState:null,htmlState:m.startState(d)}},copyState:function(e){var t;return e.localState&&(t=m.copyState(e.localMode,e.localState)),{token:e.token,inTag:e.inTag,localMode:e.localMode,localState:t,htmlState:m.copyState(d,e.htmlState)}},token:function(e,t){return t.token(e,t)},indent:function(e,t,r){return!e.localMode||/^\s*<\//.test(t)?d.indent(e.htmlState,t):e.localMode.indent?e.localMode.indent(e.localState,t,r):m.Pass},innerMode:function(e){return{state:e.localState||e.htmlState,mode:e.localMode||d}}}},"xml","javascript","css"),m.defineMIME("text/html","htmlmixed")}),function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(De){"use strict";De.defineMode("javascript",function(e,d){var n,a,p=e.indentUnit,f=d.statementIndent,i=d.jsonld,l=d.json||i,c=d.typescript,u=d.wordCharacters||/[\w$\xa1-\uffff]/,s=function(){function e(e){return{type:e,style:"keyword"}}var t=e("keyword a"),r=e("keyword b"),n=e("keyword c"),a=e("keyword d"),o=e("operator"),i={type:"atom",style:"atom"};return{if:e("if"),while:t,with:t,else:r,do:r,try:r,finally:r,return:a,break:a,continue:a,new:e("new"),delete:n,void:n,throw:n,debugger:e("debugger"),var:e("var"),const:e("var"),let:e("var"),function:e("function"),catch:e("catch"),for:e("for"),switch:e("switch"),case:e("case"),default:e("default"),in:o,typeof:o,instanceof:o,true:i,false:i,null:i,undefined:i,NaN:i,Infinity:i,this:e("this"),class:e("class"),super:e("atom"),yield:n,export:e("export"),import:e("import"),extends:n,await:n}}(),m=/[+\-*&%=<>!?|~^@]/,h=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;function g(e,t,r){return n=e,a=r,t}function b(e,t){var a,r=e.next();if('"'==r||"'"==r)return t.tokenize=(a=r,function(e,t){var r,n=!1;if(i&&"@"==e.peek()&&e.match(h))return t.tokenize=b,g("jsonld-keyword","meta");for(;null!=(r=e.next())&&(r!=a||n);)n=!n&&"\\"==r;return n||(t.tokenize=b),g("string","string")}),t.tokenize(e,t);if("."==r&&e.match(/^\d+(?:[eE][+\-]?\d+)?/))return g("number","number");if("."==r&&e.match(".."))return g("spread","meta");if(/[\[\]{}\(\),;\:\.]/.test(r))return g(r);if("="==r&&e.eat(">"))return g("=>","operator");if("0"==r&&e.match(/^(?:x[\da-f]+|o[0-7]+|b[01]+)n?/i))return g("number","number");if(/\d/.test(r))return e.match(/^\d*(?:n|(?:\.\d*)?(?:[eE][+\-]?\d+)?)?/),g("number","number");if("/"==r)return e.eat("*")?(t.tokenize=k)(e,t):e.eat("/")?(e.skipToEnd(),g("comment","comment")):Ue(e,t,1)?(function(e){for(var t,r=!1,n=!1;null!=(t=e.next());){if(!r){if("/"==t&&!n)return;"["==t?n=!0:n&&"]"==t&&(n=!1)}r=!r&&"\\"==t}}(e),e.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/),g("regexp","string-2")):(e.eat("="),g("operator","operator",e.current()));if("`"==r)return(t.tokenize=y)(e,t);if("#"==r)return e.skipToEnd(),g("error","error");if(m.test(r))return">"==r&&t.lexical&&">"==t.lexical.type||(e.eat("=")?"!"!=r&&"="!=r||e.eat("="):/[<>*+\-]/.test(r)&&(e.eat(r),">"==r&&e.eat(r))),g("operator","operator",e.current());if(u.test(r)){e.eatWhile(u);var n=e.current();if("."!=t.lastType){if(s.propertyIsEnumerable(n)){var o=s[n];return g(o.type,o.style,n)}if("async"==n&&e.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/,!1))return g("async","keyword",n)}return g("variable","variable",n)}}function k(e,t){for(var r,n=!1;r=e.next();){if("/"==r&&n){t.tokenize=b;break}n="*"==r}return g("comment","comment")}function y(e,t){for(var r,n=!1;null!=(r=e.next());){if(!n&&("`"==r||"$"==r&&e.eat("{"))){t.tokenize=b;break}n=!n&&"\\"==r}return g("quasi","string-2",e.current())}var v="([{}])";function o(e,t){t.fatArrowAt&&(t.fatArrowAt=null);var r=e.string.indexOf("=>",e.start);if(!(r<0)){if(c){var n=/:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(e.string.slice(e.start,r));n&&(r=n.index)}for(var a=0,o=!1,i=r-1;0<=i;--i){var l=e.string.charAt(i),s=v.indexOf(l);if(0<=s&&s<3){if(!a){++i;break}if(0==--a){"("==l&&(o=!0);break}}else if(3<=s&&s<6)++a;else if(u.test(l))o=!0;else{if(/["'\/]/.test(l))return;if(o&&!a){++i;break}}}o&&!a&&(t.fatArrowAt=i)}}var w={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,this:!0,"jsonld-keyword":!0};function x(e,t,r,n,a,o){this.indented=e,this.column=t,this.type=r,this.prev=a,this.info=o,null!=n&&(this.align=n)}function z(e,t){for(var r=e.localVars;r;r=r.next)if(r.name==t)return!0;for(var n=e.context;n;n=n.prev)for(r=n.vars;r;r=r.next)if(r.name==t)return!0}var M={state:null,column:null,marked:null,cc:null};function j(){for(var e=arguments.length-1;0<=e;e--)M.cc.push(arguments[e])}function T(){return j.apply(null,arguments),!0}function S(e,t){for(var r=t;r;r=r.next)if(r.name==e)return!0;return!1}function r(e){var t=M.state;if(M.marked="def",t.context)if("var"==t.lexical.info&&t.context&&t.context.block){var r=function e(t,r){{if(r){if(r.block){var n=e(t,r.prev);return n?n==r.prev?r:new C(n,r.vars,!0):null}return S(t,r.vars)?r:new C(r.prev,new P(t,r.vars),!1)}return null}}(e,t.context);if(null!=r)return void(t.context=r)}else if(!S(e,t.localVars))return void(t.localVars=new P(e,t.localVars));d.globalVars&&!S(e,t.globalVars)&&(t.globalVars=new P(e,t.globalVars))}function A(e){return"public"==e||"private"==e||"protected"==e||"abstract"==e||"readonly"==e}function C(e,t,r){this.prev=e,this.vars=t,this.block=r}function P(e,t){this.name=e,this.next=t}var t=new P("this",new P("arguments",null));function q(){M.state.context=new C(M.state.context,M.state.localVars,!1),M.state.localVars=t}function I(){M.state.context=new C(M.state.context,M.state.localVars,!0),M.state.localVars=null}function E(){M.state.localVars=M.state.context.vars,M.state.context=M.state.context.prev}function B(n,a){var e=function(){var e=M.state,t=e.indented;if("stat"==e.lexical.type)t=e.lexical.indented;else for(var r=e.lexical;r&&")"==r.type&&r.align;r=r.prev)t=r.indented;e.lexical=new x(t,M.stream.column(),n,null,e.lexical,a)};return e.lex=!0,e}function O(){var e=M.state;e.lexical.prev&&(")"==e.lexical.type&&(e.indented=e.lexical.indented),e.lexical=e.lexical.prev)}function N(r){return function e(t){return t==r?T():";"==r?j():T(e)}}function $(e,t){return"var"==e?T(B("vardef",t),be,N(";"),O):"keyword a"==e?T(B("form"),_,$,O):"keyword b"==e?T(B("form"),$,O):"keyword d"==e?M.stream.match(/^\s*$/,!1)?T():T(B("stat"),W,N(";"),O):"debugger"==e?T(N(";")):"{"==e?T(B("}"),I,oe,O,E):";"==e?T():"if"==e?("else"==M.state.lexical.info&&M.state.cc[M.state.cc.length-1]==O&&M.state.cc.pop()(),T(B("form"),_,$,O,xe)):"function"==e?T(Ae):"for"==e?T(B("form"),ze,$,O):"class"==e||c&&"interface"==t?(M.marked="keyword",T(B("form"),qe,O)):"variable"==e?c&&"declare"==t?(M.marked="keyword",T($)):c&&("module"==t||"enum"==t||"type"==t)&&M.stream.match(/^\s*\w/,!1)?(M.marked="keyword","enum"==t?T(We):"type"==t?T(ce,N("operator"),ce,N(";")):T(B("form"),ke,N("{"),B("}"),oe,O,O)):c&&"namespace"==t?(M.marked="keyword",T(B("form"),V,oe,O)):c&&"abstract"==t?(M.marked="keyword",T($)):T(B("stat"),J):"switch"==e?T(B("form"),_,N("{"),B("}","switch"),I,oe,O,O,E):"case"==e?T(V,N(":")):"default"==e?T(N(":")):"catch"==e?T(B("form"),q,K,$,O,E):"export"==e?T(B("stat"),Oe,O):"import"==e?T(B("stat"),$e,O):"async"==e?T($):"@"==t?T(V,$):j(B("stat"),V,N(";"),O)}function K(e){if("("==e)return T(Ce,N(")"))}function V(e,t){return H(e,t,!1)}function L(e,t){return H(e,t,!0)}function _(e){return"("!=e?j():T(B(")"),V,N(")"),O)}function H(e,t,r){if(M.state.fatArrowAt==M.stream.start){var n=r?Y:R;if("("==e)return T(q,B(")"),ne(Ce,")"),O,N("=>"),n,E);if("variable"==e)return j(q,ke,N("=>"),n,E)}var a,o=r?U:F;return w.hasOwnProperty(e)?T(o):"function"==e?T(Ae,o):"class"==e||c&&"interface"==t?(M.marked="keyword",T(B("form"),Pe,O)):"keyword c"==e||"async"==e?T(r?L:V):"("==e?T(B(")"),W,N(")"),O,o):"operator"==e||"spread"==e?T(r?L:V):"["==e?T(B("]"),He,O,o):"{"==e?ae(ee,"}",null,o):"quasi"==e?j(D,o):"new"==e?T((a=r,function(e){return"."==e?T(a?Z:X):"variable"==e&&c?T(me,a?U:F):j(a?L:V)})):"import"==e?T(V):T()}function W(e){return e.match(/[;\}\)\],]/)?j():j(V)}function F(e,t){return","==e?T(V):U(e,t,!1)}function U(e,t,r){var n=0==r?F:U,a=0==r?V:L;return"=>"==e?T(q,r?Y:R,E):"operator"==e?/\+\+|--/.test(t)||c&&"!"==t?T(n):c&&"<"==t&&M.stream.match(/^([^>]|<.*?>)*>\s*\(/,!1)?T(B(">"),ne(ce,">"),O,n):"?"==t?T(V,N(":"),a):T(a):"quasi"==e?j(D,n):";"!=e?"("==e?ae(L,")","call",n):"."==e?T(Q,n):"["==e?T(B("]"),W,N("]"),O,n):c&&"as"==t?(M.marked="keyword",T(ce,n)):"regexp"==e?(M.state.lastType=M.marked="operator",M.stream.backUp(M.stream.pos-M.stream.start-1),T(a)):void 0:void 0}function D(e,t){return"quasi"!=e?j():"${"!=t.slice(t.length-2)?T(D):T(V,G)}function G(e){if("}"==e)return M.marked="string-2",M.state.tokenize=y,T(D)}function R(e){return o(M.stream,M.state),j("{"==e?$:V)}function Y(e){return o(M.stream,M.state),j("{"==e?$:L)}function X(e,t){if("target"==t)return M.marked="keyword",T(F)}function Z(e,t){if("target"==t)return M.marked="keyword",T(U)}function J(e){return":"==e?T(O,$):j(F,N(";"),O)}function Q(e){if("variable"==e)return M.marked="property",T()}function ee(e,t){if("async"==e)return M.marked="property",T(ee);if("variable"==e||"keyword"==M.style){return M.marked="property","get"==t||"set"==t?T(te):(c&&M.state.fatArrowAt==M.stream.start&&(r=M.stream.match(/^\s*:\s*/,!1))&&(M.state.fatArrowAt=M.stream.pos+r[0].length),T(re));var r}else{if("number"==e||"string"==e)return M.marked=i?"property":M.style+" property",T(re);if("jsonld-keyword"==e)return T(re);if(c&&A(t))return M.marked="keyword",T(ee);if("["==e)return T(V,ie,N("]"),re);if("spread"==e)return T(L,re);if("*"==t)return M.marked="keyword",T(ee);if(":"==e)return j(re)}}function te(e){return"variable"!=e?j(re):(M.marked="property",T(Ae))}function re(e){return":"==e?T(L):"("==e?j(Ae):void 0}function ne(n,a,o){function i(e,t){if(o?-1<o.indexOf(e):","==e){var r=M.state.lexical;return"call"==r.info&&(r.pos=(r.pos||0)+1),T(function(e,t){return e==a||t==a?j():j(n)},i)}return e==a||t==a?T():T(N(a))}return function(e,t){return e==a||t==a?T():j(n,i)}}function ae(e,t,r){for(var n=3;n<arguments.length;n++)M.cc.push(arguments[n]);return T(B(t,r),ne(e,t),O)}function oe(e){return"}"==e?T():j($,oe)}function ie(e,t){if(c){if(":"==e)return T(ce);if("?"==t)return T(ie)}}function le(e){if(c&&":"==e)return M.stream.match(/^\s*\w+\s+is\b/,!1)?T(V,se,ce):T(ce)}function se(e,t){if("is"==t)return M.marked="keyword",T()}function ce(e,t){return"keyof"==t||"typeof"==t?(M.marked="keyword",T("keyof"==t?ce:L)):"variable"==e||"void"==t?(M.marked="type",T(fe)):"string"==e||"number"==e||"atom"==e?T(fe):"["==e?T(B("]"),ne(ce,"]",","),O,fe):"{"==e?T(B("}"),ne(de,"}",",;"),O,fe):"("==e?T(ne(pe,")"),ue):"<"==e?T(ne(ce,">"),ce):void 0}function ue(e){if("=>"==e)return T(ce)}function de(e,t){return"variable"==e||"keyword"==M.style?(M.marked="property",T(de)):"?"==t?T(de):":"==e?T(ce):"["==e?T(V,ie,N("]"),de):void 0}function pe(e,t){return"variable"==e&&M.stream.match(/^\s*[?:]/,!1)||"?"==t?T(pe):":"==e?T(ce):j(ce)}function fe(e,t){return"<"==t?T(B(">"),ne(ce,">"),O,fe):"|"==t||"."==e||"&"==t?T(ce):"["==e?T(N("]"),fe):"extends"==t||"implements"==t?(M.marked="keyword",T(ce)):void 0}function me(e,t){if("<"==t)return T(B(">"),ne(ce,">"),O,fe)}function he(){return j(ce,ge)}function ge(e,t){if("="==t)return T(ce)}function be(e,t){return"enum"==t?(M.marked="keyword",T(We)):j(ke,ie,ve,we)}function ke(e,t){return c&&A(t)?(M.marked="keyword",T(ke)):"variable"==e?(r(t),T()):"spread"==e?T(ke):"["==e?ae(ke,"]"):"{"==e?ae(ye,"}"):void 0}function ye(e,t){return"variable"!=e||M.stream.match(/^\s*:/,!1)?("variable"==e&&(M.marked="property"),"spread"==e?T(ke):"}"==e?j():T(N(":"),ke,ve)):(r(t),T(ve))}function ve(e,t){if("="==t)return T(L)}function we(e){if(","==e)return T(be)}function xe(e,t){if("keyword b"==e&&"else"==t)return T(B("form","else"),$,O)}function ze(e,t){return"await"==t?T(ze):"("==e?T(B(")"),Me,N(")"),O):void 0}function Me(e){return"var"==e?T(be,N(";"),Te):";"==e?T(Te):"variable"==e?T(je):j(V,N(";"),Te)}function je(e,t){return"in"==t||"of"==t?(M.marked="keyword",T(V)):T(F,Te)}function Te(e,t){return";"==e?T(Se):"in"==t||"of"==t?(M.marked="keyword",T(V)):j(V,N(";"),Se)}function Se(e){")"!=e&&T(V)}function Ae(e,t){return"*"==t?(M.marked="keyword",T(Ae)):"variable"==e?(r(t),T(Ae)):"("==e?T(q,B(")"),ne(Ce,")"),O,le,$,E):c&&"<"==t?T(B(">"),ne(he,">"),O,Ae):void 0}function Ce(e,t){return"@"==t&&T(V,Ce),"spread"==e?T(Ce):c&&A(t)?(M.marked="keyword",T(Ce)):j(ke,ie,ve)}function Pe(e,t){return"variable"==e?qe(e,t):Ie(e,t)}function qe(e,t){if("variable"==e)return r(t),T(Ie)}function Ie(e,t){return"<"==t?T(B(">"),ne(he,">"),O,Ie):"extends"==t||"implements"==t||c&&","==e?("implements"==t&&(M.marked="keyword"),T(c?ce:V,Ie)):"{"==e?T(B("}"),Ee,O):void 0}function Ee(e,t){return"async"==e||"variable"==e&&("static"==t||"get"==t||"set"==t||c&&A(t))&&M.stream.match(/^\s+[\w$\xa1-\uffff]/,!1)?(M.marked="keyword",T(Ee)):"variable"==e||"keyword"==M.style?(M.marked="property",T(c?Be:Ae,Ee)):"["==e?T(V,ie,N("]"),c?Be:Ae,Ee):"*"==t?(M.marked="keyword",T(Ee)):";"==e?T(Ee):"}"==e?T():"@"==t?T(V,Ee):void 0}function Be(e,t){return"?"==t?T(Be):":"==e?T(ce,ve):"="==t?T(L):j(Ae)}function Oe(e,t){return"*"==t?(M.marked="keyword",T(_e,N(";"))):"default"==t?(M.marked="keyword",T(V,N(";"))):"{"==e?T(ne(Ne,"}"),_e,N(";")):j($)}function Ne(e,t){return"as"==t?(M.marked="keyword",T(N("variable"))):"variable"==e?j(L,Ne):void 0}function $e(e){return"string"==e?T():"("==e?j(V):j(Ke,Ve,_e)}function Ke(e,t){return"{"==e?ae(Ke,"}"):("variable"==e&&r(t),"*"==t&&(M.marked="keyword"),T(Le))}function Ve(e){if(","==e)return T(Ke,Ve)}function Le(e,t){if("as"==t)return M.marked="keyword",T(Ke)}function _e(e,t){if("from"==t)return M.marked="keyword",T(V)}function He(e){return"]"==e?T():j(ne(L,"]"))}function We(){return j(B("form"),ke,N("{"),B("}"),ne(Fe,"}"),O,O)}function Fe(){return j(ke,ve)}function Ue(e,t,r){return t.tokenize==b&&/^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(t.lastType)||"quasi"==t.lastType&&/\{\s*$/.test(e.string.slice(0,e.pos-(r||0)))}return O.lex=E.lex=!0,{startState:function(e){var t={tokenize:b,lastType:"sof",cc:[],lexical:new x((e||0)-p,0,"block",!1),localVars:d.localVars,context:d.localVars&&new C(null,null,!1),indented:e||0};return d.globalVars&&"object"==typeof d.globalVars&&(t.globalVars=d.globalVars),t},token:function(e,t){if(e.sol()&&(t.lexical.hasOwnProperty("align")||(t.lexical.align=!1),t.indented=e.indentation(),o(e,t)),t.tokenize!=k&&e.eatSpace())return null;var r=t.tokenize(e,t);return"comment"==n?r:(t.lastType="operator"!=n||"++"!=a&&"--"!=a?n:"incdec",function(e,t,r,n,a){var o=e.cc;for(M.state=e,M.stream=a,M.marked=null,M.cc=o,M.style=t,e.lexical.hasOwnProperty("align")||(e.lexical.align=!0);;)if((o.length?o.pop():l?V:$)(r,n)){for(;o.length&&o[o.length-1].lex;)o.pop()();return M.marked?M.marked:"variable"==r&&z(e,n)?"variable-2":t}}(t,r,n,a,e))},indent:function(e,t){if(e.tokenize==k)return De.Pass;if(e.tokenize!=b)return 0;var r,n=t&&t.charAt(0),a=e.lexical;if(!/^\s*else\b/.test(t))for(var o=e.cc.length-1;0<=o;--o){var i=e.cc[o];if(i==O)a=a.prev;else if(i!=xe)break}for(;("stat"==a.type||"form"==a.type)&&("}"==n||(r=e.cc[e.cc.length-1])&&(r==F||r==U)&&!/^[,\.=+\-*:?[\(]/.test(t));)a=a.prev;f&&")"==a.type&&"stat"==a.prev.type&&(a=a.prev);var l,s,c=a.type,u=n==c;return"vardef"==c?a.indented+("operator"==e.lastType||","==e.lastType?a.info.length+1:0):"form"==c&&"{"==n?a.indented:"form"==c?a.indented+p:"stat"==c?a.indented+(s=t,"operator"==(l=e).lastType||","==l.lastType||m.test(s.charAt(0))||/[,.]/.test(s.charAt(0))?f||p:0):"switch"!=a.info||u||0==d.doubleIndentSwitch?a.align?a.column+(u?0:1):a.indented+(u?0:p):a.indented+(/^(?:case|default)\b/.test(t)?p:2*p)},electricInput:/^\s*(?:case .*?:|default:|\{|\})$/,blockCommentStart:l?null:"/*",blockCommentEnd:l?null:"*/",blockCommentContinue:l?null:" * ",lineComment:l?null:"//",fold:"brace",closeBrackets:"()[]{}''\"\"``",helperType:l?"json":"javascript",jsonldMode:i,jsonMode:l,expressionAllowed:Ue,skipExpression:function(e){var t=e.cc[e.cc.length-1];t!=V&&t!=L||e.cc.pop()}}}),De.registerHelper("wordChars","javascript",/[\w$]/),De.defineMIME("text/javascript","javascript"),De.defineMIME("text/ecmascript","javascript"),De.defineMIME("application/javascript","javascript"),De.defineMIME("application/x-javascript","javascript"),De.defineMIME("application/ecmascript","javascript"),De.defineMIME("application/json",{name:"javascript",json:!0}),De.defineMIME("application/x-json",{name:"javascript",json:!0}),De.defineMIME("application/ld+json",{name:"javascript",jsonld:!0}),De.defineMIME("text/typescript",{name:"javascript",typescript:!0}),De.defineMIME("application/typescript",{name:"javascript",typescript:!0})}),function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(n){var u=/MSIE \d/.test(navigator.userAgent)&&(null==document.documentMode||document.documentMode<8),h=n.Pos,g={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"};function d(e,t,r){var n=e.getLineHandle(t.line),a=t.ch-1,o=r&&r.afterCursor;null==o&&(o=/(^| )cm-fat-cursor($| )/.test(e.getWrapperElement().className));var i=!o&&0<=a&&g[n.text.charAt(a)]||g[n.text.charAt(++a)];if(!i)return null;var l=">"==i.charAt(1)?1:-1;if(r&&r.strict&&0<l!=(a==t.ch))return null;var s=e.getTokenTypeAt(h(t.line,a+1)),c=p(e,h(t.line,a+(0<l?1:0)),l,s||null,r);return null==c?null:{from:h(t.line,a),to:c&&c.pos,match:c&&c.ch==i.charAt(0),forward:0<l}}function p(e,t,r,n,a){for(var o=a&&a.maxScanLineLength||1e4,i=a&&a.maxScanLines||1e3,l=[],s=a&&a.bracketRegex?a.bracketRegex:/[(){}[\]]/,c=0<r?Math.min(t.line+i,e.lastLine()+1):Math.max(e.firstLine()-1,t.line-i),u=t.line;u!=c;u+=r){var d=e.getLine(u);if(d){var p=0<r?0:d.length-1,f=0<r?d.length:-1;if(!(d.length>o))for(u==t.line&&(p=t.ch-(r<0?1:0));p!=f;p+=r){var m=d.charAt(p);if(s.test(m)&&(void 0===n||e.getTokenTypeAt(h(u,p+1))==n))if(">"==g[m].charAt(1)==0<r)l.push(m);else{if(!l.length)return{pos:h(u,p),ch:m};l.pop()}}}}return u-r!=(0<r?e.lastLine():e.firstLine())&&null}function t(e,t,r){for(var n=e.state.matchBrackets.maxHighlightLineLength||1e3,a=[],o=e.listSelections(),i=0;i<o.length;i++){var l=o[i].empty()&&d(e,o[i].head,r);if(l&&e.getLine(l.from.line).length<=n){var s=l.match?"CodeMirror-matchingbracket":"CodeMirror-nonmatchingbracket";a.push(e.markText(l.from,h(l.from.line,l.from.ch+1),{className:s})),l.to&&e.getLine(l.to.line).length<=n&&a.push(e.markText(l.to,h(l.to.line,l.to.ch+1),{className:s}))}}if(a.length){u&&e.state.focused&&e.focus();var c=function(){e.operation(function(){for(var e=0;e<a.length;e++)a[e].clear()})};if(!t)return c;setTimeout(c,800)}}function a(e){e.operation(function(){e.state.matchBrackets.currentlyHighlighted&&(e.state.matchBrackets.currentlyHighlighted(),e.state.matchBrackets.currentlyHighlighted=null),e.state.matchBrackets.currentlyHighlighted=t(e,!1,e.state.matchBrackets)})}n.defineOption("matchBrackets",!1,function(e,t,r){r&&r!=n.Init&&(e.off("cursorActivity",a),e.state.matchBrackets&&e.state.matchBrackets.currentlyHighlighted&&(e.state.matchBrackets.currentlyHighlighted(),e.state.matchBrackets.currentlyHighlighted=null)),t&&(e.state.matchBrackets="object"==typeof t?t:{},e.on("cursorActivity",a))}),n.defineExtension("matchBrackets",function(){t(this,!0)}),n.defineExtension("findMatchingBracket",function(e,t,r){return(r||"boolean"==typeof t)&&(r?(r.strict=t,t=r):t=t?{strict:!0}:null),d(this,e,t)}),n.defineExtension("scanForBracket",function(e,t,r,n){return p(this,e,t,r,n)})}),function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(z){"use strict";var M={autoSelfClosers:{area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,frame:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0,menuitem:!0},implicitlyClosed:{dd:!0,li:!0,optgroup:!0,option:!0,p:!0,rp:!0,rt:!0,tbody:!0,td:!0,tfoot:!0,th:!0,tr:!0},contextGrabbers:{dd:{dd:!0,dt:!0},dt:{dd:!0,dt:!0},li:{li:!0},option:{option:!0,optgroup:!0},optgroup:{optgroup:!0},p:{address:!0,article:!0,aside:!0,blockquote:!0,dir:!0,div:!0,dl:!0,fieldset:!0,footer:!0,form:!0,h1:!0,h2:!0,h3:!0,h4:!0,h5:!0,h6:!0,header:!0,hgroup:!0,hr:!0,menu:!0,nav:!0,ol:!0,p:!0,pre:!0,section:!0,table:!0,ul:!0},rp:{rp:!0,rt:!0},rt:{rp:!0,rt:!0},tbody:{tbody:!0,tfoot:!0},td:{td:!0,th:!0},tfoot:{tbody:!0},th:{td:!0,th:!0},thead:{tbody:!0,tfoot:!0},tr:{tr:!0}},doNotIndent:{pre:!0},allowUnquoted:!0,allowMissing:!0,caseFold:!0},j={autoSelfClosers:{},implicitlyClosed:{},contextGrabbers:{},doNotIndent:{},allowUnquoted:!1,allowMissing:!1,allowMissingTagName:!1,caseFold:!1};z.defineMode("xml",function(e,t){var i,o,l=e.indentUnit,s={},r=t.htmlMode?M:j;for(var n in r)s[n]=r[n];for(var n in t)s[n]=t[n];function c(t,r){function e(e){return(r.tokenize=e)(t,r)}var n=t.next();return"<"==n?t.eat("!")?t.eat("[")?t.match("CDATA[")?e(a("atom","]]>")):null:t.match("--")?e(a("comment","--\x3e")):t.match("DOCTYPE",!0,!0)?(t.eatWhile(/[\w\._\-]/),e(function n(a){return function(e,t){for(var r;null!=(r=e.next());){if("<"==r)return t.tokenize=n(a+1),t.tokenize(e,t);if(">"==r){if(1==a){t.tokenize=c;break}return t.tokenize=n(a-1),t.tokenize(e,t)}}return"meta"}}(1))):null:t.eat("?")?(t.eatWhile(/[\w\._\-]/),r.tokenize=a("meta","?>"),"meta"):(i=t.eat("/")?"closeTag":"openTag",r.tokenize=u,"tag bracket"):"&"==n?(t.eat("#")?t.eat("x")?t.eatWhile(/[a-fA-F\d]/)&&t.eat(";"):t.eatWhile(/[\d]/)&&t.eat(";"):t.eatWhile(/[\w\.\-:]/)&&t.eat(";"))?"atom":"error":(t.eatWhile(/[^&<]/),null)}function u(e,t){var r,n,a=e.next();if(">"==a||"/"==a&&e.eat(">"))return t.tokenize=c,i=">"==a?"endTag":"selfcloseTag","tag bracket";if("="==a)return i="equals",null;if("<"==a){t.tokenize=c,t.state=m,t.tagName=t.tagStart=null;var o=t.tokenize(e,t);return o?o+" tag error":"tag error"}return/[\'\"]/.test(a)?(t.tokenize=(r=a,(n=function(e,t){for(;!e.eol();)if(e.next()==r){t.tokenize=u;break}return"string"}).isInAttribute=!0,n),t.stringStartCol=e.column(),t.tokenize(e,t)):(e.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/),"word")}function a(r,n){return function(e,t){for(;!e.eol();){if(e.match(n)){t.tokenize=c;break}e.next()}return r}}function d(e,t,r){this.prev=e.context,this.tagName=t,this.indent=e.indented,this.startOfLine=r,(s.doNotIndent.hasOwnProperty(t)||e.context&&e.context.noIndent)&&(this.noIndent=!0)}function p(e){e.context&&(e.context=e.context.prev)}function f(e,t){for(var r;;){if(!e.context)return;if(r=e.context.tagName,!s.contextGrabbers.hasOwnProperty(r)||!s.contextGrabbers[r].hasOwnProperty(t))return;p(e)}}function m(e,t,r){return"openTag"==e?(r.tagStart=t.column(),h):"closeTag"==e?g:m}function h(e,t,r){return"word"==e?(r.tagName=t.current(),o="tag",y):s.allowMissingTagName&&"endTag"==e?(o="tag bracket",y(e,t,r)):(o="error",h)}function g(e,t,r){if("word"==e){var n=t.current();return r.context&&r.context.tagName!=n&&s.implicitlyClosed.hasOwnProperty(r.context.tagName)&&p(r),r.context&&r.context.tagName==n||!1===s.matchClosing?(o="tag",b):(o="tag error",k)}return s.allowMissingTagName&&"endTag"==e?(o="tag bracket",b(e,t,r)):(o="error",k)}function b(e,t,r){return"endTag"!=e?(o="error",b):(p(r),m)}function k(e,t,r){return o="error",b(e,0,r)}function y(e,t,r){if("word"==e)return o="attribute",v;if("endTag"==e||"selfcloseTag"==e){var n=r.tagName,a=r.tagStart;return r.tagName=r.tagStart=null,"selfcloseTag"==e||s.autoSelfClosers.hasOwnProperty(n)?f(r,n):(f(r,n),r.context=new d(r,n,a==r.indented)),m}return o="error",y}function v(e,t,r){return"equals"==e?w:(s.allowMissing||(o="error"),y(e,0,r))}function w(e,t,r){return"string"==e?x:"word"==e&&s.allowUnquoted?(o="string",y):(o="error",y(e,0,r))}function x(e,t,r){return"string"==e?x:y(e,0,r)}return c.isInText=!0,{startState:function(e){var t={tokenize:c,state:m,indented:e||0,tagName:null,tagStart:null,context:null};return null!=e&&(t.baseIndent=e),t},token:function(e,t){if(!t.tagName&&e.sol()&&(t.indented=e.indentation()),e.eatSpace())return null;i=null;var r=t.tokenize(e,t);return(r||i)&&"comment"!=r&&(o=null,t.state=t.state(i||r,e,t),o&&(r="error"==o?r+" error":o)),r},indent:function(e,t,r){var n=e.context;if(e.tokenize.isInAttribute)return e.tagStart==e.indented?e.stringStartCol+1:e.indented+l;if(n&&n.noIndent)return z.Pass;if(e.tokenize!=u&&e.tokenize!=c)return r?r.match(/^(\s*)/)[0].length:0;if(e.tagName)return!1!==s.multilineTagIndentPastTag?e.tagStart+e.tagName.length+2:e.tagStart+l*(s.multilineTagIndentFactor||1);if(s.alignCDATA&&/<!\[CDATA\[/.test(t))return 0;var a=t&&/^<(\/)?([\w_:\.-]*)/.exec(t);if(a&&a[1])for(;n;){if(n.tagName==a[2]){n=n.prev;break}if(!s.implicitlyClosed.hasOwnProperty(n.tagName))break;n=n.prev}else if(a)for(;n;){var o=s.contextGrabbers[n.tagName];if(!o||!o.hasOwnProperty(a[2]))break;n=n.prev}for(;n&&n.prev&&!n.startOfLine;)n=n.prev;return n?n.indent+l:e.baseIndent||0},electricInput:/<\/[\s\w:]+>$/,blockCommentStart:"\x3c!--",blockCommentEnd:"--\x3e",configuration:s.htmlMode?"html":"xml",helperType:s.htmlMode?"html":"xml",skipAttribute:function(e){e.state==w&&(e.state=y)}}}),z.defineMIME("text/xml","xml"),z.defineMIME("application/xml","xml"),z.mimeModes.hasOwnProperty("text/html")||z.defineMIME("text/html",{name:"xml",htmlMode:!0})});
assets/vendor/codemirror/comment.js DELETED
@@ -1,209 +0,0 @@
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 noOptions = {};
15
- var nonWS = /[^\s\u00a0]/;
16
- var Pos = CodeMirror.Pos;
17
-
18
- function firstNonWS(str) {
19
- var found = str.search(nonWS);
20
- return found == -1 ? 0 : found;
21
- }
22
-
23
- CodeMirror.commands.toggleComment = function(cm) {
24
- cm.toggleComment();
25
- };
26
-
27
- CodeMirror.defineExtension("toggleComment", function(options) {
28
- if (!options) options = noOptions;
29
- var cm = this;
30
- var minLine = Infinity, ranges = this.listSelections(), mode = null;
31
- for (var i = ranges.length - 1; i >= 0; i--) {
32
- var from = ranges[i].from(), to = ranges[i].to();
33
- if (from.line >= minLine) continue;
34
- if (to.line >= minLine) to = Pos(minLine, 0);
35
- minLine = from.line;
36
- if (mode == null) {
37
- if (cm.uncomment(from, to, options)) mode = "un";
38
- else { cm.lineComment(from, to, options); mode = "line"; }
39
- } else if (mode == "un") {
40
- cm.uncomment(from, to, options);
41
- } else {
42
- cm.lineComment(from, to, options);
43
- }
44
- }
45
- });
46
-
47
- // Rough heuristic to try and detect lines that are part of multi-line string
48
- function probablyInsideString(cm, pos, line) {
49
- return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"\`]/.test(line)
50
- }
51
-
52
- function getMode(cm, pos) {
53
- var mode = cm.getMode()
54
- return mode.useInnerComments === false || !mode.innerMode ? mode : cm.getModeAt(pos)
55
- }
56
-
57
- CodeMirror.defineExtension("lineComment", function(from, to, options) {
58
- if (!options) options = noOptions;
59
- var self = this, mode = getMode(self, from);
60
- var firstLine = self.getLine(from.line);
61
- if (firstLine == null || probablyInsideString(self, from, firstLine)) return;
62
-
63
- var commentString = options.lineComment || mode.lineComment;
64
- if (!commentString) {
65
- if (options.blockCommentStart || mode.blockCommentStart) {
66
- options.fullLines = true;
67
- self.blockComment(from, to, options);
68
- }
69
- return;
70
- }
71
-
72
- var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1);
73
- var pad = options.padding == null ? " " : options.padding;
74
- var blankLines = options.commentBlankLines || from.line == to.line;
75
-
76
- self.operation(function() {
77
- if (options.indent) {
78
- var baseString = null;
79
- for (var i = from.line; i < end; ++i) {
80
- var line = self.getLine(i);
81
- var whitespace = line.slice(0, firstNonWS(line));
82
- if (baseString == null || baseString.length > whitespace.length) {
83
- baseString = whitespace;
84
- }
85
- }
86
- for (var i = from.line; i < end; ++i) {
87
- var line = self.getLine(i), cut = baseString.length;
88
- if (!blankLines && !nonWS.test(line)) continue;
89
- if (line.slice(0, cut) != baseString) cut = firstNonWS(line);
90
- self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut));
91
- }
92
- } else {
93
- for (var i = from.line; i < end; ++i) {
94
- if (blankLines || nonWS.test(self.getLine(i)))
95
- self.replaceRange(commentString + pad, Pos(i, 0));
96
- }
97
- }
98
- });
99
- });
100
-
101
- CodeMirror.defineExtension("blockComment", function(from, to, options) {
102
- if (!options) options = noOptions;
103
- var self = this, mode = getMode(self, from);
104
- var startString = options.blockCommentStart || mode.blockCommentStart;
105
- var endString = options.blockCommentEnd || mode.blockCommentEnd;
106
- if (!startString || !endString) {
107
- if ((options.lineComment || mode.lineComment) && options.fullLines != false)
108
- self.lineComment(from, to, options);
109
- return;
110
- }
111
- if (/\bcomment\b/.test(self.getTokenTypeAt(Pos(from.line, 0)))) return
112
-
113
- var end = Math.min(to.line, self.lastLine());
114
- if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end;
115
-
116
- var pad = options.padding == null ? " " : options.padding;
117
- if (from.line > end) return;
118
-
119
- self.operation(function() {
120
- if (options.fullLines != false) {
121
- var lastLineHasText = nonWS.test(self.getLine(end));
122
- self.replaceRange(pad + endString, Pos(end));
123
- self.replaceRange(startString + pad, Pos(from.line, 0));
124
- var lead = options.blockCommentLead || mode.blockCommentLead;
125
- if (lead != null) for (var i = from.line + 1; i <= end; ++i)
126
- if (i != end || lastLineHasText)
127
- self.replaceRange(lead + pad, Pos(i, 0));
128
- } else {
129
- self.replaceRange(endString, to);
130
- self.replaceRange(startString, from);
131
- }
132
- });
133
- });
134
-
135
- CodeMirror.defineExtension("uncomment", function(from, to, options) {
136
- if (!options) options = noOptions;
137
- var self = this, mode = getMode(self, from);
138
- var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
139
-
140
- // Try finding line comments
141
- var lineString = options.lineComment || mode.lineComment, lines = [];
142
- var pad = options.padding == null ? " " : options.padding, didSomething;
143
- lineComment: {
144
- if (!lineString) break lineComment;
145
- for (var i = start; i <= end; ++i) {
146
- var line = self.getLine(i);
147
- var found = line.indexOf(lineString);
148
- if (found > -1 && !/comment/.test(self.getTokenTypeAt(Pos(i, found + 1)))) found = -1;
149
- if (found == -1 && nonWS.test(line)) break lineComment;
150
- if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment;
151
- lines.push(line);
152
- }
153
- self.operation(function() {
154
- for (var i = start; i <= end; ++i) {
155
- var line = lines[i - start];
156
- var pos = line.indexOf(lineString), endPos = pos + lineString.length;
157
- if (pos < 0) continue;
158
- if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length;
159
- didSomething = true;
160
- self.replaceRange("", Pos(i, pos), Pos(i, endPos));
161
- }
162
- });
163
- if (didSomething) return true;
164
- }
165
-
166
- // Try block comments
167
- var startString = options.blockCommentStart || mode.blockCommentStart;
168
- var endString = options.blockCommentEnd || mode.blockCommentEnd;
169
- if (!startString || !endString) return false;
170
- var lead = options.blockCommentLead || mode.blockCommentLead;
171
- var startLine = self.getLine(start), open = startLine.indexOf(startString)
172
- if (open == -1) return false
173
- var endLine = end == start ? startLine : self.getLine(end)
174
- var close = endLine.indexOf(endString, end == start ? open + startString.length : 0);
175
- var insideStart = Pos(start, open + 1), insideEnd = Pos(end, close + 1)
176
- if (close == -1 ||
177
- !/comment/.test(self.getTokenTypeAt(insideStart)) ||
178
- !/comment/.test(self.getTokenTypeAt(insideEnd)) ||
179
- self.getRange(insideStart, insideEnd, "\n").indexOf(endString) > -1)
180
- return false;
181
-
182
- // Avoid killing block comments completely outside the selection.
183
- // Positions of the last startString before the start of the selection, and the first endString after it.
184
- var lastStart = startLine.lastIndexOf(startString, from.ch);
185
- var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length);
186
- if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false;
187
- // Positions of the first endString after the end of the selection, and the last startString before it.
188
- firstEnd = endLine.indexOf(endString, to.ch);
189
- var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch);
190
- lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart;
191
- if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false;
192
-
193
- self.operation(function() {
194
- self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)),
195
- Pos(end, close + endString.length));
196
- var openEnd = open + startString.length;
197
- if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length;
198
- self.replaceRange("", Pos(start, open), Pos(start, openEnd));
199
- if (lead) for (var i = start + 1; i <= end; ++i) {
200
- var line = self.getLine(i), found = line.indexOf(lead);
201
- if (found == -1 || nonWS.test(line.slice(0, found))) continue;
202
- var foundEnd = found + lead.length;
203
- if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length;
204
- self.replaceRange("", Pos(i, found), Pos(i, foundEnd));
205
- }
206
- });
207
- return true;
208
- });
209
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/vendor/codemirror/javascript.js DELETED
@@ -1,896 +0,0 @@
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("javascript", function(config, parserConfig) {
15
- var indentUnit = config.indentUnit;
16
- var statementIndent = parserConfig.statementIndent;
17
- var jsonldMode = parserConfig.jsonld;
18
- var jsonMode = parserConfig.json || jsonldMode;
19
- var isTS = parserConfig.typescript;
20
- var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
21
-
22
- // Tokenizer
23
-
24
- var keywords = function(){
25
- function kw(type) {return {type: type, style: "keyword"};}
26
- var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d");
27
- var operator = kw("operator"), atom = {type: "atom", style: "atom"};
28
-
29
- return {
30
- "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
31
- "return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C,
32
- "debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"),
33
- "function": kw("function"), "catch": kw("catch"),
34
- "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
35
- "in": operator, "typeof": operator, "instanceof": operator,
36
- "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
37
- "this": kw("this"), "class": kw("class"), "super": kw("atom"),
38
- "yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
39
- "await": C
40
- };
41
- }();
42
-
43
- var isOperatorChar = /[+\-*&%=<>!?|~^@]/;
44
- var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
45
-
46
- function readRegexp(stream) {
47
- var escaped = false, next, inSet = false;
48
- while ((next = stream.next()) != null) {
49
- if (!escaped) {
50
- if (next == "/" && !inSet) return;
51
- if (next == "[") inSet = true;
52
- else if (inSet && next == "]") inSet = false;
53
- }
54
- escaped = !escaped && next == "\\";
55
- }
56
- }
57
-
58
- // Used as scratch variables to communicate multiple values without
59
- // consing up tons of objects.
60
- var type, content;
61
- function ret(tp, style, cont) {
62
- type = tp; content = cont;
63
- return style;
64
- }
65
- function tokenBase(stream, state) {
66
- var ch = stream.next();
67
- if (ch == '"' || ch == "'") {
68
- state.tokenize = tokenString(ch);
69
- return state.tokenize(stream, state);
70
- } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
71
- return ret("number", "number");
72
- } else if (ch == "." && stream.match("..")) {
73
- return ret("spread", "meta");
74
- } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
75
- return ret(ch);
76
- } else if (ch == "=" && stream.eat(">")) {
77
- return ret("=>", "operator");
78
- } else if (ch == "0" && stream.match(/^(?:x[\da-f]+|o[0-7]+|b[01]+)n?/i)) {
79
- return ret("number", "number");
80
- } else if (/\d/.test(ch)) {
81
- stream.match(/^\d*(?:n|(?:\.\d*)?(?:[eE][+\-]?\d+)?)?/);
82
- return ret("number", "number");
83
- } else if (ch == "/") {
84
- if (stream.eat("*")) {
85
- state.tokenize = tokenComment;
86
- return tokenComment(stream, state);
87
- } else if (stream.eat("/")) {
88
- stream.skipToEnd();
89
- return ret("comment", "comment");
90
- } else if (expressionAllowed(stream, state, 1)) {
91
- readRegexp(stream);
92
- stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/);
93
- return ret("regexp", "string-2");
94
- } else {
95
- stream.eat("=");
96
- return ret("operator", "operator", stream.current());
97
- }
98
- } else if (ch == "`") {
99
- state.tokenize = tokenQuasi;
100
- return tokenQuasi(stream, state);
101
- } else if (ch == "#") {
102
- stream.skipToEnd();
103
- return ret("error", "error");
104
- } else if (isOperatorChar.test(ch)) {
105
- if (ch != ">" || !state.lexical || state.lexical.type != ">") {
106
- if (stream.eat("=")) {
107
- if (ch == "!" || ch == "=") stream.eat("=")
108
- } else if (/[<>*+\-]/.test(ch)) {
109
- stream.eat(ch)
110
- if (ch == ">") stream.eat(ch)
111
- }
112
- }
113
- return ret("operator", "operator", stream.current());
114
- } else if (wordRE.test(ch)) {
115
- stream.eatWhile(wordRE);
116
- var word = stream.current()
117
- if (state.lastType != ".") {
118
- if (keywords.propertyIsEnumerable(word)) {
119
- var kw = keywords[word]
120
- return ret(kw.type, kw.style, word)
121
- }
122
- if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false))
123
- return ret("async", "keyword", word)
124
- }
125
- return ret("variable", "variable", word)
126
- }
127
- }
128
-
129
- function tokenString(quote) {
130
- return function(stream, state) {
131
- var escaped = false, next;
132
- if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
133
- state.tokenize = tokenBase;
134
- return ret("jsonld-keyword", "meta");
135
- }
136
- while ((next = stream.next()) != null) {
137
- if (next == quote && !escaped) break;
138
- escaped = !escaped && next == "\\";
139
- }
140
- if (!escaped) state.tokenize = tokenBase;
141
- return ret("string", "string");
142
- };
143
- }
144
-
145
- function tokenComment(stream, state) {
146
- var maybeEnd = false, ch;
147
- while (ch = stream.next()) {
148
- if (ch == "/" && maybeEnd) {
149
- state.tokenize = tokenBase;
150
- break;
151
- }
152
- maybeEnd = (ch == "*");
153
- }
154
- return ret("comment", "comment");
155
- }
156
-
157
- function tokenQuasi(stream, state) {
158
- var escaped = false, next;
159
- while ((next = stream.next()) != null) {
160
- if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
161
- state.tokenize = tokenBase;
162
- break;
163
- }
164
- escaped = !escaped && next == "\\";
165
- }
166
- return ret("quasi", "string-2", stream.current());
167
- }
168
-
169
- var brackets = "([{}])";
170
- // This is a crude lookahead trick to try and notice that we're
171
- // parsing the argument patterns for a fat-arrow function before we
172
- // actually hit the arrow token. It only works if the arrow is on
173
- // the same line as the arguments and there's no strange noise
174
- // (comments) in between. Fallback is to only notice when we hit the
175
- // arrow, and not declare the arguments as locals for the arrow
176
- // body.
177
- function findFatArrow(stream, state) {
178
- if (state.fatArrowAt) state.fatArrowAt = null;
179
- var arrow = stream.string.indexOf("=>", stream.start);
180
- if (arrow < 0) return;
181
-
182
- if (isTS) { // Try to skip TypeScript return type declarations after the arguments
183
- var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow))
184
- if (m) arrow = m.index
185
- }
186
-
187
- var depth = 0, sawSomething = false;
188
- for (var pos = arrow - 1; pos >= 0; --pos) {
189
- var ch = stream.string.charAt(pos);
190
- var bracket = brackets.indexOf(ch);
191
- if (bracket >= 0 && bracket < 3) {
192
- if (!depth) { ++pos; break; }
193
- if (--depth == 0) { if (ch == "(") sawSomething = true; break; }
194
- } else if (bracket >= 3 && bracket < 6) {
195
- ++depth;
196
- } else if (wordRE.test(ch)) {
197
- sawSomething = true;
198
- } else if (/["'\/]/.test(ch)) {
199
- return;
200
- } else if (sawSomething && !depth) {
201
- ++pos;
202
- break;
203
- }
204
- }
205
- if (sawSomething && !depth) state.fatArrowAt = pos;
206
- }
207
-
208
- // Parser
209
-
210
- var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
211
-
212
- function JSLexical(indented, column, type, align, prev, info) {
213
- this.indented = indented;
214
- this.column = column;
215
- this.type = type;
216
- this.prev = prev;
217
- this.info = info;
218
- if (align != null) this.align = align;
219
- }
220
-
221
- function inScope(state, varname) {
222
- for (var v = state.localVars; v; v = v.next)
223
- if (v.name == varname) return true;
224
- for (var cx = state.context; cx; cx = cx.prev) {
225
- for (var v = cx.vars; v; v = v.next)
226
- if (v.name == varname) return true;
227
- }
228
- }
229
-
230
- function parseJS(state, style, type, content, stream) {
231
- var cc = state.cc;
232
- // Communicate our context to the combinators.
233
- // (Less wasteful than consing up a hundred closures on every call.)
234
- cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
235
-
236
- if (!state.lexical.hasOwnProperty("align"))
237
- state.lexical.align = true;
238
-
239
- while(true) {
240
- var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
241
- if (combinator(type, content)) {
242
- while(cc.length && cc[cc.length - 1].lex)
243
- cc.pop()();
244
- if (cx.marked) return cx.marked;
245
- if (type == "variable" && inScope(state, content)) return "variable-2";
246
- return style;
247
- }
248
- }
249
- }
250
-
251
- // Combinator utils
252
-
253
- var cx = {state: null, column: null, marked: null, cc: null};
254
- function pass() {
255
- for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
256
- }
257
- function cont() {
258
- pass.apply(null, arguments);
259
- return true;
260
- }
261
- function inList(name, list) {
262
- for (var v = list; v; v = v.next) if (v.name == name) return true
263
- return false;
264
- }
265
- function register(varname) {
266
- var state = cx.state;
267
- cx.marked = "def";
268
- if (state.context) {
269
- if (state.lexical.info == "var" && state.context && state.context.block) {
270
- // FIXME function decls are also not block scoped
271
- var newContext = registerVarScoped(varname, state.context)
272
- if (newContext != null) {
273
- state.context = newContext
274
- return
275
- }
276
- } else if (!inList(varname, state.localVars)) {
277
- state.localVars = new Var(varname, state.localVars)
278
- return
279
- }
280
- }
281
- // Fall through means this is global
282
- if (parserConfig.globalVars && !inList(varname, state.globalVars))
283
- state.globalVars = new Var(varname, state.globalVars)
284
- }
285
- function registerVarScoped(varname, context) {
286
- if (!context) {
287
- return null
288
- } else if (context.block) {
289
- var inner = registerVarScoped(varname, context.prev)
290
- if (!inner) return null
291
- if (inner == context.prev) return context
292
- return new Context(inner, context.vars, true)
293
- } else if (inList(varname, context.vars)) {
294
- return context
295
- } else {
296
- return new Context(context.prev, new Var(varname, context.vars), false)
297
- }
298
- }
299
-
300
- function isModifier(name) {
301
- return name == "public" || name == "private" || name == "protected" || name == "abstract" || name == "readonly"
302
- }
303
-
304
- // Combinators
305
-
306
- function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block }
307
- function Var(name, next) { this.name = name; this.next = next }
308
-
309
- var defaultVars = new Var("this", new Var("arguments", null))
310
- function pushcontext() {
311
- cx.state.context = new Context(cx.state.context, cx.state.localVars, false)
312
- cx.state.localVars = defaultVars
313
- }
314
- function pushblockcontext() {
315
- cx.state.context = new Context(cx.state.context, cx.state.localVars, true)
316
- cx.state.localVars = null
317
- }
318
- function popcontext() {
319
- cx.state.localVars = cx.state.context.vars
320
- cx.state.context = cx.state.context.prev
321
- }
322
- popcontext.lex = true
323
- function pushlex(type, info) {
324
- var result = function() {
325
- var state = cx.state, indent = state.indented;
326
- if (state.lexical.type == "stat") indent = state.lexical.indented;
327
- else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
328
- indent = outer.indented;
329
- state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
330
- };
331
- result.lex = true;
332
- return result;
333
- }
334
- function poplex() {
335
- var state = cx.state;
336
- if (state.lexical.prev) {
337
- if (state.lexical.type == ")")
338
- state.indented = state.lexical.indented;
339
- state.lexical = state.lexical.prev;
340
- }
341
- }
342
- poplex.lex = true;
343
-
344
- function expect(wanted) {
345
- function exp(type) {
346
- if (type == wanted) return cont();
347
- else if (wanted == ";") return pass();
348
- else return cont(exp);
349
- };
350
- return exp;
351
- }
352
-
353
- function statement(type, value) {
354
- if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex);
355
- if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
356
- if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
357
- if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex);
358
- if (type == "debugger") return cont(expect(";"));
359
- if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext);
360
- if (type == ";") return cont();
361
- if (type == "if") {
362
- if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
363
- cx.state.cc.pop()();
364
- return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
365
- }
366
- if (type == "function") return cont(functiondef);
367
- if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
368
- if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), className, poplex); }
369
- if (type == "variable") {
370
- if (isTS && value == "declare") {
371
- cx.marked = "keyword"
372
- return cont(statement)
373
- } else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) {
374
- cx.marked = "keyword"
375
- if (value == "enum") return cont(enumdef);
376
- else if (value == "type") return cont(typeexpr, expect("operator"), typeexpr, expect(";"));
377
- else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
378
- } else if (isTS && value == "namespace") {
379
- cx.marked = "keyword"
380
- return cont(pushlex("form"), expression, block, poplex)
381
- } else if (isTS && value == "abstract") {
382
- cx.marked = "keyword"
383
- return cont(statement)
384
- } else {
385
- return cont(pushlex("stat"), maybelabel);
386
- }
387
- }
388
- if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext,
389
- block, poplex, poplex, popcontext);
390
- if (type == "case") return cont(expression, expect(":"));
391
- if (type == "default") return cont(expect(":"));
392
- if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext);
393
- if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
394
- if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
395
- if (type == "async") return cont(statement)
396
- if (value == "@") return cont(expression, statement)
397
- return pass(pushlex("stat"), expression, expect(";"), poplex);
398
- }
399
- function maybeCatchBinding(type) {
400
- if (type == "(") return cont(funarg, expect(")"))
401
- }
402
- function expression(type, value) {
403
- return expressionInner(type, value, false);
404
- }
405
- function expressionNoComma(type, value) {
406
- return expressionInner(type, value, true);
407
- }
408
- function parenExpr(type) {
409
- if (type != "(") return pass()
410
- return cont(pushlex(")"), expression, expect(")"), poplex)
411
- }
412
- function expressionInner(type, value, noComma) {
413
- if (cx.state.fatArrowAt == cx.stream.start) {
414
- var body = noComma ? arrowBodyNoComma : arrowBody;
415
- if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext);
416
- else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
417
- }
418
-
419
- var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
420
- if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
421
- if (type == "function") return cont(functiondef, maybeop);
422
- if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), classExpression, poplex); }
423
- if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression);
424
- if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
425
- if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
426
- if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
427
- if (type == "{") return contCommasep(objprop, "}", null, maybeop);
428
- if (type == "quasi") return pass(quasi, maybeop);
429
- if (type == "new") return cont(maybeTarget(noComma));
430
- if (type == "import") return cont(expression);
431
- return cont();
432
- }
433
- function maybeexpression(type) {
434
- if (type.match(/[;\}\)\],]/)) return pass();
435
- return pass(expression);
436
- }
437
-
438
- function maybeoperatorComma(type, value) {
439
- if (type == ",") return cont(expression);
440
- return maybeoperatorNoComma(type, value, false);
441
- }
442
- function maybeoperatorNoComma(type, value, noComma) {
443
- var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
444
- var expr = noComma == false ? expression : expressionNoComma;
445
- if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
446
- if (type == "operator") {
447
- if (/\+\+|--/.test(value) || isTS && value == "!") return cont(me);
448
- if (isTS && value == "<" && cx.stream.match(/^([^>]|<.*?>)*>\s*\(/, false))
449
- return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me);
450
- if (value == "?") return cont(expression, expect(":"), expr);
451
- return cont(expr);
452
- }
453
- if (type == "quasi") { return pass(quasi, me); }
454
- if (type == ";") return;
455
- if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
456
- if (type == ".") return cont(property, me);
457
- if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
458
- if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) }
459
- if (type == "regexp") {
460
- cx.state.lastType = cx.marked = "operator"
461
- cx.stream.backUp(cx.stream.pos - cx.stream.start - 1)
462
- return cont(expr)
463
- }
464
- }
465
- function quasi(type, value) {
466
- if (type != "quasi") return pass();
467
- if (value.slice(value.length - 2) != "${") return cont(quasi);
468
- return cont(expression, continueQuasi);
469
- }
470
- function continueQuasi(type) {
471
- if (type == "}") {
472
- cx.marked = "string-2";
473
- cx.state.tokenize = tokenQuasi;
474
- return cont(quasi);
475
- }
476
- }
477
- function arrowBody(type) {
478
- findFatArrow(cx.stream, cx.state);
479
- return pass(type == "{" ? statement : expression);
480
- }
481
- function arrowBodyNoComma(type) {
482
- findFatArrow(cx.stream, cx.state);
483
- return pass(type == "{" ? statement : expressionNoComma);
484
- }
485
- function maybeTarget(noComma) {
486
- return function(type) {
487
- if (type == ".") return cont(noComma ? targetNoComma : target);
488
- else if (type == "variable" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma)
489
- else return pass(noComma ? expressionNoComma : expression);
490
- };
491
- }
492
- function target(_, value) {
493
- if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
494
- }
495
- function targetNoComma(_, value) {
496
- if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
497
- }
498
- function maybelabel(type) {
499
- if (type == ":") return cont(poplex, statement);
500
- return pass(maybeoperatorComma, expect(";"), poplex);
501
- }
502
- function property(type) {
503
- if (type == "variable") {cx.marked = "property"; return cont();}
504
- }
505
- function objprop(type, value) {
506
- if (type == "async") {
507
- cx.marked = "property";
508
- return cont(objprop);
509
- } else if (type == "variable" || cx.style == "keyword") {
510
- cx.marked = "property";
511
- if (value == "get" || value == "set") return cont(getterSetter);
512
- var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params
513
- if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false)))
514
- cx.state.fatArrowAt = cx.stream.pos + m[0].length
515
- return cont(afterprop);
516
- } else if (type == "number" || type == "string") {
517
- cx.marked = jsonldMode ? "property" : (cx.style + " property");
518
- return cont(afterprop);
519
- } else if (type == "jsonld-keyword") {
520
- return cont(afterprop);
521
- } else if (isTS && isModifier(value)) {
522
- cx.marked = "keyword"
523
- return cont(objprop)
524
- } else if (type == "[") {
525
- return cont(expression, maybetype, expect("]"), afterprop);
526
- } else if (type == "spread") {
527
- return cont(expressionNoComma, afterprop);
528
- } else if (value == "*") {
529
- cx.marked = "keyword";
530
- return cont(objprop);
531
- } else if (type == ":") {
532
- return pass(afterprop)
533
- }
534
- }
535
- function getterSetter(type) {
536
- if (type != "variable") return pass(afterprop);
537
- cx.marked = "property";
538
- return cont(functiondef);
539
- }
540
- function afterprop(type) {
541
- if (type == ":") return cont(expressionNoComma);
542
- if (type == "(") return pass(functiondef);
543
- }
544
- function commasep(what, end, sep) {
545
- function proceed(type, value) {
546
- if (sep ? sep.indexOf(type) > -1 : type == ",") {
547
- var lex = cx.state.lexical;
548
- if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
549
- return cont(function(type, value) {
550
- if (type == end || value == end) return pass()
551
- return pass(what)
552
- }, proceed);
553
- }
554
- if (type == end || value == end) return cont();
555
- return cont(expect(end));
556
- }
557
- return function(type, value) {
558
- if (type == end || value == end) return cont();
559
- return pass(what, proceed);
560
- };
561
- }
562
- function contCommasep(what, end, info) {
563
- for (var i = 3; i < arguments.length; i++)
564
- cx.cc.push(arguments[i]);
565
- return cont(pushlex(end, info), commasep(what, end), poplex);
566
- }
567
- function block(type) {
568
- if (type == "}") return cont();
569
- return pass(statement, block);
570
- }
571
- function maybetype(type, value) {
572
- if (isTS) {
573
- if (type == ":") return cont(typeexpr);
574
- if (value == "?") return cont(maybetype);
575
- }
576
- }
577
- function mayberettype(type) {
578
- if (isTS && type == ":") {
579
- if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr)
580
- else return cont(typeexpr)
581
- }
582
- }
583
- function isKW(_, value) {
584
- if (value == "is") {
585
- cx.marked = "keyword"
586
- return cont()
587
- }
588
- }
589
- function typeexpr(type, value) {
590
- if (value == "keyof" || value == "typeof") {
591
- cx.marked = "keyword"
592
- return cont(value == "keyof" ? typeexpr : expressionNoComma)
593
- }
594
- if (type == "variable" || value == "void") {
595
- cx.marked = "type"
596
- return cont(afterType)
597
- }
598
- if (type == "string" || type == "number" || type == "atom") return cont(afterType);
599
- if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
600
- if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
601
- if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType)
602
- if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
603
- }
604
- function maybeReturnType(type) {
605
- if (type == "=>") return cont(typeexpr)
606
- }
607
- function typeprop(type, value) {
608
- if (type == "variable" || cx.style == "keyword") {
609
- cx.marked = "property"
610
- return cont(typeprop)
611
- } else if (value == "?") {
612
- return cont(typeprop)
613
- } else if (type == ":") {
614
- return cont(typeexpr)
615
- } else if (type == "[") {
616
- return cont(expression, maybetype, expect("]"), typeprop)
617
- }
618
- }
619
- function typearg(type, value) {
620
- if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg)
621
- if (type == ":") return cont(typeexpr)
622
- return pass(typeexpr)
623
- }
624
- function afterType(type, value) {
625
- if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
626
- if (value == "|" || type == "." || value == "&") return cont(typeexpr)
627
- if (type == "[") return cont(expect("]"), afterType)
628
- if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) }
629
- }
630
- function maybeTypeArgs(_, value) {
631
- if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
632
- }
633
- function typeparam() {
634
- return pass(typeexpr, maybeTypeDefault)
635
- }
636
- function maybeTypeDefault(_, value) {
637
- if (value == "=") return cont(typeexpr)
638
- }
639
- function vardef(_, value) {
640
- if (value == "enum") {cx.marked = "keyword"; return cont(enumdef)}
641
- return pass(pattern, maybetype, maybeAssign, vardefCont);
642
- }
643
- function pattern(type, value) {
644
- if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(pattern) }
645
- if (type == "variable") { register(value); return cont(); }
646
- if (type == "spread") return cont(pattern);
647
- if (type == "[") return contCommasep(pattern, "]");
648
- if (type == "{") return contCommasep(proppattern, "}");
649
- }
650
- function proppattern(type, value) {
651
- if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
652
- register(value);
653
- return cont(maybeAssign);
654
- }
655
- if (type == "variable") cx.marked = "property";
656
- if (type == "spread") return cont(pattern);
657
- if (type == "}") return pass();
658
- return cont(expect(":"), pattern, maybeAssign);
659
- }
660
- function maybeAssign(_type, value) {
661
- if (value == "=") return cont(expressionNoComma);
662
- }
663
- function vardefCont(type) {
664
- if (type == ",") return cont(vardef);
665
- }
666
- function maybeelse(type, value) {
667
- if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
668
- }
669
- function forspec(type, value) {
670
- if (value == "await") return cont(forspec);
671
- if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
672
- }
673
- function forspec1(type) {
674
- if (type == "var") return cont(vardef, expect(";"), forspec2);
675
- if (type == ";") return cont(forspec2);
676
- if (type == "variable") return cont(formaybeinof);
677
- return pass(expression, expect(";"), forspec2);
678
- }
679
- function formaybeinof(_type, value) {
680
- if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
681
- return cont(maybeoperatorComma, forspec2);
682
- }
683
- function forspec2(type, value) {
684
- if (type == ";") return cont(forspec3);
685
- if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
686
- return pass(expression, expect(";"), forspec3);
687
- }
688
- function forspec3(type) {
689
- if (type != ")") cont(expression);
690
- }
691
- function functiondef(type, value) {
692
- if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
693
- if (type == "variable") {register(value); return cont(functiondef);}
694
- if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext);
695
- if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef)
696
- }
697
- function funarg(type, value) {
698
- if (value == "@") cont(expression, funarg)
699
- if (type == "spread") return cont(funarg);
700
- if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); }
701
- return pass(pattern, maybetype, maybeAssign);
702
- }
703
- function classExpression(type, value) {
704
- // Class expressions may have an optional name.
705
- if (type == "variable") return className(type, value);
706
- return classNameAfter(type, value);
707
- }
708
- function className(type, value) {
709
- if (type == "variable") {register(value); return cont(classNameAfter);}
710
- }
711
- function classNameAfter(type, value) {
712
- if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter)
713
- if (value == "extends" || value == "implements" || (isTS && type == ",")) {
714
- if (value == "implements") cx.marked = "keyword";
715
- return cont(isTS ? typeexpr : expression, classNameAfter);
716
- }
717
- if (type == "{") return cont(pushlex("}"), classBody, poplex);
718
- }
719
- function classBody(type, value) {
720
- if (type == "async" ||
721
- (type == "variable" &&
722
- (value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) &&
723
- cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) {
724
- cx.marked = "keyword";
725
- return cont(classBody);
726
- }
727
- if (type == "variable" || cx.style == "keyword") {
728
- cx.marked = "property";
729
- return cont(isTS ? classfield : functiondef, classBody);
730
- }
731
- if (type == "[")
732
- return cont(expression, maybetype, expect("]"), isTS ? classfield : functiondef, classBody)
733
- if (value == "*") {
734
- cx.marked = "keyword";
735
- return cont(classBody);
736
- }
737
- if (type == ";") return cont(classBody);
738
- if (type == "}") return cont();
739
- if (value == "@") return cont(expression, classBody)
740
- }
741
- function classfield(type, value) {
742
- if (value == "?") return cont(classfield)
743
- if (type == ":") return cont(typeexpr, maybeAssign)
744
- if (value == "=") return cont(expressionNoComma)
745
- return pass(functiondef)
746
- }
747
- function afterExport(type, value) {
748
- if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
749
- if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
750
- if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
751
- return pass(statement);
752
- }
753
- function exportField(type, value) {
754
- if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); }
755
- if (type == "variable") return pass(expressionNoComma, exportField);
756
- }
757
- function afterImport(type) {
758
- if (type == "string") return cont();
759
- if (type == "(") return pass(expression);
760
- return pass(importSpec, maybeMoreImports, maybeFrom);
761
- }
762
- function importSpec(type, value) {
763
- if (type == "{") return contCommasep(importSpec, "}");
764
- if (type == "variable") register(value);
765
- if (value == "*") cx.marked = "keyword";
766
- return cont(maybeAs);
767
- }
768
- function maybeMoreImports(type) {
769
- if (type == ",") return cont(importSpec, maybeMoreImports)
770
- }
771
- function maybeAs(_type, value) {
772
- if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
773
- }
774
- function maybeFrom(_type, value) {
775
- if (value == "from") { cx.marked = "keyword"; return cont(expression); }
776
- }
777
- function arrayLiteral(type) {
778
- if (type == "]") return cont();
779
- return pass(commasep(expressionNoComma, "]"));
780
- }
781
- function enumdef() {
782
- return pass(pushlex("form"), pattern, expect("{"), pushlex("}"), commasep(enummember, "}"), poplex, poplex)
783
- }
784
- function enummember() {
785
- return pass(pattern, maybeAssign);
786
- }
787
-
788
- function isContinuedStatement(state, textAfter) {
789
- return state.lastType == "operator" || state.lastType == "," ||
790
- isOperatorChar.test(textAfter.charAt(0)) ||
791
- /[,.]/.test(textAfter.charAt(0));
792
- }
793
-
794
- function expressionAllowed(stream, state, backUp) {
795
- return state.tokenize == tokenBase &&
796
- /^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
797
- (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
798
- }
799
-
800
- // Interface
801
-
802
- return {
803
- startState: function(basecolumn) {
804
- var state = {
805
- tokenize: tokenBase,
806
- lastType: "sof",
807
- cc: [],
808
- lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
809
- localVars: parserConfig.localVars,
810
- context: parserConfig.localVars && new Context(null, null, false),
811
- indented: basecolumn || 0
812
- };
813
- if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
814
- state.globalVars = parserConfig.globalVars;
815
- return state;
816
- },
817
-
818
- token: function(stream, state) {
819
- if (stream.sol()) {
820
- if (!state.lexical.hasOwnProperty("align"))
821
- state.lexical.align = false;
822
- state.indented = stream.indentation();
823
- findFatArrow(stream, state);
824
- }
825
- if (state.tokenize != tokenComment && stream.eatSpace()) return null;
826
- var style = state.tokenize(stream, state);
827
- if (type == "comment") return style;
828
- state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
829
- return parseJS(state, style, type, content, stream);
830
- },
831
-
832
- indent: function(state, textAfter) {
833
- if (state.tokenize == tokenComment) return CodeMirror.Pass;
834
- if (state.tokenize != tokenBase) return 0;
835
- var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top
836
- // Kludge to prevent 'maybelse' from blocking lexical scope pops
837
- if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
838
- var c = state.cc[i];
839
- if (c == poplex) lexical = lexical.prev;
840
- else if (c != maybeelse) break;
841
- }
842
- while ((lexical.type == "stat" || lexical.type == "form") &&
843
- (firstChar == "}" || ((top = state.cc[state.cc.length - 1]) &&
844
- (top == maybeoperatorComma || top == maybeoperatorNoComma) &&
845
- !/^[,\.=+\-*:?[\(]/.test(textAfter))))
846
- lexical = lexical.prev;
847
- if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
848
- lexical = lexical.prev;
849
- var type = lexical.type, closing = firstChar == type;
850
-
851
- if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0);
852
- else if (type == "form" && firstChar == "{") return lexical.indented;
853
- else if (type == "form") return lexical.indented + indentUnit;
854
- else if (type == "stat")
855
- return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
856
- else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
857
- return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
858
- else if (lexical.align) return lexical.column + (closing ? 0 : 1);
859
- else return lexical.indented + (closing ? 0 : indentUnit);
860
- },
861
-
862
- electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
863
- blockCommentStart: jsonMode ? null : "/*",
864
- blockCommentEnd: jsonMode ? null : "*/",
865
- blockCommentContinue: jsonMode ? null : " * ",
866
- lineComment: jsonMode ? null : "//",
867
- fold: "brace",
868
- closeBrackets: "()[]{}''\"\"``",
869
-
870
- helperType: jsonMode ? "json" : "javascript",
871
- jsonldMode: jsonldMode,
872
- jsonMode: jsonMode,
873
-
874
- expressionAllowed: expressionAllowed,
875
-
876
- skipExpression: function(state) {
877
- var top = state.cc[state.cc.length - 1]
878
- if (top == expression || top == expressionNoComma) state.cc.pop()
879
- }
880
- };
881
- });
882
-
883
- CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
884
-
885
- CodeMirror.defineMIME("text/javascript", "javascript");
886
- CodeMirror.defineMIME("text/ecmascript", "javascript");
887
- CodeMirror.defineMIME("application/javascript", "javascript");
888
- CodeMirror.defineMIME("application/x-javascript", "javascript");
889
- CodeMirror.defineMIME("application/ecmascript", "javascript");
890
- CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
891
- CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
892
- CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
893
- CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
894
- CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
895
-
896
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/vendor/codemirror/matchbrackets.js DELETED
@@ -1,145 +0,0 @@
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 ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
13
- (document.documentMode == null || document.documentMode < 8);
14
-
15
- var Pos = CodeMirror.Pos;
16
-
17
- var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
18
-
19
- function findMatchingBracket(cm, where, config) {
20
- var line = cm.getLineHandle(where.line), pos = where.ch - 1;
21
- var afterCursor = config && config.afterCursor
22
- if (afterCursor == null)
23
- afterCursor = /(^| )cm-fat-cursor($| )/.test(cm.getWrapperElement().className)
24
-
25
- // A cursor is defined as between two characters, but in in vim command mode
26
- // (i.e. not insert mode), the cursor is visually represented as a
27
- // highlighted box on top of the 2nd character. Otherwise, we allow matches
28
- // from before or after the cursor.
29
- var match = (!afterCursor && pos >= 0 && matching[line.text.charAt(pos)]) ||
30
- matching[line.text.charAt(++pos)];
31
- if (!match) return null;
32
- var dir = match.charAt(1) == ">" ? 1 : -1;
33
- if (config && config.strict && (dir > 0) != (pos == where.ch)) return null;
34
- var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
35
-
36
- var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
37
- if (found == null) return null;
38
- return {from: Pos(where.line, pos), to: found && found.pos,
39
- match: found && found.ch == match.charAt(0), forward: dir > 0};
40
- }
41
-
42
- // bracketRegex is used to specify which type of bracket to scan
43
- // should be a regexp, e.g. /[[\]]/
44
- //
45
- // Note: If "where" is on an open bracket, then this bracket is ignored.
46
- //
47
- // Returns false when no bracket was found, null when it reached
48
- // maxScanLines and gave up
49
- function scanForBracket(cm, where, dir, style, config) {
50
- var maxScanLen = (config && config.maxScanLineLength) || 10000;
51
- var maxScanLines = (config && config.maxScanLines) || 1000;
52
-
53
- var stack = [];
54
- var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/;
55
- var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)
56
- : Math.max(cm.firstLine() - 1, where.line - maxScanLines);
57
- for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
58
- var line = cm.getLine(lineNo);
59
- if (!line) continue;
60
- var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;
61
- if (line.length > maxScanLen) continue;
62
- if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0);
63
- for (; pos != end; pos += dir) {
64
- var ch = line.charAt(pos);
65
- if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {
66
- var match = matching[ch];
67
- if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch);
68
- else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch};
69
- else stack.pop();
70
- }
71
- }
72
- }
73
- return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;
74
- }
75
-
76
- function matchBrackets(cm, autoclear, config) {
77
- // Disable brace matching in long lines, since it'll cause hugely slow updates
78
- var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
79
- var marks = [], ranges = cm.listSelections();
80
- for (var i = 0; i < ranges.length; i++) {
81
- var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, config);
82
- if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
83
- var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
84
- marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
85
- if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)
86
- marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));
87
- }
88
- }
89
-
90
- if (marks.length) {
91
- // Kludge to work around the IE bug from issue #1193, where text
92
- // input stops going to the textare whever this fires.
93
- if (ie_lt8 && cm.state.focused) cm.focus();
94
-
95
- var clear = function() {
96
- cm.operation(function() {
97
- for (var i = 0; i < marks.length; i++) marks[i].clear();
98
- });
99
- };
100
- if (autoclear) setTimeout(clear, 800);
101
- else return clear;
102
- }
103
- }
104
-
105
- function doMatchBrackets(cm) {
106
- cm.operation(function() {
107
- if (cm.state.matchBrackets.currentlyHighlighted) {
108
- cm.state.matchBrackets.currentlyHighlighted();
109
- cm.state.matchBrackets.currentlyHighlighted = null;
110
- }
111
- cm.state.matchBrackets.currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
112
- });
113
- }
114
-
115
- CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
116
- if (old && old != CodeMirror.Init) {
117
- cm.off("cursorActivity", doMatchBrackets);
118
- if (cm.state.matchBrackets && cm.state.matchBrackets.currentlyHighlighted) {
119
- cm.state.matchBrackets.currentlyHighlighted();
120
- cm.state.matchBrackets.currentlyHighlighted = null;
121
- }
122
- }
123
- if (val) {
124
- cm.state.matchBrackets = typeof val == "object" ? val : {};
125
- cm.on("cursorActivity", doMatchBrackets);
126
- }
127
- });
128
-
129
- CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
130
- CodeMirror.defineExtension("findMatchingBracket", function(pos, config, oldConfig){
131
- // Backwards-compatibility kludge
132
- if (oldConfig || typeof config == "boolean") {
133
- if (!oldConfig) {
134
- config = config ? {strict: true} : null
135
- } else {
136
- oldConfig.strict = config
137
- config = oldConfig
138
- }
139
- }
140
- return findMatchingBracket(this, pos, config)
141
- });
142
- CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){
143
- return scanForBracket(this, pos, dir, style, config);
144
- });
145
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/wp-gdpr-compliance.pot CHANGED
@@ -2,7 +2,7 @@
2
  msgid ""
3
  msgstr ""
4
  "Project-Id-Version: WP GDPR Compliance\n"
5
- "POT-Creation-Date: 2018-06-03 14:28+0200\n"
6
  "Last-Translator: \n"
7
  "Language-Team: Van Ons <info@van-ons.nl>\n"
8
  "MIME-Version: 1.0\n"
@@ -17,54 +17,46 @@ msgstr ""
17
  "X-Poedit-Basepath: ..\n"
18
  "X-Poedit-SearchPath-0: .\n"
19
 
20
- #: Includes/Action.php:21
21
- msgid "Consent has been updated successfully."
22
- msgstr ""
23
-
24
- #: Includes/Action.php:25
25
- msgid "Consent has been added successfully."
26
- msgstr ""
27
-
28
- #: Includes/Action.php:29
29
- msgid "Couldn't find this consent."
30
- msgstr ""
31
-
32
- #: Includes/Action.php:69
33
  msgid "Data Access Request"
34
  msgstr ""
35
 
36
- #: Includes/Action.php:105
37
  msgid "Couldn't create the required database tables."
38
  msgstr ""
39
 
40
- #: Includes/Action.php:109
41
  msgid "Retry"
42
  msgstr ""
43
 
44
- #: Includes/Action.php:128 Includes/Page.php:380 Includes/Shortcode.php:154
45
  msgid "My settings"
46
  msgstr ""
47
 
48
- #: Includes/Action.php:134
49
  msgid "Accept"
50
  msgstr ""
51
 
52
- #: Includes/Action.php:170 Includes/Helper.php:116 Includes/Helper.php:137
53
- #: Includes/Page.php:324 Includes/Page.php:375 Includes/Page.php:495
54
  msgid "Note"
55
  msgstr ""
56
 
57
- #: Includes/Action.php:171
58
  msgid ""
59
  "These settings will only apply to the browser and device you are currently "
60
  "using."
61
  msgstr ""
62
 
63
- #: Includes/Action.php:201
 
 
 
 
64
  msgid "Save my settings"
65
  msgstr ""
66
 
67
- #: Includes/Action.php:208
68
  msgid "Close modal"
69
  msgstr ""
70
 
@@ -232,11 +224,11 @@ msgstr ""
232
  msgid "This request has already been processed."
233
  msgstr ""
234
 
235
- #: Includes/Consent.php:51
236
  msgid "Privacy Settings"
237
  msgstr ""
238
 
239
- #: Includes/Consent.php:64
240
  msgid ""
241
  "This site uses functional cookies and external scripts to improve your "
242
  "experience. Which cookies and scripts are used and how they impact your "
@@ -244,17 +236,25 @@ msgid ""
244
  "Your choices will not impact your visit."
245
  msgstr ""
246
 
247
- #: Includes/Consent.php:77
248
  msgid ""
249
  "This site uses functional cookies and external scripts to improve your "
250
  "experience."
251
  msgstr ""
252
 
253
- #: Includes/Consent.php:242 Includes/Page.php:522
 
 
 
 
 
 
 
 
254
  msgid "Head"
255
  msgstr ""
256
 
257
- #: Includes/Consent.php:243 Includes/Page.php:527
258
  msgid "Footer"
259
  msgstr ""
260
 
@@ -276,7 +276,7 @@ msgid "Display Name"
276
  msgstr ""
277
 
278
  #: Includes/Data.php:54 Includes/Data.php:63 Includes/Data.php:70
279
- #: Includes/Page.php:721
280
  msgid "Email Address"
281
  msgstr ""
282
 
@@ -296,7 +296,7 @@ msgstr ""
296
  msgid "Content"
297
  msgstr ""
298
 
299
- #: Includes/Data.php:64 Includes/Page.php:640 Includes/Page.php:722
300
  msgid "IP Address"
301
  msgstr ""
302
 
@@ -377,17 +377,33 @@ msgstr ""
377
  msgid "No HTML allowed due to plugin limitations."
378
  msgstr ""
379
 
380
- #: Includes/Helper.php:138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  msgid ""
382
  "Please disable the custom comments form in Jetpack to make your WordPress "
383
  "Comments GDPR compliant."
384
  msgstr ""
385
 
386
- #: Includes/Helper.php:153
387
  msgid "Do you have a contact form?"
388
  msgstr ""
389
 
390
- #: Includes/Helper.php:154
391
  msgid ""
392
  "Make sure you add a checkbox specifically asking the user of the form if "
393
  "they consent to you storing and using their personal information to get back "
@@ -395,11 +411,11 @@ msgid ""
395
  "if you will send or share the data with any 3rd-parties and which."
396
  msgstr ""
397
 
398
- #: Includes/Helper.php:157
399
  msgid "Can visitors comment anywhere on your website?"
400
  msgstr ""
401
 
402
- #: Includes/Helper.php:158
403
  msgid ""
404
  "Make sure you add a checkbox specifically asking the user of the comment "
405
  "section if they consent to storing their message attached to the e-mail "
@@ -408,11 +424,11 @@ msgid ""
408
  "which."
409
  msgstr ""
410
 
411
- #: Includes/Helper.php:161
412
  msgid "Is there an order form on your website or webshop present?"
413
  msgstr ""
414
 
415
- #: Includes/Helper.php:162
416
  msgid ""
417
  "Make sure you add a checkbox specifically asking the user of the form if "
418
  "they consent to you storing and using their personal information to ship the "
@@ -422,11 +438,11 @@ msgid ""
422
  "which."
423
  msgstr ""
424
 
425
- #: Includes/Helper.php:165
426
  msgid "Do you provide a forum or message board?"
427
  msgstr ""
428
 
429
- #: Includes/Helper.php:166
430
  msgid ""
431
  "Make sure you add a checkbox specifically asking forum / board users if they "
432
  "consent to you storing and using their personal information and messages. "
@@ -434,11 +450,11 @@ msgid ""
434
  "share the data with any 3rd-parties and which."
435
  msgstr ""
436
 
437
- #: Includes/Helper.php:169
438
  msgid "Can visitors chat with your company directly?"
439
  msgstr ""
440
 
441
- #: Includes/Helper.php:170
442
  msgid ""
443
  "Make sure you add a checkbox specifically asking chat users if they consent "
444
  "to you storing and using their personal information and messages. The "
@@ -493,7 +509,7 @@ msgid ""
493
  "request. When your data is anonymised you will receive an email confirmation."
494
  msgstr ""
495
 
496
- #: Includes/Integration.php:312 Includes/Page.php:628
497
  msgid "WordPress Comments"
498
  msgstr ""
499
 
@@ -515,7 +531,7 @@ msgstr ""
515
  msgid "Gravity Forms"
516
  msgstr ""
517
 
518
- #: Includes/Integration.php:341 Includes/Page.php:629
519
  msgid "WooCommerce"
520
  msgstr ""
521
 
@@ -537,7 +553,7 @@ msgstr ""
537
  msgid "Checklist"
538
  msgstr ""
539
 
540
- #: Includes/Page.php:78 wp-gdpr-compliance.php:131
541
  msgid "Settings"
542
  msgstr ""
543
 
@@ -690,67 +706,67 @@ msgstr ""
690
  msgid "Modal: Explanation"
691
  msgstr ""
692
 
693
- #: Includes/Page.php:460
694
  msgid "Add New Consent"
695
  msgstr ""
696
 
697
- #: Includes/Page.php:462 Includes/Page.php:564 Includes/Page.php:750
698
  msgid "Active"
699
  msgstr ""
700
 
701
- #: Includes/Page.php:468 Includes/Page.php:559
702
  msgid "Title"
703
  msgstr ""
704
 
705
- #: Includes/Page.php:472
706
  msgid "e.g. \"Google Analytics\" or \"Advertising\""
707
  msgstr ""
708
 
709
- #: Includes/Page.php:477
710
  msgid "Description"
711
  msgstr ""
712
 
713
- #: Includes/Page.php:481
714
  msgid "Describe your consent script as thoroughly as possible."
715
  msgstr ""
716
 
717
- #: Includes/Page.php:486
718
  msgid "Code Snippet"
719
  msgstr ""
720
 
721
- #: Includes/Page.php:490
722
  msgid "Code snippets for Google Analytics, Facebook Pixel, etc."
723
  msgstr ""
724
 
725
- #: Includes/Page.php:496
726
- msgid "JavaScript only. Do not add any <script> tags to your snippet."
727
  msgstr ""
728
 
729
- #: Includes/Page.php:504 Includes/Page.php:560
730
  msgid "Placement"
731
  msgstr ""
732
 
733
- #: Includes/Page.php:523
734
  msgid "Snippet will be added to the HEAD section."
735
  msgstr ""
736
 
737
- #: Includes/Page.php:528
738
  msgid "Snippet will be added to the FOOTER section."
739
  msgstr ""
740
 
741
- #: Includes/Page.php:535
742
  msgid "Update"
743
  msgstr ""
744
 
745
- #: Includes/Page.php:535
746
  msgid "Add"
747
  msgstr ""
748
 
749
- #: Includes/Page.php:536
750
  msgid "Back to overview"
751
  msgstr ""
752
 
753
- #: Includes/Page.php:551
754
  msgid ""
755
  "Ask your visitors for permission to enable certain scripts for tracking or "
756
  "advertising purposes. Add a Consent for each type of script you are "
@@ -758,103 +774,111 @@ msgid ""
758
  "given."
759
  msgstr ""
760
 
761
- #: Includes/Page.php:552
762
  msgctxt "consent"
763
  msgid "Add New"
764
  msgstr ""
765
 
766
- #: Includes/Page.php:558
767
  msgid "Consent"
768
  msgstr ""
769
 
770
- #: Includes/Page.php:561
771
  msgid "Modified at"
772
  msgstr ""
773
 
774
- #: Includes/Page.php:562
775
  msgid "Created at"
776
  msgstr ""
777
 
778
- #: Includes/Page.php:563 Includes/Page.php:643
779
  msgid "Action"
780
  msgstr ""
781
 
782
- #: Includes/Page.php:575
 
 
 
 
783
  msgid "Edit"
784
  msgstr ""
785
 
786
- #: Includes/Page.php:576 wp-gdpr-compliance.php:140 wp-gdpr-compliance.php:158
 
 
 
 
787
  msgid "Yes"
788
  msgstr ""
789
 
790
- #: Includes/Page.php:576 wp-gdpr-compliance.php:141 wp-gdpr-compliance.php:159
791
  msgid "No"
792
  msgstr ""
793
 
794
- #: Includes/Page.php:597 Includes/Page.php:691 Includes/Page.php:773
795
  #, php-format
796
  msgid "%d of %d results found"
797
  msgstr ""
798
 
799
- #: Includes/Page.php:601
800
  msgid "No consents found."
801
  msgstr ""
802
 
803
- #: Includes/Page.php:625
804
  msgid ""
805
  "Anonymise a request by ticking the checkbox and clicking on the green "
806
  "anonymise button below."
807
  msgstr ""
808
 
809
- #: Includes/Page.php:627
810
  msgid "WordPress Users"
811
  msgstr ""
812
 
813
- #: Includes/Page.php:638
814
  msgid "Request"
815
  msgstr ""
816
 
817
- #: Includes/Page.php:639
818
  msgid "Type"
819
  msgstr ""
820
 
821
- #: Includes/Page.php:641 Includes/Page.php:723
822
  msgid "Date"
823
  msgstr ""
824
 
825
- #: Includes/Page.php:642
826
  msgid "Processed"
827
  msgstr ""
828
 
829
- #: Includes/Page.php:658
830
  msgid "View"
831
  msgstr ""
832
 
833
- #: Includes/Page.php:672
834
  msgid "Anonymise selected request(s)"
835
  msgstr ""
836
 
837
- #: Includes/Page.php:697 Includes/Page.php:779
838
  msgid "No requests found."
839
  msgstr ""
840
 
841
- #: Includes/Page.php:719
842
  msgid "ID"
843
  msgstr ""
844
 
845
- #: Includes/Page.php:720
846
  msgid "Requests to Process"
847
  msgstr ""
848
 
849
- #: Includes/Page.php:724
850
  msgid "Status"
851
  msgstr ""
852
 
853
- #: Includes/Page.php:742
854
  msgid "Manage"
855
  msgstr ""
856
 
857
- #: Includes/Page.php:750
858
  msgid "Expired"
859
  msgstr ""
860
 
@@ -910,6 +934,6 @@ msgstr ""
910
  msgid "Send"
911
  msgstr ""
912
 
913
- #: wp-gdpr-compliance.php:131
914
  msgid "View WP GDPR Compliance settings"
915
  msgstr ""
2
  msgid ""
3
  msgstr ""
4
  "Project-Id-Version: WP GDPR Compliance\n"
5
+ "POT-Creation-Date: 2018-06-12 09:53+0200\n"
6
  "Last-Translator: \n"
7
  "Language-Team: Van Ons <info@van-ons.nl>\n"
8
  "MIME-Version: 1.0\n"
17
  "X-Poedit-Basepath: ..\n"
18
  "X-Poedit-SearchPath-0: .\n"
19
 
20
+ #: Includes/Action.php:89
 
 
 
 
 
 
 
 
 
 
 
 
21
  msgid "Data Access Request"
22
  msgstr ""
23
 
24
+ #: Includes/Action.php:125
25
  msgid "Couldn't create the required database tables."
26
  msgstr ""
27
 
28
+ #: Includes/Action.php:129
29
  msgid "Retry"
30
  msgstr ""
31
 
32
+ #: Includes/Action.php:148 Includes/Page.php:380 Includes/Shortcode.php:154
33
  msgid "My settings"
34
  msgstr ""
35
 
36
+ #: Includes/Action.php:154
37
  msgid "Accept"
38
  msgstr ""
39
 
40
+ #: Includes/Action.php:191 Includes/Helper.php:116 Includes/Helper.php:171
41
+ #: Includes/Page.php:324 Includes/Page.php:375
42
  msgid "Note"
43
  msgstr ""
44
 
45
+ #: Includes/Action.php:192
46
  msgid ""
47
  "These settings will only apply to the browser and device you are currently "
48
  "using."
49
  msgstr ""
50
 
51
+ #: Includes/Action.php:216
52
+ msgid "Enable"
53
+ msgstr ""
54
+
55
+ #: Includes/Action.php:224
56
  msgid "Save my settings"
57
  msgstr ""
58
 
59
+ #: Includes/Action.php:231
60
  msgid "Close modal"
61
  msgstr ""
62
 
224
  msgid "This request has already been processed."
225
  msgstr ""
226
 
227
+ #: Includes/Consent.php:53
228
  msgid "Privacy Settings"
229
  msgstr ""
230
 
231
+ #: Includes/Consent.php:66
232
  msgid ""
233
  "This site uses functional cookies and external scripts to improve your "
234
  "experience. Which cookies and scripts are used and how they impact your "
236
  "Your choices will not impact your visit."
237
  msgstr ""
238
 
239
+ #: Includes/Consent.php:79
240
  msgid ""
241
  "This site uses functional cookies and external scripts to improve your "
242
  "experience."
243
  msgstr ""
244
 
245
+ #: Includes/Consent.php:267
246
+ msgid "Wrap my code snippet with <script> tags"
247
+ msgstr ""
248
+
249
+ #: Includes/Consent.php:268
250
+ msgid "Do not wrap my code snippet"
251
+ msgstr ""
252
+
253
+ #: Includes/Consent.php:277 Includes/Page.php:510
254
  msgid "Head"
255
  msgstr ""
256
 
257
+ #: Includes/Consent.php:278 Includes/Page.php:515
258
  msgid "Footer"
259
  msgstr ""
260
 
276
  msgstr ""
277
 
278
  #: Includes/Data.php:54 Includes/Data.php:63 Includes/Data.php:70
279
+ #: Includes/Page.php:733
280
  msgid "Email Address"
281
  msgstr ""
282
 
296
  msgid "Content"
297
  msgstr ""
298
 
299
+ #: Includes/Data.php:64 Includes/Page.php:652 Includes/Page.php:734
300
  msgid "IP Address"
301
  msgstr ""
302
 
377
  msgid "No HTML allowed due to plugin limitations."
378
  msgstr ""
379
 
380
+ #: Includes/Helper.php:134
381
+ msgid "Consent has been updated successfully."
382
+ msgstr ""
383
+
384
+ #: Includes/Helper.php:137
385
+ msgid "Consent has been added successfully."
386
+ msgstr ""
387
+
388
+ #: Includes/Helper.php:140
389
+ msgid "Consent has been removed successfully."
390
+ msgstr ""
391
+
392
+ #: Includes/Helper.php:144
393
+ msgid "Couldn't find this consent."
394
+ msgstr ""
395
+
396
+ #: Includes/Helper.php:172
397
  msgid ""
398
  "Please disable the custom comments form in Jetpack to make your WordPress "
399
  "Comments GDPR compliant."
400
  msgstr ""
401
 
402
+ #: Includes/Helper.php:187
403
  msgid "Do you have a contact form?"
404
  msgstr ""
405
 
406
+ #: Includes/Helper.php:188
407
  msgid ""
408
  "Make sure you add a checkbox specifically asking the user of the form if "
409
  "they consent to you storing and using their personal information to get back "
411
  "if you will send or share the data with any 3rd-parties and which."
412
  msgstr ""
413
 
414
+ #: Includes/Helper.php:191
415
  msgid "Can visitors comment anywhere on your website?"
416
  msgstr ""
417
 
418
+ #: Includes/Helper.php:192
419
  msgid ""
420
  "Make sure you add a checkbox specifically asking the user of the comment "
421
  "section if they consent to storing their message attached to the e-mail "
424
  "which."
425
  msgstr ""
426
 
427
+ #: Includes/Helper.php:195
428
  msgid "Is there an order form on your website or webshop present?"
429
  msgstr ""
430
 
431
+ #: Includes/Helper.php:196
432
  msgid ""
433
  "Make sure you add a checkbox specifically asking the user of the form if "
434
  "they consent to you storing and using their personal information to ship the "
438
  "which."
439
  msgstr ""
440
 
441
+ #: Includes/Helper.php:199
442
  msgid "Do you provide a forum or message board?"
443
  msgstr ""
444
 
445
+ #: Includes/Helper.php:200
446
  msgid ""
447
  "Make sure you add a checkbox specifically asking forum / board users if they "
448
  "consent to you storing and using their personal information and messages. "
450
  "share the data with any 3rd-parties and which."
451
  msgstr ""
452
 
453
+ #: Includes/Helper.php:203
454
  msgid "Can visitors chat with your company directly?"
455
  msgstr ""
456
 
457
+ #: Includes/Helper.php:204
458
  msgid ""
459
  "Make sure you add a checkbox specifically asking chat users if they consent "
460
  "to you storing and using their personal information and messages. The "
509
  "request. When your data is anonymised you will receive an email confirmation."
510
  msgstr ""
511
 
512
+ #: Includes/Integration.php:312 Includes/Page.php:640
513
  msgid "WordPress Comments"
514
  msgstr ""
515
 
531
  msgid "Gravity Forms"
532
  msgstr ""
533
 
534
+ #: Includes/Integration.php:341 Includes/Page.php:641
535
  msgid "WooCommerce"
536
  msgstr ""
537
 
553
  msgid "Checklist"
554
  msgstr ""
555
 
556
+ #: Includes/Page.php:78 wp-gdpr-compliance.php:175
557
  msgid "Settings"
558
  msgstr ""
559
 
706
  msgid "Modal: Explanation"
707
  msgstr ""
708
 
709
+ #: Includes/Page.php:440
710
  msgid "Add New Consent"
711
  msgstr ""
712
 
713
+ #: Includes/Page.php:442 Includes/Page.php:552 Includes/Page.php:762
714
  msgid "Active"
715
  msgstr ""
716
 
717
+ #: Includes/Page.php:448 Includes/Page.php:547
718
  msgid "Title"
719
  msgstr ""
720
 
721
+ #: Includes/Page.php:452
722
  msgid "e.g. \"Google Analytics\" or \"Advertising\""
723
  msgstr ""
724
 
725
+ #: Includes/Page.php:457
726
  msgid "Description"
727
  msgstr ""
728
 
729
+ #: Includes/Page.php:461
730
  msgid "Describe your consent script as thoroughly as possible."
731
  msgstr ""
732
 
733
+ #: Includes/Page.php:466
734
  msgid "Code Snippet"
735
  msgstr ""
736
 
737
+ #: Includes/Page.php:470
738
  msgid "Code snippets for Google Analytics, Facebook Pixel, etc."
739
  msgstr ""
740
 
741
+ #: Includes/Page.php:475
742
+ msgid "Code Wrap"
743
  msgstr ""
744
 
745
+ #: Includes/Page.php:492 Includes/Page.php:548
746
  msgid "Placement"
747
  msgstr ""
748
 
749
+ #: Includes/Page.php:511
750
  msgid "Snippet will be added to the HEAD section."
751
  msgstr ""
752
 
753
+ #: Includes/Page.php:516
754
  msgid "Snippet will be added to the FOOTER section."
755
  msgstr ""
756
 
757
+ #: Includes/Page.php:523
758
  msgid "Update"
759
  msgstr ""
760
 
761
+ #: Includes/Page.php:523
762
  msgid "Add"
763
  msgstr ""
764
 
765
+ #: Includes/Page.php:524
766
  msgid "Back to overview"
767
  msgstr ""
768
 
769
+ #: Includes/Page.php:539
770
  msgid ""
771
  "Ask your visitors for permission to enable certain scripts for tracking or "
772
  "advertising purposes. Add a Consent for each type of script you are "
774
  "given."
775
  msgstr ""
776
 
777
+ #: Includes/Page.php:540
778
  msgctxt "consent"
779
  msgid "Add New"
780
  msgstr ""
781
 
782
+ #: Includes/Page.php:546
783
  msgid "Consent"
784
  msgstr ""
785
 
786
+ #: Includes/Page.php:549
787
  msgid "Modified at"
788
  msgstr ""
789
 
790
+ #: Includes/Page.php:550
791
  msgid "Created at"
792
  msgstr ""
793
 
794
+ #: Includes/Page.php:551 Includes/Page.php:655
795
  msgid "Action"
796
  msgstr ""
797
 
798
+ #: Includes/Page.php:564
799
+ msgid "(no title)"
800
+ msgstr ""
801
+
802
+ #: Includes/Page.php:578
803
  msgid "Edit"
804
  msgstr ""
805
 
806
+ #: Includes/Page.php:583
807
+ msgid "Remove"
808
+ msgstr ""
809
+
810
+ #: Includes/Page.php:588 wp-gdpr-compliance.php:184 wp-gdpr-compliance.php:202
811
  msgid "Yes"
812
  msgstr ""
813
 
814
+ #: Includes/Page.php:588 wp-gdpr-compliance.php:185 wp-gdpr-compliance.php:203
815
  msgid "No"
816
  msgstr ""
817
 
818
+ #: Includes/Page.php:609 Includes/Page.php:703 Includes/Page.php:785
819
  #, php-format
820
  msgid "%d of %d results found"
821
  msgstr ""
822
 
823
+ #: Includes/Page.php:613
824
  msgid "No consents found."
825
  msgstr ""
826
 
827
+ #: Includes/Page.php:637
828
  msgid ""
829
  "Anonymise a request by ticking the checkbox and clicking on the green "
830
  "anonymise button below."
831
  msgstr ""
832
 
833
+ #: Includes/Page.php:639
834
  msgid "WordPress Users"
835
  msgstr ""
836
 
837
+ #: Includes/Page.php:650
838
  msgid "Request"
839
  msgstr ""
840
 
841
+ #: Includes/Page.php:651
842
  msgid "Type"
843
  msgstr ""
844
 
845
+ #: Includes/Page.php:653 Includes/Page.php:735
846
  msgid "Date"
847
  msgstr ""
848
 
849
+ #: Includes/Page.php:654
850
  msgid "Processed"
851
  msgstr ""
852
 
853
+ #: Includes/Page.php:670
854
  msgid "View"
855
  msgstr ""
856
 
857
+ #: Includes/Page.php:684
858
  msgid "Anonymise selected request(s)"
859
  msgstr ""
860
 
861
+ #: Includes/Page.php:709 Includes/Page.php:791
862
  msgid "No requests found."
863
  msgstr ""
864
 
865
+ #: Includes/Page.php:731
866
  msgid "ID"
867
  msgstr ""
868
 
869
+ #: Includes/Page.php:732
870
  msgid "Requests to Process"
871
  msgstr ""
872
 
873
+ #: Includes/Page.php:736
874
  msgid "Status"
875
  msgstr ""
876
 
877
+ #: Includes/Page.php:754
878
  msgid "Manage"
879
  msgstr ""
880
 
881
+ #: Includes/Page.php:762
882
  msgid "Expired"
883
  msgstr ""
884
 
934
  msgid "Send"
935
  msgstr ""
936
 
937
+ #: wp-gdpr-compliance.php:175
938
  msgid "View WP GDPR Compliance settings"
939
  msgstr ""
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: gdpr, law, regulations, compliance, data, protection, privacy, data protec
4
  Requires at least: 4.5
5
  Tested up to: 4.9.4
6
  Requires PHP: 5.3
7
- Stable tag: 1.3.9
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -39,6 +39,16 @@ You'll find answers to many of your questions on [wpgdprc.com](https://www.wpgdp
39
 
40
  == Changelog ==
41
 
 
 
 
 
 
 
 
 
 
 
42
  = 1.3.9 =
43
  *Release date: June 3rd, 2018*
44
  * Small front-end fixes.
4
  Requires at least: 4.5
5
  Tested up to: 4.9.4
6
  Requires PHP: 5.3
7
+ Stable tag: 1.4.0
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
10
 
39
 
40
  == Changelog ==
41
 
42
+ = 1.4.0 =
43
+ *Release date: June 8th, 2018*
44
+ * Small front-end fixes.
45
+ * Added missing translatable strings.
46
+ * Fixed the text domain for some translatable strings.
47
+ * Show enabled consents of user.
48
+ * Small bugfix for admin redirects.
49
+ * Added the ability to remove 'Consents' via the admin panel.
50
+ * Added the option to wrap 'Consents' with <script> tags.
51
+
52
  = 1.3.9 =
53
  *Release date: June 3rd, 2018*
54
  * Small front-end fixes.
wp-gdpr-compliance.php CHANGED
@@ -4,7 +4,7 @@
4
  Plugin Name: WP GDPR Compliance
5
  Plugin URI: https://www.wpgdprc.com/
6
  Description: This plugin assists website and webshop owners to comply with European privacy regulations known as GDPR. By May 24th, 2018 your website or shop has to comply to avoid large fines.
7
- Version: 1.3.9
8
  Author: Van Ons
9
  Author URI: https://www.van-ons.nl/
10
  License: GPL2
@@ -74,11 +74,15 @@ class WPGDPRC {
74
  private static $instance = null;
75
 
76
  public function init() {
 
 
 
 
 
 
 
77
  $action = (isset($_REQUEST['wpgdprc-action'])) ? esc_html($_REQUEST['wpgdprc-action']) : false;
78
  Helper::doAction($action);
79
- if (is_admin() && !function_exists('get_plugin_data')) {
80
- require_once(ABSPATH . 'wp-admin/includes/plugin.php');
81
- }
82
  load_plugin_textdomain(WP_GDPR_C_SLUG, false, basename(dirname(__FILE__)) . '/languages/');
83
  add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'addActionLinksToPluginPage'));
84
  add_action('admin_init', array(Page::getInstance(), 'registerSettings'));
@@ -105,21 +109,61 @@ class WPGDPRC {
105
  wp_clear_scheduled_hook('wpgdprc_deactivate_access_requests');
106
  }
107
  }
108
- // TODO: Better way to create database tables
109
- if (!Consent::databaseTableExists()) {
110
- Helper::createConsentsTables();
111
- } else {
112
  add_shortcode('wpgdprc_consents_settings_link', array(Shortcode::getInstance(), 'consentsSettingsLink'));
113
  if (Consent::getInstance()->getTotal(array('active' => array('value' => 1))) > 0) {
 
114
  add_action('wp_footer', array(Action::getInstance(), 'addConsentModal'), 999);
115
- if (empty($_COOKIE['wpgdprc-consent'])) {
116
- add_action('wp_footer', array(Action::getInstance(), 'addConsentBar'), 998);
117
- } else {
118
  add_action('wp_head', array(Action::getInstance(), 'addConsentsToHead'), 999);
119
  add_action('wp_footer', array(Action::getInstance(), 'addConsentsToFooter'), 999);
120
  }
121
  }
122
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  }
124
 
125
  /**
@@ -137,7 +181,7 @@ class WPGDPRC {
137
  wp_register_script('wpgdprc.micromodal.js', WP_GDPR_C_URI_VENDOR . '/micromodal/micromodal.min.js', array(), filemtime(WP_GDPR_C_DIR_VENDOR . '/micromodal/micromodal.min.js'));
138
  wp_enqueue_style('wpgdprc.css', WP_GDPR_C_URI_CSS . '/front.css', array(), filemtime(WP_GDPR_C_DIR_CSS . '/front.css'));
139
  wp_add_inline_style('wpgdprc.css', "
140
- div.wpgdprc .wpgdprc-switch .wpgdprc-switch-inner:before { content: '" . __('Yes', WP_GDPR_C_SLUG) . "'; }
141
  div.wpgdprc .wpgdprc-switch .wpgdprc-switch-inner:after { content: '" . __('No', WP_GDPR_C_SLUG) . "'; }
142
  ");
143
  wp_enqueue_script('wpgdprc.js', WP_GDPR_C_URI_JS . '/front.js', array('wpgdprc.micromodal.js'), filemtime(WP_GDPR_C_DIR_JS . '/front.js'), true);
@@ -155,13 +199,11 @@ class WPGDPRC {
155
  wp_register_style('wpgdprc.admin.codemirror.css', WP_GDPR_C_URI_VENDOR . '/codemirror/codemirror.css', array(), filemtime(WP_GDPR_C_DIR_VENDOR . '/codemirror/codemirror.css'));
156
  wp_enqueue_style('wpgdprc.admin.css', WP_GDPR_C_URI_CSS . '/admin.css', array(), filemtime(WP_GDPR_C_DIR_CSS . '/admin.css'));
157
  wp_add_inline_style('wpgdprc.admin.css', "
158
- div.wpgdprc .wpgdprc-switch .wpgdprc-switch-inner:before { content: '" . __('Yes', WP_GDPR_C_SLUG) . "'; }
159
  div.wpgdprc .wpgdprc-switch .wpgdprc-switch-inner:after { content: '" . __('No', WP_GDPR_C_SLUG) . "'; }
160
  ");
161
  wp_register_script('wpgdprc.admin.codemirror.js', WP_GDPR_C_URI_VENDOR . '/codemirror/codemirror.js', array(), filemtime(WP_GDPR_C_DIR_VENDOR . '/codemirror/codemirror.js'));
162
- wp_register_script('wpgdprc.admin.codemirror.matchbrackets.js', WP_GDPR_C_URI_VENDOR . '/codemirror/matchbrackets.js', array('wpgdprc.admin.codemirror.js'), filemtime(WP_GDPR_C_DIR_VENDOR . '/codemirror/matchbrackets.js'));
163
- wp_register_script('wpgdprc.admin.codemirror.comment.js', WP_GDPR_C_URI_VENDOR . '/codemirror/comment.js', array('wpgdprc.admin.codemirror.js'), filemtime(WP_GDPR_C_DIR_VENDOR . '/codemirror/comment.js'));
164
- wp_register_script('wpgdprc.admin.codemirror.javascript.js', WP_GDPR_C_URI_VENDOR . '/codemirror/javascript.js', array('wpgdprc.admin.codemirror.js'), filemtime(WP_GDPR_C_DIR_VENDOR . '/codemirror/javascript.js'));
165
  wp_enqueue_script('wpgdprc.admin.js', WP_GDPR_C_URI_JS . '/admin.js', array(), filemtime(WP_GDPR_C_DIR_JS . '/admin.js'), true);
166
  wp_localize_script('wpgdprc.admin.js', 'wpgdprcData', array(
167
  'ajaxURL' => admin_url('admin-ajax.php'),
4
  Plugin Name: WP GDPR Compliance
5
  Plugin URI: https://www.wpgdprc.com/
6
  Description: This plugin assists website and webshop owners to comply with European privacy regulations known as GDPR. By May 24th, 2018 your website or shop has to comply to avoid large fines.
7
+ Version: 1.4.0
8
  Author: Van Ons
9
  Author URI: https://www.van-ons.nl/
10
  License: GPL2
74
  private static $instance = null;
75
 
76
  public function init() {
77
+ self::handleDatabaseTables();
78
+ if (is_admin()) {
79
+ Action::getInstance()->handleRedirects();
80
+ if (!function_exists('get_plugin_data')) {
81
+ require_once(ABSPATH . 'wp-admin/includes/plugin.php');
82
+ }
83
+ }
84
  $action = (isset($_REQUEST['wpgdprc-action'])) ? esc_html($_REQUEST['wpgdprc-action']) : false;
85
  Helper::doAction($action);
 
 
 
86
  load_plugin_textdomain(WP_GDPR_C_SLUG, false, basename(dirname(__FILE__)) . '/languages/');
87
  add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'addActionLinksToPluginPage'));
88
  add_action('admin_init', array(Page::getInstance(), 'registerSettings'));
109
  wp_clear_scheduled_hook('wpgdprc_deactivate_access_requests');
110
  }
111
  }
112
+ if (Consent::databaseTableExists()) {
 
 
 
113
  add_shortcode('wpgdprc_consents_settings_link', array(Shortcode::getInstance(), 'consentsSettingsLink'));
114
  if (Consent::getInstance()->getTotal(array('active' => array('value' => 1))) > 0) {
115
+ add_action('wp_footer', array(Action::getInstance(), 'addConsentBar'), 998);
116
  add_action('wp_footer', array(Action::getInstance(), 'addConsentModal'), 999);
117
+ if (!empty($_COOKIE['wpgdprc-consent'])) {
 
 
118
  add_action('wp_head', array(Action::getInstance(), 'addConsentsToHead'), 999);
119
  add_action('wp_footer', array(Action::getInstance(), 'addConsentsToFooter'), 999);
120
  }
121
  }
122
  }
123
+ add_filter('wpgdprc_the_content', 'wptexturize');
124
+ add_filter('wpgdprc_the_content', 'convert_smilies', 20);
125
+ add_filter('wpgdprc_the_content', 'wpautop');
126
+ add_filter('wpgdprc_the_content', 'shortcode_unautop');
127
+ add_filter('wpgdprc_the_content', 'prepend_attachment');
128
+ add_filter('wpgdprc_the_content', 'wp_make_content_images_responsive');
129
+ }
130
+
131
+ public static function handleDatabaseTables() {
132
+ $dbVersion = get_option('wpgdprc_db_version', 0);
133
+ if (version_compare($dbVersion, '1.1', '==')) {
134
+ return;
135
+ }
136
+
137
+ global $wpdb;
138
+ require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
139
+ $charsetCollate = $wpdb->get_charset_collate();
140
+
141
+ // Create 'Consents' table
142
+ if (version_compare($dbVersion, '1.0', '<')) {
143
+ $query = "CREATE TABLE IF NOT EXISTS `" . Consent::getDatabaseTableName() . "` (
144
+ `ID` bigint(20) NOT NULL AUTO_INCREMENT,
145
+ `site_id` bigint(20) NOT NULL,
146
+ `title` text NOT NULL,
147
+ `description` longtext NOT NULL,
148
+ `snippet` longtext NOT NULL,
149
+ `placement` varchar(20) NOT NULL,
150
+ `plugins` longtext NOT NULL,
151
+ `active` tinyint(1) DEFAULT '1' NOT NULL,
152
+ `date_modified` timestamp DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
153
+ `date_created` datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
154
+ PRIMARY KEY (`ID`)
155
+ ) $charsetCollate;";
156
+ dbDelta($query);
157
+ update_option('wpgdprc_db_version', '1.0');
158
+ }
159
+
160
+ // Add column 'wrap' to 'Consents' table
161
+ if (version_compare($dbVersion, '1.1', '<')) {
162
+ $query = "ALTER TABLE `" . Consent::getDatabaseTableName() . "`
163
+ ADD column `wrap` tinyint(1) DEFAULT '1' NOT NULL AFTER `snippet`;";
164
+ $wpdb->query($query);
165
+ update_option('wpgdprc_db_version', '1.1');
166
+ }
167
  }
168
 
169
  /**
181
  wp_register_script('wpgdprc.micromodal.js', WP_GDPR_C_URI_VENDOR . '/micromodal/micromodal.min.js', array(), filemtime(WP_GDPR_C_DIR_VENDOR . '/micromodal/micromodal.min.js'));
182
  wp_enqueue_style('wpgdprc.css', WP_GDPR_C_URI_CSS . '/front.css', array(), filemtime(WP_GDPR_C_DIR_CSS . '/front.css'));
183
  wp_add_inline_style('wpgdprc.css', "
184
+ div.wpgdprc .wpgdprc-switch .wpgdprc-switch-inner:before { content: '" . __('Yes', WP_GDPR_C_SLUG) . "'; }
185
  div.wpgdprc .wpgdprc-switch .wpgdprc-switch-inner:after { content: '" . __('No', WP_GDPR_C_SLUG) . "'; }
186
  ");
187
  wp_enqueue_script('wpgdprc.js', WP_GDPR_C_URI_JS . '/front.js', array('wpgdprc.micromodal.js'), filemtime(WP_GDPR_C_DIR_JS . '/front.js'), true);
199
  wp_register_style('wpgdprc.admin.codemirror.css', WP_GDPR_C_URI_VENDOR . '/codemirror/codemirror.css', array(), filemtime(WP_GDPR_C_DIR_VENDOR . '/codemirror/codemirror.css'));
200
  wp_enqueue_style('wpgdprc.admin.css', WP_GDPR_C_URI_CSS . '/admin.css', array(), filemtime(WP_GDPR_C_DIR_CSS . '/admin.css'));
201
  wp_add_inline_style('wpgdprc.admin.css', "
202
+ div.wpgdprc .wpgdprc-switch .wpgdprc-switch-inner:before { content: '" . __('Yes', WP_GDPR_C_SLUG) . "'; }
203
  div.wpgdprc .wpgdprc-switch .wpgdprc-switch-inner:after { content: '" . __('No', WP_GDPR_C_SLUG) . "'; }
204
  ");
205
  wp_register_script('wpgdprc.admin.codemirror.js', WP_GDPR_C_URI_VENDOR . '/codemirror/codemirror.js', array(), filemtime(WP_GDPR_C_DIR_VENDOR . '/codemirror/codemirror.js'));
206
+ wp_register_script('wpgdprc.admin.codemirror.additional.js', WP_GDPR_C_URI_VENDOR . '/codemirror/codemirror.additional.js', array('wpgdprc.admin.codemirror.js'), filemtime(WP_GDPR_C_DIR_VENDOR . '/codemirror/codemirror.additional.js'), true);
 
 
207
  wp_enqueue_script('wpgdprc.admin.js', WP_GDPR_C_URI_JS . '/admin.js', array(), filemtime(WP_GDPR_C_DIR_JS . '/admin.js'), true);
208
  wp_localize_script('wpgdprc.admin.js', 'wpgdprcData', array(
209
  'ajaxURL' => admin_url('admin-ajax.php'),