MailChimp for WordPress - Version 3.0.2

Version Description

  • November 25, 2015 =

Fixes

  • Redirect on success not working.
  • Forms overview page redirected to main WP Admin page (edge case).
  • Safari was always showing the leave-page confirmation dialog.

Improvements

  • Add form-specific classes to preview form element. This allows the Styles Builder to work with the Form Preview.
  • Form events are now triggered after the page has finished loading, so all scripts are loaded & ready to use.
  • Reset background-color in Form Themes stylesheets.
Download this release

Release Info

Developer DvanKooten
Plugin Icon 128x128 MailChimp for WordPress
Version 3.0.2
Comparing to
See all releases

Code changes from version 2.3.18 to 3.0.2

Files changed (42) hide show
  1. assets/css/admin-styles.css +699 -0
  2. assets/css/admin-styles.min.css +1 -0
  3. assets/css/admin.css +0 -229
  4. assets/css/admin.min.css +0 -1
  5. assets/css/checkbox-reset.css +22 -0
  6. assets/css/checkbox-reset.min.css +1 -0
  7. assets/css/checkbox.css +0 -38
  8. assets/css/checkbox.css.map +0 -7
  9. assets/css/checkbox.min.css +0 -1
  10. assets/css/codemirror.css +334 -0
  11. assets/css/codemirror.min.css +1 -0
  12. assets/css/form-basic.css +110 -0
  13. assets/css/form-basic.css.map +7 -0
  14. assets/css/form-basic.min.css +1 -0
  15. assets/css/form-editor.css +461 -0
  16. assets/css/form-editor.min.css +1 -0
  17. assets/css/form-theme-blue.css +0 -274
  18. assets/css/form-theme-blue.css.map +0 -7
  19. assets/css/form-theme-blue.min.css +0 -1
  20. assets/css/form-theme-dark.css +0 -274
  21. assets/css/form-theme-dark.css.map +0 -7
  22. assets/css/form-theme-dark.min.css +0 -1
  23. assets/css/form-theme-green.css +0 -274
  24. assets/css/form-theme-green.css.map +0 -7
  25. assets/css/form-theme-green.min.css +0 -1
  26. assets/css/form-theme-light.css +0 -264
  27. assets/css/form-theme-light.css.map +0 -7
  28. assets/css/form-theme-light.min.css +0 -1
  29. assets/css/form-theme-red.css +0 -274
  30. assets/css/form-theme-red.css.map +0 -7
  31. assets/css/form-theme-red.min.css +0 -1
  32. assets/css/form-themes.css +325 -0
  33. assets/css/form-themes.css.map +7 -0
  34. assets/css/form-themes.min.css +1 -0
  35. assets/css/form.css +0 -115
  36. assets/css/form.css.map +0 -7
  37. assets/css/form.min.css +0 -1
  38. assets/js/admin.js +1949 -573
  39. assets/js/admin.min.js +1 -1
  40. assets/js/form-request.js +0 -182
  41. assets/js/form-request.min.js +0 -1
  42. assets/js/forms-admin.js +13487 -0
assets/css/admin-styles.css ADDED
@@ -0,0 +1,699 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* settings pages */
2
+ #mc4wp-admin,
3
+ .mc4wp-admin {
4
+ /* Grid */
5
+ /** Whitespace control */
6
+ /* Tabs */
7
+ /* settings pages */
8
+ /* BASICS */
9
+ /* PADDING */
10
+ /* GUTTER */
11
+ /* CURSOR */
12
+ /* Shown when moving in bi-directional text */
13
+ /* Can style cursor different in overwrite (non-insert) mode */
14
+ /* DEFAULT THEME */
15
+ /* Default styles for common addons */
16
+ /* STOP */
17
+ /* The rest of this file contains styles related to the mechanics of
18
+ the editor. You probably shouldn't touch them. */
19
+ /* The fake, visible scrollbars. Used to force redraw during scrolling
20
+ before actuall scrolling happens, thus preventing shaking and
21
+ flickering artifacts. */
22
+ /* Force content-box sizing for the elements where we expect it */
23
+ /* IE7 hack to prevent it from returning funny offsetTops on the spans */
24
+ /* Used to force a border model for a node */
25
+ /* See issue #2901 */
26
+ /* Help users use markselection to safely style text background */
27
+ /* Codemirror */
28
+ /* Add logo to page title */
29
+ /** Core Customizations */ }
30
+ #mc4wp-admin .row,
31
+ .mc4wp-admin .row {
32
+ margin: 20px -20px; }
33
+ #mc4wp-admin .row:after,
34
+ .mc4wp-admin .row:after {
35
+ content: "";
36
+ clear: both;
37
+ display: table; }
38
+ #mc4wp-admin .row .col,
39
+ .mc4wp-admin .row .col {
40
+ padding: 0 20px;
41
+ float: left;
42
+ -webkit-box-sizing: border-box;
43
+ box-sizing: border-box; }
44
+ #mc4wp-admin .row .col-1,
45
+ .mc4wp-admin .row .col-1 {
46
+ width: 16.666%; }
47
+ #mc4wp-admin .row .col-2,
48
+ .mc4wp-admin .row .col-2 {
49
+ width: 33.333%; }
50
+ #mc4wp-admin .row .col-3,
51
+ .mc4wp-admin .row .col-3 {
52
+ width: 50%; }
53
+ #mc4wp-admin .row .col-4,
54
+ .mc4wp-admin .row .col-4 {
55
+ width: 66.666%; }
56
+ #mc4wp-admin .row .col-5,
57
+ .mc4wp-admin .row .col-5 {
58
+ width: 83.333%; }
59
+ #mc4wp-admin .row .col-6,
60
+ .mc4wp-admin .row .col-6 {
61
+ width: 100%; }
62
+ @media (max-width: 1200px) {
63
+ #mc4wp-admin .row .col,
64
+ .mc4wp-admin .row .col {
65
+ width: 100%;
66
+ float: none;
67
+ margin: 20px 0; } }
68
+ #mc4wp-admin .status,
69
+ .mc4wp-admin .status {
70
+ display: inline-block;
71
+ margin-left: 1em;
72
+ padding: 3px 6px;
73
+ color: white;
74
+ font-size: 12px;
75
+ font-weight: bold; }
76
+ #mc4wp-admin .status.positive,
77
+ .mc4wp-admin .status.positive {
78
+ background-color: limeGreen; }
79
+ #mc4wp-admin .status.negative,
80
+ .mc4wp-admin .status.negative {
81
+ background-color: red; }
82
+ #mc4wp-admin .status.neutral,
83
+ .mc4wp-admin .status.neutral {
84
+ background: gray; }
85
+ #mc4wp-admin .valigntop,
86
+ .mc4wp-admin .valigntop {
87
+ vertical-align: top !important; }
88
+ #mc4wp-admin .medium-margin,
89
+ .mc4wp-admin .medium-margin {
90
+ margin: 40px 0; }
91
+ #mc4wp-admin .small-margin,
92
+ .mc4wp-admin .small-margin {
93
+ margin: 20px 0; }
94
+ #mc4wp-admin .hover-activated,
95
+ .mc4wp-admin .hover-activated {
96
+ opacity: 0.5; }
97
+ #mc4wp-admin .hover-activated:hover,
98
+ .mc4wp-admin .hover-activated:hover {
99
+ cursor: pointer;
100
+ opacity: 1; }
101
+ #mc4wp-admin .help-text,
102
+ .mc4wp-admin .help-text {
103
+ font-size: 14px; }
104
+ #mc4wp-admin .help-text p,
105
+ .mc4wp-admin .help-text p {
106
+ margin: 10px 0;
107
+ font-size: 14px; }
108
+ #mc4wp-admin .help-text ul,
109
+ .mc4wp-admin .help-text ul {
110
+ list-style: square;
111
+ margin-top: 15px;
112
+ padding-left: 40px; }
113
+ #mc4wp-admin .help,
114
+ .mc4wp-admin .help {
115
+ font-style: italic; }
116
+ #mc4wp-admin .muted,
117
+ .mc4wp-admin .muted {
118
+ color: #aaa; }
119
+ #mc4wp-admin .red,
120
+ .mc4wp-admin .red {
121
+ color: red; }
122
+ #mc4wp-admin .green,
123
+ .mc4wp-admin .green {
124
+ color: #32cd32; }
125
+ #mc4wp-admin .mc4wp-notice,
126
+ .mc4wp-admin .mc4wp-notice {
127
+ padding: 6px 12px;
128
+ color: #31708f;
129
+ background: #d9edf7;
130
+ border: 1px solid #bce8f1;
131
+ margin: 1em 0 !important; }
132
+ #mc4wp-admin .column-ID,
133
+ .mc4wp-admin .column-ID {
134
+ width: 10%; }
135
+ #mc4wp-admin .block,
136
+ .mc4wp-admin .block {
137
+ display: block; }
138
+ #mc4wp-admin .code-sample,
139
+ .mc4wp-admin .code-sample {
140
+ font-family: Consolas, Monaco, Lucida Console, monospace;
141
+ font-size: 12px;
142
+ background: white; }
143
+ #mc4wp-admin .breadcrumbs,
144
+ .mc4wp-admin .breadcrumbs {
145
+ border-bottom: 1px solid #ccc;
146
+ padding-bottom: 1em; }
147
+ #mc4wp-admin .tab,
148
+ .mc4wp-admin .tab {
149
+ display: none; }
150
+ #mc4wp-admin .tab.tab-active,
151
+ .mc4wp-admin .tab.tab-active {
152
+ display: block; }
153
+ #mc4wp-admin .tab h2,
154
+ .mc4wp-admin .tab h2 {
155
+ margin-top: 20px; }
156
+ #mc4wp-admin .CodeMirror,
157
+ .mc4wp-admin .CodeMirror {
158
+ /* Set height, width, borders, and global font properties here */
159
+ font-family: monospace;
160
+ height: 300px;
161
+ color: black; }
162
+ #mc4wp-admin .CodeMirror-lines,
163
+ .mc4wp-admin .CodeMirror-lines {
164
+ padding: 4px 0;
165
+ /* Vertical padding around content */ }
166
+ #mc4wp-admin .CodeMirror pre,
167
+ .mc4wp-admin .CodeMirror pre {
168
+ padding: 0 4px;
169
+ /* Horizontal padding of content */ }
170
+ #mc4wp-admin .CodeMirror-scrollbar-filler, #mc4wp-admin .CodeMirror-gutter-filler,
171
+ .mc4wp-admin .CodeMirror-scrollbar-filler,
172
+ .mc4wp-admin .CodeMirror-gutter-filler {
173
+ background-color: white;
174
+ /* The little square between H and V scrollbars */ }
175
+ #mc4wp-admin .CodeMirror-gutters,
176
+ .mc4wp-admin .CodeMirror-gutters {
177
+ border-right: 1px solid #ddd;
178
+ background-color: #f7f7f7;
179
+ white-space: nowrap; }
180
+ #mc4wp-admin .CodeMirror-linenumber,
181
+ .mc4wp-admin .CodeMirror-linenumber {
182
+ padding: 0 3px 0 5px;
183
+ min-width: 20px;
184
+ text-align: right;
185
+ color: #999;
186
+ white-space: nowrap; }
187
+ #mc4wp-admin .CodeMirror-guttermarker,
188
+ .mc4wp-admin .CodeMirror-guttermarker {
189
+ color: black; }
190
+ #mc4wp-admin .CodeMirror-guttermarker-subtle,
191
+ .mc4wp-admin .CodeMirror-guttermarker-subtle {
192
+ color: #999; }
193
+ #mc4wp-admin .CodeMirror-cursor,
194
+ .mc4wp-admin .CodeMirror-cursor {
195
+ border-left: 1px solid black;
196
+ border-right: none;
197
+ width: 0; }
198
+ #mc4wp-admin .CodeMirror div.CodeMirror-secondarycursor,
199
+ .mc4wp-admin .CodeMirror div.CodeMirror-secondarycursor {
200
+ border-left: 1px solid silver; }
201
+ #mc4wp-admin .cm-fat-cursor .CodeMirror-cursor,
202
+ .mc4wp-admin .cm-fat-cursor .CodeMirror-cursor {
203
+ width: auto;
204
+ border: 0;
205
+ background: #7e7; }
206
+ #mc4wp-admin .cm-fat-cursor div.CodeMirror-cursors,
207
+ .mc4wp-admin .cm-fat-cursor div.CodeMirror-cursors {
208
+ z-index: 1; }
209
+ #mc4wp-admin .cm-animate-fat-cursor,
210
+ .mc4wp-admin .cm-animate-fat-cursor {
211
+ width: auto;
212
+ border: 0;
213
+ -webkit-animation: blink 1.06s steps(1) infinite;
214
+ -moz-animation: blink 1.06s steps(1) infinite;
215
+ animation: blink 1.06s steps(1) infinite;
216
+ background-color: #7e7; }
217
+
218
+ @-moz-keyframes blink {
219
+ 0% { }
220
+ 50% {
221
+ background-color: transparent; }
222
+ 100% { } }
223
+
224
+ @-webkit-keyframes blink {
225
+ 0% { }
226
+ 50% {
227
+ background-color: transparent; }
228
+ 100% { } }
229
+
230
+ @keyframes blink {
231
+ 0% { }
232
+ 50% {
233
+ background-color: transparent; }
234
+ 100% { } }
235
+ #mc4wp-admin .cm-tab,
236
+ .mc4wp-admin .cm-tab {
237
+ display: inline-block;
238
+ text-decoration: inherit; }
239
+ #mc4wp-admin .CodeMirror-ruler,
240
+ .mc4wp-admin .CodeMirror-ruler {
241
+ border-left: 1px solid #ccc;
242
+ position: absolute; }
243
+ #mc4wp-admin .cm-s-default .cm-header,
244
+ .mc4wp-admin .cm-s-default .cm-header {
245
+ color: blue; }
246
+ #mc4wp-admin .cm-s-default .cm-quote,
247
+ .mc4wp-admin .cm-s-default .cm-quote {
248
+ color: #090; }
249
+ #mc4wp-admin .cm-negative,
250
+ .mc4wp-admin .cm-negative {
251
+ color: #d44; }
252
+ #mc4wp-admin .cm-positive,
253
+ .mc4wp-admin .cm-positive {
254
+ color: #292; }
255
+ #mc4wp-admin .cm-header, #mc4wp-admin .cm-strong,
256
+ .mc4wp-admin .cm-header,
257
+ .mc4wp-admin .cm-strong {
258
+ font-weight: bold; }
259
+ #mc4wp-admin .cm-em,
260
+ .mc4wp-admin .cm-em {
261
+ font-style: italic; }
262
+ #mc4wp-admin .cm-link,
263
+ .mc4wp-admin .cm-link {
264
+ text-decoration: underline; }
265
+ #mc4wp-admin .cm-strikethrough,
266
+ .mc4wp-admin .cm-strikethrough {
267
+ text-decoration: line-through; }
268
+ #mc4wp-admin .cm-s-default .cm-keyword,
269
+ .mc4wp-admin .cm-s-default .cm-keyword {
270
+ color: #708; }
271
+ #mc4wp-admin .cm-s-default .cm-atom,
272
+ .mc4wp-admin .cm-s-default .cm-atom {
273
+ color: #219; }
274
+ #mc4wp-admin .cm-s-default .cm-number,
275
+ .mc4wp-admin .cm-s-default .cm-number {
276
+ color: #164; }
277
+ #mc4wp-admin .cm-s-default .cm-def,
278
+ .mc4wp-admin .cm-s-default .cm-def {
279
+ color: #00f; }
280
+ #mc4wp-admin .cm-s-default .cm-variable-2,
281
+ .mc4wp-admin .cm-s-default .cm-variable-2 {
282
+ color: #05a; }
283
+ #mc4wp-admin .cm-s-default .cm-variable-3,
284
+ .mc4wp-admin .cm-s-default .cm-variable-3 {
285
+ color: #085; }
286
+ #mc4wp-admin .cm-s-default .cm-comment,
287
+ .mc4wp-admin .cm-s-default .cm-comment {
288
+ color: #a50; }
289
+ #mc4wp-admin .cm-s-default .cm-string,
290
+ .mc4wp-admin .cm-s-default .cm-string {
291
+ color: #a11; }
292
+ #mc4wp-admin .cm-s-default .cm-string-2,
293
+ .mc4wp-admin .cm-s-default .cm-string-2 {
294
+ color: #f50; }
295
+ #mc4wp-admin .cm-s-default .cm-meta,
296
+ .mc4wp-admin .cm-s-default .cm-meta {
297
+ color: #555; }
298
+ #mc4wp-admin .cm-s-default .cm-qualifier,
299
+ .mc4wp-admin .cm-s-default .cm-qualifier {
300
+ color: #555; }
301
+ #mc4wp-admin .cm-s-default .cm-builtin,
302
+ .mc4wp-admin .cm-s-default .cm-builtin {
303
+ color: #30a; }
304
+ #mc4wp-admin .cm-s-default .cm-bracket,
305
+ .mc4wp-admin .cm-s-default .cm-bracket {
306
+ color: #997; }
307
+ #mc4wp-admin .cm-s-default .cm-tag,
308
+ .mc4wp-admin .cm-s-default .cm-tag {
309
+ color: #170; }
310
+ #mc4wp-admin .cm-s-default .cm-attribute,
311
+ .mc4wp-admin .cm-s-default .cm-attribute {
312
+ color: #00c; }
313
+ #mc4wp-admin .cm-s-default .cm-hr,
314
+ .mc4wp-admin .cm-s-default .cm-hr {
315
+ color: #999; }
316
+ #mc4wp-admin .cm-s-default .cm-link,
317
+ .mc4wp-admin .cm-s-default .cm-link {
318
+ color: #00c; }
319
+ #mc4wp-admin .cm-s-default .cm-error,
320
+ .mc4wp-admin .cm-s-default .cm-error {
321
+ color: #f00; }
322
+ #mc4wp-admin .cm-invalidchar,
323
+ .mc4wp-admin .cm-invalidchar {
324
+ color: #f00; }
325
+ #mc4wp-admin .CodeMirror-composing,
326
+ .mc4wp-admin .CodeMirror-composing {
327
+ border-bottom: 2px solid; }
328
+ #mc4wp-admin div.CodeMirror span.CodeMirror-matchingbracket,
329
+ .mc4wp-admin div.CodeMirror span.CodeMirror-matchingbracket {
330
+ color: #0f0; }
331
+ #mc4wp-admin div.CodeMirror span.CodeMirror-nonmatchingbracket,
332
+ .mc4wp-admin div.CodeMirror span.CodeMirror-nonmatchingbracket {
333
+ color: #f22; }
334
+ #mc4wp-admin .CodeMirror-matchingtag,
335
+ .mc4wp-admin .CodeMirror-matchingtag {
336
+ background: rgba(255, 150, 0, 0.3); }
337
+ #mc4wp-admin .CodeMirror-activeline-background,
338
+ .mc4wp-admin .CodeMirror-activeline-background {
339
+ background: #e8f2ff; }
340
+ #mc4wp-admin .CodeMirror,
341
+ .mc4wp-admin .CodeMirror {
342
+ position: relative;
343
+ overflow: hidden;
344
+ background: white; }
345
+ #mc4wp-admin .CodeMirror-scroll,
346
+ .mc4wp-admin .CodeMirror-scroll {
347
+ overflow: scroll !important;
348
+ /* Things will break if this is overridden */
349
+ /* 30px is the magic margin used to hide the element's real scrollbars */
350
+ /* See overflow: hidden in .CodeMirror */
351
+ margin-bottom: -30px;
352
+ margin-right: -30px;
353
+ padding-bottom: 30px;
354
+ height: 100%;
355
+ outline: none;
356
+ /* Prevent dragging from highlighting the element */
357
+ position: relative; }
358
+ #mc4wp-admin .CodeMirror-sizer,
359
+ .mc4wp-admin .CodeMirror-sizer {
360
+ position: relative;
361
+ border-right: 30px solid transparent; }
362
+ #mc4wp-admin .CodeMirror-vscrollbar, #mc4wp-admin .CodeMirror-hscrollbar, #mc4wp-admin .CodeMirror-scrollbar-filler, #mc4wp-admin .CodeMirror-gutter-filler,
363
+ .mc4wp-admin .CodeMirror-vscrollbar,
364
+ .mc4wp-admin .CodeMirror-hscrollbar,
365
+ .mc4wp-admin .CodeMirror-scrollbar-filler,
366
+ .mc4wp-admin .CodeMirror-gutter-filler {
367
+ position: absolute;
368
+ z-index: 6;
369
+ display: none; }
370
+ #mc4wp-admin .CodeMirror-vscrollbar,
371
+ .mc4wp-admin .CodeMirror-vscrollbar {
372
+ right: 0;
373
+ top: 0;
374
+ overflow-x: hidden;
375
+ overflow-y: scroll; }
376
+ #mc4wp-admin .CodeMirror-hscrollbar,
377
+ .mc4wp-admin .CodeMirror-hscrollbar {
378
+ bottom: 0;
379
+ left: 0;
380
+ overflow-y: hidden;
381
+ overflow-x: scroll; }
382
+ #mc4wp-admin .CodeMirror-scrollbar-filler,
383
+ .mc4wp-admin .CodeMirror-scrollbar-filler {
384
+ right: 0;
385
+ bottom: 0; }
386
+ #mc4wp-admin .CodeMirror-gutter-filler,
387
+ .mc4wp-admin .CodeMirror-gutter-filler {
388
+ left: 0;
389
+ bottom: 0; }
390
+ #mc4wp-admin .CodeMirror-gutters,
391
+ .mc4wp-admin .CodeMirror-gutters {
392
+ position: absolute;
393
+ left: 0;
394
+ top: 0;
395
+ z-index: 3; }
396
+ #mc4wp-admin .CodeMirror-gutter,
397
+ .mc4wp-admin .CodeMirror-gutter {
398
+ white-space: normal;
399
+ height: 100%;
400
+ display: inline-block;
401
+ margin-bottom: -30px;
402
+ /* Hack to make IE7 behave */
403
+ *zoom: 1;
404
+ *display: inline; }
405
+ #mc4wp-admin .CodeMirror-gutter-wrapper,
406
+ .mc4wp-admin .CodeMirror-gutter-wrapper {
407
+ position: absolute;
408
+ z-index: 4;
409
+ background: none !important;
410
+ border: none !important; }
411
+ #mc4wp-admin .CodeMirror-gutter-background,
412
+ .mc4wp-admin .CodeMirror-gutter-background {
413
+ position: absolute;
414
+ top: 0;
415
+ bottom: 0;
416
+ z-index: 4; }
417
+ #mc4wp-admin .CodeMirror-gutter-elt,
418
+ .mc4wp-admin .CodeMirror-gutter-elt {
419
+ position: absolute;
420
+ cursor: default;
421
+ z-index: 4; }
422
+ #mc4wp-admin .CodeMirror-gutter-wrapper,
423
+ .mc4wp-admin .CodeMirror-gutter-wrapper {
424
+ -webkit-user-select: none;
425
+ -moz-user-select: none;
426
+ user-select: none; }
427
+ #mc4wp-admin .CodeMirror-lines,
428
+ .mc4wp-admin .CodeMirror-lines {
429
+ cursor: text;
430
+ min-height: 1px;
431
+ /* prevents collapsing before first draw */ }
432
+ #mc4wp-admin .CodeMirror pre,
433
+ .mc4wp-admin .CodeMirror pre {
434
+ /* Reset some styles that the rest of the page might have set */
435
+ -moz-border-radius: 0;
436
+ -webkit-border-radius: 0;
437
+ border-radius: 0;
438
+ border-width: 0;
439
+ background: transparent;
440
+ font-family: inherit;
441
+ font-size: inherit;
442
+ margin: 0;
443
+ white-space: pre;
444
+ word-wrap: normal;
445
+ line-height: inherit;
446
+ color: inherit;
447
+ z-index: 2;
448
+ position: relative;
449
+ overflow: visible;
450
+ -webkit-tap-highlight-color: transparent; }
451
+ #mc4wp-admin .CodeMirror-wrap pre,
452
+ .mc4wp-admin .CodeMirror-wrap pre {
453
+ word-wrap: break-word;
454
+ white-space: pre-wrap;
455
+ word-break: normal; }
456
+ #mc4wp-admin .CodeMirror-linebackground,
457
+ .mc4wp-admin .CodeMirror-linebackground {
458
+ position: absolute;
459
+ left: 0;
460
+ right: 0;
461
+ top: 0;
462
+ bottom: 0;
463
+ z-index: 0; }
464
+ #mc4wp-admin .CodeMirror-linewidget,
465
+ .mc4wp-admin .CodeMirror-linewidget {
466
+ position: relative;
467
+ z-index: 2;
468
+ overflow: auto; }
469
+ #mc4wp-admin .CodeMirror-code,
470
+ .mc4wp-admin .CodeMirror-code {
471
+ outline: none; }
472
+ #mc4wp-admin .CodeMirror-scroll,
473
+ #mc4wp-admin .CodeMirror-sizer,
474
+ #mc4wp-admin .CodeMirror-gutter,
475
+ #mc4wp-admin .CodeMirror-gutters,
476
+ #mc4wp-admin .CodeMirror-linenumber,
477
+ .mc4wp-admin .CodeMirror-scroll,
478
+ .mc4wp-admin .CodeMirror-sizer,
479
+ .mc4wp-admin .CodeMirror-gutter,
480
+ .mc4wp-admin .CodeMirror-gutters,
481
+ .mc4wp-admin .CodeMirror-linenumber {
482
+ -moz-box-sizing: content-box;
483
+ box-sizing: content-box; }
484
+ #mc4wp-admin .CodeMirror-measure,
485
+ .mc4wp-admin .CodeMirror-measure {
486
+ position: absolute;
487
+ width: 100%;
488
+ height: 0;
489
+ overflow: hidden;
490
+ visibility: hidden; }
491
+ #mc4wp-admin .CodeMirror-cursor,
492
+ .mc4wp-admin .CodeMirror-cursor {
493
+ position: absolute; }
494
+ #mc4wp-admin .CodeMirror-measure pre,
495
+ .mc4wp-admin .CodeMirror-measure pre {
496
+ position: static; }
497
+ #mc4wp-admin div.CodeMirror-cursors,
498
+ .mc4wp-admin div.CodeMirror-cursors {
499
+ visibility: hidden;
500
+ position: relative;
501
+ z-index: 3; }
502
+ #mc4wp-admin div.CodeMirror-dragcursors,
503
+ .mc4wp-admin div.CodeMirror-dragcursors {
504
+ visibility: visible; }
505
+ #mc4wp-admin .CodeMirror-focused div.CodeMirror-cursors,
506
+ .mc4wp-admin .CodeMirror-focused div.CodeMirror-cursors {
507
+ visibility: visible; }
508
+ #mc4wp-admin .CodeMirror-selected,
509
+ .mc4wp-admin .CodeMirror-selected {
510
+ background: #d9d9d9; }
511
+ #mc4wp-admin .CodeMirror-focused .CodeMirror-selected,
512
+ .mc4wp-admin .CodeMirror-focused .CodeMirror-selected {
513
+ background: #d7d4f0; }
514
+ #mc4wp-admin .CodeMirror-crosshair,
515
+ .mc4wp-admin .CodeMirror-crosshair {
516
+ cursor: crosshair; }
517
+ #mc4wp-admin .CodeMirror-line::selection, #mc4wp-admin .CodeMirror-line > span::selection, #mc4wp-admin .CodeMirror-line > span > span::selection,
518
+ .mc4wp-admin .CodeMirror-line::selection,
519
+ .mc4wp-admin .CodeMirror-line > span::selection,
520
+ .mc4wp-admin .CodeMirror-line > span > span::selection {
521
+ background: #d7d4f0; }
522
+ #mc4wp-admin .CodeMirror-line::-moz-selection, #mc4wp-admin .CodeMirror-line > span::-moz-selection, #mc4wp-admin .CodeMirror-line > span > span::-moz-selection,
523
+ .mc4wp-admin .CodeMirror-line::-moz-selection,
524
+ .mc4wp-admin .CodeMirror-line > span::-moz-selection,
525
+ .mc4wp-admin .CodeMirror-line > span > span::-moz-selection {
526
+ background: #d7d4f0; }
527
+ #mc4wp-admin .cm-searching,
528
+ .mc4wp-admin .cm-searching {
529
+ background: #ffa;
530
+ background: rgba(255, 255, 0, 0.4); }
531
+ #mc4wp-admin .CodeMirror span,
532
+ .mc4wp-admin .CodeMirror span {
533
+ *vertical-align: text-bottom; }
534
+ #mc4wp-admin .cm-force-border,
535
+ .mc4wp-admin .cm-force-border {
536
+ padding-right: .1px; }
537
+ @media print {
538
+ #mc4wp-admin,
539
+ .mc4wp-admin {
540
+ /* Hide the cursor when printing */ }
541
+ #mc4wp-admin .CodeMirror div.CodeMirror-cursors,
542
+ .mc4wp-admin .CodeMirror div.CodeMirror-cursors {
543
+ visibility: hidden; } }
544
+ #mc4wp-admin .cm-tab-wrap-hack:after,
545
+ .mc4wp-admin .cm-tab-wrap-hack:after {
546
+ content: ''; }
547
+ #mc4wp-admin span.CodeMirror-selectedtext,
548
+ .mc4wp-admin span.CodeMirror-selectedtext {
549
+ background: none; }
550
+ #mc4wp-admin .CodeMirror,
551
+ .mc4wp-admin .CodeMirror {
552
+ border: 1px solid #ccc;
553
+ padding: 10px;
554
+ min-height: 500px; }
555
+ #mc4wp-admin .CodeMirror-empty,
556
+ .mc4wp-admin .CodeMirror-empty {
557
+ color: #999; }
558
+ #mc4wp-admin .field-wizard,
559
+ .mc4wp-admin .field-wizard {
560
+ /* table */
561
+ /* checkboxes in label */ }
562
+ #mc4wp-admin .field-wizard h3,
563
+ .mc4wp-admin .field-wizard h3 {
564
+ margin-top: 0; }
565
+ #mc4wp-admin .field-wizard code,
566
+ .mc4wp-admin .field-wizard code {
567
+ margin-left: 10px; }
568
+ #mc4wp-admin .field-wizard > div,
569
+ .mc4wp-admin .field-wizard > div {
570
+ margin: 20px 0; }
571
+ #mc4wp-admin .field-wizard label,
572
+ .mc4wp-admin .field-wizard label {
573
+ font-weight: 600;
574
+ display: block;
575
+ margin-bottom: 4px; }
576
+ #mc4wp-admin .field-wizard input,
577
+ .mc4wp-admin .field-wizard input {
578
+ margin-bottom: 6px; }
579
+ #mc4wp-admin .field-wizard table,
580
+ .mc4wp-admin .field-wizard table {
581
+ table-layout: fixed;
582
+ border-collapse: collapse;
583
+ border-spacing: 0; }
584
+ #mc4wp-admin .field-wizard tr, #mc4wp-admin .field-wizard td,
585
+ .mc4wp-admin .field-wizard tr,
586
+ .mc4wp-admin .field-wizard td {
587
+ vertical-align: middle; }
588
+ #mc4wp-admin .field-wizard td.stretch,
589
+ .mc4wp-admin .field-wizard td.stretch {
590
+ width: 100%; }
591
+ #mc4wp-admin .field-wizard .cb-wrap,
592
+ .mc4wp-admin .field-wizard .cb-wrap {
593
+ font-weight: normal; }
594
+ #mc4wp-admin .field-wizard .cb-wrap input,
595
+ .mc4wp-admin .field-wizard .cb-wrap input {
596
+ margin-right: 6px; }
597
+ #mc4wp-admin .field-wizard .limit-height,
598
+ .mc4wp-admin .field-wizard .limit-height {
599
+ border: 1px solid #eee;
600
+ padding: 6px;
601
+ max-height: 200px;
602
+ overflow-y: scroll; }
603
+ #mc4wp-admin .field-wizard .dashicons,
604
+ .mc4wp-admin .field-wizard .dashicons {
605
+ vertical-align: middle; }
606
+ #mc4wp-admin .available-fields,
607
+ .mc4wp-admin .available-fields {
608
+ border: 1px solid #ccc;
609
+ padding: 20px;
610
+ background: white; }
611
+ #mc4wp-admin .available-fields strong,
612
+ .mc4wp-admin .available-fields strong {
613
+ display: block;
614
+ margin-bottom: 10px; }
615
+ #mc4wp-admin .available-fields button,
616
+ .mc4wp-admin .available-fields button {
617
+ margin: 0 6px 6px 0; }
618
+ #mc4wp-admin .available-fields .is-required:after,
619
+ .mc4wp-admin .available-fields .is-required:after {
620
+ content: " *";
621
+ color: red; }
622
+ #mc4wp-admin .available-fields .is-required.not-in-form,
623
+ .mc4wp-admin .available-fields .is-required.not-in-form {
624
+ -webkit-box-shadow: 0 0 3px 1px red;
625
+ -moz-box-shadow: 0 0 3px 1px red;
626
+ box-shadow: 0 0 3px 1px red; }
627
+ #mc4wp-admin .available-fields .in-form,
628
+ .mc4wp-admin .available-fields .in-form {
629
+ opacity: 0.5; }
630
+ #mc4wp-admin .page-title,
631
+ .mc4wp-admin .page-title {
632
+ background: url("../img/icon-large.png") no-repeat left center;
633
+ padding-left: 42px;
634
+ line-height: 32px;
635
+ margin-bottom: 20px; }
636
+ #mc4wp-admin .page-title-action .dashicons,
637
+ #mc4wp-admin .button .dashicons,
638
+ #mc4wp-admin .button-secondary .dashicons,
639
+ .mc4wp-admin .page-title-action .dashicons,
640
+ .mc4wp-admin .button .dashicons,
641
+ .mc4wp-admin .button-secondary .dashicons {
642
+ vertical-align: middle;
643
+ line-height: 16px;
644
+ margin: 0 4px 0 0; }
645
+ #mc4wp-admin .form-table td p,
646
+ .mc4wp-admin .form-table td p {
647
+ margin-top: 1em; }
648
+ #mc4wp-admin .sidebar,
649
+ .mc4wp-admin .sidebar {
650
+ border-left: 1px solid #ccc; }
651
+ #mc4wp-admin .sidebar h3,
652
+ #mc4wp-admin .sidebar h4,
653
+ .mc4wp-admin .sidebar h3,
654
+ .mc4wp-admin .sidebar h4 {
655
+ font-size: 16px;
656
+ margin-bottom: 0; }
657
+ #mc4wp-admin .sidebar > div,
658
+ .mc4wp-admin .sidebar > div {
659
+ border-bottom: 1px solid #ccc;
660
+ margin-bottom: 20px;
661
+ padding-bottom: 20px; }
662
+ #mc4wp-admin .sidebar > div:last-of-type,
663
+ .mc4wp-admin .sidebar > div:last-of-type {
664
+ border-bottom: 0; }
665
+
666
+ .overlay {
667
+ position: fixed;
668
+ left: 0;
669
+ top: 0;
670
+ z-index: 99999;
671
+ padding: 20px;
672
+ width: 100%;
673
+ max-width: 480px;
674
+ max-height: 100%;
675
+ background: #fefefe;
676
+ border: 1px solid #ccc;
677
+ overflow-y: scroll;
678
+ -webkit-box-sizing: border-box;
679
+ -moz-box-sizing: border-box;
680
+ box-sizing: border-box; }
681
+ .overlay .close {
682
+ position: absolute;
683
+ padding: 10px;
684
+ right: 0;
685
+ top: 0;
686
+ font-size: 24px;
687
+ cursor: pointer;
688
+ opacity: 0.5; }
689
+ .overlay .close:hover {
690
+ opacity: 1; }
691
+
692
+ .overlay-background {
693
+ z-index: 99998;
694
+ background: rgba(0, 0, 0, 0.67);
695
+ position: fixed;
696
+ left: 0;
697
+ right: 0;
698
+ bottom: 0;
699
+ top: 0; }
assets/css/admin-styles.min.css ADDED
@@ -0,0 +1 @@
 
1
+ #mc4wp-admin .cm-em,#mc4wp-admin .help,.mc4wp-admin .cm-em,.mc4wp-admin .help{font-style:italic}#mc4wp-admin .row,.mc4wp-admin .row{margin:20px -20px}#mc4wp-admin .row:after,.mc4wp-admin .row:after{content:"";clear:both;display:table}#mc4wp-admin .row .col,.mc4wp-admin .row .col{padding:0 20px;float:left;-webkit-box-sizing:border-box;box-sizing:border-box}#mc4wp-admin .row .col-1,.mc4wp-admin .row .col-1{width:16.666%}#mc4wp-admin .row .col-2,.mc4wp-admin .row .col-2{width:33.333%}#mc4wp-admin .row .col-3,.mc4wp-admin .row .col-3{width:50%}#mc4wp-admin .row .col-4,.mc4wp-admin .row .col-4{width:66.666%}#mc4wp-admin .row .col-5,.mc4wp-admin .row .col-5{width:83.333%}#mc4wp-admin .field-wizard td.stretch,#mc4wp-admin .row .col-6,.mc4wp-admin .field-wizard td.stretch,.mc4wp-admin .row .col-6,.overlay{width:100%}@media (max-width:1200px){#mc4wp-admin .row .col,.mc4wp-admin .row .col{width:100%;float:none;margin:20px 0}}#mc4wp-admin .status,.mc4wp-admin .status{display:inline-block;margin-left:1em;padding:3px 6px;color:#fff;font-size:12px;font-weight:700}#mc4wp-admin .status.positive,.mc4wp-admin .status.positive{background-color:#32cd32}#mc4wp-admin .status.negative,.mc4wp-admin .status.negative{background-color:red}#mc4wp-admin .status.neutral,.mc4wp-admin .status.neutral{background:gray}#mc4wp-admin .valigntop,.mc4wp-admin .valigntop{vertical-align:top!important}#mc4wp-admin .field-wizard .dashicons,#mc4wp-admin .field-wizard td,#mc4wp-admin .field-wizard tr,.mc4wp-admin .field-wizard .dashicons,.mc4wp-admin .field-wizard td,.mc4wp-admin .field-wizard tr{vertical-align:middle}#mc4wp-admin .medium-margin,.mc4wp-admin .medium-margin{margin:40px 0}#mc4wp-admin .small-margin,.mc4wp-admin .small-margin{margin:20px 0}#mc4wp-admin .hover-activated,.mc4wp-admin .hover-activated{opacity:.5}#mc4wp-admin .hover-activated:hover,.mc4wp-admin .hover-activated:hover{cursor:pointer;opacity:1}#mc4wp-admin .help-text,.mc4wp-admin .help-text{font-size:14px}#mc4wp-admin .help-text p,.mc4wp-admin .help-text p{margin:10px 0;font-size:14px}#mc4wp-admin .help-text ul,.mc4wp-admin .help-text ul{list-style:square;margin-top:15px;padding-left:40px}#mc4wp-admin .muted,.mc4wp-admin .muted{color:#aaa}#mc4wp-admin .red,.mc4wp-admin .red{color:red}#mc4wp-admin .green,.mc4wp-admin .green{color:#32cd32}#mc4wp-admin .mc4wp-notice,.mc4wp-admin .mc4wp-notice{padding:6px 12px;color:#31708f;background:#d9edf7;border:1px solid #bce8f1;margin:1em 0!important}#mc4wp-admin .column-ID,.mc4wp-admin .column-ID{width:10%}#mc4wp-admin .block,.mc4wp-admin .block{display:block}#mc4wp-admin .code-sample,.mc4wp-admin .code-sample{font-family:Consolas,Monaco,Lucida Console,monospace;font-size:12px;background:#fff}#mc4wp-admin .breadcrumbs,.mc4wp-admin .breadcrumbs{border-bottom:1px solid #ccc;padding-bottom:1em}#mc4wp-admin .tab,.mc4wp-admin .tab{display:none}#mc4wp-admin .tab.tab-active,.mc4wp-admin .tab.tab-active{display:block}#mc4wp-admin .tab h2,.mc4wp-admin .tab h2{margin-top:20px}#mc4wp-admin .CodeMirror,.mc4wp-admin .CodeMirror{font-family:monospace;height:300px;color:#000}#mc4wp-admin .CodeMirror-lines,.mc4wp-admin .CodeMirror-lines{padding:4px 0}#mc4wp-admin .CodeMirror pre,.mc4wp-admin .CodeMirror pre{padding:0 4px}#mc4wp-admin .CodeMirror-gutter-filler,#mc4wp-admin .CodeMirror-scrollbar-filler,.mc4wp-admin .CodeMirror-gutter-filler,.mc4wp-admin .CodeMirror-scrollbar-filler{background-color:#fff}#mc4wp-admin .CodeMirror-gutters,.mc4wp-admin .CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}#mc4wp-admin .CodeMirror-linenumber,.mc4wp-admin .CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}#mc4wp-admin .CodeMirror-guttermarker,.mc4wp-admin .CodeMirror-guttermarker{color:#000}#mc4wp-admin .CodeMirror-guttermarker-subtle,.mc4wp-admin .CodeMirror-guttermarker-subtle{color:#999}#mc4wp-admin .CodeMirror-cursor,.mc4wp-admin .CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}#mc4wp-admin .CodeMirror div.CodeMirror-secondarycursor,.mc4wp-admin .CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}#mc4wp-admin .cm-fat-cursor .CodeMirror-cursor,.mc4wp-admin .cm-fat-cursor .CodeMirror-cursor{width:auto;border:0;background:#7e7}#mc4wp-admin .cm-fat-cursor div.CodeMirror-cursors,.mc4wp-admin .cm-fat-cursor div.CodeMirror-cursors{z-index:1}#mc4wp-admin .cm-animate-fat-cursor,.mc4wp-admin .cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}#mc4wp-admin .cm-tab,.mc4wp-admin .cm-tab{display:inline-block;text-decoration:inherit}#mc4wp-admin .CodeMirror-ruler,.mc4wp-admin .CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}#mc4wp-admin .cm-s-default .cm-header,.mc4wp-admin .cm-s-default .cm-header{color:#00f}#mc4wp-admin .cm-s-default .cm-quote,.mc4wp-admin .cm-s-default .cm-quote{color:#090}#mc4wp-admin .cm-negative,.mc4wp-admin .cm-negative{color:#d44}#mc4wp-admin .cm-positive,.mc4wp-admin .cm-positive{color:#292}#mc4wp-admin .cm-header,#mc4wp-admin .cm-strong,.mc4wp-admin .cm-header,.mc4wp-admin .cm-strong{font-weight:700}#mc4wp-admin .cm-link,.mc4wp-admin .cm-link{text-decoration:underline}#mc4wp-admin .cm-strikethrough,.mc4wp-admin .cm-strikethrough{text-decoration:line-through}#mc4wp-admin .cm-s-default .cm-keyword,.mc4wp-admin .cm-s-default .cm-keyword{color:#708}#mc4wp-admin .cm-s-default .cm-atom,.mc4wp-admin .cm-s-default .cm-atom{color:#219}#mc4wp-admin .cm-s-default .cm-number,.mc4wp-admin .cm-s-default .cm-number{color:#164}#mc4wp-admin .cm-s-default .cm-def,.mc4wp-admin .cm-s-default .cm-def{color:#00f}#mc4wp-admin .cm-s-default .cm-variable-2,.mc4wp-admin .cm-s-default .cm-variable-2{color:#05a}#mc4wp-admin .cm-s-default .cm-variable-3,.mc4wp-admin .cm-s-default .cm-variable-3{color:#085}#mc4wp-admin .cm-s-default .cm-comment,.mc4wp-admin .cm-s-default .cm-comment{color:#a50}#mc4wp-admin .cm-s-default .cm-string,.mc4wp-admin .cm-s-default .cm-string{color:#a11}#mc4wp-admin .cm-s-default .cm-string-2,.mc4wp-admin .cm-s-default .cm-string-2{color:#f50}#mc4wp-admin .cm-s-default .cm-meta,#mc4wp-admin .cm-s-default .cm-qualifier,.mc4wp-admin .cm-s-default .cm-meta,.mc4wp-admin .cm-s-default .cm-qualifier{color:#555}#mc4wp-admin .cm-s-default .cm-builtin,.mc4wp-admin .cm-s-default .cm-builtin{color:#30a}#mc4wp-admin .cm-s-default .cm-bracket,.mc4wp-admin .cm-s-default .cm-bracket{color:#997}#mc4wp-admin .cm-s-default .cm-tag,.mc4wp-admin .cm-s-default .cm-tag{color:#170}#mc4wp-admin .cm-s-default .cm-attribute,.mc4wp-admin .cm-s-default .cm-attribute{color:#00c}#mc4wp-admin .cm-s-default .cm-hr,.mc4wp-admin .cm-s-default .cm-hr{color:#999}#mc4wp-admin .cm-s-default .cm-link,.mc4wp-admin .cm-s-default .cm-link{color:#00c}#mc4wp-admin .cm-invalidchar,#mc4wp-admin .cm-s-default .cm-error,.mc4wp-admin .cm-invalidchar,.mc4wp-admin .cm-s-default .cm-error{color:red}#mc4wp-admin .CodeMirror-composing,.mc4wp-admin .CodeMirror-composing{border-bottom:2px solid}#mc4wp-admin div.CodeMirror span.CodeMirror-matchingbracket,.mc4wp-admin div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}#mc4wp-admin div.CodeMirror span.CodeMirror-nonmatchingbracket,.mc4wp-admin div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}#mc4wp-admin .CodeMirror-matchingtag,.mc4wp-admin .CodeMirror-matchingtag{background:rgba(255,150,0,.3)}#mc4wp-admin .CodeMirror-activeline-background,.mc4wp-admin .CodeMirror-activeline-background{background:#e8f2ff}#mc4wp-admin .CodeMirror,.mc4wp-admin .CodeMirror{position:relative;overflow:hidden;background:#fff}#mc4wp-admin .CodeMirror-scroll,.mc4wp-admin .CodeMirror-scroll{overflow:scroll!important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:0;position:relative}#mc4wp-admin .CodeMirror-sizer,.mc4wp-admin .CodeMirror-sizer{position:relative;border-right:30px solid transparent}#mc4wp-admin .CodeMirror-gutter-filler,#mc4wp-admin .CodeMirror-hscrollbar,#mc4wp-admin .CodeMirror-scrollbar-filler,#mc4wp-admin .CodeMirror-vscrollbar,.mc4wp-admin .CodeMirror-gutter-filler,.mc4wp-admin .CodeMirror-hscrollbar,.mc4wp-admin .CodeMirror-scrollbar-filler,.mc4wp-admin .CodeMirror-vscrollbar{position:absolute;z-index:6;display:none}#mc4wp-admin .CodeMirror-vscrollbar,.mc4wp-admin .CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}#mc4wp-admin .CodeMirror-hscrollbar,.mc4wp-admin .CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}#mc4wp-admin .CodeMirror-scrollbar-filler,.mc4wp-admin .CodeMirror-scrollbar-filler{right:0;bottom:0}#mc4wp-admin .CodeMirror-gutter-filler,.mc4wp-admin .CodeMirror-gutter-filler{left:0;bottom:0}#mc4wp-admin .CodeMirror-gutters,.mc4wp-admin .CodeMirror-gutters{position:absolute;left:0;top:0;z-index:3}#mc4wp-admin .CodeMirror-gutter,.mc4wp-admin .CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;margin-bottom:-30px}#mc4wp-admin .CodeMirror-gutter-wrapper,.mc4wp-admin .CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:0 0!important;border:none!important;-webkit-user-select:none;-moz-user-select:none;user-select:none}#mc4wp-admin .CodeMirror-gutter-background,.mc4wp-admin .CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}#mc4wp-admin .CodeMirror-gutter-elt,.mc4wp-admin .CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}#mc4wp-admin .CodeMirror-lines,.mc4wp-admin .CodeMirror-lines{cursor:text;min-height:1px}#mc4wp-admin .CodeMirror pre,.mc4wp-admin .CodeMirror pre{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent}#mc4wp-admin .CodeMirror-wrap pre,.mc4wp-admin .CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}#mc4wp-admin .CodeMirror-linebackground,.mc4wp-admin .CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}#mc4wp-admin .CodeMirror-linewidget,.mc4wp-admin .CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}#mc4wp-admin .CodeMirror-code,.mc4wp-admin .CodeMirror-code{outline:0}#mc4wp-admin .CodeMirror-gutter,#mc4wp-admin .CodeMirror-gutters,#mc4wp-admin .CodeMirror-linenumber,#mc4wp-admin .CodeMirror-scroll,#mc4wp-admin .CodeMirror-sizer,.mc4wp-admin .CodeMirror-gutter,.mc4wp-admin .CodeMirror-gutters,.mc4wp-admin .CodeMirror-linenumber,.mc4wp-admin .CodeMirror-scroll,.mc4wp-admin .CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}#mc4wp-admin .CodeMirror-measure,.mc4wp-admin .CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}#mc4wp-admin .CodeMirror-cursor,.mc4wp-admin .CodeMirror-cursor{position:absolute}#mc4wp-admin .CodeMirror-measure pre,.mc4wp-admin .CodeMirror-measure pre{position:static}#mc4wp-admin div.CodeMirror-cursors,.mc4wp-admin div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}#mc4wp-admin .CodeMirror-focused div.CodeMirror-cursors,#mc4wp-admin div.CodeMirror-dragcursors,.mc4wp-admin .CodeMirror-focused div.CodeMirror-cursors,.mc4wp-admin div.CodeMirror-dragcursors{visibility:visible}#mc4wp-admin .CodeMirror-selected,.mc4wp-admin .CodeMirror-selected{background:#d9d9d9}#mc4wp-admin .CodeMirror-focused .CodeMirror-selected,#mc4wp-admin .CodeMirror-line::selection,#mc4wp-admin .CodeMirror-line>span::selection,#mc4wp-admin .CodeMirror-line>span>span::selection,.mc4wp-admin .CodeMirror-focused .CodeMirror-selected,.mc4wp-admin .CodeMirror-line::selection,.mc4wp-admin .CodeMirror-line>span::selection,.mc4wp-admin .CodeMirror-line>span>span::selection{background:#d7d4f0}#mc4wp-admin .CodeMirror-crosshair,.mc4wp-admin .CodeMirror-crosshair{cursor:crosshair}#mc4wp-admin .CodeMirror-line::-moz-selection,#mc4wp-admin .CodeMirror-line>span::-moz-selection,#mc4wp-admin .CodeMirror-line>span>span::-moz-selection,.mc4wp-admin .CodeMirror-line::-moz-selection,.mc4wp-admin .CodeMirror-line>span::-moz-selection,.mc4wp-admin .CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}#mc4wp-admin .cm-searching,.mc4wp-admin .cm-searching{background:#ffa;background:rgba(255,255,0,.4)}#mc4wp-admin .cm-force-border,.mc4wp-admin .cm-force-border{padding-right:.1px}@media print{#mc4wp-admin .CodeMirror div.CodeMirror-cursors,.mc4wp-admin .CodeMirror div.CodeMirror-cursors{visibility:hidden}}#mc4wp-admin .cm-tab-wrap-hack:after,.mc4wp-admin .cm-tab-wrap-hack:after{content:''}#mc4wp-admin span.CodeMirror-selectedtext,.mc4wp-admin span.CodeMirror-selectedtext{background:0 0}#mc4wp-admin .CodeMirror,.mc4wp-admin .CodeMirror{border:1px solid #ccc;padding:10px;min-height:500px}#mc4wp-admin .CodeMirror-empty,.mc4wp-admin .CodeMirror-empty{color:#999}#mc4wp-admin .field-wizard h3,.mc4wp-admin .field-wizard h3{margin-top:0}#mc4wp-admin .field-wizard code,.mc4wp-admin .field-wizard code{margin-left:10px}#mc4wp-admin .field-wizard>div,.mc4wp-admin .field-wizard>div{margin:20px 0}#mc4wp-admin .field-wizard label,.mc4wp-admin .field-wizard label{font-weight:600;display:block;margin-bottom:4px}#mc4wp-admin .field-wizard input,.mc4wp-admin .field-wizard input{margin-bottom:6px}#mc4wp-admin .field-wizard table,.mc4wp-admin .field-wizard table{table-layout:fixed;border-collapse:collapse;border-spacing:0}#mc4wp-admin .field-wizard .cb-wrap,.mc4wp-admin .field-wizard .cb-wrap{font-weight:400}#mc4wp-admin .field-wizard .cb-wrap input,.mc4wp-admin .field-wizard .cb-wrap input{margin-right:6px}#mc4wp-admin .field-wizard .limit-height,.mc4wp-admin .field-wizard .limit-height{border:1px solid #eee;padding:6px;max-height:200px;overflow-y:scroll}#mc4wp-admin .available-fields,.mc4wp-admin .available-fields{border:1px solid #ccc;padding:20px;background:#fff}#mc4wp-admin .available-fields strong,.mc4wp-admin .available-fields strong{display:block;margin-bottom:10px}#mc4wp-admin .available-fields button,.mc4wp-admin .available-fields button{margin:0 6px 6px 0}#mc4wp-admin .available-fields .is-required:after,.mc4wp-admin .available-fields .is-required:after{content:" *";color:red}#mc4wp-admin .available-fields .is-required.not-in-form,.mc4wp-admin .available-fields .is-required.not-in-form{-webkit-box-shadow:0 0 3px 1px red;-moz-box-shadow:0 0 3px 1px red;box-shadow:0 0 3px 1px red}#mc4wp-admin .available-fields .in-form,.mc4wp-admin .available-fields .in-form{opacity:.5}#mc4wp-admin .page-title,.mc4wp-admin .page-title{background:url(../img/icon-large.png) left center no-repeat;padding-left:42px;line-height:32px;margin-bottom:20px}#mc4wp-admin .button .dashicons,#mc4wp-admin .button-secondary .dashicons,#mc4wp-admin .page-title-action .dashicons,.mc4wp-admin .button .dashicons,.mc4wp-admin .button-secondary .dashicons,.mc4wp-admin .page-title-action .dashicons{vertical-align:middle;line-height:16px;margin:0 4px 0 0}#mc4wp-admin .form-table td p,.mc4wp-admin .form-table td p{margin-top:1em}#mc4wp-admin .sidebar,.mc4wp-admin .sidebar{border-left:1px solid #ccc}#mc4wp-admin .sidebar h3,#mc4wp-admin .sidebar h4,.mc4wp-admin .sidebar h3,.mc4wp-admin .sidebar h4{font-size:16px;margin-bottom:0}#mc4wp-admin .sidebar>div,.mc4wp-admin .sidebar>div{border-bottom:1px solid #ccc;margin-bottom:20px;padding-bottom:20px}#mc4wp-admin .sidebar>div:last-of-type,.mc4wp-admin .sidebar>div:last-of-type{border-bottom:0}.overlay{position:fixed;left:0;top:0;z-index:99999;padding:20px;max-width:480px;max-height:100%;background:#fefefe;border:1px solid #ccc;overflow-y:scroll;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.overlay .close{position:absolute;padding:10px;right:0;top:0;font-size:24px;cursor:pointer;opacity:.5}.overlay .close:hover{opacity:1}.overlay-background{z-index:99998;background:rgba(0,0,0,.67);position:fixed;left:0;right:0;bottom:0;top:0}
assets/css/admin.css DELETED
@@ -1,229 +0,0 @@
1
- /* settings pages */
2
- #mc4wp-admin .page-title {
3
- background: url( "../img/icon-large.png" ) no-repeat left center;
4
- padding-left: 42px;
5
- line-height: 32px;
6
- margin-bottom: 20px;
7
- }
8
-
9
- #mc4wp-admin hr {
10
- margin: 20px 0 40px 0;
11
- }
12
-
13
- #mc4wp-content{
14
- float:left;
15
- width:65%;
16
- }
17
-
18
- #mc4wp-sidebar{
19
- float:left;
20
- width:33%;
21
- margin-left:2%;
22
- border-left:1px solid #ccc;
23
- padding:0 0 0 2%;
24
- -moz-box-sizing: border-box;
25
- -webkit-box-sizing: border-box;
26
- box-sizing: border-box;
27
- }
28
-
29
- .valigntop{
30
- vertical-align: top !important;
31
- }
32
-
33
- .mc4wp-box{
34
- margin-bottom:20px;
35
- }
36
-
37
- .mc4wp-box label {
38
- font-weight: bold;
39
- }
40
-
41
-
42
- #mc4wp-fw h4{
43
- margin-top: 0;
44
- }
45
- #mc4wp-fw p{
46
- margin-bottom: 1em;
47
- }
48
-
49
- #mc4wp-fw-fields {
50
- display:none;
51
- }
52
-
53
- #mc4wp-fw-preview {
54
- font-family: "Courier New", Courier, monospace;
55
- min-height:200px;
56
- font-size:11px;
57
- background:white;
58
- z-index:99;
59
- }
60
-
61
- #mc4wp-lists{
62
- margin:0;
63
- }
64
-
65
- #mc4wp-lists input{
66
- margin-right:5px;
67
- }
68
-
69
- .pro-feature,
70
- .mc4wp-settings tr.pro-feature th,
71
- .mc4wp-settings tr.pro-feature td{
72
- color:#aaa;
73
- }
74
-
75
- #mc4wp-admin .status{
76
- display:inline-block;
77
- margin-left:1em;
78
- padding:3px 6px;
79
- color:white;
80
- font-size:12px;
81
- font-weight:bold;
82
- }
83
- #mc4wp-admin .positive{
84
- background-color:limeGreen;
85
- }
86
-
87
- #mc4wp-admin .negative{
88
- background-color: red;
89
- }
90
-
91
- #mc4wp-admin .neutral{
92
- background: gray;
93
- }
94
-
95
- #mc4wp-admin table th{
96
- text-align:left;
97
- }
98
-
99
- #mc4wp-admin table.form-table tr td:first-child,
100
- #mc4wp-admin table.form-table tr th:first-child{
101
- padding-left:0;
102
- }
103
-
104
- #mc4wp-admin td.nowrap{
105
- white-space: nowrap
106
- }
107
-
108
- #mc4wp-admin td.desc{
109
- font-style:italic;
110
- font-size:11px;
111
- }
112
-
113
- .mc4wp-notice{
114
- padding: 6px 8px;
115
- color: #31708f;
116
- background: #d9edf7;
117
- border: 1px solid #bce8f1;
118
- margin: 1em 0 !important;
119
- }
120
-
121
- #mc4wp-admin .mc4wp-col {
122
- float:left;
123
- -webkit-box-sizing: border-box;
124
- -moz-box-sizing:border-box;
125
- box-sizing: border-box;
126
- width:50%;
127
- padding:0 5px;
128
- }
129
-
130
- #mc4wp-admin .mc4wp-first{
131
- padding-left:0;
132
- }
133
-
134
- #mc4wp-admin .mc4wp-last{
135
- padding-right:0;
136
- }
137
-
138
- .mc4wp-well{
139
- background:white;
140
- padding:10px;
141
- border:1px solid #ccc;
142
- }
143
-
144
- .mc4wp-title{
145
- font-size: 1.4em;
146
- margin:1.6em 0 1em;
147
- padding:0 0 6px 0;
148
- border-bottom:1px solid #ddd;
149
- }
150
-
151
- table.mc4wp-help,
152
- table.mc4wp-help th,
153
- table.mc4wp-help td {
154
- border: 1px solid #ddd;
155
- border-collapse: collapse;
156
- font-size: 12px;
157
- }
158
-
159
- table.mc4wp-help th,
160
- table.mc4wp-help td {
161
- vertical-align: text-top;
162
- text-align: left;
163
- padding: 5px 10px;
164
- }
165
-
166
- table.mc4wp-help tr:hover {
167
- background-color: #ddd;
168
- }
169
-
170
- #mc4wp-admin .wp-list-table code {
171
- float:right;
172
- }
173
-
174
- .mc4wp-lists-overview {
175
- border-collapse: collapse;
176
- background: white;
177
- padding: 20px;
178
- max-height: 500px;
179
- overflow-y: scroll;
180
- }
181
-
182
- .mc4wp-lists-overview table {
183
- border: 0;
184
- }
185
-
186
- .mc4wp-lists-overview th {
187
- font-weight: bold;
188
- vertical-align: top;
189
- }
190
-
191
- .mc4wp-lists-overview th,
192
- .mc4wp-lists-overview td {
193
- border: 1px solid #efefef;
194
- }
195
-
196
- .mc4wp-lists-overview h3{
197
- margin: 0 !important;
198
- }
199
-
200
-
201
- @media(max-width: 1279px) {
202
-
203
- #mc4wp-sidebar,
204
- #mc4wp-content{
205
- float: none;
206
- width: 100%;
207
- padding:0;
208
- margin:0;
209
- }
210
-
211
- #mc4wp-sidebar{
212
- border-left:0;
213
- border-top: 1px solid #ccc;
214
- margin-top:25px;
215
- padding-top: 25px;
216
- }
217
- #mc4wp-admin .wp-list-table code {
218
- float: none;
219
- }
220
-
221
- }
222
-
223
- @media(max-width: 860px) {
224
-
225
- .mc4wp-hide-smallscreens{
226
- display: none;
227
- }
228
-
229
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/admin.min.css DELETED
@@ -1 +0,0 @@
1
- #mc4wp-admin .page-title{background:url("../img/icon-large.png") left center no-repeat;padding-left:42px;line-height:32px;margin-bottom:20px}#mc4wp-admin hr{margin:20px 0 40px}#mc4wp-content{float:left;width:65%}#mc4wp-sidebar{float:left;width:33%;margin-left:2%;border-left:1px solid #ccc;padding:0 0 0 2%;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.valigntop{vertical-align:top!important}.mc4wp-box{margin-bottom:20px}.mc4wp-box label{font-weight:700}#mc4wp-fw h4{margin-top:0}#mc4wp-fw p{margin-bottom:1em}#mc4wp-fw-fields{display:none}#mc4wp-fw-preview{font-family:"Courier New",Courier,monospace;min-height:200px;font-size:11px;background:#fff;z-index:99}#mc4wp-lists{margin:0}#mc4wp-lists input{margin-right:5px}.mc4wp-settings tr.pro-feature td,.mc4wp-settings tr.pro-feature th,.pro-feature{color:#aaa}#mc4wp-admin .status{display:inline-block;margin-left:1em;padding:3px 6px;color:#fff;font-size:12px;font-weight:700}#mc4wp-admin .positive{background-color:#32cd32}#mc4wp-admin .negative{background-color:red}#mc4wp-admin .neutral{background:gray}#mc4wp-admin table th{text-align:left}#mc4wp-admin table.form-table tr td:first-child,#mc4wp-admin table.form-table tr th:first-child{padding-left:0}#mc4wp-admin td.nowrap{white-space:nowrap}#mc4wp-admin td.desc{font-style:italic;font-size:11px}.mc4wp-notice{padding:6px 8px;color:#31708f;background:#d9edf7;border:1px solid #bce8f1;margin:1em 0!important}#mc4wp-admin .mc4wp-col{float:left;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:50%;padding:0 5px}#mc4wp-admin .mc4wp-first{padding-left:0}#mc4wp-admin .mc4wp-last{padding-right:0}.mc4wp-well{background:#fff;padding:10px;border:1px solid #ccc}.mc4wp-title{font-size:1.4em;margin:1.6em 0 1em;padding:0 0 6px;border-bottom:1px solid #ddd}table.mc4wp-help,table.mc4wp-help td,table.mc4wp-help th{border:1px solid #ddd;border-collapse:collapse;font-size:12px}table.mc4wp-help td,table.mc4wp-help th{vertical-align:text-top;text-align:left;padding:5px 10px}table.mc4wp-help tr:hover{background-color:#ddd}#mc4wp-admin .wp-list-table code{float:right}.mc4wp-lists-overview{border-collapse:collapse;background:#fff;padding:20px;max-height:500px;overflow-y:scroll}.mc4wp-lists-overview table{border:0}.mc4wp-lists-overview th{font-weight:700;vertical-align:top}.mc4wp-lists-overview td,.mc4wp-lists-overview th{border:1px solid #efefef}.mc4wp-lists-overview h3{margin:0!important}@media(max-width:1279px){#mc4wp-content,#mc4wp-sidebar{float:none;width:100%;padding:0;margin:0}#mc4wp-sidebar{border-left:0;border-top:1px solid #ccc;margin-top:25px;padding-top:25px}#mc4wp-admin .wp-list-table code{float:none}}@media(max-width:860px){.mc4wp-hide-smallscreens{display:none}}
 
assets/css/checkbox-reset.css ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* MailChimp for WP - Checkbox Styles */
2
+ .mc4wp-checkbox-__INTEGRATION_SLUG__ {
3
+ clear: both;
4
+ display: block;
5
+ position: static;
6
+ width: auto; }
7
+ .mc4wp-checkbox-__INTEGRATION_SLUG__ input {
8
+ float: none;
9
+ width: auto;
10
+ position: static;
11
+ margin: 0 6px 0 0;
12
+ padding: 0;
13
+ vertical-align: middle;
14
+ display: inline-block !important;
15
+ max-width: 21px;
16
+ -webkit-appearance: checkbox; }
17
+ .mc4wp-checkbox-__INTEGRATION_SLUG__ label {
18
+ float: none;
19
+ display: block;
20
+ cursor: pointer;
21
+ width: auto;
22
+ position: static; }
assets/css/checkbox-reset.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .mc4wp-checkbox-__INTEGRATION_SLUG__{clear:both;display:block;position:static;width:auto}.mc4wp-checkbox-__INTEGRATION_SLUG__ input{float:none;width:auto;position:static;margin:0 6px 0 0;padding:0;vertical-align:middle;display:inline-block!important;max-width:21px;-webkit-appearance:checkbox}.mc4wp-checkbox-__INTEGRATION_SLUG__ label{float:none;display:block;cursor:pointer;width:auto;position:static}
assets/css/checkbox.css DELETED
@@ -1,38 +0,0 @@
1
- /* MailChimp for WP - Checkbox Styles */
2
- #mc4wp-checkbox {
3
- clear: both;
4
- display: block;
5
- position: static;
6
- width: auto;
7
- }
8
- #mc4wp-checkbox input {
9
- float: none;
10
- width: auto;
11
- position: static;
12
- margin: 0 6px 0 0;
13
- padding: 0;
14
- vertical-align: middle;
15
- display: inline-block !important;
16
- max-width: 21px;
17
- -webkit-appearance: checkbox;
18
- }
19
- #mc4wp-checkbox label {
20
- float: none;
21
- display: block;
22
- cursor: pointer;
23
- width: auto;
24
- position: static;
25
- }
26
-
27
- #_mc4wp_subscribe_woocommerce_checkout_field label,
28
- #_mc4wp_subscribe_woocommerce_checkout_field input {
29
- float: none !important;
30
- width: auto !important;
31
- display: inline-block !important;
32
- }
33
-
34
- #registerform #mc4wp-checkbox {
35
- margin-bottom: 10px;
36
- }
37
-
38
- /*# sourceMappingURL=checkbox.css.map */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/checkbox.css.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "mappings": ";AACA,eAAgB;EAEf,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EACd,QAAQ,EAAE,MAAM;EAChB,KAAK,EAAE,IAAI;;AAEX,qBAAM;EACL,KAAK,EAAE,IAAI;EACX,KAAK,EAAE,IAAI;EACX,QAAQ,EAAE,MAAM;EAChB,MAAM,EAAE,SAAS;EACjB,OAAO,EAAE,CAAC;EACV,cAAc,EAAE,MAAM;EACtB,OAAO,EAAE,uBAAuB;EAChC,SAAS,EAAE,IAAI;EACf,kBAAkB,EAAE,QAAQ;;AAG7B,qBAAM;EACL,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EACd,MAAM,EAAE,OAAO;EACf,KAAK,EAAE,IAAI;EACX,QAAQ,EAAE,MAAM;;;AAMjB;kDACK;EACJ,KAAK,EAAE,eAAe;EACtB,KAAK,EAAE,eAAe;EACtB,OAAO,EAAE,uBAAuB;;;AAMlC,6BAA6B;EAC5B,aAAa,EAAE,IAAI",
4
- "sources": ["../sass/checkbox.scss"],
5
- "names": [],
6
- "file": "checkbox.css"
7
- }
 
 
 
 
 
 
 
assets/css/checkbox.min.css DELETED
@@ -1 +0,0 @@
1
- #mc4wp-checkbox{clear:both;display:block;position:static;width:auto}#mc4wp-checkbox input{float:none;width:auto;position:static;margin:0 6px 0 0;padding:0;vertical-align:middle;display:inline-block!important;max-width:21px;-webkit-appearance:checkbox}#mc4wp-checkbox label{float:none;display:block;cursor:pointer;width:auto;position:static}#_mc4wp_subscribe_woocommerce_checkout_field input,#_mc4wp_subscribe_woocommerce_checkout_field label{float:none!important;width:auto!important;display:inline-block!important}#registerform #mc4wp-checkbox{margin-bottom:10px}
 
assets/css/codemirror.css ADDED
@@ -0,0 +1,334 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* BASICS */
2
+
3
+ .CodeMirror {
4
+ /* Set height, width, borders, and global font properties here */
5
+ font-family: monospace;
6
+ height: 300px;
7
+ color: black;
8
+ }
9
+
10
+ /* PADDING */
11
+
12
+ .CodeMirror-lines {
13
+ padding: 4px 0; /* Vertical padding around content */
14
+ }
15
+ .CodeMirror pre {
16
+ padding: 0 4px; /* Horizontal padding of content */
17
+ }
18
+
19
+ .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
20
+ background-color: white; /* The little square between H and V scrollbars */
21
+ }
22
+
23
+ /* GUTTER */
24
+
25
+ .CodeMirror-gutters {
26
+ border-right: 1px solid #ddd;
27
+ background-color: #f7f7f7;
28
+ white-space: nowrap;
29
+ }
30
+ .CodeMirror-linenumbers {}
31
+ .CodeMirror-linenumber {
32
+ padding: 0 3px 0 5px;
33
+ min-width: 20px;
34
+ text-align: right;
35
+ color: #999;
36
+ white-space: nowrap;
37
+ }
38
+
39
+ .CodeMirror-guttermarker { color: black; }
40
+ .CodeMirror-guttermarker-subtle { color: #999; }
41
+
42
+ /* CURSOR */
43
+
44
+ .CodeMirror-cursor {
45
+ border-left: 1px solid black;
46
+ border-right: none;
47
+ width: 0;
48
+ }
49
+ /* Shown when moving in bi-directional text */
50
+ .CodeMirror div.CodeMirror-secondarycursor {
51
+ border-left: 1px solid silver;
52
+ }
53
+ .cm-fat-cursor .CodeMirror-cursor {
54
+ width: auto;
55
+ border: 0;
56
+ background: #7e7;
57
+ }
58
+ .cm-fat-cursor div.CodeMirror-cursors {
59
+ z-index: 1;
60
+ }
61
+
62
+ .cm-animate-fat-cursor {
63
+ width: auto;
64
+ border: 0;
65
+ -webkit-animation: blink 1.06s steps(1) infinite;
66
+ -moz-animation: blink 1.06s steps(1) infinite;
67
+ animation: blink 1.06s steps(1) infinite;
68
+ background-color: #7e7;
69
+ }
70
+ @-moz-keyframes blink {
71
+ 0% {}
72
+ 50% { background-color: transparent; }
73
+ 100% {}
74
+ }
75
+ @-webkit-keyframes blink {
76
+ 0% {}
77
+ 50% { background-color: transparent; }
78
+ 100% {}
79
+ }
80
+ @keyframes blink {
81
+ 0% {}
82
+ 50% { background-color: transparent; }
83
+ 100% {}
84
+ }
85
+
86
+ /* Can style cursor different in overwrite (non-insert) mode */
87
+ .CodeMirror-overwrite .CodeMirror-cursor {}
88
+
89
+ .cm-tab { display: inline-block; text-decoration: inherit; }
90
+
91
+ .CodeMirror-ruler {
92
+ border-left: 1px solid #ccc;
93
+ position: absolute;
94
+ }
95
+
96
+ /* DEFAULT THEME */
97
+
98
+ .cm-s-default .cm-header {color: blue;}
99
+ .cm-s-default .cm-quote {color: #090;}
100
+ .cm-negative {color: #d44;}
101
+ .cm-positive {color: #292;}
102
+ .cm-header, .cm-strong {font-weight: bold;}
103
+ .cm-em {font-style: italic;}
104
+ .cm-link {text-decoration: underline;}
105
+ .cm-strikethrough {text-decoration: line-through;}
106
+
107
+ .cm-s-default .cm-keyword {color: #708;}
108
+ .cm-s-default .cm-atom {color: #219;}
109
+ .cm-s-default .cm-number {color: #164;}
110
+ .cm-s-default .cm-def {color: #00f;}
111
+ .cm-s-default .cm-variable,
112
+ .cm-s-default .cm-punctuation,
113
+ .cm-s-default .cm-property,
114
+ .cm-s-default .cm-operator {}
115
+ .cm-s-default .cm-variable-2 {color: #05a;}
116
+ .cm-s-default .cm-variable-3 {color: #085;}
117
+ .cm-s-default .cm-comment {color: #a50;}
118
+ .cm-s-default .cm-string {color: #a11;}
119
+ .cm-s-default .cm-string-2 {color: #f50;}
120
+ .cm-s-default .cm-meta {color: #555;}
121
+ .cm-s-default .cm-qualifier {color: #555;}
122
+ .cm-s-default .cm-builtin {color: #30a;}
123
+ .cm-s-default .cm-bracket {color: #997;}
124
+ .cm-s-default .cm-tag {color: #170;}
125
+ .cm-s-default .cm-attribute {color: #00c;}
126
+ .cm-s-default .cm-hr {color: #999;}
127
+ .cm-s-default .cm-link {color: #00c;}
128
+
129
+ .cm-s-default .cm-error {color: #f00;}
130
+ .cm-invalidchar {color: #f00;}
131
+
132
+ .CodeMirror-composing { border-bottom: 2px solid; }
133
+
134
+ /* Default styles for common addons */
135
+
136
+ div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
137
+ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
138
+ .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
139
+ .CodeMirror-activeline-background {background: #e8f2ff;}
140
+
141
+ /* STOP */
142
+
143
+ /* The rest of this file contains styles related to the mechanics of
144
+ the editor. You probably shouldn't touch them. */
145
+
146
+ .CodeMirror {
147
+ position: relative;
148
+ overflow: hidden;
149
+ background: white;
150
+ }
151
+
152
+ .CodeMirror-scroll {
153
+ overflow: scroll !important; /* Things will break if this is overridden */
154
+ /* 30px is the magic margin used to hide the element's real scrollbars */
155
+ /* See overflow: hidden in .CodeMirror */
156
+ margin-bottom: -30px; margin-right: -30px;
157
+ padding-bottom: 30px;
158
+ height: 100%;
159
+ outline: none; /* Prevent dragging from highlighting the element */
160
+ position: relative;
161
+ }
162
+ .CodeMirror-sizer {
163
+ position: relative;
164
+ border-right: 30px solid transparent;
165
+ }
166
+
167
+ /* The fake, visible scrollbars. Used to force redraw during scrolling
168
+ before actuall scrolling happens, thus preventing shaking and
169
+ flickering artifacts. */
170
+ .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
171
+ position: absolute;
172
+ z-index: 6;
173
+ display: none;
174
+ }
175
+ .CodeMirror-vscrollbar {
176
+ right: 0; top: 0;
177
+ overflow-x: hidden;
178
+ overflow-y: scroll;
179
+ }
180
+ .CodeMirror-hscrollbar {
181
+ bottom: 0; left: 0;
182
+ overflow-y: hidden;
183
+ overflow-x: scroll;
184
+ }
185
+ .CodeMirror-scrollbar-filler {
186
+ right: 0; bottom: 0;
187
+ }
188
+ .CodeMirror-gutter-filler {
189
+ left: 0; bottom: 0;
190
+ }
191
+
192
+ .CodeMirror-gutters {
193
+ position: absolute; left: 0; top: 0;
194
+ z-index: 3;
195
+ }
196
+ .CodeMirror-gutter {
197
+ white-space: normal;
198
+ height: 100%;
199
+ display: inline-block;
200
+ margin-bottom: -30px;
201
+ /* Hack to make IE7 behave */
202
+ *zoom:1;
203
+ *display:inline;
204
+ }
205
+ .CodeMirror-gutter-wrapper {
206
+ position: absolute;
207
+ z-index: 4;
208
+ background: none !important;
209
+ border: none !important;
210
+ }
211
+ .CodeMirror-gutter-background {
212
+ position: absolute;
213
+ top: 0; bottom: 0;
214
+ z-index: 4;
215
+ }
216
+ .CodeMirror-gutter-elt {
217
+ position: absolute;
218
+ cursor: default;
219
+ z-index: 4;
220
+ }
221
+ .CodeMirror-gutter-wrapper {
222
+ -webkit-user-select: none;
223
+ -moz-user-select: none;
224
+ user-select: none;
225
+ }
226
+
227
+ .CodeMirror-lines {
228
+ cursor: text;
229
+ min-height: 1px; /* prevents collapsing before first draw */
230
+ }
231
+ .CodeMirror pre {
232
+ /* Reset some styles that the rest of the page might have set */
233
+ -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
234
+ border-width: 0;
235
+ background: transparent;
236
+ font-family: inherit;
237
+ font-size: inherit;
238
+ margin: 0;
239
+ white-space: pre;
240
+ word-wrap: normal;
241
+ line-height: inherit;
242
+ color: inherit;
243
+ z-index: 2;
244
+ position: relative;
245
+ overflow: visible;
246
+ -webkit-tap-highlight-color: transparent;
247
+ }
248
+ .CodeMirror-wrap pre {
249
+ word-wrap: break-word;
250
+ white-space: pre-wrap;
251
+ word-break: normal;
252
+ }
253
+
254
+ .CodeMirror-linebackground {
255
+ position: absolute;
256
+ left: 0; right: 0; top: 0; bottom: 0;
257
+ z-index: 0;
258
+ }
259
+
260
+ .CodeMirror-linewidget {
261
+ position: relative;
262
+ z-index: 2;
263
+ overflow: auto;
264
+ }
265
+
266
+ .CodeMirror-widget {}
267
+
268
+ .CodeMirror-code {
269
+ outline: none;
270
+ }
271
+
272
+ /* Force content-box sizing for the elements where we expect it */
273
+ .CodeMirror-scroll,
274
+ .CodeMirror-sizer,
275
+ .CodeMirror-gutter,
276
+ .CodeMirror-gutters,
277
+ .CodeMirror-linenumber {
278
+ -moz-box-sizing: content-box;
279
+ box-sizing: content-box;
280
+ }
281
+
282
+ .CodeMirror-measure {
283
+ position: absolute;
284
+ width: 100%;
285
+ height: 0;
286
+ overflow: hidden;
287
+ visibility: hidden;
288
+ }
289
+
290
+ .CodeMirror-cursor { position: absolute; }
291
+ .CodeMirror-measure pre { position: static; }
292
+
293
+ div.CodeMirror-cursors {
294
+ visibility: hidden;
295
+ position: relative;
296
+ z-index: 3;
297
+ }
298
+ div.CodeMirror-dragcursors {
299
+ visibility: visible;
300
+ }
301
+
302
+ .CodeMirror-focused div.CodeMirror-cursors {
303
+ visibility: visible;
304
+ }
305
+
306
+ .CodeMirror-selected { background: #d9d9d9; }
307
+ .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
308
+ .CodeMirror-crosshair { cursor: crosshair; }
309
+ .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
310
+ .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
311
+
312
+ .cm-searching {
313
+ background: #ffa;
314
+ background: rgba(255, 255, 0, .4);
315
+ }
316
+
317
+ /* IE7 hack to prevent it from returning funny offsetTops on the spans */
318
+ .CodeMirror span { *vertical-align: text-bottom; }
319
+
320
+ /* Used to force a border model for a node */
321
+ .cm-force-border { padding-right: .1px; }
322
+
323
+ @media print {
324
+ /* Hide the cursor when printing */
325
+ .CodeMirror div.CodeMirror-cursors {
326
+ visibility: hidden;
327
+ }
328
+ }
329
+
330
+ /* See issue #2901 */
331
+ .cm-tab-wrap-hack:after { content: ''; }
332
+
333
+ /* Help users use markselection to safely style text background */
334
+ span.CodeMirror-selectedtext { background: none; }
assets/css/codemirror.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .CodeMirror{font-family:monospace;height:300px;color:#000}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:0;position:relative}.CodeMirror-sizer{position:relative;border-right:30px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;margin-bottom:-30px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:0 0!important;border:none!important;-webkit-user-select:none;-moz-user-select:none;user-select:none}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.CodeMirror-code{outline:0}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected,.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:0 0}
assets/css/form-basic.css ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* MailChimp for WP - Default Form Styles */
2
+ .mc4wp-form-basic,
3
+ .mc4wp-form-theme {
4
+ margin: 1em 0;
5
+ /* Form Elements */
6
+ /* Remove font-weight bold from nested elements */
7
+ /* Alert */ }
8
+ .mc4wp-form-basic,
9
+ .mc4wp-form-basic label,
10
+ .mc4wp-form-basic input,
11
+ .mc4wp-form-theme,
12
+ .mc4wp-form-theme label,
13
+ .mc4wp-form-theme input {
14
+ width: auto;
15
+ display: block;
16
+ -webkit-box-sizing: border-box;
17
+ -moz-box-sizing: border-box;
18
+ box-sizing: border-box;
19
+ cursor: auto;
20
+ height: auto;
21
+ vertical-align: baseline;
22
+ line-height: normal; }
23
+ .mc4wp-form-basic:after,
24
+ .mc4wp-form-theme:after {
25
+ content: "";
26
+ display: table;
27
+ clear: both; }
28
+ .mc4wp-form-basic label,
29
+ .mc4wp-form-theme label {
30
+ font-weight: bold;
31
+ margin-bottom: 6px;
32
+ display: block; }
33
+ .mc4wp-form-basic input.placeholdersjs,
34
+ .mc4wp-form-theme input.placeholdersjs {
35
+ color: #aaa !important; }
36
+ .mc4wp-form-basic input[type="text"],
37
+ .mc4wp-form-basic input[type="email"],
38
+ .mc4wp-form-basic input[type="tel"],
39
+ .mc4wp-form-basic input[type="url"],
40
+ .mc4wp-form-basic input[type="date"],
41
+ .mc4wp-form-basic textarea,
42
+ .mc4wp-form-basic select,
43
+ .mc4wp-form-theme input[type="text"],
44
+ .mc4wp-form-theme input[type="email"],
45
+ .mc4wp-form-theme input[type="tel"],
46
+ .mc4wp-form-theme input[type="url"],
47
+ .mc4wp-form-theme input[type="date"],
48
+ .mc4wp-form-theme textarea,
49
+ .mc4wp-form-theme select {
50
+ min-height: 28px;
51
+ width: 100%;
52
+ max-width: 480px; }
53
+ .mc4wp-form-basic input[type="number"],
54
+ .mc4wp-form-theme input[type="number"] {
55
+ min-width: 40px; }
56
+ .mc4wp-form-basic input[type="checkbox"],
57
+ .mc4wp-form-basic input[type="radio"],
58
+ .mc4wp-form-theme input[type="checkbox"],
59
+ .mc4wp-form-theme input[type="radio"] {
60
+ position: relative;
61
+ margin: 0 6px 0 0;
62
+ padding: 0;
63
+ height: 13px;
64
+ width: 13px;
65
+ display: inline-block;
66
+ border: 0; }
67
+ .mc4wp-form-basic input[type="checkbox"],
68
+ .mc4wp-form-theme input[type="checkbox"] {
69
+ -webkit-appearance: checkbox;
70
+ -moz-appearance: checkbox;
71
+ appearance: checkbox; }
72
+ .mc4wp-form-basic input[type="radio"],
73
+ .mc4wp-form-theme input[type="radio"] {
74
+ -webkit-appearance: radio;
75
+ -moz-appearance: radio;
76
+ appearance: radio; }
77
+ .mc4wp-form-basic input[type="submit"],
78
+ .mc4wp-form-basic button,
79
+ .mc4wp-form-basic input[type="button"],
80
+ .mc4wp-form-theme input[type="submit"],
81
+ .mc4wp-form-theme button,
82
+ .mc4wp-form-theme input[type="button"] {
83
+ cursor: pointer;
84
+ display: inline-block;
85
+ -webkit-appearance: none;
86
+ -moz-appearance: none;
87
+ appearance: none; }
88
+ .mc4wp-form-basic label > span,
89
+ .mc4wp-form-basic li > label,
90
+ .mc4wp-form-theme label > span,
91
+ .mc4wp-form-theme li > label {
92
+ font-weight: normal; }
93
+ .mc4wp-form-basic .mc4wp-alert,
94
+ .mc4wp-form-theme .mc4wp-alert {
95
+ color: #c09853;
96
+ clear: both; }
97
+ .mc4wp-form-basic .mc4wp-success,
98
+ .mc4wp-form-theme .mc4wp-success {
99
+ color: #468847; }
100
+ .mc4wp-form-basic .mc4wp-notice,
101
+ .mc4wp-form-theme .mc4wp-notice {
102
+ color: #3a87ad; }
103
+ .mc4wp-form-basic .mc4wp-error,
104
+ .mc4wp-form-theme .mc4wp-error {
105
+ color: #CD5C5C; }
106
+
107
+ /* Right-To-Left specific styles */
108
+ .rtl .mc4wp-form-reset input[type="checkbox"],
109
+ .rtl .mc4wp-form-reset input[type="radio"] {
110
+ margin: 0 0 0 6px; }
assets/css/form-basic.css.map ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ {
2
+ "version": 3,
3
+ "mappings": ";AACA;iBACkB;EAChB,MAAM,EAAE,KAAK;;;;;AAIb;;;;;uBAKwB;EACtB,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EACd,kBAAkB,EAAE,UAAU;EAC9B,eAAe,EAAE,UAAU;EAC3B,UAAU,EAAE,UAAU;EACtB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,cAAc,EAAE,QAAQ;EACxB,WAAW,EAAE,MAAM;;AACrB;uBACwB;EACtB,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,KAAK;EACd,KAAK,EAAE,IAAI;;AACb;uBACwB;EACtB,WAAW,EAAE,IAAI;EACjB,aAAa,EAAE,GAAG;EAClB,OAAO,EAAE,KAAK;;AAChB;sCACuC;EACrC,KAAK,EAAE,eAAe;;AACxB;;;;;;;;;;;;;wBAayB;EACvB,UAAU,EAAE,IAAI;EAChB,KAAK,EAAE,IAAI;EACX,SAAS,EAAE,KAAK;;AAClB;sCACuC;EACrC,SAAS,EAAE,IAAI;;AACjB;;;qCAGsC;EACpC,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,SAAS;EACjB,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,YAAY;EACrB,MAAM,EAAE,CAAC;;AACX;wCACyC;EACvC,kBAAkB,EAAE,QAAQ;EAC5B,eAAe,EAAE,QAAQ;EACzB,UAAU,EAAE,QAAQ;;AACtB;qCACsC;EACpC,kBAAkB,EAAE,KAAK;EACzB,eAAe,EAAE,KAAK;EACtB,UAAU,EAAE,KAAK;;AACnB;;;;;sCAKuC;EACrC,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,YAAY;EACrB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,IAAI;;AAClB;;;4BAG6B;EAC3B,WAAW,EAAE,MAAM;;AACrB;8BAC+B;EAC7B,KAAK,EAAE,OAAO;EACd,KAAK,EAAE,IAAI;;AACb;gCACiC;EAC/B,KAAK,EAAE,OAAO;;AAChB;+BACgC;EAC9B,KAAK,EAAE,OAAO;;AAChB;8BAC+B;EAC7B,KAAK,EAAE,OAAO;;;AAGlB;0CAC2C;EACzC,MAAM,EAAE,SAAS",
4
+ "sources": ["form-basic.scss"],
5
+ "names": [],
6
+ "file": "form-basic.css"
7
+ }
assets/css/form-basic.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .mc4wp-form-basic,.mc4wp-form-theme{margin:1em 0}.mc4wp-form-basic,.mc4wp-form-basic input,.mc4wp-form-basic label,.mc4wp-form-theme,.mc4wp-form-theme input,.mc4wp-form-theme label{width:auto;display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:auto;height:auto;vertical-align:baseline;line-height:normal}.mc4wp-form-basic:after,.mc4wp-form-theme:after{content:"";display:table;clear:both}.mc4wp-form-basic label,.mc4wp-form-theme label{font-weight:700;margin-bottom:6px;display:block}.mc4wp-form-basic input.placeholdersjs,.mc4wp-form-theme input.placeholdersjs{color:#aaa!important}.mc4wp-form-basic input[type=text],.mc4wp-form-basic input[type=email],.mc4wp-form-basic input[type=tel],.mc4wp-form-basic input[type=url],.mc4wp-form-basic input[type=date],.mc4wp-form-basic select,.mc4wp-form-basic textarea,.mc4wp-form-theme input[type=text],.mc4wp-form-theme input[type=email],.mc4wp-form-theme input[type=tel],.mc4wp-form-theme input[type=url],.mc4wp-form-theme input[type=date],.mc4wp-form-theme select,.mc4wp-form-theme textarea{min-height:28px;width:100%;max-width:480px}.mc4wp-form-basic input[type=number],.mc4wp-form-theme input[type=number]{min-width:40px}.mc4wp-form-basic input[type=checkbox],.mc4wp-form-basic input[type=radio],.mc4wp-form-theme input[type=checkbox],.mc4wp-form-theme input[type=radio]{position:relative;margin:0 6px 0 0;padding:0;height:13px;width:13px;display:inline-block;border:0}.mc4wp-form-basic input[type=checkbox],.mc4wp-form-theme input[type=checkbox]{-webkit-appearance:checkbox;-moz-appearance:checkbox;appearance:checkbox}.mc4wp-form-basic input[type=radio],.mc4wp-form-theme input[type=radio]{-webkit-appearance:radio;-moz-appearance:radio;appearance:radio}.mc4wp-form-basic button,.mc4wp-form-basic input[type=button],.mc4wp-form-basic input[type=submit],.mc4wp-form-theme button,.mc4wp-form-theme input[type=button],.mc4wp-form-theme input[type=submit]{cursor:pointer;display:inline-block;-webkit-appearance:none;-moz-appearance:none;appearance:none}.mc4wp-form-basic label>span,.mc4wp-form-basic li>label,.mc4wp-form-theme label>span,.mc4wp-form-theme li>label{font-weight:400}.mc4wp-form-basic .mc4wp-alert,.mc4wp-form-theme .mc4wp-alert{color:#c09853;clear:both}.mc4wp-form-basic .mc4wp-success,.mc4wp-form-theme .mc4wp-success{color:#468847}.mc4wp-form-basic .mc4wp-notice,.mc4wp-form-theme .mc4wp-notice{color:#3a87ad}.mc4wp-form-basic .mc4wp-error,.mc4wp-form-theme .mc4wp-error{color:#CD5C5C}.rtl .mc4wp-form-reset input[type=checkbox],.rtl .mc4wp-form-reset input[type=radio]{margin:0 0 0 6px}
assets/css/form-editor.css ADDED
@@ -0,0 +1,461 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* settings pages */
2
+ /* BASICS */
3
+ .CodeMirror {
4
+ /* Set height, width, borders, and global font properties here */
5
+ font-family: monospace;
6
+ height: 300px;
7
+ color: black; }
8
+
9
+ /* PADDING */
10
+ .CodeMirror-lines {
11
+ padding: 4px 0;
12
+ /* Vertical padding around content */ }
13
+
14
+ .CodeMirror pre {
15
+ padding: 0 4px;
16
+ /* Horizontal padding of content */ }
17
+
18
+ .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
19
+ background-color: white;
20
+ /* The little square between H and V scrollbars */ }
21
+
22
+ /* GUTTER */
23
+ .CodeMirror-gutters {
24
+ border-right: 1px solid #ddd;
25
+ background-color: #f7f7f7;
26
+ white-space: nowrap; }
27
+
28
+ .CodeMirror-linenumber {
29
+ padding: 0 3px 0 5px;
30
+ min-width: 20px;
31
+ text-align: right;
32
+ color: #999;
33
+ white-space: nowrap; }
34
+
35
+ .CodeMirror-guttermarker {
36
+ color: black; }
37
+
38
+ .CodeMirror-guttermarker-subtle {
39
+ color: #999; }
40
+
41
+ /* CURSOR */
42
+ .CodeMirror-cursor {
43
+ border-left: 1px solid black;
44
+ border-right: none;
45
+ width: 0; }
46
+
47
+ /* Shown when moving in bi-directional text */
48
+ .CodeMirror div.CodeMirror-secondarycursor {
49
+ border-left: 1px solid silver; }
50
+
51
+ .cm-fat-cursor .CodeMirror-cursor {
52
+ width: auto;
53
+ border: 0;
54
+ background: #7e7; }
55
+
56
+ .cm-fat-cursor div.CodeMirror-cursors {
57
+ z-index: 1; }
58
+
59
+ .cm-animate-fat-cursor {
60
+ width: auto;
61
+ border: 0;
62
+ -webkit-animation: blink 1.06s steps(1) infinite;
63
+ -moz-animation: blink 1.06s steps(1) infinite;
64
+ animation: blink 1.06s steps(1) infinite;
65
+ background-color: #7e7; }
66
+
67
+ @-moz-keyframes blink {
68
+ 0% { }
69
+ 50% {
70
+ background-color: transparent; }
71
+ 100% { } }
72
+
73
+ @-webkit-keyframes blink {
74
+ 0% { }
75
+ 50% {
76
+ background-color: transparent; }
77
+ 100% { } }
78
+
79
+ @keyframes blink {
80
+ 0% { }
81
+ 50% {
82
+ background-color: transparent; }
83
+ 100% { } }
84
+
85
+ /* Can style cursor different in overwrite (non-insert) mode */
86
+ .cm-tab {
87
+ display: inline-block;
88
+ text-decoration: inherit; }
89
+
90
+ .CodeMirror-ruler {
91
+ border-left: 1px solid #ccc;
92
+ position: absolute; }
93
+
94
+ /* DEFAULT THEME */
95
+ .cm-s-default .cm-header {
96
+ color: blue; }
97
+
98
+ .cm-s-default .cm-quote {
99
+ color: #090; }
100
+
101
+ .cm-negative {
102
+ color: #d44; }
103
+
104
+ .cm-positive {
105
+ color: #292; }
106
+
107
+ .cm-header, .cm-strong {
108
+ font-weight: bold; }
109
+
110
+ .cm-em {
111
+ font-style: italic; }
112
+
113
+ .cm-link {
114
+ text-decoration: underline; }
115
+
116
+ .cm-strikethrough {
117
+ text-decoration: line-through; }
118
+
119
+ .cm-s-default .cm-keyword {
120
+ color: #708; }
121
+
122
+ .cm-s-default .cm-atom {
123
+ color: #219; }
124
+
125
+ .cm-s-default .cm-number {
126
+ color: #164; }
127
+
128
+ .cm-s-default .cm-def {
129
+ color: #00f; }
130
+
131
+ .cm-s-default .cm-variable-2 {
132
+ color: #05a; }
133
+
134
+ .cm-s-default .cm-variable-3 {
135
+ color: #085; }
136
+
137
+ .cm-s-default .cm-comment {
138
+ color: #a50; }
139
+
140
+ .cm-s-default .cm-string {
141
+ color: #a11; }
142
+
143
+ .cm-s-default .cm-string-2 {
144
+ color: #f50; }
145
+
146
+ .cm-s-default .cm-meta {
147
+ color: #555; }
148
+
149
+ .cm-s-default .cm-qualifier {
150
+ color: #555; }
151
+
152
+ .cm-s-default .cm-builtin {
153
+ color: #30a; }
154
+
155
+ .cm-s-default .cm-bracket {
156
+ color: #997; }
157
+
158
+ .cm-s-default .cm-tag {
159
+ color: #170; }
160
+
161
+ .cm-s-default .cm-attribute {
162
+ color: #00c; }
163
+
164
+ .cm-s-default .cm-hr {
165
+ color: #999; }
166
+
167
+ .cm-s-default .cm-link {
168
+ color: #00c; }
169
+
170
+ .cm-s-default .cm-error {
171
+ color: #f00; }
172
+
173
+ .cm-invalidchar {
174
+ color: #f00; }
175
+
176
+ .CodeMirror-composing {
177
+ border-bottom: 2px solid; }
178
+
179
+ /* Default styles for common addons */
180
+ div.CodeMirror span.CodeMirror-matchingbracket {
181
+ color: #0f0; }
182
+
183
+ div.CodeMirror span.CodeMirror-nonmatchingbracket {
184
+ color: #f22; }
185
+
186
+ .CodeMirror-matchingtag {
187
+ background: rgba(255, 150, 0, 0.3); }
188
+
189
+ .CodeMirror-activeline-background {
190
+ background: #e8f2ff; }
191
+
192
+ /* STOP */
193
+ /* The rest of this file contains styles related to the mechanics of
194
+ the editor. You probably shouldn't touch them. */
195
+ .CodeMirror {
196
+ position: relative;
197
+ overflow: hidden;
198
+ background: white; }
199
+
200
+ .CodeMirror-scroll {
201
+ overflow: scroll !important;
202
+ /* Things will break if this is overridden */
203
+ /* 30px is the magic margin used to hide the element's real scrollbars */
204
+ /* See overflow: hidden in .CodeMirror */
205
+ margin-bottom: -30px;
206
+ margin-right: -30px;
207
+ padding-bottom: 30px;
208
+ height: 100%;
209
+ outline: none;
210
+ /* Prevent dragging from highlighting the element */
211
+ position: relative; }
212
+
213
+ .CodeMirror-sizer {
214
+ position: relative;
215
+ border-right: 30px solid transparent; }
216
+
217
+ /* The fake, visible scrollbars. Used to force redraw during scrolling
218
+ before actuall scrolling happens, thus preventing shaking and
219
+ flickering artifacts. */
220
+ .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
221
+ position: absolute;
222
+ z-index: 6;
223
+ display: none; }
224
+
225
+ .CodeMirror-vscrollbar {
226
+ right: 0;
227
+ top: 0;
228
+ overflow-x: hidden;
229
+ overflow-y: scroll; }
230
+
231
+ .CodeMirror-hscrollbar {
232
+ bottom: 0;
233
+ left: 0;
234
+ overflow-y: hidden;
235
+ overflow-x: scroll; }
236
+
237
+ .CodeMirror-scrollbar-filler {
238
+ right: 0;
239
+ bottom: 0; }
240
+
241
+ .CodeMirror-gutter-filler {
242
+ left: 0;
243
+ bottom: 0; }
244
+
245
+ .CodeMirror-gutters {
246
+ position: absolute;
247
+ left: 0;
248
+ top: 0;
249
+ z-index: 3; }
250
+
251
+ .CodeMirror-gutter {
252
+ white-space: normal;
253
+ height: 100%;
254
+ display: inline-block;
255
+ margin-bottom: -30px;
256
+ /* Hack to make IE7 behave */
257
+ *zoom: 1;
258
+ *display: inline; }
259
+
260
+ .CodeMirror-gutter-wrapper {
261
+ position: absolute;
262
+ z-index: 4;
263
+ background: none !important;
264
+ border: none !important; }
265
+
266
+ .CodeMirror-gutter-background {
267
+ position: absolute;
268
+ top: 0;
269
+ bottom: 0;
270
+ z-index: 4; }
271
+
272
+ .CodeMirror-gutter-elt {
273
+ position: absolute;
274
+ cursor: default;
275
+ z-index: 4; }
276
+
277
+ .CodeMirror-gutter-wrapper {
278
+ -webkit-user-select: none;
279
+ -moz-user-select: none;
280
+ user-select: none; }
281
+
282
+ .CodeMirror-lines {
283
+ cursor: text;
284
+ min-height: 1px;
285
+ /* prevents collapsing before first draw */ }
286
+
287
+ .CodeMirror pre {
288
+ /* Reset some styles that the rest of the page might have set */
289
+ -moz-border-radius: 0;
290
+ -webkit-border-radius: 0;
291
+ border-radius: 0;
292
+ border-width: 0;
293
+ background: transparent;
294
+ font-family: inherit;
295
+ font-size: inherit;
296
+ margin: 0;
297
+ white-space: pre;
298
+ word-wrap: normal;
299
+ line-height: inherit;
300
+ color: inherit;
301
+ z-index: 2;
302
+ position: relative;
303
+ overflow: visible;
304
+ -webkit-tap-highlight-color: transparent; }
305
+
306
+ .CodeMirror-wrap pre {
307
+ word-wrap: break-word;
308
+ white-space: pre-wrap;
309
+ word-break: normal; }
310
+
311
+ .CodeMirror-linebackground {
312
+ position: absolute;
313
+ left: 0;
314
+ right: 0;
315
+ top: 0;
316
+ bottom: 0;
317
+ z-index: 0; }
318
+
319
+ .CodeMirror-linewidget {
320
+ position: relative;
321
+ z-index: 2;
322
+ overflow: auto; }
323
+
324
+ .CodeMirror-code {
325
+ outline: none; }
326
+
327
+ /* Force content-box sizing for the elements where we expect it */
328
+ .CodeMirror-scroll,
329
+ .CodeMirror-sizer,
330
+ .CodeMirror-gutter,
331
+ .CodeMirror-gutters,
332
+ .CodeMirror-linenumber {
333
+ -moz-box-sizing: content-box;
334
+ box-sizing: content-box; }
335
+
336
+ .CodeMirror-measure {
337
+ position: absolute;
338
+ width: 100%;
339
+ height: 0;
340
+ overflow: hidden;
341
+ visibility: hidden; }
342
+
343
+ .CodeMirror-cursor {
344
+ position: absolute; }
345
+
346
+ .CodeMirror-measure pre {
347
+ position: static; }
348
+
349
+ div.CodeMirror-cursors {
350
+ visibility: hidden;
351
+ position: relative;
352
+ z-index: 3; }
353
+
354
+ div.CodeMirror-dragcursors {
355
+ visibility: visible; }
356
+
357
+ .CodeMirror-focused div.CodeMirror-cursors {
358
+ visibility: visible; }
359
+
360
+ .CodeMirror-selected {
361
+ background: #d9d9d9; }
362
+
363
+ .CodeMirror-focused .CodeMirror-selected {
364
+ background: #d7d4f0; }
365
+
366
+ .CodeMirror-crosshair {
367
+ cursor: crosshair; }
368
+
369
+ .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection {
370
+ background: #d7d4f0; }
371
+
372
+ .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection {
373
+ background: #d7d4f0; }
374
+
375
+ .cm-searching {
376
+ background: #ffa;
377
+ background: rgba(255, 255, 0, 0.4); }
378
+
379
+ /* IE7 hack to prevent it from returning funny offsetTops on the spans */
380
+ .CodeMirror span {
381
+ *vertical-align: text-bottom; }
382
+
383
+ /* Used to force a border model for a node */
384
+ .cm-force-border {
385
+ padding-right: .1px; }
386
+
387
+ @media print {
388
+ /* Hide the cursor when printing */
389
+ .CodeMirror div.CodeMirror-cursors {
390
+ visibility: hidden; } }
391
+
392
+ /* See issue #2901 */
393
+ .cm-tab-wrap-hack:after {
394
+ content: ''; }
395
+
396
+ /* Help users use markselection to safely style text background */
397
+ span.CodeMirror-selectedtext {
398
+ background: none; }
399
+
400
+ /* Codemirror */
401
+ .CodeMirror {
402
+ border: 1px solid #ccc;
403
+ padding: 10px;
404
+ min-height: 500px; }
405
+
406
+ .CodeMirror-empty {
407
+ color: #999; }
408
+
409
+ .field-wizard {
410
+ /* table */
411
+ /* checkboxes in label */ }
412
+ .field-wizard h3 {
413
+ margin-top: 0; }
414
+ .field-wizard code {
415
+ margin-left: 10px; }
416
+ .field-wizard > div {
417
+ margin: 20px 0; }
418
+ .field-wizard label {
419
+ font-weight: 600;
420
+ display: block;
421
+ margin-bottom: 4px; }
422
+ .field-wizard input {
423
+ margin-bottom: 6px; }
424
+ .field-wizard table {
425
+ table-layout: fixed;
426
+ border-collapse: collapse;
427
+ border-spacing: 0; }
428
+ .field-wizard tr, .field-wizard td {
429
+ vertical-align: middle; }
430
+ .field-wizard td.stretch {
431
+ width: 100%; }
432
+ .field-wizard .cb-wrap {
433
+ font-weight: normal; }
434
+ .field-wizard .cb-wrap input {
435
+ margin-right: 6px; }
436
+ .field-wizard .limit-height {
437
+ border: 1px solid #eee;
438
+ padding: 6px;
439
+ max-height: 200px;
440
+ overflow-y: scroll; }
441
+ .field-wizard .dashicons {
442
+ vertical-align: middle; }
443
+
444
+ .available-fields {
445
+ border: 1px solid #ccc;
446
+ padding: 20px;
447
+ background: white; }
448
+ .available-fields strong {
449
+ display: block;
450
+ margin-bottom: 10px; }
451
+ .available-fields button {
452
+ margin: 0 6px 6px 0; }
453
+ .available-fields .is-required:after {
454
+ content: " *";
455
+ color: red; }
456
+ .available-fields .is-required.not-in-form {
457
+ -webkit-box-shadow: 0 0 3px 1px red;
458
+ -moz-box-shadow: 0 0 3px 1px red;
459
+ box-shadow: 0 0 3px 1px red; }
460
+ .available-fields .in-form {
461
+ opacity: 0.5; }
assets/css/form-editor.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .field-wizard .dashicons,.field-wizard td,.field-wizard tr{vertical-align:middle}.CodeMirror{font-family:monospace;height:300px;color:#000}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:0;position:relative}.CodeMirror-sizer{position:relative;border-right:30px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;margin-bottom:-30px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:0 0!important;border:none!important;-webkit-user-select:none;-moz-user-select:none;user-select:none}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.CodeMirror-code{outline:0}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected,.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:0 0}.CodeMirror{border:1px solid #ccc;padding:10px;min-height:500px}.CodeMirror-empty{color:#999}.field-wizard h3{margin-top:0}.field-wizard code{margin-left:10px}.field-wizard>div{margin:20px 0}.field-wizard label{font-weight:600;display:block;margin-bottom:4px}.field-wizard input{margin-bottom:6px}.field-wizard table{table-layout:fixed;border-collapse:collapse;border-spacing:0}.field-wizard td.stretch{width:100%}.field-wizard .cb-wrap{font-weight:400}.field-wizard .cb-wrap input{margin-right:6px}.field-wizard .limit-height{border:1px solid #eee;padding:6px;max-height:200px;overflow-y:scroll}.available-fields{border:1px solid #ccc;padding:20px;background:#fff}.available-fields strong{display:block;margin-bottom:10px}.available-fields button{margin:0 6px 6px 0}.available-fields .is-required:after{content:" *";color:red}.available-fields .is-required.not-in-form{-webkit-box-shadow:0 0 3px 1px red;-moz-box-shadow:0 0 3px 1px red;box-shadow:0 0 3px 1px red}.available-fields .in-form{opacity:.5}
assets/css/form-theme-blue.css DELETED
@@ -1,274 +0,0 @@
1
- /* MailChimp for WP - Default Form Styles */
2
- .mc4wp-form {
3
- margin: 1em 0;
4
- /* Form Elements */
5
- /* Remove font-weight bold from nested elements */
6
- }
7
- .mc4wp-form form,
8
- .mc4wp-form label,
9
- .mc4wp-form input {
10
- width: auto;
11
- display: block;
12
- -webkit-box-sizing: border-box;
13
- -moz-box-sizing: border-box;
14
- box-sizing: border-box;
15
- cursor: auto;
16
- height: auto;
17
- vertical-align: baseline;
18
- line-height: normal;
19
- }
20
- .mc4wp-form form:after {
21
- content: "";
22
- display: table;
23
- clear: both;
24
- }
25
- .mc4wp-form label {
26
- font-weight: bold;
27
- margin-bottom: 5px;
28
- }
29
- .mc4wp-form input.placeholdersjs {
30
- color: #aaa !important;
31
- }
32
- .mc4wp-form input[type="text"],
33
- .mc4wp-form input[type="email"],
34
- .mc4wp-form input[type="tel"],
35
- .mc4wp-form input[type="url"],
36
- .mc4wp-form input[type="date"],
37
- .mc4wp-form input[type="number"],
38
- .mc4wp-form textarea,
39
- .mc4wp-form select {
40
- width: 100%;
41
- }
42
- .mc4wp-form input[type="number"] {
43
- min-width: 40px;
44
- }
45
- .mc4wp-form input[type="checkbox"],
46
- .mc4wp-form input[type="radio"] {
47
- position: relative;
48
- margin: 0 6px 0 0;
49
- padding: 0;
50
- height: 13px;
51
- width: 13px;
52
- display: inline-block;
53
- border: 0;
54
- }
55
- .mc4wp-form input[type="checkbox"] {
56
- -webkit-appearance: checkbox;
57
- -moz-appearance: checkbox;
58
- }
59
- .mc4wp-form input[type="radio"] {
60
- -webkit-appearance: radio;
61
- -moz-appearance: radio;
62
- }
63
- .mc4wp-form input[type="submit"],
64
- .mc4wp-form button,
65
- .mc4wp-form input[type="button"] {
66
- cursor: pointer;
67
- display: inline-block;
68
- -webkit-appearance: none;
69
- -moz-appearance: none;
70
- appearance: none;
71
- }
72
- .mc4wp-form label > span,
73
- .mc4wp-form li > label {
74
- font-weight: normal;
75
- }
76
-
77
- /* Right-To-Left specific styles */
78
- .rtl .mc4wp-form input[type="checkbox"],
79
- .rtl .mc4wp-form input[type="radio"] {
80
- margin: 0 0 0 6px;
81
- }
82
-
83
- /* Alert */
84
- .mc4wp-alert {
85
- margin: 1em 0;
86
- padding: 10px 15px;
87
- color: #c09853;
88
- background-color: #fcf8e3;
89
- border: 1px solid #fbeed5;
90
- -webkit-border-radius: 2px;
91
- -moz-border-radius: 2px;
92
- border-radius: 2px;
93
- display: block;
94
- position: relative;
95
- }
96
-
97
- .mc4wp-success {
98
- color: #468847;
99
- background-color: #dff0d8;
100
- border-color: #d6e9c6;
101
- }
102
-
103
- .mc4wp-notice {
104
- color: #3a87ad;
105
- background-color: #d9edf7;
106
- border-color: #bce8f1;
107
- }
108
-
109
- .mc4wp-error {
110
- color: #b94a48;
111
- background-color: #f2dede;
112
- border-color: #eed3d7;
113
- }
114
-
115
- /* Form base theme */
116
- form.mc4wp-form,
117
- .mc4wp-form form {
118
- -webkit-box-shadow: none;
119
- -moz-box-shadow: none;
120
- box-shadow: none !important;
121
- width: auto;
122
- }
123
-
124
- .mc4wp-form p {
125
- margin: 10px 0;
126
- padding: 0;
127
- }
128
-
129
- .mc4wp-form label {
130
- font-size: 1em;
131
- margin: 6px 0;
132
- }
133
-
134
- .mc4wp-form input[type="text"],
135
- .mc4wp-form input[type="email"],
136
- .mc4wp-form input[type="tel"],
137
- .mc4wp-form input[type="url"],
138
- .mc4wp-form input[type="date"],
139
- .mc4wp-form input[type="number"],
140
- .mc4wp-form textarea,
141
- .mc4wp-form select {
142
- width: 100%;
143
- height: 34px;
144
- margin: 0;
145
- padding: 6px 12px;
146
- font-size: 14px;
147
- line-height: 1.428571429;
148
- color: #555555 !important;
149
- vertical-align: middle;
150
- background-color: #ffffff;
151
- border: 1px solid #cccccc;
152
- -webkit-border-radius: 2px;
153
- -moz-border-radius: 2px;
154
- border-radius: 2px;
155
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
156
- -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
157
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
158
- -moz-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
159
- -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
160
- transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
161
- background-image: none;
162
- text-shadow: none;
163
- }
164
-
165
- .mc4wp-form input[type="text"]:focus,
166
- .mc4wp-form input[type="email"]:focus,
167
- .mc4wp-form input[type="tel"]:focus,
168
- .mc4wp-form input[type="url"]:focus,
169
- .mc4wp-form input[type="date"]:focus,
170
- .mc4wp-form input[type="number"]:focus,
171
- .mc4wp-form textarea:focus,
172
- .mc4wp-form select:focus {
173
- border-color: #66afe9;
174
- outline: 0;
175
- -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
176
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
177
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
178
- }
179
-
180
- .mc4wp-form textarea {
181
- height: auto;
182
- }
183
-
184
- .mc4wp-form input[readonly],
185
- .mc4wp-form input[disabled] {
186
- background-color: #eeeeee;
187
- }
188
-
189
- .mc4wp-form input[type="submit"],
190
- .mc4wp-form input[type="button"],
191
- .mc4wp-form button {
192
- display: inline-block;
193
- padding: 6px 12px;
194
- margin: 0;
195
- font-size: 14px;
196
- font-weight: normal;
197
- line-height: 1.428571429;
198
- text-align: center;
199
- white-space: nowrap;
200
- vertical-align: middle;
201
- cursor: pointer;
202
- border: 1px solid transparent;
203
- border-radius: 2px;
204
- -webkit-user-select: none;
205
- -moz-user-select: none;
206
- -ms-user-select: none;
207
- -o-user-select: none;
208
- user-select: none;
209
- box-shadow: none;
210
- background: none;
211
- text-shadow: none;
212
- filter: none;
213
- height: auto;
214
- width: auto;
215
- }
216
-
217
- .mc4wp-form input[type="submit"]:focus,
218
- .mc4wp-form input[type="button"]:focus,
219
- .mc4wp-form button:focus {
220
- outline: thin dotted #333;
221
- outline: 5px auto -webkit-focus-ring-color;
222
- outline-offset: -2px;
223
- }
224
-
225
- .mc4wp-form input[type="submit"]:hover,
226
- .mc4wp-form input[type="button"]:hover,
227
- .mc4wp-form button:hover,
228
- .mc4wp-form input[type="submit"]:focus,
229
- .mc4wp-form input[type="button"]:focus,
230
- .mc4wp-form button:focus {
231
- color: #333333;
232
- text-decoration: none;
233
- background: none;
234
- }
235
-
236
- .mc4wp-form input[type="submit"]:active,
237
- .mc4wp-form input[type="button"]:active,
238
- .mc4wp-form button:active {
239
- background-image: none;
240
- outline: 0;
241
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
242
- -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
243
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
244
- }
245
-
246
- .mc4wp-form input[type="submit"],
247
- .mc4wp-form button {
248
- color: #ffffff !important;
249
- background-color: #428bca !important;
250
- border-color: #357ebd;
251
- }
252
-
253
- .mc4wp-form input[type="submit"]:hover,
254
- .mc4wp-form button:hover,
255
- .mc4wp-form input[type="submit"]:active,
256
- .mc4wp-form button:active,
257
- .mc4wp-form input[type="submit"]:focus,
258
- .mc4wp-form button:focus {
259
- color: #ffffff !important;
260
- background-color: #3276b1 !important;
261
- border-color: #285e8e;
262
- }
263
-
264
- .mc4wp-form input[type="text"]:focus,
265
- .mc4wp-form input[type="email"]:focus,
266
- .mc4wp-form input[type="tel"]:focus,
267
- .mc4wp-form input[type="url"]:focus,
268
- .mc4wp-form input[type="date"]:focus,
269
- .mc4wp-form textarea:focus,
270
- .mc4wp-form select:focus {
271
- border-color: #428bca;
272
- }
273
-
274
- /*# sourceMappingURL=form-theme-blue.css.map */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/form-theme-blue.css.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "mappings": ";AAEA,WAAW;EACV,MAAM,EAAE,KAAK;;;;AAEb;;iBAEM;EACL,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EACd,kBAAkB,EAAE,UAAU;EAC9B,eAAe,EAAE,UAAU;EAC3B,UAAU,EAAE,UAAU;EACtB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,cAAc,EAAE,QAAQ;EACxB,WAAW,EAAE,MAAM;;AAKnB,sBAAQ;EACP,OAAO,EAAC,EAAE;EACV,OAAO,EAAC,KAAK;EACb,KAAK,EAAC,IAAI;;AAIZ,iBAAM;EACL,WAAW,EAAE,IAAI;EACjB,aAAa,EAAE,GAAG;;AAMlB,gCAAiB;EAChB,KAAK,EAAE,eAAe;;AAKxB;;;;;;;kBAOO;EACN,KAAK,EAAE,IAAI;;AAGZ,gCAAqB;EACpB,SAAS,EAAE,IAAI;;AAGhB;+BACoB;EACnB,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,SAAS;EACjB,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,YAAY;EACrB,MAAM,EAAE,CAAC;;AAGV,kCAAuB;EACtB,kBAAkB,EAAE,QAAQ;EAC5B,eAAe,EAAE,QAAQ;;AAG1B,+BAAoB;EACnB,kBAAkB,EAAE,KAAK;EACzB,eAAe,EAAE,KAAK;;AAGvB;;gCAEqB;EACpB,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,YAAY;EACrB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAK,IAAI;EACxB,UAAU,EAAU,IAAI;;AAIzB;sBACW;EACV,WAAW,EAAE,MAAM;;;;AAQnB;oCACoB;EACnB,MAAM,EAAE,SAAS;;;;AAMpB,YAAY;EACX,MAAM,EAAE,KAAK;EACb,OAAO,EAAE,SAAS;EAClB,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,iBAAiB;EACzB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,OAAO,EAAE,KAAK;EACd,QAAQ,EAAE,QAAQ;;;AAGnB,cAAe;EACd,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;AAGtB,aAAc;EACb,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;AAGtB,YAAa;EACZ,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;;ACtItB;gBACiB;EAChB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,eAAe;EAC3B,KAAK,EAAE,IAAI;;;AAGZ,aAAc;EACb,MAAM,EAAE,MAAM;EACd,OAAO,EAAE,CAAC;;;AAGX,iBAAiB;EAChB,SAAS,EAAC,GAAG;EACb,MAAM,EAAC,KAAK;;;AAGb;;;;;;;kBAOmB;EAClB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,QAAQ;EACjB,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,WAAW;EACxB,KAAK,EAAE,kBAAkB;EACzB,cAAc,EAAE,MAAM;EACtB,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,iBAAiB;EACzB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,kBAAkB,EAAE,oCAAoC;EACxD,eAAe,EAAE,oCAAoC;EACrD,UAAU,EAAE,oCAAoC;EAChD,eAAe,EAAE,4DAA4D;EAC7E,kBAAkB,EAAE,4DAA4D;EAChF,UAAU,EAAE,4DAA4D;EACxE,gBAAgB,EAAE,IAAI;EACtB,WAAW,EAAE,IAAI;;;AAGlB;;;;;;;wBAOyB;EACxB,YAAY,EAAE,OAAO;EACrB,OAAO,EAAE,CAAC;EACV,eAAe,EAAE,sEAAoC;EACrD,kBAAkB,EAAE,sEAAoC;EACxD,UAAU,EAAE,sEAAoC;;;AAGjD,oBAAoB;EACnB,MAAM,EAAE,IAAI;;;AAGb;2BAC4B;EAC3B,gBAAgB,EAAE,OAAO;;;AAG1B;;kBAEmB;EAClB,OAAO,EAAE,YAAY;EACrB,OAAO,EAAE,QAAQ;EACjB,MAAM,EAAE,CAAC;EACT,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,MAAM;EACnB,WAAW,EAAE,WAAW;EACxB,UAAU,EAAE,MAAM;EAClB,WAAW,EAAE,MAAM;EACnB,cAAc,EAAE,MAAM;EACtB,MAAM,EAAE,OAAO;EACf,MAAM,EAAE,qBAAqB;EAC7B,aAAa,EAAE,GAAG;EAClB,mBAAmB,EAAE,IAAI;EACzB,gBAAgB,EAAE,IAAI;EACtB,eAAe,EAAE,IAAI;EACrB,cAAc,EAAE,IAAI;EACpB,WAAW,EAAE,IAAI;EACjB,UAAU,EAAE,IAAI;EAChB,UAAU,EAAE,IAAI;EAChB,WAAW,EAAE,IAAI;EACjB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;;;AAGZ;;wBAEyB;EACxB,OAAO,EAAE,gBAAgB;EACzB,OAAO,EAAE,iCAAiC;EAC1C,cAAc,EAAE,IAAI;;;AAGrB;;;;;wBAKyB;EACxB,KAAK,EAAE,OAAO;EACd,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,IAAI;;;AAGjB;;yBAE0B;EACzB,gBAAgB,EAAE,IAAI;EACtB,OAAO,EAAE,CAAC;EACV,kBAAkB,EAAE,oCAAoC;EACxD,eAAe,EAAE,oCAAoC;EACrD,UAAU,EAAE,oCAAoC;;;AC7HjD;kBACmB;EACjB,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;;AAGvB;;;;;wBAKyB;EACvB,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;;AAGvB;;;;;;wBAMyB;EACvB,YAAY,EAAE,OAAO",
4
- "sources": ["../sass/partials/_form-reset.scss","../sass/partials/_form-theme-base.scss","../sass/form-theme-blue.scss"],
5
- "names": [],
6
- "file": "form-theme-blue.css"
7
- }
 
 
 
 
 
 
 
assets/css/form-theme-blue.min.css DELETED
@@ -1 +0,0 @@
1
- .mc4wp-form{margin:1em 0}.mc4wp-form form,.mc4wp-form input,.mc4wp-form label{width:auto;display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:auto;height:auto;vertical-align:baseline;line-height:normal}.mc4wp-form form:after{content:"";display:table;clear:both}.mc4wp-form label{font-weight:700}.mc4wp-form input.placeholdersjs{color:#aaa!important}.mc4wp-form input[type=number]{min-width:40px}.mc4wp-form input[type=checkbox],.mc4wp-form input[type=radio]{position:relative;margin:0 6px 0 0;padding:0;height:13px;width:13px;display:inline-block;border:0}.mc4wp-form input[type=checkbox]{-webkit-appearance:checkbox;-moz-appearance:checkbox}.mc4wp-form input[type=radio]{-webkit-appearance:radio;-moz-appearance:radio}.mc4wp-form button,.mc4wp-form input[type=button],.mc4wp-form input[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none}.mc4wp-form label>span,.mc4wp-form li>label{font-weight:400}.rtl .mc4wp-form input[type=checkbox],.rtl .mc4wp-form input[type=radio]{margin:0 0 0 6px}.mc4wp-alert{margin:1em 0;padding:10px 15px;color:#c09853;background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;display:block;position:relative}.mc4wp-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.mc4wp-notice{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.mc4wp-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.mc4wp-form form,form.mc4wp-form{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none!important;width:auto}.mc4wp-form p{margin:10px 0;padding:0}.mc4wp-form label{font-size:1em;margin:6px 0}.mc4wp-form input[type=date],.mc4wp-form input[type=email],.mc4wp-form input[type=number],.mc4wp-form input[type=tel],.mc4wp-form input[type=text],.mc4wp-form input[type=url],.mc4wp-form select,.mc4wp-form textarea{width:100%;height:34px;margin:0;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555!important;vertical-align:middle;background-color:#fff;border:1px solid #ccc;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;background-image:none;text-shadow:none}.mc4wp-form input[type=date]:focus,.mc4wp-form input[type=email]:focus,.mc4wp-form input[type=number]:focus,.mc4wp-form input[type=tel]:focus,.mc4wp-form input[type=text]:focus,.mc4wp-form input[type=url]:focus,.mc4wp-form select:focus,.mc4wp-form textarea:focus{border-color:#66afe9;outline:0;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.mc4wp-form textarea{height:auto}.mc4wp-form input[disabled],.mc4wp-form input[readonly]{background-color:#eee}.mc4wp-form button,.mc4wp-form input[type=button],.mc4wp-form input[type=submit]{display:inline-block;padding:6px 12px;margin:0;font-size:14px;font-weight:400;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:2px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;box-shadow:none;background:0 0;text-shadow:none;filter:none;height:auto;width:auto}.mc4wp-form button:focus,.mc4wp-form input[type=button]:focus,.mc4wp-form input[type=submit]:focus{outline:#333 dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.mc4wp-form button:focus,.mc4wp-form button:hover,.mc4wp-form input[type=button]:focus,.mc4wp-form input[type=button]:hover,.mc4wp-form input[type=submit]:focus,.mc4wp-form input[type=submit]:hover{color:#333;text-decoration:none;background:0 0}.mc4wp-form button:active,.mc4wp-form input[type=button]:active,.mc4wp-form input[type=submit]:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);-moz-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.mc4wp-form button,.mc4wp-form input[type=submit]{color:#fff!important;background-color:#428bca!important;border-color:#357ebd}.mc4wp-form button:active,.mc4wp-form button:focus,.mc4wp-form button:hover,.mc4wp-form input[type=submit]:active,.mc4wp-form input[type=submit]:focus,.mc4wp-form input[type=submit]:hover{color:#fff!important;background-color:#3276b1!important;border-color:#285e8e}.mc4wp-form input[type=date]:focus,.mc4wp-form input[type=email]:focus,.mc4wp-form input[type=tel]:focus,.mc4wp-form input[type=text]:focus,.mc4wp-form input[type=url]:focus,.mc4wp-form select:focus,.mc4wp-form textarea:focus{border-color:#428bca}
 
assets/css/form-theme-dark.css DELETED
@@ -1,274 +0,0 @@
1
- /* MailChimp for WP - Default Form Styles */
2
- .mc4wp-form {
3
- margin: 1em 0;
4
- /* Form Elements */
5
- /* Remove font-weight bold from nested elements */
6
- }
7
- .mc4wp-form form,
8
- .mc4wp-form label,
9
- .mc4wp-form input {
10
- width: auto;
11
- display: block;
12
- -webkit-box-sizing: border-box;
13
- -moz-box-sizing: border-box;
14
- box-sizing: border-box;
15
- cursor: auto;
16
- height: auto;
17
- vertical-align: baseline;
18
- line-height: normal;
19
- }
20
- .mc4wp-form form:after {
21
- content: "";
22
- display: table;
23
- clear: both;
24
- }
25
- .mc4wp-form label {
26
- font-weight: bold;
27
- margin-bottom: 5px;
28
- }
29
- .mc4wp-form input.placeholdersjs {
30
- color: #aaa !important;
31
- }
32
- .mc4wp-form input[type="text"],
33
- .mc4wp-form input[type="email"],
34
- .mc4wp-form input[type="tel"],
35
- .mc4wp-form input[type="url"],
36
- .mc4wp-form input[type="date"],
37
- .mc4wp-form input[type="number"],
38
- .mc4wp-form textarea,
39
- .mc4wp-form select {
40
- width: 100%;
41
- }
42
- .mc4wp-form input[type="number"] {
43
- min-width: 40px;
44
- }
45
- .mc4wp-form input[type="checkbox"],
46
- .mc4wp-form input[type="radio"] {
47
- position: relative;
48
- margin: 0 6px 0 0;
49
- padding: 0;
50
- height: 13px;
51
- width: 13px;
52
- display: inline-block;
53
- border: 0;
54
- }
55
- .mc4wp-form input[type="checkbox"] {
56
- -webkit-appearance: checkbox;
57
- -moz-appearance: checkbox;
58
- }
59
- .mc4wp-form input[type="radio"] {
60
- -webkit-appearance: radio;
61
- -moz-appearance: radio;
62
- }
63
- .mc4wp-form input[type="submit"],
64
- .mc4wp-form button,
65
- .mc4wp-form input[type="button"] {
66
- cursor: pointer;
67
- display: inline-block;
68
- -webkit-appearance: none;
69
- -moz-appearance: none;
70
- appearance: none;
71
- }
72
- .mc4wp-form label > span,
73
- .mc4wp-form li > label {
74
- font-weight: normal;
75
- }
76
-
77
- /* Right-To-Left specific styles */
78
- .rtl .mc4wp-form input[type="checkbox"],
79
- .rtl .mc4wp-form input[type="radio"] {
80
- margin: 0 0 0 6px;
81
- }
82
-
83
- /* Alert */
84
- .mc4wp-alert {
85
- margin: 1em 0;
86
- padding: 10px 15px;
87
- color: #c09853;
88
- background-color: #fcf8e3;
89
- border: 1px solid #fbeed5;
90
- -webkit-border-radius: 2px;
91
- -moz-border-radius: 2px;
92
- border-radius: 2px;
93
- display: block;
94
- position: relative;
95
- }
96
-
97
- .mc4wp-success {
98
- color: #468847;
99
- background-color: #dff0d8;
100
- border-color: #d6e9c6;
101
- }
102
-
103
- .mc4wp-notice {
104
- color: #3a87ad;
105
- background-color: #d9edf7;
106
- border-color: #bce8f1;
107
- }
108
-
109
- .mc4wp-error {
110
- color: #b94a48;
111
- background-color: #f2dede;
112
- border-color: #eed3d7;
113
- }
114
-
115
- /* Form base theme */
116
- form.mc4wp-form,
117
- .mc4wp-form form {
118
- -webkit-box-shadow: none;
119
- -moz-box-shadow: none;
120
- box-shadow: none !important;
121
- width: auto;
122
- }
123
-
124
- .mc4wp-form p {
125
- margin: 10px 0;
126
- padding: 0;
127
- }
128
-
129
- .mc4wp-form label {
130
- font-size: 1em;
131
- margin: 6px 0;
132
- }
133
-
134
- .mc4wp-form input[type="text"],
135
- .mc4wp-form input[type="email"],
136
- .mc4wp-form input[type="tel"],
137
- .mc4wp-form input[type="url"],
138
- .mc4wp-form input[type="date"],
139
- .mc4wp-form input[type="number"],
140
- .mc4wp-form textarea,
141
- .mc4wp-form select {
142
- width: 100%;
143
- height: 34px;
144
- margin: 0;
145
- padding: 6px 12px;
146
- font-size: 14px;
147
- line-height: 1.428571429;
148
- color: #555555 !important;
149
- vertical-align: middle;
150
- background-color: #ffffff;
151
- border: 1px solid #cccccc;
152
- -webkit-border-radius: 2px;
153
- -moz-border-radius: 2px;
154
- border-radius: 2px;
155
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
156
- -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
157
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
158
- -moz-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
159
- -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
160
- transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
161
- background-image: none;
162
- text-shadow: none;
163
- }
164
-
165
- .mc4wp-form input[type="text"]:focus,
166
- .mc4wp-form input[type="email"]:focus,
167
- .mc4wp-form input[type="tel"]:focus,
168
- .mc4wp-form input[type="url"]:focus,
169
- .mc4wp-form input[type="date"]:focus,
170
- .mc4wp-form input[type="number"]:focus,
171
- .mc4wp-form textarea:focus,
172
- .mc4wp-form select:focus {
173
- border-color: #66afe9;
174
- outline: 0;
175
- -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
176
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
177
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
178
- }
179
-
180
- .mc4wp-form textarea {
181
- height: auto;
182
- }
183
-
184
- .mc4wp-form input[readonly],
185
- .mc4wp-form input[disabled] {
186
- background-color: #eeeeee;
187
- }
188
-
189
- .mc4wp-form input[type="submit"],
190
- .mc4wp-form input[type="button"],
191
- .mc4wp-form button {
192
- display: inline-block;
193
- padding: 6px 12px;
194
- margin: 0;
195
- font-size: 14px;
196
- font-weight: normal;
197
- line-height: 1.428571429;
198
- text-align: center;
199
- white-space: nowrap;
200
- vertical-align: middle;
201
- cursor: pointer;
202
- border: 1px solid transparent;
203
- border-radius: 2px;
204
- -webkit-user-select: none;
205
- -moz-user-select: none;
206
- -ms-user-select: none;
207
- -o-user-select: none;
208
- user-select: none;
209
- box-shadow: none;
210
- background: none;
211
- text-shadow: none;
212
- filter: none;
213
- height: auto;
214
- width: auto;
215
- }
216
-
217
- .mc4wp-form input[type="submit"]:focus,
218
- .mc4wp-form input[type="button"]:focus,
219
- .mc4wp-form button:focus {
220
- outline: thin dotted #333;
221
- outline: 5px auto -webkit-focus-ring-color;
222
- outline-offset: -2px;
223
- }
224
-
225
- .mc4wp-form input[type="submit"]:hover,
226
- .mc4wp-form input[type="button"]:hover,
227
- .mc4wp-form button:hover,
228
- .mc4wp-form input[type="submit"]:focus,
229
- .mc4wp-form input[type="button"]:focus,
230
- .mc4wp-form button:focus {
231
- color: #333333;
232
- text-decoration: none;
233
- background: none;
234
- }
235
-
236
- .mc4wp-form input[type="submit"]:active,
237
- .mc4wp-form input[type="button"]:active,
238
- .mc4wp-form button:active {
239
- background-image: none;
240
- outline: 0;
241
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
242
- -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
243
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
244
- }
245
-
246
- .mc4wp-form input[type="submit"],
247
- .mc4wp-form button {
248
- color: #ffffff !important;
249
- background-color: #444444 !important;
250
- border-color: #282828;
251
- }
252
-
253
- .mc4wp-form input[type="submit"]:hover,
254
- .mc4wp-form button:hover,
255
- .mc4wp-form input[type="submit"]:active,
256
- .mc4wp-form button:active,
257
- .mc4wp-form input[type="submit"]:focus,
258
- .mc4wp-form button:focus {
259
- color: #ffffff !important;
260
- background-color: #282828 !important;
261
- border-color: #111111;
262
- }
263
-
264
- .mc4wp-form input[type="text"]:focus,
265
- .mc4wp-form input[type="email"]:focus,
266
- .mc4wp-form input[type="tel"]:focus,
267
- .mc4wp-form input[type="url"]:focus,
268
- .mc4wp-form input[type="date"]:focus,
269
- .mc4wp-form textarea:focus,
270
- .mc4wp-form select:focus {
271
- border-color: #444444;
272
- }
273
-
274
- /*# sourceMappingURL=form-theme-dark.css.map */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/form-theme-dark.css.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "mappings": ";AAEA,WAAW;EACV,MAAM,EAAE,KAAK;;;;AAEb;;iBAEM;EACL,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EACd,kBAAkB,EAAE,UAAU;EAC9B,eAAe,EAAE,UAAU;EAC3B,UAAU,EAAE,UAAU;EACtB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,cAAc,EAAE,QAAQ;EACxB,WAAW,EAAE,MAAM;;AAKnB,sBAAQ;EACP,OAAO,EAAC,EAAE;EACV,OAAO,EAAC,KAAK;EACb,KAAK,EAAC,IAAI;;AAIZ,iBAAM;EACL,WAAW,EAAE,IAAI;EACjB,aAAa,EAAE,GAAG;;AAMlB,gCAAiB;EAChB,KAAK,EAAE,eAAe;;AAKxB;;;;;;;kBAOO;EACN,KAAK,EAAE,IAAI;;AAGZ,gCAAqB;EACpB,SAAS,EAAE,IAAI;;AAGhB;+BACoB;EACnB,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,SAAS;EACjB,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,YAAY;EACrB,MAAM,EAAE,CAAC;;AAGV,kCAAuB;EACtB,kBAAkB,EAAE,QAAQ;EAC5B,eAAe,EAAE,QAAQ;;AAG1B,+BAAoB;EACnB,kBAAkB,EAAE,KAAK;EACzB,eAAe,EAAE,KAAK;;AAGvB;;gCAEqB;EACpB,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,YAAY;EACrB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAK,IAAI;EACxB,UAAU,EAAU,IAAI;;AAIzB;sBACW;EACV,WAAW,EAAE,MAAM;;;;AAQnB;oCACoB;EACnB,MAAM,EAAE,SAAS;;;;AAMpB,YAAY;EACX,MAAM,EAAE,KAAK;EACb,OAAO,EAAE,SAAS;EAClB,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,iBAAiB;EACzB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,OAAO,EAAE,KAAK;EACd,QAAQ,EAAE,QAAQ;;;AAGnB,cAAe;EACd,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;AAGtB,aAAc;EACb,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;AAGtB,YAAa;EACZ,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;;ACtItB;gBACiB;EAChB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,eAAe;EAC3B,KAAK,EAAE,IAAI;;;AAGZ,aAAc;EACb,MAAM,EAAE,MAAM;EACd,OAAO,EAAE,CAAC;;;AAGX,iBAAiB;EAChB,SAAS,EAAC,GAAG;EACb,MAAM,EAAC,KAAK;;;AAGb;;;;;;;kBAOmB;EAClB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,QAAQ;EACjB,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,WAAW;EACxB,KAAK,EAAE,kBAAkB;EACzB,cAAc,EAAE,MAAM;EACtB,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,iBAAiB;EACzB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,kBAAkB,EAAE,oCAAoC;EACxD,eAAe,EAAE,oCAAoC;EACrD,UAAU,EAAE,oCAAoC;EAChD,eAAe,EAAE,4DAA4D;EAC7E,kBAAkB,EAAE,4DAA4D;EAChF,UAAU,EAAE,4DAA4D;EACxE,gBAAgB,EAAE,IAAI;EACtB,WAAW,EAAE,IAAI;;;AAGlB;;;;;;;wBAOyB;EACxB,YAAY,EAAE,OAAO;EACrB,OAAO,EAAE,CAAC;EACV,eAAe,EAAE,sEAAoC;EACrD,kBAAkB,EAAE,sEAAoC;EACxD,UAAU,EAAE,sEAAoC;;;AAGjD,oBAAoB;EACnB,MAAM,EAAE,IAAI;;;AAGb;2BAC4B;EAC3B,gBAAgB,EAAE,OAAO;;;AAG1B;;kBAEmB;EAClB,OAAO,EAAE,YAAY;EACrB,OAAO,EAAE,QAAQ;EACjB,MAAM,EAAE,CAAC;EACT,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,MAAM;EACnB,WAAW,EAAE,WAAW;EACxB,UAAU,EAAE,MAAM;EAClB,WAAW,EAAE,MAAM;EACnB,cAAc,EAAE,MAAM;EACtB,MAAM,EAAE,OAAO;EACf,MAAM,EAAE,qBAAqB;EAC7B,aAAa,EAAE,GAAG;EAClB,mBAAmB,EAAE,IAAI;EACzB,gBAAgB,EAAE,IAAI;EACtB,eAAe,EAAE,IAAI;EACrB,cAAc,EAAE,IAAI;EACpB,WAAW,EAAE,IAAI;EACjB,UAAU,EAAE,IAAI;EAChB,UAAU,EAAE,IAAI;EAChB,WAAW,EAAE,IAAI;EACjB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;;;AAGZ;;wBAEyB;EACxB,OAAO,EAAE,gBAAgB;EACzB,OAAO,EAAE,iCAAiC;EAC1C,cAAc,EAAE,IAAI;;;AAGrB;;;;;wBAKyB;EACxB,KAAK,EAAE,OAAO;EACd,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,IAAI;;;AAGjB;;yBAE0B;EACzB,gBAAgB,EAAE,IAAI;EACtB,OAAO,EAAE,CAAC;EACV,kBAAkB,EAAE,oCAAoC;EACxD,eAAe,EAAE,oCAAoC;EACrD,UAAU,EAAE,oCAAoC;;;AC7HjD;kBACmB;EACjB,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;;AAGvB;;;;;wBAKyB;EACvB,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;;AAGvB;;;;;;wBAMyB;EACvB,YAAY,EAAE,OAAO",
4
- "sources": ["../sass/partials/_form-reset.scss","../sass/partials/_form-theme-base.scss","../sass/form-theme-dark.scss"],
5
- "names": [],
6
- "file": "form-theme-dark.css"
7
- }
 
 
 
 
 
 
 
assets/css/form-theme-dark.min.css DELETED
@@ -1 +0,0 @@
1
- .mc4wp-form{margin:1em 0}.mc4wp-form form,.mc4wp-form input,.mc4wp-form label{width:auto;display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:auto;height:auto;vertical-align:baseline;line-height:normal}.mc4wp-form form:after{content:"";display:table;clear:both}.mc4wp-form label{font-weight:700}.mc4wp-form input.placeholdersjs{color:#aaa!important}.mc4wp-form input[type=number]{min-width:40px}.mc4wp-form input[type=checkbox],.mc4wp-form input[type=radio]{position:relative;margin:0 6px 0 0;padding:0;height:13px;width:13px;display:inline-block;border:0}.mc4wp-form input[type=checkbox]{-webkit-appearance:checkbox;-moz-appearance:checkbox}.mc4wp-form input[type=radio]{-webkit-appearance:radio;-moz-appearance:radio}.mc4wp-form button,.mc4wp-form input[type=button],.mc4wp-form input[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none}.mc4wp-form label>span,.mc4wp-form li>label{font-weight:400}.rtl .mc4wp-form input[type=checkbox],.rtl .mc4wp-form input[type=radio]{margin:0 0 0 6px}.mc4wp-alert{margin:1em 0;padding:10px 15px;color:#c09853;background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;display:block;position:relative}.mc4wp-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.mc4wp-notice{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.mc4wp-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.mc4wp-form form,form.mc4wp-form{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none!important;width:auto}.mc4wp-form p{margin:10px 0;padding:0}.mc4wp-form label{font-size:1em;margin:6px 0}.mc4wp-form input[type=date],.mc4wp-form input[type=email],.mc4wp-form input[type=number],.mc4wp-form input[type=tel],.mc4wp-form input[type=text],.mc4wp-form input[type=url],.mc4wp-form select,.mc4wp-form textarea{width:100%;height:34px;margin:0;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555!important;vertical-align:middle;background-color:#fff;border:1px solid #ccc;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;background-image:none;text-shadow:none}.mc4wp-form input[type=date]:focus,.mc4wp-form input[type=email]:focus,.mc4wp-form input[type=number]:focus,.mc4wp-form input[type=tel]:focus,.mc4wp-form input[type=text]:focus,.mc4wp-form input[type=url]:focus,.mc4wp-form select:focus,.mc4wp-form textarea:focus{border-color:#66afe9;outline:0;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.mc4wp-form textarea{height:auto}.mc4wp-form input[disabled],.mc4wp-form input[readonly]{background-color:#eee}.mc4wp-form button,.mc4wp-form input[type=button],.mc4wp-form input[type=submit]{display:inline-block;padding:6px 12px;margin:0;font-size:14px;font-weight:400;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:2px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;box-shadow:none;background:0 0;text-shadow:none;filter:none;height:auto;width:auto}.mc4wp-form button:focus,.mc4wp-form input[type=button]:focus,.mc4wp-form input[type=submit]:focus{outline:#333 dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.mc4wp-form button:focus,.mc4wp-form button:hover,.mc4wp-form input[type=button]:focus,.mc4wp-form input[type=button]:hover,.mc4wp-form input[type=submit]:focus,.mc4wp-form input[type=submit]:hover{color:#333;text-decoration:none;background:0 0}.mc4wp-form button:active,.mc4wp-form input[type=button]:active,.mc4wp-form input[type=submit]:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);-moz-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.mc4wp-form button,.mc4wp-form input[type=submit]{color:#fff!important;background-color:#444!important;border-color:#282828}.mc4wp-form button:active,.mc4wp-form button:focus,.mc4wp-form button:hover,.mc4wp-form input[type=submit]:active,.mc4wp-form input[type=submit]:focus,.mc4wp-form input[type=submit]:hover{color:#fff!important;background-color:#282828!important;border-color:#111}.mc4wp-form input[type=date]:focus,.mc4wp-form input[type=email]:focus,.mc4wp-form input[type=tel]:focus,.mc4wp-form input[type=text]:focus,.mc4wp-form input[type=url]:focus,.mc4wp-form select:focus,.mc4wp-form textarea:focus{border-color:#444}
 
assets/css/form-theme-green.css DELETED
@@ -1,274 +0,0 @@
1
- /* MailChimp for WP - Default Form Styles */
2
- .mc4wp-form {
3
- margin: 1em 0;
4
- /* Form Elements */
5
- /* Remove font-weight bold from nested elements */
6
- }
7
- .mc4wp-form form,
8
- .mc4wp-form label,
9
- .mc4wp-form input {
10
- width: auto;
11
- display: block;
12
- -webkit-box-sizing: border-box;
13
- -moz-box-sizing: border-box;
14
- box-sizing: border-box;
15
- cursor: auto;
16
- height: auto;
17
- vertical-align: baseline;
18
- line-height: normal;
19
- }
20
- .mc4wp-form form:after {
21
- content: "";
22
- display: table;
23
- clear: both;
24
- }
25
- .mc4wp-form label {
26
- font-weight: bold;
27
- margin-bottom: 5px;
28
- }
29
- .mc4wp-form input.placeholdersjs {
30
- color: #aaa !important;
31
- }
32
- .mc4wp-form input[type="text"],
33
- .mc4wp-form input[type="email"],
34
- .mc4wp-form input[type="tel"],
35
- .mc4wp-form input[type="url"],
36
- .mc4wp-form input[type="date"],
37
- .mc4wp-form input[type="number"],
38
- .mc4wp-form textarea,
39
- .mc4wp-form select {
40
- width: 100%;
41
- }
42
- .mc4wp-form input[type="number"] {
43
- min-width: 40px;
44
- }
45
- .mc4wp-form input[type="checkbox"],
46
- .mc4wp-form input[type="radio"] {
47
- position: relative;
48
- margin: 0 6px 0 0;
49
- padding: 0;
50
- height: 13px;
51
- width: 13px;
52
- display: inline-block;
53
- border: 0;
54
- }
55
- .mc4wp-form input[type="checkbox"] {
56
- -webkit-appearance: checkbox;
57
- -moz-appearance: checkbox;
58
- }
59
- .mc4wp-form input[type="radio"] {
60
- -webkit-appearance: radio;
61
- -moz-appearance: radio;
62
- }
63
- .mc4wp-form input[type="submit"],
64
- .mc4wp-form button,
65
- .mc4wp-form input[type="button"] {
66
- cursor: pointer;
67
- display: inline-block;
68
- -webkit-appearance: none;
69
- -moz-appearance: none;
70
- appearance: none;
71
- }
72
- .mc4wp-form label > span,
73
- .mc4wp-form li > label {
74
- font-weight: normal;
75
- }
76
-
77
- /* Right-To-Left specific styles */
78
- .rtl .mc4wp-form input[type="checkbox"],
79
- .rtl .mc4wp-form input[type="radio"] {
80
- margin: 0 0 0 6px;
81
- }
82
-
83
- /* Alert */
84
- .mc4wp-alert {
85
- margin: 1em 0;
86
- padding: 10px 15px;
87
- color: #c09853;
88
- background-color: #fcf8e3;
89
- border: 1px solid #fbeed5;
90
- -webkit-border-radius: 2px;
91
- -moz-border-radius: 2px;
92
- border-radius: 2px;
93
- display: block;
94
- position: relative;
95
- }
96
-
97
- .mc4wp-success {
98
- color: #468847;
99
- background-color: #dff0d8;
100
- border-color: #d6e9c6;
101
- }
102
-
103
- .mc4wp-notice {
104
- color: #3a87ad;
105
- background-color: #d9edf7;
106
- border-color: #bce8f1;
107
- }
108
-
109
- .mc4wp-error {
110
- color: #b94a48;
111
- background-color: #f2dede;
112
- border-color: #eed3d7;
113
- }
114
-
115
- /* Form base theme */
116
- form.mc4wp-form,
117
- .mc4wp-form form {
118
- -webkit-box-shadow: none;
119
- -moz-box-shadow: none;
120
- box-shadow: none !important;
121
- width: auto;
122
- }
123
-
124
- .mc4wp-form p {
125
- margin: 10px 0;
126
- padding: 0;
127
- }
128
-
129
- .mc4wp-form label {
130
- font-size: 1em;
131
- margin: 6px 0;
132
- }
133
-
134
- .mc4wp-form input[type="text"],
135
- .mc4wp-form input[type="email"],
136
- .mc4wp-form input[type="tel"],
137
- .mc4wp-form input[type="url"],
138
- .mc4wp-form input[type="date"],
139
- .mc4wp-form input[type="number"],
140
- .mc4wp-form textarea,
141
- .mc4wp-form select {
142
- width: 100%;
143
- height: 34px;
144
- margin: 0;
145
- padding: 6px 12px;
146
- font-size: 14px;
147
- line-height: 1.428571429;
148
- color: #555555 !important;
149
- vertical-align: middle;
150
- background-color: #ffffff;
151
- border: 1px solid #cccccc;
152
- -webkit-border-radius: 2px;
153
- -moz-border-radius: 2px;
154
- border-radius: 2px;
155
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
156
- -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
157
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
158
- -moz-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
159
- -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
160
- transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
161
- background-image: none;
162
- text-shadow: none;
163
- }
164
-
165
- .mc4wp-form input[type="text"]:focus,
166
- .mc4wp-form input[type="email"]:focus,
167
- .mc4wp-form input[type="tel"]:focus,
168
- .mc4wp-form input[type="url"]:focus,
169
- .mc4wp-form input[type="date"]:focus,
170
- .mc4wp-form input[type="number"]:focus,
171
- .mc4wp-form textarea:focus,
172
- .mc4wp-form select:focus {
173
- border-color: #66afe9;
174
- outline: 0;
175
- -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
176
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
177
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
178
- }
179
-
180
- .mc4wp-form textarea {
181
- height: auto;
182
- }
183
-
184
- .mc4wp-form input[readonly],
185
- .mc4wp-form input[disabled] {
186
- background-color: #eeeeee;
187
- }
188
-
189
- .mc4wp-form input[type="submit"],
190
- .mc4wp-form input[type="button"],
191
- .mc4wp-form button {
192
- display: inline-block;
193
- padding: 6px 12px;
194
- margin: 0;
195
- font-size: 14px;
196
- font-weight: normal;
197
- line-height: 1.428571429;
198
- text-align: center;
199
- white-space: nowrap;
200
- vertical-align: middle;
201
- cursor: pointer;
202
- border: 1px solid transparent;
203
- border-radius: 2px;
204
- -webkit-user-select: none;
205
- -moz-user-select: none;
206
- -ms-user-select: none;
207
- -o-user-select: none;
208
- user-select: none;
209
- box-shadow: none;
210
- background: none;
211
- text-shadow: none;
212
- filter: none;
213
- height: auto;
214
- width: auto;
215
- }
216
-
217
- .mc4wp-form input[type="submit"]:focus,
218
- .mc4wp-form input[type="button"]:focus,
219
- .mc4wp-form button:focus {
220
- outline: thin dotted #333;
221
- outline: 5px auto -webkit-focus-ring-color;
222
- outline-offset: -2px;
223
- }
224
-
225
- .mc4wp-form input[type="submit"]:hover,
226
- .mc4wp-form input[type="button"]:hover,
227
- .mc4wp-form button:hover,
228
- .mc4wp-form input[type="submit"]:focus,
229
- .mc4wp-form input[type="button"]:focus,
230
- .mc4wp-form button:focus {
231
- color: #333333;
232
- text-decoration: none;
233
- background: none;
234
- }
235
-
236
- .mc4wp-form input[type="submit"]:active,
237
- .mc4wp-form input[type="button"]:active,
238
- .mc4wp-form button:active {
239
- background-image: none;
240
- outline: 0;
241
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
242
- -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
243
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
244
- }
245
-
246
- .mc4wp-form input[type="submit"],
247
- .mc4wp-form button {
248
- color: #ffffff !important;
249
- background-color: #5cb85c !important;
250
- border-color: #4cae4c;
251
- }
252
-
253
- .mc4wp-form input[type="submit"]:hover,
254
- .mc4wp-form button:hover,
255
- .mc4wp-form input[type="submit"]:active,
256
- .mc4wp-form button:active,
257
- .mc4wp-form input[type="submit"]:focus,
258
- .mc4wp-form button:focus {
259
- color: #ffffff !important;
260
- background-color: #47a447 !important;
261
- border-color: #398439;
262
- }
263
-
264
- .mc4wp-form input[type="text"]:focus,
265
- .mc4wp-form input[type="email"]:focus,
266
- .mc4wp-form input[type="tel"]:focus,
267
- .mc4wp-form input[type="url"]:focus,
268
- .mc4wp-form input[type="date"]:focus,
269
- .mc4wp-form textarea:focus,
270
- .mc4wp-form select:focus {
271
- border-color: #5cb85c;
272
- }
273
-
274
- /*# sourceMappingURL=form-theme-green.css.map */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/form-theme-green.css.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "mappings": ";AAEA,WAAW;EACV,MAAM,EAAE,KAAK;;;;AAEb;;iBAEM;EACL,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EACd,kBAAkB,EAAE,UAAU;EAC9B,eAAe,EAAE,UAAU;EAC3B,UAAU,EAAE,UAAU;EACtB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,cAAc,EAAE,QAAQ;EACxB,WAAW,EAAE,MAAM;;AAKnB,sBAAQ;EACP,OAAO,EAAC,EAAE;EACV,OAAO,EAAC,KAAK;EACb,KAAK,EAAC,IAAI;;AAIZ,iBAAM;EACL,WAAW,EAAE,IAAI;EACjB,aAAa,EAAE,GAAG;;AAMlB,gCAAiB;EAChB,KAAK,EAAE,eAAe;;AAKxB;;;;;;;kBAOO;EACN,KAAK,EAAE,IAAI;;AAGZ,gCAAqB;EACpB,SAAS,EAAE,IAAI;;AAGhB;+BACoB;EACnB,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,SAAS;EACjB,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,YAAY;EACrB,MAAM,EAAE,CAAC;;AAGV,kCAAuB;EACtB,kBAAkB,EAAE,QAAQ;EAC5B,eAAe,EAAE,QAAQ;;AAG1B,+BAAoB;EACnB,kBAAkB,EAAE,KAAK;EACzB,eAAe,EAAE,KAAK;;AAGvB;;gCAEqB;EACpB,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,YAAY;EACrB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAK,IAAI;EACxB,UAAU,EAAU,IAAI;;AAIzB;sBACW;EACV,WAAW,EAAE,MAAM;;;;AAQnB;oCACoB;EACnB,MAAM,EAAE,SAAS;;;;AAMpB,YAAY;EACX,MAAM,EAAE,KAAK;EACb,OAAO,EAAE,SAAS;EAClB,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,iBAAiB;EACzB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,OAAO,EAAE,KAAK;EACd,QAAQ,EAAE,QAAQ;;;AAGnB,cAAe;EACd,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;AAGtB,aAAc;EACb,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;AAGtB,YAAa;EACZ,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;;ACtItB;gBACiB;EAChB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,eAAe;EAC3B,KAAK,EAAE,IAAI;;;AAGZ,aAAc;EACb,MAAM,EAAE,MAAM;EACd,OAAO,EAAE,CAAC;;;AAGX,iBAAiB;EAChB,SAAS,EAAC,GAAG;EACb,MAAM,EAAC,KAAK;;;AAGb;;;;;;;kBAOmB;EAClB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,QAAQ;EACjB,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,WAAW;EACxB,KAAK,EAAE,kBAAkB;EACzB,cAAc,EAAE,MAAM;EACtB,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,iBAAiB;EACzB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,kBAAkB,EAAE,oCAAoC;EACxD,eAAe,EAAE,oCAAoC;EACrD,UAAU,EAAE,oCAAoC;EAChD,eAAe,EAAE,4DAA4D;EAC7E,kBAAkB,EAAE,4DAA4D;EAChF,UAAU,EAAE,4DAA4D;EACxE,gBAAgB,EAAE,IAAI;EACtB,WAAW,EAAE,IAAI;;;AAGlB;;;;;;;wBAOyB;EACxB,YAAY,EAAE,OAAO;EACrB,OAAO,EAAE,CAAC;EACV,eAAe,EAAE,sEAAoC;EACrD,kBAAkB,EAAE,sEAAoC;EACxD,UAAU,EAAE,sEAAoC;;;AAGjD,oBAAoB;EACnB,MAAM,EAAE,IAAI;;;AAGb;2BAC4B;EAC3B,gBAAgB,EAAE,OAAO;;;AAG1B;;kBAEmB;EAClB,OAAO,EAAE,YAAY;EACrB,OAAO,EAAE,QAAQ;EACjB,MAAM,EAAE,CAAC;EACT,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,MAAM;EACnB,WAAW,EAAE,WAAW;EACxB,UAAU,EAAE,MAAM;EAClB,WAAW,EAAE,MAAM;EACnB,cAAc,EAAE,MAAM;EACtB,MAAM,EAAE,OAAO;EACf,MAAM,EAAE,qBAAqB;EAC7B,aAAa,EAAE,GAAG;EAClB,mBAAmB,EAAE,IAAI;EACzB,gBAAgB,EAAE,IAAI;EACtB,eAAe,EAAE,IAAI;EACrB,cAAc,EAAE,IAAI;EACpB,WAAW,EAAE,IAAI;EACjB,UAAU,EAAE,IAAI;EAChB,UAAU,EAAE,IAAI;EAChB,WAAW,EAAE,IAAI;EACjB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;;;AAGZ;;wBAEyB;EACxB,OAAO,EAAE,gBAAgB;EACzB,OAAO,EAAE,iCAAiC;EAC1C,cAAc,EAAE,IAAI;;;AAGrB;;;;;wBAKyB;EACxB,KAAK,EAAE,OAAO;EACd,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,IAAI;;;AAGjB;;yBAE0B;EACzB,gBAAgB,EAAE,IAAI;EACtB,OAAO,EAAE,CAAC;EACV,kBAAkB,EAAE,oCAAoC;EACxD,eAAe,EAAE,oCAAoC;EACrD,UAAU,EAAE,oCAAoC;;;AC7HjD;kBACmB;EACjB,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;;AAGvB;;;;;wBAKyB;EACvB,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;;AAGvB;;;;;;wBAMyB;EACvB,YAAY,EAAE,OAAO",
4
- "sources": ["../sass/partials/_form-reset.scss","../sass/partials/_form-theme-base.scss","../sass/form-theme-green.scss"],
5
- "names": [],
6
- "file": "form-theme-green.css"
7
- }
 
 
 
 
 
 
 
assets/css/form-theme-green.min.css DELETED
@@ -1 +0,0 @@
1
- .mc4wp-form{margin:1em 0}.mc4wp-form form,.mc4wp-form input,.mc4wp-form label{width:auto;display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:auto;height:auto;vertical-align:baseline;line-height:normal}.mc4wp-form form:after{content:"";display:table;clear:both}.mc4wp-form label{font-weight:700}.mc4wp-form input.placeholdersjs{color:#aaa!important}.mc4wp-form input[type=number]{min-width:40px}.mc4wp-form input[type=checkbox],.mc4wp-form input[type=radio]{position:relative;margin:0 6px 0 0;padding:0;height:13px;width:13px;display:inline-block;border:0}.mc4wp-form input[type=checkbox]{-webkit-appearance:checkbox;-moz-appearance:checkbox}.mc4wp-form input[type=radio]{-webkit-appearance:radio;-moz-appearance:radio}.mc4wp-form button,.mc4wp-form input[type=button],.mc4wp-form input[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none}.mc4wp-form label>span,.mc4wp-form li>label{font-weight:400}.rtl .mc4wp-form input[type=checkbox],.rtl .mc4wp-form input[type=radio]{margin:0 0 0 6px}.mc4wp-alert{margin:1em 0;padding:10px 15px;color:#c09853;background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;display:block;position:relative}.mc4wp-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.mc4wp-notice{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.mc4wp-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.mc4wp-form form,form.mc4wp-form{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none!important;width:auto}.mc4wp-form p{margin:10px 0;padding:0}.mc4wp-form label{font-size:1em;margin:6px 0}.mc4wp-form input[type=date],.mc4wp-form input[type=email],.mc4wp-form input[type=number],.mc4wp-form input[type=tel],.mc4wp-form input[type=text],.mc4wp-form input[type=url],.mc4wp-form select,.mc4wp-form textarea{width:100%;height:34px;margin:0;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555!important;vertical-align:middle;background-color:#fff;border:1px solid #ccc;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;background-image:none;text-shadow:none}.mc4wp-form input[type=date]:focus,.mc4wp-form input[type=email]:focus,.mc4wp-form input[type=number]:focus,.mc4wp-form input[type=tel]:focus,.mc4wp-form input[type=text]:focus,.mc4wp-form input[type=url]:focus,.mc4wp-form select:focus,.mc4wp-form textarea:focus{border-color:#66afe9;outline:0;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.mc4wp-form textarea{height:auto}.mc4wp-form input[disabled],.mc4wp-form input[readonly]{background-color:#eee}.mc4wp-form button,.mc4wp-form input[type=button],.mc4wp-form input[type=submit]{display:inline-block;padding:6px 12px;margin:0;font-size:14px;font-weight:400;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:2px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;box-shadow:none;background:0 0;text-shadow:none;filter:none;height:auto;width:auto}.mc4wp-form button:focus,.mc4wp-form input[type=button]:focus,.mc4wp-form input[type=submit]:focus{outline:#333 dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.mc4wp-form button:focus,.mc4wp-form button:hover,.mc4wp-form input[type=button]:focus,.mc4wp-form input[type=button]:hover,.mc4wp-form input[type=submit]:focus,.mc4wp-form input[type=submit]:hover{color:#333;text-decoration:none;background:0 0}.mc4wp-form button:active,.mc4wp-form input[type=button]:active,.mc4wp-form input[type=submit]:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);-moz-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.mc4wp-form button,.mc4wp-form input[type=submit]{color:#fff!important;background-color:#5cb85c!important;border-color:#4cae4c}.mc4wp-form button:active,.mc4wp-form button:focus,.mc4wp-form button:hover,.mc4wp-form input[type=submit]:active,.mc4wp-form input[type=submit]:focus,.mc4wp-form input[type=submit]:hover{color:#fff!important;background-color:#47a447!important;border-color:#398439}.mc4wp-form input[type=date]:focus,.mc4wp-form input[type=email]:focus,.mc4wp-form input[type=tel]:focus,.mc4wp-form input[type=text]:focus,.mc4wp-form input[type=url]:focus,.mc4wp-form select:focus,.mc4wp-form textarea:focus{border-color:#5cb85c}
 
assets/css/form-theme-light.css DELETED
@@ -1,264 +0,0 @@
1
- /* MailChimp for WP - Default Form Styles */
2
- .mc4wp-form {
3
- margin: 1em 0;
4
- /* Form Elements */
5
- /* Remove font-weight bold from nested elements */
6
- }
7
- .mc4wp-form form,
8
- .mc4wp-form label,
9
- .mc4wp-form input {
10
- width: auto;
11
- display: block;
12
- -webkit-box-sizing: border-box;
13
- -moz-box-sizing: border-box;
14
- box-sizing: border-box;
15
- cursor: auto;
16
- height: auto;
17
- vertical-align: baseline;
18
- line-height: normal;
19
- }
20
- .mc4wp-form form:after {
21
- content: "";
22
- display: table;
23
- clear: both;
24
- }
25
- .mc4wp-form label {
26
- font-weight: bold;
27
- margin-bottom: 5px;
28
- }
29
- .mc4wp-form input.placeholdersjs {
30
- color: #aaa !important;
31
- }
32
- .mc4wp-form input[type="text"],
33
- .mc4wp-form input[type="email"],
34
- .mc4wp-form input[type="tel"],
35
- .mc4wp-form input[type="url"],
36
- .mc4wp-form input[type="date"],
37
- .mc4wp-form input[type="number"],
38
- .mc4wp-form textarea,
39
- .mc4wp-form select {
40
- width: 100%;
41
- }
42
- .mc4wp-form input[type="number"] {
43
- min-width: 40px;
44
- }
45
- .mc4wp-form input[type="checkbox"],
46
- .mc4wp-form input[type="radio"] {
47
- position: relative;
48
- margin: 0 6px 0 0;
49
- padding: 0;
50
- height: 13px;
51
- width: 13px;
52
- display: inline-block;
53
- border: 0;
54
- }
55
- .mc4wp-form input[type="checkbox"] {
56
- -webkit-appearance: checkbox;
57
- -moz-appearance: checkbox;
58
- }
59
- .mc4wp-form input[type="radio"] {
60
- -webkit-appearance: radio;
61
- -moz-appearance: radio;
62
- }
63
- .mc4wp-form input[type="submit"],
64
- .mc4wp-form button,
65
- .mc4wp-form input[type="button"] {
66
- cursor: pointer;
67
- display: inline-block;
68
- -webkit-appearance: none;
69
- -moz-appearance: none;
70
- appearance: none;
71
- }
72
- .mc4wp-form label > span,
73
- .mc4wp-form li > label {
74
- font-weight: normal;
75
- }
76
-
77
- /* Right-To-Left specific styles */
78
- .rtl .mc4wp-form input[type="checkbox"],
79
- .rtl .mc4wp-form input[type="radio"] {
80
- margin: 0 0 0 6px;
81
- }
82
-
83
- /* Alert */
84
- .mc4wp-alert {
85
- margin: 1em 0;
86
- padding: 10px 15px;
87
- color: #c09853;
88
- background-color: #fcf8e3;
89
- border: 1px solid #fbeed5;
90
- -webkit-border-radius: 2px;
91
- -moz-border-radius: 2px;
92
- border-radius: 2px;
93
- display: block;
94
- position: relative;
95
- }
96
-
97
- .mc4wp-success {
98
- color: #468847;
99
- background-color: #dff0d8;
100
- border-color: #d6e9c6;
101
- }
102
-
103
- .mc4wp-notice {
104
- color: #3a87ad;
105
- background-color: #d9edf7;
106
- border-color: #bce8f1;
107
- }
108
-
109
- .mc4wp-error {
110
- color: #b94a48;
111
- background-color: #f2dede;
112
- border-color: #eed3d7;
113
- }
114
-
115
- /* Form base theme */
116
- form.mc4wp-form,
117
- .mc4wp-form form {
118
- -webkit-box-shadow: none;
119
- -moz-box-shadow: none;
120
- box-shadow: none !important;
121
- width: auto;
122
- }
123
-
124
- .mc4wp-form p {
125
- margin: 10px 0;
126
- padding: 0;
127
- }
128
-
129
- .mc4wp-form label {
130
- font-size: 1em;
131
- margin: 6px 0;
132
- }
133
-
134
- .mc4wp-form input[type="text"],
135
- .mc4wp-form input[type="email"],
136
- .mc4wp-form input[type="tel"],
137
- .mc4wp-form input[type="url"],
138
- .mc4wp-form input[type="date"],
139
- .mc4wp-form input[type="number"],
140
- .mc4wp-form textarea,
141
- .mc4wp-form select {
142
- width: 100%;
143
- height: 34px;
144
- margin: 0;
145
- padding: 6px 12px;
146
- font-size: 14px;
147
- line-height: 1.428571429;
148
- color: #555555 !important;
149
- vertical-align: middle;
150
- background-color: #ffffff;
151
- border: 1px solid #cccccc;
152
- -webkit-border-radius: 2px;
153
- -moz-border-radius: 2px;
154
- border-radius: 2px;
155
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
156
- -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
157
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
158
- -moz-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
159
- -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
160
- transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
161
- background-image: none;
162
- text-shadow: none;
163
- }
164
-
165
- .mc4wp-form input[type="text"]:focus,
166
- .mc4wp-form input[type="email"]:focus,
167
- .mc4wp-form input[type="tel"]:focus,
168
- .mc4wp-form input[type="url"]:focus,
169
- .mc4wp-form input[type="date"]:focus,
170
- .mc4wp-form input[type="number"]:focus,
171
- .mc4wp-form textarea:focus,
172
- .mc4wp-form select:focus {
173
- border-color: #66afe9;
174
- outline: 0;
175
- -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
176
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
177
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
178
- }
179
-
180
- .mc4wp-form textarea {
181
- height: auto;
182
- }
183
-
184
- .mc4wp-form input[readonly],
185
- .mc4wp-form input[disabled] {
186
- background-color: #eeeeee;
187
- }
188
-
189
- .mc4wp-form input[type="submit"],
190
- .mc4wp-form input[type="button"],
191
- .mc4wp-form button {
192
- display: inline-block;
193
- padding: 6px 12px;
194
- margin: 0;
195
- font-size: 14px;
196
- font-weight: normal;
197
- line-height: 1.428571429;
198
- text-align: center;
199
- white-space: nowrap;
200
- vertical-align: middle;
201
- cursor: pointer;
202
- border: 1px solid transparent;
203
- border-radius: 2px;
204
- -webkit-user-select: none;
205
- -moz-user-select: none;
206
- -ms-user-select: none;
207
- -o-user-select: none;
208
- user-select: none;
209
- box-shadow: none;
210
- background: none;
211
- text-shadow: none;
212
- filter: none;
213
- height: auto;
214
- width: auto;
215
- }
216
-
217
- .mc4wp-form input[type="submit"]:focus,
218
- .mc4wp-form input[type="button"]:focus,
219
- .mc4wp-form button:focus {
220
- outline: thin dotted #333;
221
- outline: 5px auto -webkit-focus-ring-color;
222
- outline-offset: -2px;
223
- }
224
-
225
- .mc4wp-form input[type="submit"]:hover,
226
- .mc4wp-form input[type="button"]:hover,
227
- .mc4wp-form button:hover,
228
- .mc4wp-form input[type="submit"]:focus,
229
- .mc4wp-form input[type="button"]:focus,
230
- .mc4wp-form button:focus {
231
- color: #333333;
232
- text-decoration: none;
233
- background: none;
234
- }
235
-
236
- .mc4wp-form input[type="submit"]:active,
237
- .mc4wp-form input[type="button"]:active,
238
- .mc4wp-form button:active {
239
- background-image: none;
240
- outline: 0;
241
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
242
- -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
243
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
244
- }
245
-
246
- .mc4wp-form input[type="submit"],
247
- .mc4wp-form button {
248
- color: #333333 !important;
249
- background-color: #ffffff !important;
250
- border-color: #E6E6E6;
251
- }
252
-
253
- .mc4wp-form input[type="submit"]:hover,
254
- .mc4wp-form button:hover,
255
- .mc4wp-form input[type="submit"]:active,
256
- .mc4wp-form button:active,
257
- .mc4wp-form input[type="submit"]:focus,
258
- .mc4wp-form button:focus {
259
- color: #E6E6E6 !important;
260
- background-color: #ebebeb !important;
261
- border-color: #CCCCCC;
262
- }
263
-
264
- /*# sourceMappingURL=form-theme-light.css.map */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/form-theme-light.css.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "mappings": ";AAEA,WAAW;EACV,MAAM,EAAE,KAAK;;;;AAEb;;iBAEM;EACL,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EACd,kBAAkB,EAAE,UAAU;EAC9B,eAAe,EAAE,UAAU;EAC3B,UAAU,EAAE,UAAU;EACtB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,cAAc,EAAE,QAAQ;EACxB,WAAW,EAAE,MAAM;;AAKnB,sBAAQ;EACP,OAAO,EAAC,EAAE;EACV,OAAO,EAAC,KAAK;EACb,KAAK,EAAC,IAAI;;AAIZ,iBAAM;EACL,WAAW,EAAE,IAAI;EACjB,aAAa,EAAE,GAAG;;AAMlB,gCAAiB;EAChB,KAAK,EAAE,eAAe;;AAKxB;;;;;;;kBAOO;EACN,KAAK,EAAE,IAAI;;AAGZ,gCAAqB;EACpB,SAAS,EAAE,IAAI;;AAGhB;+BACoB;EACnB,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,SAAS;EACjB,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,YAAY;EACrB,MAAM,EAAE,CAAC;;AAGV,kCAAuB;EACtB,kBAAkB,EAAE,QAAQ;EAC5B,eAAe,EAAE,QAAQ;;AAG1B,+BAAoB;EACnB,kBAAkB,EAAE,KAAK;EACzB,eAAe,EAAE,KAAK;;AAGvB;;gCAEqB;EACpB,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,YAAY;EACrB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAK,IAAI;EACxB,UAAU,EAAU,IAAI;;AAIzB;sBACW;EACV,WAAW,EAAE,MAAM;;;;AAQnB;oCACoB;EACnB,MAAM,EAAE,SAAS;;;;AAMpB,YAAY;EACX,MAAM,EAAE,KAAK;EACb,OAAO,EAAE,SAAS;EAClB,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,iBAAiB;EACzB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,OAAO,EAAE,KAAK;EACd,QAAQ,EAAE,QAAQ;;;AAGnB,cAAe;EACd,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;AAGtB,aAAc;EACb,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;AAGtB,YAAa;EACZ,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;;ACtItB;gBACiB;EAChB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,eAAe;EAC3B,KAAK,EAAE,IAAI;;;AAGZ,aAAc;EACb,MAAM,EAAE,MAAM;EACd,OAAO,EAAE,CAAC;;;AAGX,iBAAiB;EAChB,SAAS,EAAC,GAAG;EACb,MAAM,EAAC,KAAK;;;AAGb;;;;;;;kBAOmB;EAClB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,QAAQ;EACjB,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,WAAW;EACxB,KAAK,EAAE,kBAAkB;EACzB,cAAc,EAAE,MAAM;EACtB,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,iBAAiB;EACzB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,kBAAkB,EAAE,oCAAoC;EACxD,eAAe,EAAE,oCAAoC;EACrD,UAAU,EAAE,oCAAoC;EAChD,eAAe,EAAE,4DAA4D;EAC7E,kBAAkB,EAAE,4DAA4D;EAChF,UAAU,EAAE,4DAA4D;EACxE,gBAAgB,EAAE,IAAI;EACtB,WAAW,EAAE,IAAI;;;AAGlB;;;;;;;wBAOyB;EACxB,YAAY,EAAE,OAAO;EACrB,OAAO,EAAE,CAAC;EACV,eAAe,EAAE,sEAAoC;EACrD,kBAAkB,EAAE,sEAAoC;EACxD,UAAU,EAAE,sEAAoC;;;AAGjD,oBAAoB;EACnB,MAAM,EAAE,IAAI;;;AAGb;2BAC4B;EAC3B,gBAAgB,EAAE,OAAO;;;AAG1B;;kBAEmB;EAClB,OAAO,EAAE,YAAY;EACrB,OAAO,EAAE,QAAQ;EACjB,MAAM,EAAE,CAAC;EACT,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,MAAM;EACnB,WAAW,EAAE,WAAW;EACxB,UAAU,EAAE,MAAM;EAClB,WAAW,EAAE,MAAM;EACnB,cAAc,EAAE,MAAM;EACtB,MAAM,EAAE,OAAO;EACf,MAAM,EAAE,qBAAqB;EAC7B,aAAa,EAAE,GAAG;EAClB,mBAAmB,EAAE,IAAI;EACzB,gBAAgB,EAAE,IAAI;EACtB,eAAe,EAAE,IAAI;EACrB,cAAc,EAAE,IAAI;EACpB,WAAW,EAAE,IAAI;EACjB,UAAU,EAAE,IAAI;EAChB,UAAU,EAAE,IAAI;EAChB,WAAW,EAAE,IAAI;EACjB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;;;AAGZ;;wBAEyB;EACxB,OAAO,EAAE,gBAAgB;EACzB,OAAO,EAAE,iCAAiC;EAC1C,cAAc,EAAE,IAAI;;;AAGrB;;;;;wBAKyB;EACxB,KAAK,EAAE,OAAO;EACd,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,IAAI;;;AAGjB;;yBAE0B;EACzB,gBAAgB,EAAE,IAAI;EACtB,OAAO,EAAE,CAAC;EACV,kBAAkB,EAAE,oCAAoC;EACxD,eAAe,EAAE,oCAAoC;EACrD,UAAU,EAAE,oCAAoC;;;AC7HjD;kBACmB;EACjB,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;;AAGvB;;;;;wBAKyB;EACvB,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO",
4
- "sources": ["../sass/partials/_form-reset.scss","../sass/partials/_form-theme-base.scss","../sass/form-theme-light.scss"],
5
- "names": [],
6
- "file": "form-theme-light.css"
7
- }
 
 
 
 
 
 
 
assets/css/form-theme-light.min.css DELETED
@@ -1 +0,0 @@
1
- .mc4wp-form{margin:1em 0}.mc4wp-form form,.mc4wp-form input,.mc4wp-form label{width:auto;display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:auto;height:auto;vertical-align:baseline;line-height:normal}.mc4wp-form form:after{content:"";display:table;clear:both}.mc4wp-form label{font-weight:700}.mc4wp-form input.placeholdersjs{color:#aaa!important}.mc4wp-form input[type=number]{min-width:40px}.mc4wp-form input[type=checkbox],.mc4wp-form input[type=radio]{position:relative;margin:0 6px 0 0;padding:0;height:13px;width:13px;display:inline-block;border:0}.mc4wp-form input[type=checkbox]{-webkit-appearance:checkbox;-moz-appearance:checkbox}.mc4wp-form input[type=radio]{-webkit-appearance:radio;-moz-appearance:radio}.mc4wp-form button,.mc4wp-form input[type=button],.mc4wp-form input[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none}.mc4wp-form label>span,.mc4wp-form li>label{font-weight:400}.rtl .mc4wp-form input[type=checkbox],.rtl .mc4wp-form input[type=radio]{margin:0 0 0 6px}.mc4wp-alert{margin:1em 0;padding:10px 15px;color:#c09853;background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;display:block;position:relative}.mc4wp-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.mc4wp-notice{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.mc4wp-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.mc4wp-form form,form.mc4wp-form{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none!important;width:auto}.mc4wp-form p{margin:10px 0;padding:0}.mc4wp-form label{font-size:1em;margin:6px 0}.mc4wp-form input[type=date],.mc4wp-form input[type=email],.mc4wp-form input[type=number],.mc4wp-form input[type=tel],.mc4wp-form input[type=text],.mc4wp-form input[type=url],.mc4wp-form select,.mc4wp-form textarea{width:100%;height:34px;margin:0;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555!important;vertical-align:middle;background-color:#fff;border:1px solid #ccc;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;background-image:none;text-shadow:none}.mc4wp-form input[type=date]:focus,.mc4wp-form input[type=email]:focus,.mc4wp-form input[type=number]:focus,.mc4wp-form input[type=tel]:focus,.mc4wp-form input[type=text]:focus,.mc4wp-form input[type=url]:focus,.mc4wp-form select:focus,.mc4wp-form textarea:focus{border-color:#66afe9;outline:0;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.mc4wp-form textarea{height:auto}.mc4wp-form input[disabled],.mc4wp-form input[readonly]{background-color:#eee}.mc4wp-form button,.mc4wp-form input[type=button],.mc4wp-form input[type=submit]{display:inline-block;padding:6px 12px;margin:0;font-size:14px;font-weight:400;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:2px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;box-shadow:none;background:0 0;text-shadow:none;filter:none;height:auto;width:auto}.mc4wp-form button:focus,.mc4wp-form input[type=button]:focus,.mc4wp-form input[type=submit]:focus{outline:#333 dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.mc4wp-form button:focus,.mc4wp-form button:hover,.mc4wp-form input[type=button]:focus,.mc4wp-form input[type=button]:hover,.mc4wp-form input[type=submit]:focus,.mc4wp-form input[type=submit]:hover{color:#333;text-decoration:none;background:0 0}.mc4wp-form button:active,.mc4wp-form input[type=button]:active,.mc4wp-form input[type=submit]:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);-moz-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.mc4wp-form button,.mc4wp-form input[type=submit]{color:#333!important;background-color:#fff!important;border-color:#E6E6E6}.mc4wp-form button:active,.mc4wp-form button:focus,.mc4wp-form button:hover,.mc4wp-form input[type=submit]:active,.mc4wp-form input[type=submit]:focus,.mc4wp-form input[type=submit]:hover{color:#E6E6E6!important;background-color:#ebebeb!important;border-color:#CCC}
 
assets/css/form-theme-red.css DELETED
@@ -1,274 +0,0 @@
1
- /* MailChimp for WP - Default Form Styles */
2
- .mc4wp-form {
3
- margin: 1em 0;
4
- /* Form Elements */
5
- /* Remove font-weight bold from nested elements */
6
- }
7
- .mc4wp-form form,
8
- .mc4wp-form label,
9
- .mc4wp-form input {
10
- width: auto;
11
- display: block;
12
- -webkit-box-sizing: border-box;
13
- -moz-box-sizing: border-box;
14
- box-sizing: border-box;
15
- cursor: auto;
16
- height: auto;
17
- vertical-align: baseline;
18
- line-height: normal;
19
- }
20
- .mc4wp-form form:after {
21
- content: "";
22
- display: table;
23
- clear: both;
24
- }
25
- .mc4wp-form label {
26
- font-weight: bold;
27
- margin-bottom: 5px;
28
- }
29
- .mc4wp-form input.placeholdersjs {
30
- color: #aaa !important;
31
- }
32
- .mc4wp-form input[type="text"],
33
- .mc4wp-form input[type="email"],
34
- .mc4wp-form input[type="tel"],
35
- .mc4wp-form input[type="url"],
36
- .mc4wp-form input[type="date"],
37
- .mc4wp-form input[type="number"],
38
- .mc4wp-form textarea,
39
- .mc4wp-form select {
40
- width: 100%;
41
- }
42
- .mc4wp-form input[type="number"] {
43
- min-width: 40px;
44
- }
45
- .mc4wp-form input[type="checkbox"],
46
- .mc4wp-form input[type="radio"] {
47
- position: relative;
48
- margin: 0 6px 0 0;
49
- padding: 0;
50
- height: 13px;
51
- width: 13px;
52
- display: inline-block;
53
- border: 0;
54
- }
55
- .mc4wp-form input[type="checkbox"] {
56
- -webkit-appearance: checkbox;
57
- -moz-appearance: checkbox;
58
- }
59
- .mc4wp-form input[type="radio"] {
60
- -webkit-appearance: radio;
61
- -moz-appearance: radio;
62
- }
63
- .mc4wp-form input[type="submit"],
64
- .mc4wp-form button,
65
- .mc4wp-form input[type="button"] {
66
- cursor: pointer;
67
- display: inline-block;
68
- -webkit-appearance: none;
69
- -moz-appearance: none;
70
- appearance: none;
71
- }
72
- .mc4wp-form label > span,
73
- .mc4wp-form li > label {
74
- font-weight: normal;
75
- }
76
-
77
- /* Right-To-Left specific styles */
78
- .rtl .mc4wp-form input[type="checkbox"],
79
- .rtl .mc4wp-form input[type="radio"] {
80
- margin: 0 0 0 6px;
81
- }
82
-
83
- /* Alert */
84
- .mc4wp-alert {
85
- margin: 1em 0;
86
- padding: 10px 15px;
87
- color: #c09853;
88
- background-color: #fcf8e3;
89
- border: 1px solid #fbeed5;
90
- -webkit-border-radius: 2px;
91
- -moz-border-radius: 2px;
92
- border-radius: 2px;
93
- display: block;
94
- position: relative;
95
- }
96
-
97
- .mc4wp-success {
98
- color: #468847;
99
- background-color: #dff0d8;
100
- border-color: #d6e9c6;
101
- }
102
-
103
- .mc4wp-notice {
104
- color: #3a87ad;
105
- background-color: #d9edf7;
106
- border-color: #bce8f1;
107
- }
108
-
109
- .mc4wp-error {
110
- color: #b94a48;
111
- background-color: #f2dede;
112
- border-color: #eed3d7;
113
- }
114
-
115
- /* Form base theme */
116
- form.mc4wp-form,
117
- .mc4wp-form form {
118
- -webkit-box-shadow: none;
119
- -moz-box-shadow: none;
120
- box-shadow: none !important;
121
- width: auto;
122
- }
123
-
124
- .mc4wp-form p {
125
- margin: 10px 0;
126
- padding: 0;
127
- }
128
-
129
- .mc4wp-form label {
130
- font-size: 1em;
131
- margin: 6px 0;
132
- }
133
-
134
- .mc4wp-form input[type="text"],
135
- .mc4wp-form input[type="email"],
136
- .mc4wp-form input[type="tel"],
137
- .mc4wp-form input[type="url"],
138
- .mc4wp-form input[type="date"],
139
- .mc4wp-form input[type="number"],
140
- .mc4wp-form textarea,
141
- .mc4wp-form select {
142
- width: 100%;
143
- height: 34px;
144
- margin: 0;
145
- padding: 6px 12px;
146
- font-size: 14px;
147
- line-height: 1.428571429;
148
- color: #555555 !important;
149
- vertical-align: middle;
150
- background-color: #ffffff;
151
- border: 1px solid #cccccc;
152
- -webkit-border-radius: 2px;
153
- -moz-border-radius: 2px;
154
- border-radius: 2px;
155
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
156
- -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
157
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
158
- -moz-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
159
- -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
160
- transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
161
- background-image: none;
162
- text-shadow: none;
163
- }
164
-
165
- .mc4wp-form input[type="text"]:focus,
166
- .mc4wp-form input[type="email"]:focus,
167
- .mc4wp-form input[type="tel"]:focus,
168
- .mc4wp-form input[type="url"]:focus,
169
- .mc4wp-form input[type="date"]:focus,
170
- .mc4wp-form input[type="number"]:focus,
171
- .mc4wp-form textarea:focus,
172
- .mc4wp-form select:focus {
173
- border-color: #66afe9;
174
- outline: 0;
175
- -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
176
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
177
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
178
- }
179
-
180
- .mc4wp-form textarea {
181
- height: auto;
182
- }
183
-
184
- .mc4wp-form input[readonly],
185
- .mc4wp-form input[disabled] {
186
- background-color: #eeeeee;
187
- }
188
-
189
- .mc4wp-form input[type="submit"],
190
- .mc4wp-form input[type="button"],
191
- .mc4wp-form button {
192
- display: inline-block;
193
- padding: 6px 12px;
194
- margin: 0;
195
- font-size: 14px;
196
- font-weight: normal;
197
- line-height: 1.428571429;
198
- text-align: center;
199
- white-space: nowrap;
200
- vertical-align: middle;
201
- cursor: pointer;
202
- border: 1px solid transparent;
203
- border-radius: 2px;
204
- -webkit-user-select: none;
205
- -moz-user-select: none;
206
- -ms-user-select: none;
207
- -o-user-select: none;
208
- user-select: none;
209
- box-shadow: none;
210
- background: none;
211
- text-shadow: none;
212
- filter: none;
213
- height: auto;
214
- width: auto;
215
- }
216
-
217
- .mc4wp-form input[type="submit"]:focus,
218
- .mc4wp-form input[type="button"]:focus,
219
- .mc4wp-form button:focus {
220
- outline: thin dotted #333;
221
- outline: 5px auto -webkit-focus-ring-color;
222
- outline-offset: -2px;
223
- }
224
-
225
- .mc4wp-form input[type="submit"]:hover,
226
- .mc4wp-form input[type="button"]:hover,
227
- .mc4wp-form button:hover,
228
- .mc4wp-form input[type="submit"]:focus,
229
- .mc4wp-form input[type="button"]:focus,
230
- .mc4wp-form button:focus {
231
- color: #333333;
232
- text-decoration: none;
233
- background: none;
234
- }
235
-
236
- .mc4wp-form input[type="submit"]:active,
237
- .mc4wp-form input[type="button"]:active,
238
- .mc4wp-form button:active {
239
- background-image: none;
240
- outline: 0;
241
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
242
- -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
243
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
244
- }
245
-
246
- .mc4wp-form input[type="submit"],
247
- .mc4wp-form button {
248
- color: #ffffff !important;
249
- background-color: #d9534f !important;
250
- border-color: #d43f3a;
251
- }
252
-
253
- .mc4wp-form input[type="submit"]:hover,
254
- .mc4wp-form button:hover,
255
- .mc4wp-form input[type="submit"]:active,
256
- .mc4wp-form button:active,
257
- .mc4wp-form input[type="submit"]:focus,
258
- .mc4wp-form button:focus {
259
- color: #ffffff !important;
260
- background-color: #d2322d !important;
261
- border-color: #ac2925;
262
- }
263
-
264
- .mc4wp-form input[type="text"]:focus,
265
- .mc4wp-form input[type="email"]:focus,
266
- .mc4wp-form input[type="tel"]:focus,
267
- .mc4wp-form input[type="url"]:focus,
268
- .mc4wp-form input[type="date"]:focus,
269
- .mc4wp-form textarea:focus,
270
- .mc4wp-form select:focus {
271
- border-color: #d9534f;
272
- }
273
-
274
- /*# sourceMappingURL=form-theme-red.css.map */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/form-theme-red.css.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "mappings": ";AAEA,WAAW;EACV,MAAM,EAAE,KAAK;;;;AAEb;;iBAEM;EACL,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EACd,kBAAkB,EAAE,UAAU;EAC9B,eAAe,EAAE,UAAU;EAC3B,UAAU,EAAE,UAAU;EACtB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,cAAc,EAAE,QAAQ;EACxB,WAAW,EAAE,MAAM;;AAKnB,sBAAQ;EACP,OAAO,EAAC,EAAE;EACV,OAAO,EAAC,KAAK;EACb,KAAK,EAAC,IAAI;;AAIZ,iBAAM;EACL,WAAW,EAAE,IAAI;EACjB,aAAa,EAAE,GAAG;;AAMlB,gCAAiB;EAChB,KAAK,EAAE,eAAe;;AAKxB;;;;;;;kBAOO;EACN,KAAK,EAAE,IAAI;;AAGZ,gCAAqB;EACpB,SAAS,EAAE,IAAI;;AAGhB;+BACoB;EACnB,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,SAAS;EACjB,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,YAAY;EACrB,MAAM,EAAE,CAAC;;AAGV,kCAAuB;EACtB,kBAAkB,EAAE,QAAQ;EAC5B,eAAe,EAAE,QAAQ;;AAG1B,+BAAoB;EACnB,kBAAkB,EAAE,KAAK;EACzB,eAAe,EAAE,KAAK;;AAGvB;;gCAEqB;EACpB,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,YAAY;EACrB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAK,IAAI;EACxB,UAAU,EAAU,IAAI;;AAIzB;sBACW;EACV,WAAW,EAAE,MAAM;;;;AAQnB;oCACoB;EACnB,MAAM,EAAE,SAAS;;;;AAMpB,YAAY;EACX,MAAM,EAAE,KAAK;EACb,OAAO,EAAE,SAAS;EAClB,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,iBAAiB;EACzB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,OAAO,EAAE,KAAK;EACd,QAAQ,EAAE,QAAQ;;;AAGnB,cAAe;EACd,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;AAGtB,aAAc;EACb,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;AAGtB,YAAa;EACZ,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;;ACtItB;gBACiB;EAChB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,eAAe;EAC3B,KAAK,EAAE,IAAI;;;AAGZ,aAAc;EACb,MAAM,EAAE,MAAM;EACd,OAAO,EAAE,CAAC;;;AAGX,iBAAiB;EAChB,SAAS,EAAC,GAAG;EACb,MAAM,EAAC,KAAK;;;AAGb;;;;;;;kBAOmB;EAClB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,QAAQ;EACjB,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,WAAW;EACxB,KAAK,EAAE,kBAAkB;EACzB,cAAc,EAAE,MAAM;EACtB,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,iBAAiB;EACzB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,kBAAkB,EAAE,oCAAoC;EACxD,eAAe,EAAE,oCAAoC;EACrD,UAAU,EAAE,oCAAoC;EAChD,eAAe,EAAE,4DAA4D;EAC7E,kBAAkB,EAAE,4DAA4D;EAChF,UAAU,EAAE,4DAA4D;EACxE,gBAAgB,EAAE,IAAI;EACtB,WAAW,EAAE,IAAI;;;AAGlB;;;;;;;wBAOyB;EACxB,YAAY,EAAE,OAAO;EACrB,OAAO,EAAE,CAAC;EACV,eAAe,EAAE,sEAAoC;EACrD,kBAAkB,EAAE,sEAAoC;EACxD,UAAU,EAAE,sEAAoC;;;AAGjD,oBAAoB;EACnB,MAAM,EAAE,IAAI;;;AAGb;2BAC4B;EAC3B,gBAAgB,EAAE,OAAO;;;AAG1B;;kBAEmB;EAClB,OAAO,EAAE,YAAY;EACrB,OAAO,EAAE,QAAQ;EACjB,MAAM,EAAE,CAAC;EACT,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,MAAM;EACnB,WAAW,EAAE,WAAW;EACxB,UAAU,EAAE,MAAM;EAClB,WAAW,EAAE,MAAM;EACnB,cAAc,EAAE,MAAM;EACtB,MAAM,EAAE,OAAO;EACf,MAAM,EAAE,qBAAqB;EAC7B,aAAa,EAAE,GAAG;EAClB,mBAAmB,EAAE,IAAI;EACzB,gBAAgB,EAAE,IAAI;EACtB,eAAe,EAAE,IAAI;EACrB,cAAc,EAAE,IAAI;EACpB,WAAW,EAAE,IAAI;EACjB,UAAU,EAAE,IAAI;EAChB,UAAU,EAAE,IAAI;EAChB,WAAW,EAAE,IAAI;EACjB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;;;AAGZ;;wBAEyB;EACxB,OAAO,EAAE,gBAAgB;EACzB,OAAO,EAAE,iCAAiC;EAC1C,cAAc,EAAE,IAAI;;;AAGrB;;;;;wBAKyB;EACxB,KAAK,EAAE,OAAO;EACd,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,IAAI;;;AAGjB;;yBAE0B;EACzB,gBAAgB,EAAE,IAAI;EACtB,OAAO,EAAE,CAAC;EACV,kBAAkB,EAAE,oCAAoC;EACxD,eAAe,EAAE,oCAAoC;EACrD,UAAU,EAAE,oCAAoC;;;AC7HjD;kBACmB;EACjB,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;;AAGvB;;;;;wBAKyB;EACvB,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;;AAGvB;;;;;;wBAMyB;EACvB,YAAY,EAAE,OAAO",
4
- "sources": ["../sass/partials/_form-reset.scss","../sass/partials/_form-theme-base.scss","../sass/form-theme-red.scss"],
5
- "names": [],
6
- "file": "form-theme-red.css"
7
- }
 
 
 
 
 
 
 
assets/css/form-theme-red.min.css DELETED
@@ -1 +0,0 @@
1
- .mc4wp-form{margin:1em 0}.mc4wp-form form,.mc4wp-form input,.mc4wp-form label{width:auto;display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:auto;height:auto;vertical-align:baseline;line-height:normal}.mc4wp-form form:after{content:"";display:table;clear:both}.mc4wp-form label{font-weight:700}.mc4wp-form input.placeholdersjs{color:#aaa!important}.mc4wp-form input[type=number]{min-width:40px}.mc4wp-form input[type=checkbox],.mc4wp-form input[type=radio]{position:relative;margin:0 6px 0 0;padding:0;height:13px;width:13px;display:inline-block;border:0}.mc4wp-form input[type=checkbox]{-webkit-appearance:checkbox;-moz-appearance:checkbox}.mc4wp-form input[type=radio]{-webkit-appearance:radio;-moz-appearance:radio}.mc4wp-form button,.mc4wp-form input[type=button],.mc4wp-form input[type=submit]{-webkit-appearance:none;-moz-appearance:none;appearance:none}.mc4wp-form label>span,.mc4wp-form li>label{font-weight:400}.rtl .mc4wp-form input[type=checkbox],.rtl .mc4wp-form input[type=radio]{margin:0 0 0 6px}.mc4wp-alert{margin:1em 0;padding:10px 15px;color:#c09853;background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;display:block;position:relative}.mc4wp-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.mc4wp-notice{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.mc4wp-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.mc4wp-form form,form.mc4wp-form{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none!important;width:auto}.mc4wp-form p{margin:10px 0;padding:0}.mc4wp-form label{font-size:1em;margin:6px 0}.mc4wp-form input[type=date],.mc4wp-form input[type=email],.mc4wp-form input[type=number],.mc4wp-form input[type=tel],.mc4wp-form input[type=text],.mc4wp-form input[type=url],.mc4wp-form select,.mc4wp-form textarea{width:100%;height:34px;margin:0;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555!important;vertical-align:middle;background-color:#fff;border:1px solid #ccc;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;background-image:none;text-shadow:none}.mc4wp-form input[type=date]:focus,.mc4wp-form input[type=email]:focus,.mc4wp-form input[type=number]:focus,.mc4wp-form input[type=tel]:focus,.mc4wp-form input[type=text]:focus,.mc4wp-form input[type=url]:focus,.mc4wp-form select:focus,.mc4wp-form textarea:focus{border-color:#66afe9;outline:0;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.mc4wp-form textarea{height:auto}.mc4wp-form input[disabled],.mc4wp-form input[readonly]{background-color:#eee}.mc4wp-form button,.mc4wp-form input[type=button],.mc4wp-form input[type=submit]{display:inline-block;padding:6px 12px;margin:0;font-size:14px;font-weight:400;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:2px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;box-shadow:none;background:0 0;text-shadow:none;filter:none;height:auto;width:auto}.mc4wp-form button:focus,.mc4wp-form input[type=button]:focus,.mc4wp-form input[type=submit]:focus{outline:#333 dotted thin;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.mc4wp-form button:focus,.mc4wp-form button:hover,.mc4wp-form input[type=button]:focus,.mc4wp-form input[type=button]:hover,.mc4wp-form input[type=submit]:focus,.mc4wp-form input[type=submit]:hover{color:#333;text-decoration:none;background:0 0}.mc4wp-form button:active,.mc4wp-form input[type=button]:active,.mc4wp-form input[type=submit]:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);-moz-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.mc4wp-form button,.mc4wp-form input[type=submit]{color:#fff!important;background-color:#d9534f!important;border-color:#d43f3a}.mc4wp-form button:active,.mc4wp-form button:focus,.mc4wp-form button:hover,.mc4wp-form input[type=submit]:active,.mc4wp-form input[type=submit]:focus,.mc4wp-form input[type=submit]:hover{color:#fff!important;background-color:#d2322d!important;border-color:#ac2925}.mc4wp-form input[type=date]:focus,.mc4wp-form input[type=email]:focus,.mc4wp-form input[type=tel]:focus,.mc4wp-form input[type=text]:focus,.mc4wp-form input[type=url]:focus,.mc4wp-form select:focus,.mc4wp-form textarea:focus{border-color:#d9534f}
 
assets/css/form-themes.css ADDED
@@ -0,0 +1,325 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* MailChimp for WP - Default Form Styles */
2
+ .mc4wp-form-basic,
3
+ .mc4wp-form-theme {
4
+ margin: 1em 0;
5
+ /* Form Elements */
6
+ /* Remove font-weight bold from nested elements */
7
+ /* Alert */ }
8
+ .mc4wp-form-basic,
9
+ .mc4wp-form-basic label,
10
+ .mc4wp-form-basic input,
11
+ .mc4wp-form-theme,
12
+ .mc4wp-form-theme label,
13
+ .mc4wp-form-theme input {
14
+ width: auto;
15
+ display: block;
16
+ -webkit-box-sizing: border-box;
17
+ -moz-box-sizing: border-box;
18
+ box-sizing: border-box;
19
+ cursor: auto;
20
+ height: auto;
21
+ vertical-align: baseline;
22
+ line-height: normal; }
23
+ .mc4wp-form-basic:after,
24
+ .mc4wp-form-theme:after {
25
+ content: "";
26
+ display: table;
27
+ clear: both; }
28
+ .mc4wp-form-basic label,
29
+ .mc4wp-form-theme label {
30
+ font-weight: bold;
31
+ margin-bottom: 6px;
32
+ display: block; }
33
+ .mc4wp-form-basic input.placeholdersjs,
34
+ .mc4wp-form-theme input.placeholdersjs {
35
+ color: #aaa !important; }
36
+ .mc4wp-form-basic input[type="text"],
37
+ .mc4wp-form-basic input[type="email"],
38
+ .mc4wp-form-basic input[type="tel"],
39
+ .mc4wp-form-basic input[type="url"],
40
+ .mc4wp-form-basic input[type="date"],
41
+ .mc4wp-form-basic textarea,
42
+ .mc4wp-form-basic select,
43
+ .mc4wp-form-theme input[type="text"],
44
+ .mc4wp-form-theme input[type="email"],
45
+ .mc4wp-form-theme input[type="tel"],
46
+ .mc4wp-form-theme input[type="url"],
47
+ .mc4wp-form-theme input[type="date"],
48
+ .mc4wp-form-theme textarea,
49
+ .mc4wp-form-theme select {
50
+ min-height: 28px;
51
+ width: 100%;
52
+ max-width: 480px; }
53
+ .mc4wp-form-basic input[type="number"],
54
+ .mc4wp-form-theme input[type="number"] {
55
+ min-width: 40px; }
56
+ .mc4wp-form-basic input[type="checkbox"],
57
+ .mc4wp-form-basic input[type="radio"],
58
+ .mc4wp-form-theme input[type="checkbox"],
59
+ .mc4wp-form-theme input[type="radio"] {
60
+ position: relative;
61
+ margin: 0 6px 0 0;
62
+ padding: 0;
63
+ height: 13px;
64
+ width: 13px;
65
+ display: inline-block;
66
+ border: 0; }
67
+ .mc4wp-form-basic input[type="checkbox"],
68
+ .mc4wp-form-theme input[type="checkbox"] {
69
+ -webkit-appearance: checkbox;
70
+ -moz-appearance: checkbox;
71
+ appearance: checkbox; }
72
+ .mc4wp-form-basic input[type="radio"],
73
+ .mc4wp-form-theme input[type="radio"] {
74
+ -webkit-appearance: radio;
75
+ -moz-appearance: radio;
76
+ appearance: radio; }
77
+ .mc4wp-form-basic input[type="submit"],
78
+ .mc4wp-form-basic button,
79
+ .mc4wp-form-basic input[type="button"],
80
+ .mc4wp-form-theme input[type="submit"],
81
+ .mc4wp-form-theme button,
82
+ .mc4wp-form-theme input[type="button"] {
83
+ cursor: pointer;
84
+ display: inline-block;
85
+ -webkit-appearance: none;
86
+ -moz-appearance: none;
87
+ appearance: none; }
88
+ .mc4wp-form-basic label > span,
89
+ .mc4wp-form-basic li > label,
90
+ .mc4wp-form-theme label > span,
91
+ .mc4wp-form-theme li > label {
92
+ font-weight: normal; }
93
+ .mc4wp-form-basic .mc4wp-alert,
94
+ .mc4wp-form-theme .mc4wp-alert {
95
+ color: #c09853;
96
+ clear: both; }
97
+ .mc4wp-form-basic .mc4wp-success,
98
+ .mc4wp-form-theme .mc4wp-success {
99
+ color: #468847; }
100
+ .mc4wp-form-basic .mc4wp-notice,
101
+ .mc4wp-form-theme .mc4wp-notice {
102
+ color: #3a87ad; }
103
+ .mc4wp-form-basic .mc4wp-error,
104
+ .mc4wp-form-theme .mc4wp-error {
105
+ color: #CD5C5C; }
106
+
107
+ /* Right-To-Left specific styles */
108
+ .rtl .mc4wp-form-reset input[type="checkbox"],
109
+ .rtl .mc4wp-form-reset input[type="radio"] {
110
+ margin: 0 0 0 6px; }
111
+
112
+ /* Form base theme */
113
+ .mc4wp-form-theme input[type="text"],
114
+ .mc4wp-form-theme input[type="email"],
115
+ .mc4wp-form-theme input[type="tel"],
116
+ .mc4wp-form-theme input[type="url"],
117
+ .mc4wp-form-theme input[type="date"],
118
+ .mc4wp-form-theme input[type="number"],
119
+ .mc4wp-form-theme textarea,
120
+ .mc4wp-form-theme select {
121
+ height: auto;
122
+ margin: 0;
123
+ padding: 8px 16px;
124
+ line-height: 1.428571429;
125
+ color: #555555 !important;
126
+ vertical-align: middle;
127
+ background: none;
128
+ background-color: #ffffff;
129
+ border: 1px solid #cccccc;
130
+ -webkit-border-radius: 2px;
131
+ -moz-border-radius: 2px;
132
+ border-radius: 2px;
133
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
134
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
135
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
136
+ text-shadow: none; }
137
+
138
+ .mc4wp-form-theme input:focus,
139
+ .mc4wp-form-theme textarea:focus,
140
+ .mc4wp-form-theme select:focus,
141
+ .mc4wp-form-theme button:focus {
142
+ outline: 0;
143
+ background-image: none; }
144
+
145
+ .mc4wp-form-theme textarea {
146
+ height: auto; }
147
+
148
+ .mc4wp-form-theme input[readonly],
149
+ .mc4wp-form-theme input[disabled] {
150
+ background-color: #eeeeee; }
151
+
152
+ .mc4wp-form-theme input[type="submit"],
153
+ .mc4wp-form-theme input[type="button"],
154
+ .mc4wp-form-theme button {
155
+ display: inline-block;
156
+ padding: 8px 16px;
157
+ margin: 0;
158
+ font-weight: normal;
159
+ line-height: 1.428571429;
160
+ text-align: center;
161
+ white-space: nowrap;
162
+ vertical-align: middle;
163
+ cursor: pointer;
164
+ border: 1px solid transparent;
165
+ border-radius: 2px;
166
+ -webkit-user-select: none;
167
+ -moz-user-select: none;
168
+ user-select: none;
169
+ box-shadow: none;
170
+ background: none;
171
+ text-shadow: none;
172
+ filter: none;
173
+ height: auto;
174
+ width: auto; }
175
+
176
+ .mc4wp-form-theme input[type="submit"]:hover,
177
+ .mc4wp-form-theme input[type="button"]:hover,
178
+ .mc4wp-form-theme button:hover,
179
+ .mc4wp-form-theme input[type="submit"]:focus,
180
+ .mc4wp-form-theme input[type="button"]:focus,
181
+ .mc4wp-form-theme button:focus {
182
+ outline: 0;
183
+ color: #333333;
184
+ text-decoration: none;
185
+ background: none; }
186
+
187
+ .mc4wp-form-theme-dark input[type="submit"],
188
+ .mc4wp-form-theme-dark button {
189
+ color: #ffffff !important;
190
+ background-color: #444444 !important;
191
+ border-color: #1e1e1e; }
192
+
193
+ .mc4wp-form-theme-dark input[type="submit"]:hover,
194
+ .mc4wp-form-theme-dark button:hover,
195
+ .mc4wp-form-theme-dark input[type="submit"]:active,
196
+ .mc4wp-form-theme-dark button:active,
197
+ .mc4wp-form-theme-dark input[type="submit"]:focus,
198
+ .mc4wp-form-theme-dark button:focus {
199
+ color: #ffffff !important;
200
+ background-color: #1e1e1e !important;
201
+ border-color: black; }
202
+
203
+ .mc4wp-form-theme-dark input[type="text"]:focus,
204
+ .mc4wp-form-theme-dark input[type="email"]:focus,
205
+ .mc4wp-form-theme-dark input[type="tel"]:focus,
206
+ .mc4wp-form-theme-dark input[type="url"]:focus,
207
+ .mc4wp-form-theme-dark input[type="date"]:focus,
208
+ .mc4wp-form-theme-dark textarea:focus,
209
+ .mc4wp-form-theme-dark select:focus {
210
+ border-color: #6a6a6a;
211
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(68, 68, 68, 0.15);
212
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(68, 68, 68, 0.15);
213
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(68, 68, 68, 0.15); }
214
+
215
+ .mc4wp-form-theme-light input[type="submit"],
216
+ .mc4wp-form-theme-light button {
217
+ color: #000000 !important;
218
+ background-color: #ffffff !important;
219
+ border-color: #d9d9d9; }
220
+
221
+ .mc4wp-form-theme-light input[type="submit"]:hover,
222
+ .mc4wp-form-theme-light button:hover,
223
+ .mc4wp-form-theme-light input[type="submit"]:active,
224
+ .mc4wp-form-theme-light button:active,
225
+ .mc4wp-form-theme-light input[type="submit"]:focus,
226
+ .mc4wp-form-theme-light button:focus {
227
+ color: #000000 !important;
228
+ background-color: #d9d9d9 !important;
229
+ border-color: #b3b3b3; }
230
+
231
+ .mc4wp-form-theme-light input[type="text"]:focus,
232
+ .mc4wp-form-theme-light input[type="email"]:focus,
233
+ .mc4wp-form-theme-light input[type="tel"]:focus,
234
+ .mc4wp-form-theme-light input[type="url"]:focus,
235
+ .mc4wp-form-theme-light input[type="date"]:focus,
236
+ .mc4wp-form-theme-light textarea:focus,
237
+ .mc4wp-form-theme-light select:focus {
238
+ border-color: #d9d9d9;
239
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(255, 255, 255, 0.15);
240
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(255, 255, 255, 0.15);
241
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(255, 255, 255, 0.15); }
242
+
243
+ .mc4wp-form-theme-red input[type="submit"],
244
+ .mc4wp-form-theme-red button {
245
+ color: #ffffff !important;
246
+ background-color: #d9534f !important;
247
+ border-color: #b52b27; }
248
+
249
+ .mc4wp-form-theme-red input[type="submit"]:hover,
250
+ .mc4wp-form-theme-red button:hover,
251
+ .mc4wp-form-theme-red input[type="submit"]:active,
252
+ .mc4wp-form-theme-red button:active,
253
+ .mc4wp-form-theme-red input[type="submit"]:focus,
254
+ .mc4wp-form-theme-red button:focus {
255
+ color: #ffffff !important;
256
+ background-color: #b52b27 !important;
257
+ border-color: #761c19; }
258
+
259
+ .mc4wp-form-theme-red input[type="text"]:focus,
260
+ .mc4wp-form-theme-red input[type="email"]:focus,
261
+ .mc4wp-form-theme-red input[type="tel"]:focus,
262
+ .mc4wp-form-theme-red input[type="url"]:focus,
263
+ .mc4wp-form-theme-red input[type="date"]:focus,
264
+ .mc4wp-form-theme-red textarea:focus,
265
+ .mc4wp-form-theme-red select:focus {
266
+ border-color: #e7908e;
267
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(217, 83, 79, 0.15);
268
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(217, 83, 79, 0.15);
269
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(217, 83, 79, 0.15); }
270
+
271
+ .mc4wp-form-theme-blue input[type="submit"],
272
+ .mc4wp-form-theme-blue button {
273
+ color: #ffffff !important;
274
+ background-color: #428bca !important;
275
+ border-color: #2a6496; }
276
+
277
+ .mc4wp-form-theme-blue input[type="submit"]:hover,
278
+ .mc4wp-form-theme-blue button:hover,
279
+ .mc4wp-form-theme-blue input[type="submit"]:active,
280
+ .mc4wp-form-theme-blue button:active,
281
+ .mc4wp-form-theme-blue input[type="submit"]:focus,
282
+ .mc4wp-form-theme-blue button:focus {
283
+ color: #ffffff !important;
284
+ background-color: #2a6496 !important;
285
+ border-color: #193c5a; }
286
+
287
+ .mc4wp-form-theme-blue input[type="text"]:focus,
288
+ .mc4wp-form-theme-blue input[type="email"]:focus,
289
+ .mc4wp-form-theme-blue input[type="tel"]:focus,
290
+ .mc4wp-form-theme-blue input[type="url"]:focus,
291
+ .mc4wp-form-theme-blue input[type="date"]:focus,
292
+ .mc4wp-form-theme-blue textarea:focus,
293
+ .mc4wp-form-theme-blue select:focus {
294
+ border-color: #7eb0db;
295
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(66, 139, 202, 0.15);
296
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(66, 139, 202, 0.15);
297
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(66, 139, 202, 0.15); }
298
+
299
+ .mc4wp-form-theme-green input[type="submit"],
300
+ .mc4wp-form-theme-green button {
301
+ color: #ffffff !important;
302
+ background-color: #5cb85c !important;
303
+ border-color: #3d8b3d; }
304
+
305
+ .mc4wp-form-theme-green input[type="submit"]:hover,
306
+ .mc4wp-form-theme-green button:hover,
307
+ .mc4wp-form-theme-green input[type="submit"]:active,
308
+ .mc4wp-form-theme-green button:active,
309
+ .mc4wp-form-theme-green input[type="submit"]:focus,
310
+ .mc4wp-form-theme-green button:focus {
311
+ color: #ffffff !important;
312
+ background-color: #3d8b3d !important;
313
+ border-color: #255625; }
314
+
315
+ .mc4wp-form-theme-green input[type="text"]:focus,
316
+ .mc4wp-form-theme-green input[type="email"]:focus,
317
+ .mc4wp-form-theme-green input[type="tel"]:focus,
318
+ .mc4wp-form-theme-green input[type="url"]:focus,
319
+ .mc4wp-form-theme-green input[type="date"]:focus,
320
+ .mc4wp-form-theme-green textarea:focus,
321
+ .mc4wp-form-theme-green select:focus {
322
+ border-color: #91cf91;
323
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(92, 184, 92, 0.15);
324
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(92, 184, 92, 0.15);
325
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(92, 184, 92, 0.15); }
assets/css/form-themes.css.map ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ {
2
+ "version": 3,
3
+ "mappings": ";AACA;iBACkB;EAChB,MAAM,EAAE,KAAK;;;;;AAIb;;;;;uBAKwB;EACtB,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EACd,kBAAkB,EAAE,UAAU;EAC9B,eAAe,EAAE,UAAU;EAC3B,UAAU,EAAE,UAAU;EACtB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,cAAc,EAAE,QAAQ;EACxB,WAAW,EAAE,MAAM;;AACrB;uBACwB;EACtB,OAAO,EAAE,EAAE;EACX,OAAO,EAAE,KAAK;EACd,KAAK,EAAE,IAAI;;AACb;uBACwB;EACtB,WAAW,EAAE,IAAI;EACjB,aAAa,EAAE,GAAG;EAClB,OAAO,EAAE,KAAK;;AAChB;sCACuC;EACrC,KAAK,EAAE,eAAe;;AACxB;;;;;;;;;;;;;wBAayB;EACvB,UAAU,EAAE,IAAI;EAChB,KAAK,EAAE,IAAI;EACX,SAAS,EAAE,KAAK;;AAClB;sCACuC;EACrC,SAAS,EAAE,IAAI;;AACjB;;;qCAGsC;EACpC,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,SAAS;EACjB,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,YAAY;EACrB,MAAM,EAAE,CAAC;;AACX;wCACyC;EACvC,kBAAkB,EAAE,QAAQ;EAC5B,eAAe,EAAE,QAAQ;EACzB,UAAU,EAAE,QAAQ;;AACtB;qCACsC;EACpC,kBAAkB,EAAE,KAAK;EACzB,eAAe,EAAE,KAAK;EACtB,UAAU,EAAE,KAAK;;AACnB;;;;;sCAKuC;EACrC,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,YAAY;EACrB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,IAAI;;AAClB;;;4BAG6B;EAC3B,WAAW,EAAE,MAAM;;AACrB;8BAC+B;EAC7B,KAAK,EAAE,OAAO;EACd,KAAK,EAAE,IAAI;;AACb;gCACiC;EAC/B,KAAK,EAAE,OAAO;;AAChB;+BACgC;EAC9B,KAAK,EAAE,OAAO;;AAChB;8BAC+B;EAC7B,KAAK,EAAE,OAAO;;;AAGlB;0CAC2C;EACzC,MAAM,EAAE,SAAS;;;AAGnB;;;;;;;wBAOyB;EACvB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,QAAQ;EACjB,WAAW,EAAE,WAAW;EACxB,KAAK,EAAE,kBAAkB;EACzB,cAAc,EAAE,MAAM;EACtB,UAAU,EAAE,IAAI;EAChB,MAAM,EAAE,iBAAiB;EACzB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,kBAAkB,EAAE,oCAAoC;EACxD,eAAe,EAAE,oCAAoC;EACrD,UAAU,EAAE,oCAAoC;EAChD,WAAW,EAAE,IAAI;;AACnB;;;8BAG+B;EAC7B,OAAO,EAAE,CAAC;EACV,gBAAgB,EAAE,IAAI;;AACxB,0BAA2B;EACzB,MAAM,EAAE,IAAI;;AACd;iCACkC;EAChC,gBAAgB,EAAE,OAAO;;AAC3B;;wBAEyB;EACvB,OAAO,EAAE,YAAY;EACrB,OAAO,EAAE,QAAQ;EACjB,MAAM,EAAE,CAAC;EACT,WAAW,EAAE,MAAM;EACnB,WAAW,EAAE,WAAW;EACxB,UAAU,EAAE,MAAM;EAClB,WAAW,EAAE,MAAM;EACnB,cAAc,EAAE,MAAM;EACtB,MAAM,EAAE,OAAO;EACf,MAAM,EAAE,qBAAqB;EAC7B,aAAa,EAAE,GAAG;EAClB,mBAAmB,EAAE,IAAI;EACzB,gBAAgB,EAAE,IAAI;EACtB,WAAW,EAAE,IAAI;EACjB,UAAU,EAAE,IAAI;EAChB,UAAU,EAAE,IAAI;EAChB,WAAW,EAAE,IAAI;EACjB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;;AACb;;;;;8BAK+B;EAC7B,OAAO,EAAE,CAAC;EACV,KAAK,EAAE,OAAO;EACd,eAAe,EAAE,IAAI;EACrB,UAAU,EAAE,IAAI;;AAElB;6BAC8B;EAC5B,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;AACvB;;;;;mCAKoC;EAClC,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,KAAK;;AACrB;;;;;;mCAMoC;EAClC,YAAY,EAAE,OAAO;EACrB,kBAAkB,EAAE,oEAAoC;EACxD,eAAe,EAAE,oEAAoC;EACrD,UAAU,EAAE,oEAAoC;;AAElD;8BAC+B;EAC7B,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;AACvB;;;;;oCAKqC;EACnC,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;AACvB;;;;;;oCAMqC;EACnC,YAAY,EAAE,OAAO;EACrB,kBAAkB,EAAE,uEAAoC;EACxD,eAAe,EAAE,uEAAoC;EACrD,UAAU,EAAE,uEAAoC;;AAElD;4BAC6B;EAC3B,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;AACvB;;;;;kCAKmC;EACjC,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;AACvB;;;;;;kCAMmC;EACjC,YAAY,EAAE,OAAO;EACrB,kBAAkB,EAAE,qEAAoC;EACxD,eAAe,EAAE,qEAAoC;EACrD,UAAU,EAAE,qEAAoC;;AAElD;6BAC8B;EAC5B,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;AACvB;;;;;mCAKoC;EAClC,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;AACvB;;;;;;mCAMoC;EAClC,YAAY,EAAE,OAAO;EACrB,kBAAkB,EAAE,sEAAoC;EACxD,eAAe,EAAE,sEAAoC;EACrD,UAAU,EAAE,sEAAoC;;AAElD;8BAC+B;EAC7B,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;AACvB;;;;;oCAKqC;EACnC,KAAK,EAAE,kBAAkB;EACzB,gBAAgB,EAAE,kBAAkB;EACpC,YAAY,EAAE,OAAO;;AACvB;;;;;;oCAMqC;EACnC,YAAY,EAAE,OAAO;EACrB,kBAAkB,EAAE,qEAAoC;EACxD,eAAe,EAAE,qEAAoC;EACrD,UAAU,EAAE,qEAAoC",
4
+ "sources": ["form-themes.scss"],
5
+ "names": [],
6
+ "file": "form-themes.css"
7
+ }
assets/css/form-themes.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .mc4wp-form-basic,.mc4wp-form-theme{margin:1em 0}.mc4wp-form-basic,.mc4wp-form-basic input,.mc4wp-form-basic label,.mc4wp-form-theme,.mc4wp-form-theme input,.mc4wp-form-theme label{width:auto;display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:auto;height:auto;vertical-align:baseline;line-height:normal}.mc4wp-form-basic:after,.mc4wp-form-theme:after{content:"";display:table;clear:both}.mc4wp-form-basic label,.mc4wp-form-theme label{font-weight:700;margin-bottom:6px;display:block}.mc4wp-form-basic input.placeholdersjs,.mc4wp-form-theme input.placeholdersjs{color:#aaa!important}.mc4wp-form-basic input[type=text],.mc4wp-form-basic input[type=email],.mc4wp-form-basic input[type=tel],.mc4wp-form-basic input[type=url],.mc4wp-form-basic input[type=date],.mc4wp-form-basic select,.mc4wp-form-basic textarea,.mc4wp-form-theme input[type=text],.mc4wp-form-theme input[type=email],.mc4wp-form-theme input[type=tel],.mc4wp-form-theme input[type=url],.mc4wp-form-theme input[type=date],.mc4wp-form-theme select,.mc4wp-form-theme textarea{min-height:28px;width:100%;max-width:480px}.mc4wp-form-basic input[type=number],.mc4wp-form-theme input[type=number]{min-width:40px}.mc4wp-form-basic input[type=checkbox],.mc4wp-form-basic input[type=radio],.mc4wp-form-theme input[type=checkbox],.mc4wp-form-theme input[type=radio]{position:relative;margin:0 6px 0 0;padding:0;height:13px;width:13px;display:inline-block;border:0}.mc4wp-form-basic input[type=checkbox],.mc4wp-form-theme input[type=checkbox]{-webkit-appearance:checkbox;-moz-appearance:checkbox;appearance:checkbox}.mc4wp-form-basic input[type=radio],.mc4wp-form-theme input[type=radio]{-webkit-appearance:radio;-moz-appearance:radio;appearance:radio}.mc4wp-form-basic button,.mc4wp-form-basic input[type=button],.mc4wp-form-basic input[type=submit],.mc4wp-form-theme button,.mc4wp-form-theme input[type=button],.mc4wp-form-theme input[type=submit]{cursor:pointer;display:inline-block;-webkit-appearance:none;-moz-appearance:none;appearance:none}.mc4wp-form-basic label>span,.mc4wp-form-basic li>label,.mc4wp-form-theme label>span,.mc4wp-form-theme li>label{font-weight:400}.mc4wp-form-basic .mc4wp-alert,.mc4wp-form-theme .mc4wp-alert{color:#c09853;clear:both}.mc4wp-form-basic .mc4wp-success,.mc4wp-form-theme .mc4wp-success{color:#468847}.mc4wp-form-basic .mc4wp-notice,.mc4wp-form-theme .mc4wp-notice{color:#3a87ad}.mc4wp-form-basic .mc4wp-error,.mc4wp-form-theme .mc4wp-error{color:#CD5C5C}.rtl .mc4wp-form-reset input[type=checkbox],.rtl .mc4wp-form-reset input[type=radio]{margin:0 0 0 6px}.mc4wp-form-theme input[type=text],.mc4wp-form-theme input[type=email],.mc4wp-form-theme input[type=tel],.mc4wp-form-theme input[type=url],.mc4wp-form-theme input[type=date],.mc4wp-form-theme input[type=number],.mc4wp-form-theme select,.mc4wp-form-theme textarea{height:auto;margin:0;padding:8px 16px;line-height:1.428571429;color:#555!important;vertical-align:middle;background:#fff;border:1px solid #ccc;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);text-shadow:none}.mc4wp-form-theme button:focus,.mc4wp-form-theme input:focus,.mc4wp-form-theme select:focus,.mc4wp-form-theme textarea:focus{outline:0;background-image:none}.mc4wp-form-theme textarea{height:auto}.mc4wp-form-theme input[disabled],.mc4wp-form-theme input[readonly]{background-color:#eee}.mc4wp-form-theme button,.mc4wp-form-theme input[type=button],.mc4wp-form-theme input[type=submit]{display:inline-block;padding:8px 16px;margin:0;font-weight:400;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:2px;-webkit-user-select:none;-moz-user-select:none;user-select:none;box-shadow:none;background:0 0;text-shadow:none;filter:none;height:auto;width:auto}.mc4wp-form-theme button:focus,.mc4wp-form-theme button:hover,.mc4wp-form-theme input[type=button]:focus,.mc4wp-form-theme input[type=button]:hover,.mc4wp-form-theme input[type=submit]:focus,.mc4wp-form-theme input[type=submit]:hover{outline:0;color:#333;text-decoration:none;background:0 0}.mc4wp-form-theme-dark button,.mc4wp-form-theme-dark input[type=submit]{color:#fff!important;background-color:#444!important;border-color:#1e1e1e}.mc4wp-form-theme-dark button:active,.mc4wp-form-theme-dark button:focus,.mc4wp-form-theme-dark button:hover,.mc4wp-form-theme-dark input[type=submit]:active,.mc4wp-form-theme-dark input[type=submit]:focus,.mc4wp-form-theme-dark input[type=submit]:hover{color:#fff!important;background-color:#1e1e1e!important;border-color:#000}.mc4wp-form-theme-dark input[type=text]:focus,.mc4wp-form-theme-dark input[type=email]:focus,.mc4wp-form-theme-dark input[type=tel]:focus,.mc4wp-form-theme-dark input[type=url]:focus,.mc4wp-form-theme-dark input[type=date]:focus,.mc4wp-form-theme-dark select:focus,.mc4wp-form-theme-dark textarea:focus{border-color:#6a6a6a;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(68,68,68,.15);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(68,68,68,.15);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(68,68,68,.15)}.mc4wp-form-theme-light button,.mc4wp-form-theme-light input[type=submit]{color:#000!important;background-color:#fff!important;border-color:#d9d9d9}.mc4wp-form-theme-light button:active,.mc4wp-form-theme-light button:focus,.mc4wp-form-theme-light button:hover,.mc4wp-form-theme-light input[type=submit]:active,.mc4wp-form-theme-light input[type=submit]:focus,.mc4wp-form-theme-light input[type=submit]:hover{color:#000!important;background-color:#d9d9d9!important;border-color:#b3b3b3}.mc4wp-form-theme-light input[type=text]:focus,.mc4wp-form-theme-light input[type=email]:focus,.mc4wp-form-theme-light input[type=tel]:focus,.mc4wp-form-theme-light input[type=url]:focus,.mc4wp-form-theme-light input[type=date]:focus,.mc4wp-form-theme-light select:focus,.mc4wp-form-theme-light textarea:focus{border-color:#d9d9d9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(255,255,255,.15);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(255,255,255,.15);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(255,255,255,.15)}.mc4wp-form-theme-red button,.mc4wp-form-theme-red input[type=submit]{color:#fff!important;background-color:#d9534f!important;border-color:#b52b27}.mc4wp-form-theme-red button:active,.mc4wp-form-theme-red button:focus,.mc4wp-form-theme-red button:hover,.mc4wp-form-theme-red input[type=submit]:active,.mc4wp-form-theme-red input[type=submit]:focus,.mc4wp-form-theme-red input[type=submit]:hover{color:#fff!important;background-color:#b52b27!important;border-color:#761c19}.mc4wp-form-theme-red input[type=text]:focus,.mc4wp-form-theme-red input[type=email]:focus,.mc4wp-form-theme-red input[type=tel]:focus,.mc4wp-form-theme-red input[type=url]:focus,.mc4wp-form-theme-red input[type=date]:focus,.mc4wp-form-theme-red select:focus,.mc4wp-form-theme-red textarea:focus{border-color:#e7908e;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(217,83,79,.15);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(217,83,79,.15);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(217,83,79,.15)}.mc4wp-form-theme-blue button,.mc4wp-form-theme-blue input[type=submit]{color:#fff!important;background-color:#428bca!important;border-color:#2a6496}.mc4wp-form-theme-blue button:active,.mc4wp-form-theme-blue button:focus,.mc4wp-form-theme-blue button:hover,.mc4wp-form-theme-blue input[type=submit]:active,.mc4wp-form-theme-blue input[type=submit]:focus,.mc4wp-form-theme-blue input[type=submit]:hover{color:#fff!important;background-color:#2a6496!important;border-color:#193c5a}.mc4wp-form-theme-blue input[type=text]:focus,.mc4wp-form-theme-blue input[type=email]:focus,.mc4wp-form-theme-blue input[type=tel]:focus,.mc4wp-form-theme-blue input[type=url]:focus,.mc4wp-form-theme-blue input[type=date]:focus,.mc4wp-form-theme-blue select:focus,.mc4wp-form-theme-blue textarea:focus{border-color:#7eb0db;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(66,139,202,.15);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(66,139,202,.15);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(66,139,202,.15)}.mc4wp-form-theme-green button,.mc4wp-form-theme-green input[type=submit]{color:#fff!important;background-color:#5cb85c!important;border-color:#3d8b3d}.mc4wp-form-theme-green button:active,.mc4wp-form-theme-green button:focus,.mc4wp-form-theme-green button:hover,.mc4wp-form-theme-green input[type=submit]:active,.mc4wp-form-theme-green input[type=submit]:focus,.mc4wp-form-theme-green input[type=submit]:hover{color:#fff!important;background-color:#3d8b3d!important;border-color:#255625}.mc4wp-form-theme-green input[type=text]:focus,.mc4wp-form-theme-green input[type=email]:focus,.mc4wp-form-theme-green input[type=tel]:focus,.mc4wp-form-theme-green input[type=url]:focus,.mc4wp-form-theme-green input[type=date]:focus,.mc4wp-form-theme-green select:focus,.mc4wp-form-theme-green textarea:focus{border-color:#91cf91;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(92,184,92,.15);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(92,184,92,.15);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(92,184,92,.15)}
assets/css/form.css DELETED
@@ -1,115 +0,0 @@
1
- /* MailChimp for WP - Default Form Styles */
2
- .mc4wp-form {
3
- margin: 1em 0;
4
- /* Form Elements */
5
- /* Remove font-weight bold from nested elements */
6
- }
7
- .mc4wp-form form,
8
- .mc4wp-form label,
9
- .mc4wp-form input {
10
- width: auto;
11
- display: block;
12
- -webkit-box-sizing: border-box;
13
- -moz-box-sizing: border-box;
14
- box-sizing: border-box;
15
- cursor: auto;
16
- height: auto;
17
- vertical-align: baseline;
18
- line-height: normal;
19
- }
20
- .mc4wp-form form:after {
21
- content: "";
22
- display: table;
23
- clear: both;
24
- }
25
- .mc4wp-form label {
26
- font-weight: bold;
27
- margin-bottom: 5px;
28
- }
29
- .mc4wp-form input.placeholdersjs {
30
- color: #aaa !important;
31
- }
32
- .mc4wp-form input[type="text"],
33
- .mc4wp-form input[type="email"],
34
- .mc4wp-form input[type="tel"],
35
- .mc4wp-form input[type="url"],
36
- .mc4wp-form input[type="date"],
37
- .mc4wp-form input[type="number"],
38
- .mc4wp-form textarea,
39
- .mc4wp-form select {
40
- width: 100%;
41
- }
42
- .mc4wp-form input[type="number"] {
43
- min-width: 40px;
44
- }
45
- .mc4wp-form input[type="checkbox"],
46
- .mc4wp-form input[type="radio"] {
47
- position: relative;
48
- margin: 0 6px 0 0;
49
- padding: 0;
50
- height: 13px;
51
- width: 13px;
52
- display: inline-block;
53
- border: 0;
54
- }
55
- .mc4wp-form input[type="checkbox"] {
56
- -webkit-appearance: checkbox;
57
- -moz-appearance: checkbox;
58
- }
59
- .mc4wp-form input[type="radio"] {
60
- -webkit-appearance: radio;
61
- -moz-appearance: radio;
62
- }
63
- .mc4wp-form input[type="submit"],
64
- .mc4wp-form button,
65
- .mc4wp-form input[type="button"] {
66
- cursor: pointer;
67
- display: inline-block;
68
- -webkit-appearance: none;
69
- -moz-appearance: none;
70
- appearance: none;
71
- }
72
- .mc4wp-form label > span,
73
- .mc4wp-form li > label {
74
- font-weight: normal;
75
- }
76
-
77
- /* Right-To-Left specific styles */
78
- .rtl .mc4wp-form input[type="checkbox"],
79
- .rtl .mc4wp-form input[type="radio"] {
80
- margin: 0 0 0 6px;
81
- }
82
-
83
- /* Alert */
84
- .mc4wp-alert {
85
- margin: 1em 0;
86
- padding: 10px 15px;
87
- color: #c09853;
88
- background-color: #fcf8e3;
89
- border: 1px solid #fbeed5;
90
- -webkit-border-radius: 2px;
91
- -moz-border-radius: 2px;
92
- border-radius: 2px;
93
- display: block;
94
- position: relative;
95
- }
96
-
97
- .mc4wp-success {
98
- color: #468847;
99
- background-color: #dff0d8;
100
- border-color: #d6e9c6;
101
- }
102
-
103
- .mc4wp-notice {
104
- color: #3a87ad;
105
- background-color: #d9edf7;
106
- border-color: #bce8f1;
107
- }
108
-
109
- .mc4wp-error {
110
- color: #b94a48;
111
- background-color: #f2dede;
112
- border-color: #eed3d7;
113
- }
114
-
115
- /*# sourceMappingURL=form.css.map */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/css/form.css.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "mappings": ";AAEA,WAAW;EACV,MAAM,EAAE,KAAK;;;;AAEb;;iBAEM;EACL,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EACd,kBAAkB,EAAE,UAAU;EAC9B,eAAe,EAAE,UAAU;EAC3B,UAAU,EAAE,UAAU;EACtB,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,IAAI;EACZ,cAAc,EAAE,QAAQ;EACxB,WAAW,EAAE,MAAM;;AAKnB,sBAAQ;EACP,OAAO,EAAC,EAAE;EACV,OAAO,EAAC,KAAK;EACb,KAAK,EAAC,IAAI;;AAIZ,iBAAM;EACL,WAAW,EAAE,IAAI;EACjB,aAAa,EAAE,GAAG;;AAMlB,gCAAiB;EAChB,KAAK,EAAE,eAAe;;AAKxB;;;;;;;kBAOO;EACN,KAAK,EAAE,IAAI;;AAGZ,gCAAqB;EACpB,SAAS,EAAE,IAAI;;AAGhB;+BACoB;EACnB,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,SAAS;EACjB,OAAO,EAAE,CAAC;EACV,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,YAAY;EACrB,MAAM,EAAE,CAAC;;AAGV,kCAAuB;EACtB,kBAAkB,EAAE,QAAQ;EAC5B,eAAe,EAAE,QAAQ;;AAG1B,+BAAoB;EACnB,kBAAkB,EAAE,KAAK;EACzB,eAAe,EAAE,KAAK;;AAGvB;;gCAEqB;EACpB,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,YAAY;EACrB,kBAAkB,EAAE,IAAI;EACxB,eAAe,EAAK,IAAI;EACxB,UAAU,EAAU,IAAI;;AAIzB;sBACW;EACV,WAAW,EAAE,MAAM;;;;AAQnB;oCACoB;EACnB,MAAM,EAAE,SAAS;;;;AAMpB,YAAY;EACX,MAAM,EAAE,KAAK;EACb,OAAO,EAAE,SAAS;EAClB,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,MAAM,EAAE,iBAAiB;EACzB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,OAAO,EAAE,KAAK;EACd,QAAQ,EAAE,QAAQ;;;AAGnB,cAAe;EACd,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;AAGtB,aAAc;EACb,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO;;;AAGtB,YAAa;EACZ,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO;EACzB,YAAY,EAAE,OAAO",
4
- "sources": ["../sass/partials/_form-reset.scss"],
5
- "names": [],
6
- "file": "form.css"
7
- }
 
 
 
 
 
 
 
assets/css/form.min.css DELETED
@@ -1 +0,0 @@
1
- .mc4wp-form{margin:1em 0}.mc4wp-form form,.mc4wp-form input,.mc4wp-form label{width:auto;display:block;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:auto;height:auto;vertical-align:baseline;line-height:normal}.mc4wp-form form:after{content:"";display:table;clear:both}.mc4wp-form label{font-weight:700;margin-bottom:5px}.mc4wp-form input.placeholdersjs{color:#aaa!important}.mc4wp-form input[type=date],.mc4wp-form input[type=email],.mc4wp-form input[type=number],.mc4wp-form input[type=tel],.mc4wp-form input[type=text],.mc4wp-form input[type=url],.mc4wp-form select,.mc4wp-form textarea{width:100%}.mc4wp-form input[type=number]{min-width:40px}.mc4wp-form input[type=checkbox],.mc4wp-form input[type=radio]{position:relative;margin:0 6px 0 0;padding:0;height:13px;width:13px;display:inline-block;border:0}.mc4wp-form input[type=checkbox]{-webkit-appearance:checkbox;-moz-appearance:checkbox}.mc4wp-form input[type=radio]{-webkit-appearance:radio;-moz-appearance:radio}.mc4wp-form button,.mc4wp-form input[type=button],.mc4wp-form input[type=submit]{cursor:pointer;display:inline-block;-webkit-appearance:none;-moz-appearance:none;appearance:none}.mc4wp-form label>span,.mc4wp-form li>label{font-weight:400}.rtl .mc4wp-form input[type=checkbox],.rtl .mc4wp-form input[type=radio]{margin:0 0 0 6px}.mc4wp-alert{margin:1em 0;padding:10px 15px;color:#c09853;background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;display:block;position:relative}.mc4wp-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.mc4wp-notice{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.mc4wp-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}
 
assets/js/admin.js CHANGED
@@ -1,645 +1,2021 @@
1
- (function($) {
2
- 'use strict';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
- /**
5
- * Variables
6
- */
7
- var $context = $(document.getElementById('mc4wp-admin'));
8
- var $listInputs = $(document.getElementById('mc4wp-lists')).find(':input');
9
- var $formMarkup = $(document.getElementById('mc4wpformmarkup'));
10
- var $missingFieldsNotice = $(document.getElementById('missing-fields-notice'));
11
- var $missingFieldsList = $(document.getElementById('missing-fields-list'));
12
-
13
- /**
14
- * Functions
15
- */
16
- function showProNotice() {
17
-
18
- // prevent checking of radio buttons
19
- if( typeof this.checked === 'boolean' ) {
20
- this.checked = false;
21
  }
22
 
23
- alert( mc4wp.strings.proOnlyNotice );
24
- event.stopPropagation();
25
- }
 
26
 
27
- function toggleSendWelcomeFields() {
 
 
 
28
 
29
- var $el = $(document.getElementById('mc4wp-send-welcome'));
 
 
 
30
 
31
- if($(this).val() == 0) {
32
- $el.removeClass('hidden').find(':input').removeAttr('disabled');
33
- } else {
34
- $el.addClass('hidden').find(':input').attr('disabled', 'disabled').prop('checked', false);
35
- }
 
 
 
 
 
 
 
 
36
  }
37
 
38
- function toggleWooCommerceSettings() {
39
- var $el = $(document.getElementById('woocommerce-settings'));
40
- $el.toggle(this.checked);
41
  }
42
 
43
- function toggleFieldWizard() {
44
- var hasListSelected = $listInputs.filter(':checked').length > 0;
45
- $(".mc4wp-notice.no-lists-selected").toggle( ! hasListSelected );
46
- $( document.getElementById( 'mc4wp-fw-mailchimp-fields' )).toggle( hasListSelected );
47
- }
 
 
 
48
 
49
- function allowTabKey(e) {
50
- var keyCode = e.keyCode || e.which;
 
 
51
 
52
- if (keyCode === 9) {
53
- e.preventDefault();
54
- var start = this.selectionStart;
55
- var end = this.selectionEnd;
56
 
57
- // set textarea value to: text before caret + tab + text after caret
58
- $(this).val($(this).val().substring(0, start) + "\t" + $(this).val().substring(end));
 
59
 
60
- // put caret at right position again
61
- this.selectionStart = this.selectionEnd = start + 1;
62
- }
 
 
 
 
 
 
63
  }
64
 
65
- function addQTagsButtons() {
66
- if ( typeof(QTags) === 'undefined' ) {
67
- return;
68
- }
69
 
70
- QTags.addButton( 'mc4wp_paragraph', '<p>', '<p>', '</p>', 'paragraph', 'Paragraph tag', 1 );
71
- QTags.addButton( 'mc4wp_label', 'label', '<label>', '</label>', 'label', 'Label tag', 2 );
72
- QTags.addButton( 'mc4wp_response', 'form response', '{response}', '', 'response', 'Shows the form response' );
73
- QTags.addButton( 'mc4wp_subscriber_count', '# of subscribers', '{subscriber_count}', '', 'subscribers', 'Shows number of subscribers of selected list(s)' );
74
 
75
- if( window.mc4wp.hasCaptchaPlugin === true ) {
76
- QTags.addButton( 'mc4wp_captcha', 'CAPTCHA', '{captcha}', '', 'captcha', 'Display a CAPTCHA field' );
77
- }
78
  }
79
 
80
- /**
81
- * Bind Event Handlers
82
- */
83
-
84
- // show a notice when clicking a pro feature
85
- $context.find(".pro-feature, .pro-feature label, .pro-feature :radio").click(showProNotice);
86
-
87
- // Show send-welcome field only when double opt-in is disabled
88
- $context.find('input[name$="[double_optin]"]').change(toggleSendWelcomeFields);
89
-
90
- // show woocommerce settings only when `show at woocommerce checkout` is checked.
91
- $context.find('input[name$="[show_at_woocommerce_checkout]"]').change(toggleWooCommerceSettings);
92
-
93
- // only show fieldwizard when a list is selected
94
- $listInputs.change(toggleFieldWizard);
95
-
96
- // Allow tabs inside the form mark-up
97
- $(document).delegate('#mc4wpformmarkup', 'keydown', allowTabKey);
98
-
99
- addQTagsButtons();
100
-
101
-
102
- /**
103
- * MailChimp for WordPress Field Wizard
104
- * Created by Danny van Kooten
105
- */
106
- (function() {
107
- 'use strict';
108
-
109
- // setup variables
110
- var $lists = $("#mc4wp-lists :input");
111
- var $mailchimpFields = $("#mc4wp-fw-mailchimp-fields");
112
- var $mailchimpMergeFields = $mailchimpFields.find('.merge-fields');
113
- var $mailchimpGroupings = $mailchimpFields.find(".groupings");
114
- var $wizardFields = $("#mc4wp-fw-fields");
115
- var $value = $("#mc4wp-fw-value");
116
- var $valueLabel = $("#mc4wp-fw-value-label");
117
- var $multipleValues = $("#mc4wp-fw-values");
118
- var $label = $("#mc4wp-fw-label");
119
- var $placeholder = $("#mc4wp-fw-placeholder");
120
- var $required = $("#mc4wp-fw-required");
121
- var $wrapp = $("#mc4wp-fw-wrap-p");
122
- var fieldType, fieldName;
123
- var $codePreview = $("#mc4wp-fw-preview");
124
- var strings = mc4wp.strings.fieldWizard;
125
- var requiredFields = [];
126
-
127
- // functions
128
- function checkRequiredFields() {
129
-
130
- // check presence of reach required field
131
- var missingFields = {};
132
- for(var i=0; i<requiredFields.length; i++) {
133
- var htmlString = 'name="' + requiredFields[i].tag.toLowerCase();
134
- if( $formMarkup.val().toLowerCase().indexOf( htmlString ) == -1 ) {
135
- missingFields[requiredFields[i].tag] = requiredFields[i];
136
- }
137
- }
138
 
139
- // do nothing if no fields are missing
140
- if($.isEmptyObject(missingFields)) {
141
- $missingFieldsNotice.hide();
142
- return;
143
- }
 
144
 
145
- // show notice
146
- $missingFieldsList.html('');
147
- for( var key in missingFields ) {
148
- var field = missingFields[key];
149
- var $listItem = $("<li></li>");
150
- $listItem.html( field.name + " (<code>" + field.tag + "</code>)");
151
- $listItem.appendTo( $missingFieldsList );
152
- }
153
 
154
- $missingFieldsNotice.show();
155
- return;
156
- }
157
 
158
- // set the fields the user can choose from
159
- function setMailChimpFields()
160
- {
161
- // empty field select
162
- $mailchimpFields.find('option').not('.default').remove();
163
-
164
- // empty required fields array
165
- requiredFields = [];
166
-
167
- // loop through checked lists
168
- $lists.filter(':checked').each(function() {
169
- var listId = $(this).val();
170
- var list = mc4wp.mailchimpLists[listId];
171
-
172
- // loop through merge fields from this list
173
- for(var i = 0, fieldCount = list.merge_vars.length; i < fieldCount; i++) {
174
-
175
- var listField = list.merge_vars[i];
176
-
177
- if( listField.req ) {
178
- requiredFields.push( listField );
179
- }
180
-
181
- // add field to select if no similar option exists yet
182
- if($mailchimpMergeFields.children("option[value='"+ listField.tag +"']").length === 0) {
183
-
184
- var text = (listField.name.length > 25) ? listField.name.substring(0, 25) + '..' : listField.name;
185
- if(listField.req) { text += '*'; }
186
-
187
- var $option = $("<option />")
188
- .text(text)
189
- .val(listField.tag)
190
- .data('list-field', listField);
191
-
192
- $mailchimpMergeFields.append($option);
193
- }
194
- }
195
-
196
- // loop through interest groupings
197
- for(var i = 0, groupingsCount = list.interest_groupings.length; i < groupingsCount; i++) {
198
- var listGrouping = list.interest_groupings[i];
199
-
200
- // add field to select if no similar option exists yet
201
- if($mailchimpGroupings.children("option[value='"+ listGrouping.id +"']").length === 0) {
202
- var text = (listGrouping.name.length > 25) ? listGrouping.name.substring(0, 25) + '..' : listGrouping.name;
203
-
204
- // build option HTML
205
- var $option = $("<option />")
206
- .text(text)
207
- .val(listGrouping.id)
208
- .data('list-grouping', listGrouping);
209
-
210
- // only show 1 grouping per list
211
- if(i >= 1) {
212
- $option.text( strings.proOnly + " " + text)
213
- .attr('disabled', 'disabled')
214
- .data('list-grouping', null);
215
- }
216
-
217
- $mailchimpGroupings.append($option);
218
- }
219
- }
220
 
 
 
 
 
 
221
 
222
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
 
224
- // check required fields with new selected lists
225
- checkRequiredFields();
226
- }
227
 
228
- /**
229
- * Set Presets
230
- */
231
- function setPresets()
232
- {
233
- resetFields();
234
-
235
- var selected = $(this).find(':selected');
236
- switch( selected.val() ) {
237
-
238
- case '_action':
239
- fieldType = 'action';
240
- $wizardFields.find('.wrap-p').show();
241
- break;
242
-
243
- case 'submit':
244
- fieldType = 'submit';
245
- $valueLabel.text( strings.buttonText );
246
- $value.val( strings.subscribe );
247
- $wizardFields.find('p.row').filter('.value, .wrap-p').show();
248
- break;
249
-
250
- case 'lists':
251
- fieldType = 'lists';
252
- $wizardFields.find('.wrap-p').show();
253
- break;
254
-
255
- default:
256
- // try data for MailChimp field
257
- var data = selected.data('list-field');
258
- if(data) {
259
- return setPresetsForField(data);
260
- }
261
-
262
- // try data for interest grouping
263
- var data = selected.data('list-grouping');
264
- if(data) {
265
- return setPresetsForGrouping(data);
266
- }
267
-
268
- break;
269
  }
270
-
271
- updateCodePreview();
272
  }
273
 
274
- /**
275
- * Resets all wizard fields back to their default state
276
- */
277
- function resetFields() {
278
- $wizardFields.find('.row :input').each(function() {
279
- if($(this).is(":checkbox")) { this.checked = true; } else { this.value = ''; }
280
- });
281
 
282
- $wizardFields.find('p.row').hide();
283
- $multipleValues.find(':input').remove();
284
- $wizardFields.show();
285
 
286
- fieldType = 'text';
287
- fieldName = '';
288
- $valueLabel.html( strings.initialValue + " <small>" + strings.optional + "</small>" );
289
  }
290
 
291
- /**
292
- * Add inputs for each group
293
- */
294
- function addGroupInputs(groups)
295
- {
296
- // add a text input to $multipleValues for each group
297
- for(var i = 0, groupsCount = groups.length; i < groupsCount; i++) {
298
- $("<input />").attr('type', 'text')
299
- .addClass('widefat').data('value', groups[i].name)
300
- .attr('placeholder', strings.labelFor + ' "' + groups[i].name + '" ' + strings.orLeaveEmpty )
301
- .attr('value', groups[i].name)
302
- .appendTo($multipleValues);
303
- }
304
- }
305
 
306
- /**
307
- * Set presets for interest groupings
308
- */
309
- function setPresetsForGrouping(data)
310
- {
311
- $wizardFields.find('p.row').filter('.values, .label, .wrap-p').show();
312
- $label.val(data.name + ":");
313
- fieldName = 'GROUPINGS[' + data.id + ']';
314
- addGroupInputs(data.groups);
315
-
316
- switch(data.form_field) {
317
- case 'radio':
318
- fieldType = 'radio';
319
- break;
320
-
321
- case 'hidden':
322
- // hide all rows except value row
323
- $wizardFields.find('p.row').filter('.values, .label, .wrap-p').hide();
324
- $wizardFields.find('p.row.value').show();
325
-
326
- // add group name to hidden input value
327
- for(var i = 0, groupsCount = data.groups.length; i < groupsCount; i++) {
328
- $value.val($value.val() + data.groups[i].name + ',');
329
- }
330
-
331
- fieldType = 'hidden';
332
- break;
333
-
334
- case 'dropdown':
335
- fieldType = 'select';
336
- break;
337
-
338
- default:
339
- fieldType = 'checkbox';
340
-
341
- // turn field name into an array
342
- fieldName += '[]';
343
- break;
344
- }
345
-
346
- // update code preview
347
- updateCodePreview();
348
  }
349
 
350
- /**
351
- * Build list choice HTML
352
- */
353
- function getListChoiceHTML()
354
- {
355
- var html = '';
356
- $lists.each(function() {
357
- var list_id = $(this).val();
358
- var list_name = $(this).parent('label').text();
359
- var attrs = '';
360
-
361
- if($(this).is(':checked')) {
362
- attrs += 'checked ';
363
- }
364
-
365
- html += '<label>' + "\n"
366
- html += "\t" + '<input type="checkbox" name="_mc4wp_lists[]" value="' + list_id +'" '+ attrs + ' /> '+ list_name + "\n";
367
- html += '</label>' + "\n";
368
- });
369
 
370
- return html;
371
- }
372
-
373
- function getActionChoiceHTML() {
374
- var actions = [
375
- { name: "subscribe", label: strings.subscribe, checked: true },
376
- { name: "unsubscribe", label: strings.unsubscribe, checked: false }
377
- ];
378
 
379
- var html = '';
380
- for( var i=0; i<actions.length; i++ ) {
381
- var action = actions[i];
382
 
383
- html += '<label>' + "\n";
384
- html += "\t" + '<input type="radio" name="_mc4wp_action" value="' + action.name + '" '+ ( ( action.checked ) ? 'checked' : '' ) +' > ' + action.label + "\n";
385
- html += '</label>' + "\n";
386
- }
387
 
388
- return html;
 
 
389
  }
390
 
 
 
391
 
 
 
392
 
393
- /**
394
- * Set presets for a fields
395
- */
396
- function setPresetsForField(data)
397
- {
398
-
399
- // show fields for this field type
400
- var visibleRowsMap = {
401
- 'default': [ 'label', 'value', 'placeholder', 'required', 'wrap-p' ],
402
- 'select': [ 'label', 'required', 'wrap-p', 'values'],
403
- 'radio': [ 'label', 'required', 'wrap-p', 'values'],
404
- 'date': [ 'label', 'required', 'wrap-p', 'value']
405
- };
406
-
407
- // map MailChimp field types to HTML5 field type
408
- var fieldTypesMap = {
409
- 'text': 'text',
410
- 'email': 'email',
411
- 'phone': 'tel',
412
- 'address': 'text',
413
- 'number': 'number',
414
- 'dropdown': 'select',
415
- 'date': 'date',
416
- 'birthday': 'date',
417
- 'radio': 'radio',
418
- 'checkbox': 'checkbox',
419
- 'url': 'url'
420
- };
421
-
422
- if( typeof(fieldTypesMap[data.field_type]) !== "undefined") {
423
- fieldType = fieldTypesMap[data.field_type];
424
- } else {
425
- fieldType = 'text';
426
- }
427
-
428
- if( typeof(visibleRowsMap[fieldType]) !== "undefined") {
429
- var visibleRows = visibleRowsMap[fieldType];
430
- } else {
431
- var visibleRows = visibleRowsMap["default"];
432
- }
433
 
434
- for(var i = 0; i < visibleRows.length; i++) {
435
- $wizardFields.find('p.row.' + visibleRows[i]).show();
436
- }
 
 
437
 
438
- fieldType = fieldType;
439
- fieldName = data.tag;
440
 
441
- // set placeholder text
442
- $placeholder.val( "Your " + data.name.toLowerCase());
 
 
443
 
444
- // set label text
445
- $label.val( data.name + ":" );
446
 
447
- // set required attribute
448
- $required.prop('checked', data.req);
449
 
450
- if($multipleValues.is(":visible") && data.choices) {
451
- for(var i = 0; i < data.choices.length; i++) {
452
- $("<input />")
453
- .attr('type', 'text')
454
- .addClass('widefat')
455
- .data('value', data.choices[i])
456
- .attr('placeholder', strings.labelFor + ' "' + data.choices[i] + '" ' + strings.orLeaveEmpty )
457
- .attr('value', data.choices[i])
458
- .appendTo($multipleValues);
459
- }
460
  }
461
-
462
- // update code preview
463
- updateCodePreview();
464
  }
465
 
466
- /**
467
- * Format and indent the generated HTML
468
- * Then add it to the code preview textarea
469
- */
470
- function setCodePreview(html) {
471
- html = html_beautify(html);
472
- $codePreview.val(html);
473
  }
474
 
 
475
 
476
- /**
477
- * Generate HTML based on the various field values
478
- */
479
- function updateCodePreview()
480
- {
481
- var $code = $("<div></div>");
482
- var $input;
483
-
484
- switch(fieldType) {
485
-
486
- case 'action':
487
- var html = getActionChoiceHTML();
488
-
489
- if( wrapInParagraph() ) {
490
- html = "<p>" + html + "</p>";
491
- }
492
-
493
- return setCodePreview(html);
494
- break;
495
-
496
- // MailChimp lists
497
- case 'lists':
498
- var html = getListChoiceHTML();
499
-
500
- if( wrapInParagraph() ) {
501
- html = "<p>" + html + "</p>";
502
- }
503
-
504
- return setCodePreview(html);
505
- break;
506
-
507
- // MailChimp dropdown
508
- case 'select':
509
- $input = $("<select />");
510
-
511
- // add options to select
512
- $multipleValues.find(":input").each(function() {
513
- if($(this).val().length > 0) {
514
- $("<option />")
515
- .val($(this).data("value"))
516
- .text($(this).val())
517
- .appendTo($input); }
518
- });
519
- break;
520
-
521
- // MailChimo choices
522
- case 'radio':
523
- case 'checkbox':
524
- // build multiple input values
525
- $multipleValues.find(":input").each(function() {
526
- if($(this).val().length > 0) {
527
- $input = $("<input />").attr('type', fieldType).attr('name', fieldName).val($(this).data('value'));
528
-
529
- if($required.is(':visible:checked')) {
530
- $input.attr('required', true);
531
- }
532
-
533
- $code.append($input);
534
-
535
- $input.wrap("<label />");
536
- $("<span />").text($(this).val() + ' ').insertAfter($input);
537
- }
538
- });
539
- break;
540
-
541
- // MailChimp long text
542
- case 'textarea':
543
- $input = $("<textarea />");
544
- break;
545
-
546
- default:
547
- $input = $("<input />").attr('type', fieldType);
548
- break;
549
- }
550
 
551
- // only do this piece when we're not adding radio inputs
552
- if(fieldType !== 'radio' && fieldType !== 'checkbox') {
553
-
554
- // set name attribute
555
- if(fieldName.length > 0) {
556
- $input.attr('name', fieldName);
557
- }
558
-
559
- // set value
560
- if($value.is(":visible") && $value.val().length > 0) {
561
- if(fieldType === 'textarea') {
562
- $input.text($value.val());
563
- } else {
564
- $input.attr('value', $value.val());
565
- }
566
- }
567
-
568
- // add placeholder to element
569
- if($placeholder.is(":visible") && $placeholder.val().length > 0) {
570
- $input.attr('placeholder', $placeholder.val());
571
- }
572
-
573
- // add required attribute
574
- if($required.is(':visible:checked')) {
575
- $input.attr('required', true);
576
- }
577
-
578
- $code.append($input);
579
- }
580
 
581
- // build label
582
- if($label.is(":visible") && $label.val().length > 0) {
583
- $("<label />").text($label.val()).prependTo($code);
584
- }
585
 
586
- // wrap in paragraphs?
587
- if( wrapInParagraph() ) {
588
- $code.wrapInner($("<p />"));
589
- }
590
-
591
- setCodePreview($code.html());
592
  }
593
 
594
- /**
595
- * Transfer code preview field to form mark-up
596
- */
597
- function addCodeToFormMarkup() {
598
-
599
- var result = false;
600
-
601
- // try to insert in QuickTags editor at cursor position
602
- if(typeof wpActiveEditor !== 'undefined' && typeof QTags !== 'undefined' && QTags.insertContent) {
603
- result = QTags.insertContent($codePreview.val());
604
- }
605
-
606
- // fallback, just append
607
- if(!result) {
608
- $formMarkup.val($formMarkup.val() + "\n" + $codePreview.val());
609
- }
610
 
611
- // trigger change event
612
- $formMarkup.change();
 
613
  }
614
 
615
- /**
616
- * Should we wrap the HTML in paragraph tags?
617
- *
618
- * @returns {boolean}
619
- */
620
- function wrapInParagraph() {
621
- return ( $wrapp.is(':visible:checked') ) ? true: false;
622
- }
623
 
624
- // setup events
625
- $lists.change(setMailChimpFields);
626
- $mailchimpFields.change(setPresets);
627
- $wizardFields.change(updateCodePreview);
628
- $("#mc4wp-fw-add-to-form").click(addCodeToFormMarkup);
629
-
630
- // Validate the form fields after every change
631
- $formMarkup.bind({
632
- 'input': function() {
633
- $formMarkup.unbind('keydown');
634
- checkRequiredFields.call(this);
635
- },
636
- 'keydown': checkRequiredFields
637
  });
 
638
 
639
- // init
640
- setMailChimpFields();
 
 
641
 
642
- })();
643
 
644
- })(jQuery);
 
 
645
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
+ 'use strict';
3
+
4
+ // dependencies
5
+ var m = require('mithril');
6
+ var EventEmitter = require('wolfy87-eventemitter');
7
+
8
+ // vars
9
+ var context = document.getElementById('mc4wp-admin');
10
+ var events = new EventEmitter();
11
+ var tabs = require ('./admin/tabs.js')(context);
12
+ var helpers = require('./admin/helpers.js');
13
+ var settings = require('./admin/settings.js')(context, helpers, events);
14
+
15
+ // expose some things
16
+ window.mc4wp = window.mc4wp || {};
17
+ window.mc4wp.deps = window.mc4wp.deps || {};
18
+ window.mc4wp.deps.mithril = m;
19
+ window.mc4wp.helpers = helpers;
20
+ window.mc4wp.events = events;
21
+ window.mc4wp.settings = settings;
22
+ window.mc4wp.tabs = tabs;
23
+
24
+ },{"./admin/helpers.js":2,"./admin/settings.js":3,"./admin/tabs.js":4,"mithril":6,"wolfy87-eventemitter":7}],2:[function(require,module,exports){
25
+ 'use strict';
26
+
27
+ var helpers = {};
28
+
29
+ helpers.toggleElement = function(selector) {
30
+ var elements = document.querySelectorAll(selector);
31
+ for( var i=0; i<elements.length;i++){
32
+ var show = elements[i].clientHeight <= 0;
33
+ elements[i].style.display = show ? '' : 'none';
34
+ }
35
+ };
36
+
37
+ helpers.bindEventToElement = function(element,event,handler) {
38
+ if ( element.addEventListener) {
39
+ element.addEventListener(event, handler);
40
+ } else if (element.attachEvent) {
41
+ element.attachEvent('on' + event, handler);
42
+ }
43
+ };
44
+
45
+ helpers.bindEventToElements = function( elements, event, handler ) {
46
+ Array.prototype.forEach.call( elements, function(element) {
47
+ helpers.bindEventToElement(element,event,handler);
48
+ });
49
+ };
50
+
51
+ /**
52
+ * Showif.js
53
+ */
54
+ (function() {
55
+ var showIfElements = document.querySelectorAll('[data-showif]');
56
+
57
+ // dependent elements
58
+ Array.prototype.forEach.call( showIfElements, function(element) {
59
+ var config = JSON.parse( element.getAttribute('data-showif') );
60
+ var parentElements = document.querySelectorAll('[name="'+ config.element +'"]');
61
+ var inputs = element.querySelectorAll('input');
62
+
63
+ function toggleElement() {
64
+
65
+ // do nothing with unchecked elements
66
+ if( typeof( this.checked ) === "boolean" && ! this.checked ) {
67
+ return;
68
+ }
69
+
70
+ // check if element value matches expected value
71
+ var conditionMet = ( this.value == config.value );
72
+ element.style.display = conditionMet ? '' : 'none';
73
+ element.style.visibility = conditionMet ? '' : 'hidden';
74
 
75
+ // disable input fields to stop sending their values to server
76
+ Array.prototype.forEach.call( inputs, function(inputElement) {
77
+ inputElement.disabled = !conditionMet;
78
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
80
 
81
+ // find checked element and call toggleElement function
82
+ Array.prototype.forEach.call( parentElements, function( parentElement ) {
83
+ toggleElement.call(parentElement);
84
+ });
85
 
86
+ // bind on all changes
87
+ helpers.bindEventToElements(parentElements, 'change', toggleElement);
88
+ });
89
+ })();
90
 
91
+ module.exports = helpers;
92
+ },{}],3:[function(require,module,exports){
93
+ var Settings = function(context, helpers, events ) {
94
+ 'use strict';
95
 
96
+ // vars
97
+ var unsaved = false;
98
+ var changes = 0;
99
+ var form = context.querySelector('form');
100
+ var listInputs = context.querySelectorAll('.mc4wp-list-input');
101
+ var lists = mc4wp_vars.mailchimp.lists;
102
+ var selectedLists = [];
103
+
104
+ // functions
105
+ function getSelectedListsWhere(searchKey,searchValue) {
106
+ return selectedLists.filter(function(el) {
107
+ return el[searchKey] === searchValue;
108
+ });
109
  }
110
 
111
+ function getSelectedLists() {
112
+ return selectedLists;
 
113
  }
114
 
115
+ function updateSelectedLists() {
116
+ selectedLists = [];
117
+
118
+ Array.prototype.forEach.call(listInputs, function(input) {
119
+ // skip unchecked checkboxes
120
+ if( typeof( input.checked ) === "boolean" && ! input.checked ) {
121
+ return;
122
+ }
123
 
124
+ if( typeof( lists[ input.value ] ) === "object" ){
125
+ selectedLists.push( lists[ input.value ] );
126
+ }
127
+ });
128
 
129
+ events.trigger('selectedLists.change', [ selectedLists ]);
130
+ return selectedLists;
131
+ }
 
132
 
133
+ function toggleVisibleLists() {
134
+ var rows = document.querySelectorAll('.lists--only-selected > *');
135
+ Array.prototype.forEach.call(rows, function(el) {
136
 
137
+ var listId = el.getAttribute('data-list-id');
138
+ var isSelected = getSelectedListsWhere('id', listId).length > 0;
139
+
140
+ if( isSelected ) {
141
+ el.setAttribute('class', el.getAttribute('class').replace('hidden',''));
142
+ } else {
143
+ el.setAttribute('class', el.getAttribute('class') + " hidden" );
144
+ }
145
+ });
146
  }
147
 
148
+ // TODO: make this translatable
149
+ function confirmPageLeave(e) {
150
+ if(!unsaved) return;
 
151
 
152
+ e = e|| window.event;
153
+ var confirmationMessage = 'It looks like you have been editing something. '
154
+ + 'If you leave before saving, your changes will be lost.';
 
155
 
156
+ e.returnValue = confirmationMessage; //Gecko + IE
157
+ return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
 
158
  }
159
 
160
+ events.on('selectedLists.change', toggleVisibleLists);
161
+ helpers.bindEventToElements(listInputs,'change',updateSelectedLists);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
+ // make it hard to leave big forms with unsaved changes
164
+ if( form && form.elements.length > 10 ) {
165
+ helpers.bindEventToElement(form,'change',function() { changes++; if( changes > 5 ) { unsaved = true; } });
166
+ helpers.bindEventToElement(form,'submit',function() { unsaved = false; changes = 0; });
167
+ helpers.bindEventToElement(window,'beforeunload', confirmPageLeave);
168
+ }
169
 
170
+ updateSelectedLists();
 
 
 
 
 
 
 
171
 
172
+ return {
173
+ getSelectedLists: getSelectedLists
174
+ }
175
 
176
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
 
178
+ module.exports = Settings;
179
+ },{}],4:[function(require,module,exports){
180
+ // Tabs
181
+ var Tabs = function(context) {
182
+ 'use strict';
183
 
184
+ // @todo last piece of jQuery... can we get rid of it?
185
+ var $ = window.jQuery;
186
+
187
+ var URL = require('./url.js');
188
+ var $context = $(context);
189
+ var $tabs = $context.find('.tab');
190
+ var $tabNavs = $context.find('.nav-tab');
191
+ var refererField = context.querySelector('input[name="_wp_http_referer"]');
192
+ var tabs = [];
193
+
194
+ $.each($tabs, function(i,t) {
195
+ var id = t.id.substring(4);
196
+ var title = $(t).find('h2').first().text();
197
+
198
+ tabs.push({
199
+ id: id,
200
+ title: title,
201
+ element: t,
202
+ nav: context.querySelectorAll('.nav-tab-' + id),
203
+ open: function() { return open(id); }
204
+ });
205
+ });
206
 
207
+ function get(id) {
 
 
208
 
209
+ for( var i=0; i<tabs.length; i++){
210
+ if(tabs[i].id === id ) {
211
+ return tabs[i];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  }
 
 
213
  }
214
 
215
+ return undefined;
216
+ }
 
 
 
 
 
217
 
218
+ function open( tab, updateState ) {
 
 
219
 
220
+ // make sure we have a tab object
221
+ if(typeof(tab) === "string"){
222
+ tab = get(tab);
223
  }
224
 
225
+ if(!tab) { return false; }
 
 
 
 
 
 
 
 
 
 
 
 
 
226
 
227
+ // should we update state?
228
+ if( updateState == undefined ) {
229
+ updateState = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  }
231
 
232
+ // hide all tabs & remove active class
233
+ $tabs.removeClass('tab-active').css('display', 'none');
234
+ $tabNavs.removeClass('nav-tab-active');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
+ // add `nav-tab-active` to this tab
237
+ Array.prototype.forEach.call(tab.nav, function(nav) {
238
+ nav.className += " nav-tab-active";
239
+ nav.blur();
240
+ });
 
 
 
241
 
242
+ // show target tab
243
+ tab.element.style.display = 'block';
244
+ tab.element.className += " tab-active";
245
 
246
+ // create new URL
247
+ var url = URL.setParameter(window.location.href, "tab", tab.id );
 
 
248
 
249
+ // update hash
250
+ if( history.pushState && updateState ) {
251
+ history.pushState( tab.id, '', url );
252
  }
253
 
254
+ // update document title
255
+ title(tab);
256
 
257
+ // update referer field
258
+ refererField.value = url;
259
 
260
+ // if thickbox is open, close it.
261
+ if( typeof(tb_remove) === "function" ) {
262
+ tb_remove();
263
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
 
265
+ // refresh editor after switching tabs
266
+ // TODO: decouple decouple decouple
267
+ if( tab.id === 'fields' && window.mc4wp && window.mc4wp.forms && window.mc4wp.forms.editor ) {
268
+ mc4wp.forms.editor.refresh();
269
+ }
270
 
271
+ return true;
272
+ }
273
 
274
+ function title(tab) {
275
+ var title = document.title.split('-');
276
+ document.title = document.title.replace(title[0], tab.title + " ");
277
+ }
278
 
279
+ function switchTab(e) {
280
+ e = e || window.event;
281
 
282
+ // get from data attribute
283
+ var tabId = this.getAttribute('data-tab');
284
 
285
+ // get from classname
286
+ if( ! tabId ) {
287
+ var match = this.className.match(/nav-tab-(\w+)?/);
288
+ if( match ) {
289
+ tabId = match[1];
 
 
 
 
 
290
  }
 
 
 
291
  }
292
 
293
+ // get from href
294
+ if( ! tabId ) {
295
+ var urlParams = URL.parse( this.href );
296
+ if( ! urlParams.tab ) { return; }
297
+ tabId = urlParams.tab;
 
 
298
  }
299
 
300
+ var opened = open( tabId );
301
 
302
+ if( opened ) {
303
+ e.preventDefault();
304
+ e.returnValue = false;
305
+ return false;
306
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
 
308
+ return true;
309
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
 
311
+ function init() {
 
 
 
312
 
313
+ // check for current tab
314
+ if(! history.pushState) {
315
+ return;
 
 
 
316
  }
317
 
318
+ var activeTab = $tabs.filter(':visible').get(0);
319
+ if( ! activeTab ) { return; }
320
+ var tab = get(activeTab.id.substring(4));
321
+ if(!tab) return;
 
 
 
 
 
 
 
 
 
 
 
 
322
 
323
+ // check if tab is in html5 history
324
+ if( history.replaceState && history.state === null) {
325
+ history.replaceState( tab.id, '' );
326
  }
327
 
328
+ // update document title
329
+ title(tab);
330
+ }
 
 
 
 
 
331
 
332
+ $tabNavs.click(switchTab);
333
+ $(document.body).on('click', '.tab-link', switchTab);
334
+ init();
335
+
336
+ if(window.addEventListener && history.pushState ) {
337
+ window.addEventListener('popstate', function(e) {
338
+ if(!e.state) return true;
339
+ var tabId = e.state;
340
+ return open(tabId,false);
 
 
 
 
341
  });
342
+ }
343
 
344
+ return {
345
+ open: open,
346
+ get: get
347
+ }
348
 
349
+ };
350
 
351
+ module.exports = Tabs;
352
+ },{"./url.js":5}],5:[function(require,module,exports){
353
+ 'use strict';
354
 
355
+ var URL = {
356
+ parse: function(url) {
357
+ var query = {};
358
+ var a = url.split('&');
359
+ for (var i in a) {
360
+ if(!a.hasOwnProperty(i)) {
361
+ continue;
362
+ }
363
+ var b = a[i].split('=');
364
+ query[decodeURIComponent(b[0])] = decodeURIComponent(b[1]);
365
+ }
366
+
367
+ return query;
368
+ },
369
+ build: function(data) {
370
+ var ret = [];
371
+ for (var d in data)
372
+ ret.push(d + "=" + encodeURIComponent(data[d]));
373
+ return ret.join("&");
374
+ },
375
+ setParameter: function( url, key, value ) {
376
+ var data = URL.parse( url );
377
+ data[ key ] = value;
378
+ return URL.build( data );
379
+ }
380
+ };
381
+
382
+ module.exports = URL;
383
+ },{}],6:[function(require,module,exports){
384
+ var m = (function app(window, undefined) {
385
+ var OBJECT = "[object Object]", ARRAY = "[object Array]", STRING = "[object String]", FUNCTION = "function";
386
+ var type = {}.toString;
387
+ var parser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[.+?\])/g, attrParser = /\[(.+?)(?:=("|'|)(.*?)\2)?\]/;
388
+ var voidElements = /^(AREA|BASE|BR|COL|COMMAND|EMBED|HR|IMG|INPUT|KEYGEN|LINK|META|PARAM|SOURCE|TRACK|WBR)$/;
389
+ var noop = function() {}
390
+
391
+ // caching commonly used variables
392
+ var $document, $location, $requestAnimationFrame, $cancelAnimationFrame;
393
+
394
+ // self invoking function needed because of the way mocks work
395
+ function initialize(window){
396
+ $document = window.document;
397
+ $location = window.location;
398
+ $cancelAnimationFrame = window.cancelAnimationFrame || window.clearTimeout;
399
+ $requestAnimationFrame = window.requestAnimationFrame || window.setTimeout;
400
+ }
401
+
402
+ initialize(window);
403
+
404
+
405
+ /**
406
+ * @typedef {String} Tag
407
+ * A string that looks like -> div.classname#id[param=one][param2=two]
408
+ * Which describes a DOM node
409
+ */
410
+
411
+ /**
412
+ *
413
+ * @param {Tag} The DOM node tag
414
+ * @param {Object=[]} optional key-value pairs to be mapped to DOM attrs
415
+ * @param {...mNode=[]} Zero or more Mithril child nodes. Can be an array, or splat (optional)
416
+ *
417
+ */
418
+ function m() {
419
+ var args = [].slice.call(arguments);
420
+ var hasAttrs = args[1] != null && type.call(args[1]) === OBJECT && !("tag" in args[1] || "view" in args[1]) && !("subtree" in args[1]);
421
+ var attrs = hasAttrs ? args[1] : {};
422
+ var classAttrName = "class" in attrs ? "class" : "className";
423
+ var cell = {tag: "div", attrs: {}};
424
+ var match, classes = [];
425
+ if (type.call(args[0]) != STRING) throw new Error("selector in m(selector, attrs, children) should be a string")
426
+ while (match = parser.exec(args[0])) {
427
+ if (match[1] === "" && match[2]) cell.tag = match[2];
428
+ else if (match[1] === "#") cell.attrs.id = match[2];
429
+ else if (match[1] === ".") classes.push(match[2]);
430
+ else if (match[3][0] === "[") {
431
+ var pair = attrParser.exec(match[3]);
432
+ cell.attrs[pair[1]] = pair[3] || (pair[2] ? "" :true)
433
+ }
434
+ }
435
+
436
+ var children = hasAttrs ? args.slice(2) : args.slice(1);
437
+ if (children.length === 1 && type.call(children[0]) === ARRAY) {
438
+ cell.children = children[0]
439
+ }
440
+ else {
441
+ cell.children = children
442
+ }
443
+
444
+ for (var attrName in attrs) {
445
+ if (attrs.hasOwnProperty(attrName)) {
446
+ if (attrName === classAttrName && attrs[attrName] != null && attrs[attrName] !== "") {
447
+ classes.push(attrs[attrName])
448
+ cell.attrs[attrName] = "" //create key in correct iteration order
449
+ }
450
+ else cell.attrs[attrName] = attrs[attrName]
451
+ }
452
+ }
453
+ if (classes.length > 0) cell.attrs[classAttrName] = classes.join(" ");
454
+
455
+ return cell
456
+ }
457
+ function build(parentElement, parentTag, parentCache, parentIndex, data, cached, shouldReattach, index, editable, namespace, configs) {
458
+ //`build` is a recursive function that manages creation/diffing/removal of DOM elements based on comparison between `data` and `cached`
459
+ //the diff algorithm can be summarized as this:
460
+ //1 - compare `data` and `cached`
461
+ //2 - if they are different, copy `data` to `cached` and update the DOM based on what the difference is
462
+ //3 - recursively apply this algorithm for every array and for the children of every virtual element
463
+
464
+ //the `cached` data structure is essentially the same as the previous redraw's `data` data structure, with a few additions:
465
+ //- `cached` always has a property called `nodes`, which is a list of DOM elements that correspond to the data represented by the respective virtual element
466
+ //- in order to support attaching `nodes` as a property of `cached`, `cached` is *always* a non-primitive object, i.e. if the data was a string, then cached is a String instance. If data was `null` or `undefined`, cached is `new String("")`
467
+ //- `cached also has a `configContext` property, which is the state storage object exposed by config(element, isInitialized, context)
468
+ //- when `cached` is an Object, it represents a virtual element; when it's an Array, it represents a list of elements; when it's a String, Number or Boolean, it represents a text node
469
+
470
+ //`parentElement` is a DOM element used for W3C DOM API calls
471
+ //`parentTag` is only used for handling a corner case for textarea values
472
+ //`parentCache` is used to remove nodes in some multi-node cases
473
+ //`parentIndex` and `index` are used to figure out the offset of nodes. They're artifacts from before arrays started being flattened and are likely refactorable
474
+ //`data` and `cached` are, respectively, the new and old nodes being diffed
475
+ //`shouldReattach` is a flag indicating whether a parent node was recreated (if so, and if this node is reused, then this node must reattach itself to the new parent)
476
+ //`editable` is a flag that indicates whether an ancestor is contenteditable
477
+ //`namespace` indicates the closest HTML namespace as it cascades down from an ancestor
478
+ //`configs` is a list of config functions to run after the topmost `build` call finishes running
479
+
480
+ //there's logic that relies on the assumption that null and undefined data are equivalent to empty strings
481
+ //- this prevents lifecycle surprises from procedural helpers that mix implicit and explicit return statements (e.g. function foo() {if (cond) return m("div")}
482
+ //- it simplifies diffing code
483
+ //data.toString() might throw or return null if data is the return value of Console.log in Firefox (behavior depends on version)
484
+ try {if (data == null || data.toString() == null) data = "";} catch (e) {data = ""}
485
+ if (data.subtree === "retain") return cached;
486
+ var cachedType = type.call(cached), dataType = type.call(data);
487
+ if (cached == null || cachedType !== dataType) {
488
+ if (cached != null) {
489
+ if (parentCache && parentCache.nodes) {
490
+ var offset = index - parentIndex;
491
+ var end = offset + (dataType === ARRAY ? data : cached.nodes).length;
492
+ clear(parentCache.nodes.slice(offset, end), parentCache.slice(offset, end))
493
+ }
494
+ else if (cached.nodes) clear(cached.nodes, cached)
495
+ }
496
+ cached = new data.constructor;
497
+ if (cached.tag) cached = {}; //if constructor creates a virtual dom element, use a blank object as the base cached node instead of copying the virtual el (#277)
498
+ cached.nodes = []
499
+ }
500
+
501
+ if (dataType === ARRAY) {
502
+ //recursively flatten array
503
+ for (var i = 0, len = data.length; i < len; i++) {
504
+ if (type.call(data[i]) === ARRAY) {
505
+ data = data.concat.apply([], data);
506
+ i-- //check current index again and flatten until there are no more nested arrays at that index
507
+ len = data.length
508
+ }
509
+ }
510
+
511
+ var nodes = [], intact = cached.length === data.length, subArrayCount = 0;
512
+
513
+ //keys algorithm: sort elements without recreating them if keys are present
514
+ //1) create a map of all existing keys, and mark all for deletion
515
+ //2) add new keys to map and mark them for addition
516
+ //3) if key exists in new list, change action from deletion to a move
517
+ //4) for each key, handle its corresponding action as marked in previous steps
518
+ var DELETION = 1, INSERTION = 2 , MOVE = 3;
519
+ var existing = {}, shouldMaintainIdentities = false;
520
+ for (var i = 0; i < cached.length; i++) {
521
+ if (cached[i] && cached[i].attrs && cached[i].attrs.key != null) {
522
+ shouldMaintainIdentities = true;
523
+ existing[cached[i].attrs.key] = {action: DELETION, index: i}
524
+ }
525
+ }
526
+
527
+ var guid = 0
528
+ for (var i = 0, len = data.length; i < len; i++) {
529
+ if (data[i] && data[i].attrs && data[i].attrs.key != null) {
530
+ for (var j = 0, len = data.length; j < len; j++) {
531
+ if (data[j] && data[j].attrs && data[j].attrs.key == null) data[j].attrs.key = "__mithril__" + guid++
532
+ }
533
+ break
534
+ }
535
+ }
536
+
537
+ if (shouldMaintainIdentities) {
538
+ var keysDiffer = false
539
+ if (data.length != cached.length) keysDiffer = true
540
+ else for (var i = 0, cachedCell, dataCell; cachedCell = cached[i], dataCell = data[i]; i++) {
541
+ if (cachedCell.attrs && dataCell.attrs && cachedCell.attrs.key != dataCell.attrs.key) {
542
+ keysDiffer = true
543
+ break
544
+ }
545
+ }
546
+
547
+ if (keysDiffer) {
548
+ for (var i = 0, len = data.length; i < len; i++) {
549
+ if (data[i] && data[i].attrs) {
550
+ if (data[i].attrs.key != null) {
551
+ var key = data[i].attrs.key;
552
+ if (!existing[key]) existing[key] = {action: INSERTION, index: i};
553
+ else existing[key] = {
554
+ action: MOVE,
555
+ index: i,
556
+ from: existing[key].index,
557
+ element: cached.nodes[existing[key].index] || $document.createElement("div")
558
+ }
559
+ }
560
+ }
561
+ }
562
+ var actions = []
563
+ for (var prop in existing) actions.push(existing[prop])
564
+ var changes = actions.sort(sortChanges);
565
+ var newCached = new Array(cached.length)
566
+ newCached.nodes = cached.nodes.slice()
567
+
568
+ for (var i = 0, change; change = changes[i]; i++) {
569
+ if (change.action === DELETION) {
570
+ clear(cached[change.index].nodes, cached[change.index]);
571
+ newCached.splice(change.index, 1)
572
+ }
573
+ if (change.action === INSERTION) {
574
+ var dummy = $document.createElement("div");
575
+ dummy.key = data[change.index].attrs.key;
576
+ parentElement.insertBefore(dummy, parentElement.childNodes[change.index] || null);
577
+ newCached.splice(change.index, 0, {attrs: {key: data[change.index].attrs.key}, nodes: [dummy]})
578
+ newCached.nodes[change.index] = dummy
579
+ }
580
+
581
+ if (change.action === MOVE) {
582
+ if (parentElement.childNodes[change.index] !== change.element && change.element !== null) {
583
+ parentElement.insertBefore(change.element, parentElement.childNodes[change.index] || null)
584
+ }
585
+ newCached[change.index] = cached[change.from]
586
+ newCached.nodes[change.index] = change.element
587
+ }
588
+ }
589
+ cached = newCached;
590
+ }
591
+ }
592
+ //end key algorithm
593
+
594
+ for (var i = 0, cacheCount = 0, len = data.length; i < len; i++) {
595
+ //diff each item in the array
596
+ var item = build(parentElement, parentTag, cached, index, data[i], cached[cacheCount], shouldReattach, index + subArrayCount || subArrayCount, editable, namespace, configs);
597
+ if (item === undefined) continue;
598
+ if (!item.nodes.intact) intact = false;
599
+ if (item.$trusted) {
600
+ //fix offset of next element if item was a trusted string w/ more than one html element
601
+ //the first clause in the regexp matches elements
602
+ //the second clause (after the pipe) matches text nodes
603
+ subArrayCount += (item.match(/<[^\/]|\>\s*[^<]/g) || [0]).length
604
+ }
605
+ else subArrayCount += type.call(item) === ARRAY ? item.length : 1;
606
+ cached[cacheCount++] = item
607
+ }
608
+ if (!intact) {
609
+ //diff the array itself
610
+
611
+ //update the list of DOM nodes by collecting the nodes from each item
612
+ for (var i = 0, len = data.length; i < len; i++) {
613
+ if (cached[i] != null) nodes.push.apply(nodes, cached[i].nodes)
614
+ }
615
+ //remove items from the end of the array if the new array is shorter than the old one
616
+ //if errors ever happen here, the issue is most likely a bug in the construction of the `cached` data structure somewhere earlier in the program
617
+ for (var i = 0, node; node = cached.nodes[i]; i++) {
618
+ if (node.parentNode != null && nodes.indexOf(node) < 0) clear([node], [cached[i]])
619
+ }
620
+ if (data.length < cached.length) cached.length = data.length;
621
+ cached.nodes = nodes
622
+ }
623
+ }
624
+ else if (data != null && dataType === OBJECT) {
625
+ var views = [], controllers = []
626
+ while (data.view) {
627
+ var view = data.view.$original || data.view
628
+ var controllerIndex = m.redraw.strategy() == "diff" && cached.views ? cached.views.indexOf(view) : -1
629
+ var controller = controllerIndex > -1 ? cached.controllers[controllerIndex] : new (data.controller || noop)
630
+ var key = data && data.attrs && data.attrs.key
631
+ data = pendingRequests == 0 || (cached && cached.controllers && cached.controllers.indexOf(controller) > -1) ? data.view(controller) : {tag: "placeholder"}
632
+ if (data.subtree === "retain") return cached;
633
+ if (key) {
634
+ if (!data.attrs) data.attrs = {}
635
+ data.attrs.key = key
636
+ }
637
+ if (controller.onunload) unloaders.push({controller: controller, handler: controller.onunload})
638
+ views.push(view)
639
+ controllers.push(controller)
640
+ }
641
+ if (!data.tag && controllers.length) throw new Error("Component template must return a virtual element, not an array, string, etc.")
642
+ if (!data.attrs) data.attrs = {};
643
+ if (!cached.attrs) cached.attrs = {};
644
+
645
+ var dataAttrKeys = Object.keys(data.attrs)
646
+ var hasKeys = dataAttrKeys.length > ("key" in data.attrs ? 1 : 0)
647
+ //if an element is different enough from the one in cache, recreate it
648
+ if (data.tag != cached.tag || dataAttrKeys.sort().join() != Object.keys(cached.attrs).sort().join() || data.attrs.id != cached.attrs.id || data.attrs.key != cached.attrs.key || (m.redraw.strategy() == "all" && (!cached.configContext || cached.configContext.retain !== true)) || (m.redraw.strategy() == "diff" && cached.configContext && cached.configContext.retain === false)) {
649
+ if (cached.nodes.length) clear(cached.nodes);
650
+ if (cached.configContext && typeof cached.configContext.onunload === FUNCTION) cached.configContext.onunload()
651
+ if (cached.controllers) {
652
+ for (var i = 0, controller; controller = cached.controllers[i]; i++) {
653
+ if (typeof controller.onunload === FUNCTION) controller.onunload({preventDefault: noop})
654
+ }
655
+ }
656
+ }
657
+ if (type.call(data.tag) != STRING) return;
658
+
659
+ var node, isNew = cached.nodes.length === 0;
660
+ if (data.attrs.xmlns) namespace = data.attrs.xmlns;
661
+ else if (data.tag === "svg") namespace = "http://www.w3.org/2000/svg";
662
+ else if (data.tag === "math") namespace = "http://www.w3.org/1998/Math/MathML";
663
+
664
+ if (isNew) {
665
+ if (data.attrs.is) node = namespace === undefined ? $document.createElement(data.tag, data.attrs.is) : $document.createElementNS(namespace, data.tag, data.attrs.is);
666
+ else node = namespace === undefined ? $document.createElement(data.tag) : $document.createElementNS(namespace, data.tag);
667
+ cached = {
668
+ tag: data.tag,
669
+ //set attributes first, then create children
670
+ attrs: hasKeys ? setAttributes(node, data.tag, data.attrs, {}, namespace) : data.attrs,
671
+ children: data.children != null && data.children.length > 0 ?
672
+ build(node, data.tag, undefined, undefined, data.children, cached.children, true, 0, data.attrs.contenteditable ? node : editable, namespace, configs) :
673
+ data.children,
674
+ nodes: [node]
675
+ };
676
+ if (controllers.length) {
677
+ cached.views = views
678
+ cached.controllers = controllers
679
+ for (var i = 0, controller; controller = controllers[i]; i++) {
680
+ if (controller.onunload && controller.onunload.$old) controller.onunload = controller.onunload.$old
681
+ if (pendingRequests && controller.onunload) {
682
+ var onunload = controller.onunload
683
+ controller.onunload = noop
684
+ controller.onunload.$old = onunload
685
+ }
686
+ }
687
+ }
688
+
689
+ if (cached.children && !cached.children.nodes) cached.children.nodes = [];
690
+ //edge case: setting value on <select> doesn't work before children exist, so set it again after children have been created
691
+ if (data.tag === "select" && "value" in data.attrs) setAttributes(node, data.tag, {value: data.attrs.value}, {}, namespace);
692
+ parentElement.insertBefore(node, parentElement.childNodes[index] || null)
693
+ }
694
+ else {
695
+ node = cached.nodes[0];
696
+ if (hasKeys) setAttributes(node, data.tag, data.attrs, cached.attrs, namespace);
697
+ cached.children = build(node, data.tag, undefined, undefined, data.children, cached.children, false, 0, data.attrs.contenteditable ? node : editable, namespace, configs);
698
+ cached.nodes.intact = true;
699
+ if (controllers.length) {
700
+ cached.views = views
701
+ cached.controllers = controllers
702
+ }
703
+ if (shouldReattach === true && node != null) parentElement.insertBefore(node, parentElement.childNodes[index] || null)
704
+ }
705
+ //schedule configs to be called. They are called after `build` finishes running
706
+ if (typeof data.attrs["config"] === FUNCTION) {
707
+ var context = cached.configContext = cached.configContext || {};
708
+
709
+ // bind
710
+ var callback = function(data, args) {
711
+ return function() {
712
+ return data.attrs["config"].apply(data, args)
713
+ }
714
+ };
715
+ configs.push(callback(data, [node, !isNew, context, cached]))
716
+ }
717
+ }
718
+ else if (typeof data != FUNCTION) {
719
+ //handle text nodes
720
+ var nodes;
721
+ if (cached.nodes.length === 0) {
722
+ if (data.$trusted) {
723
+ nodes = injectHTML(parentElement, index, data)
724
+ }
725
+ else {
726
+ nodes = [$document.createTextNode(data)];
727
+ if (!parentElement.nodeName.match(voidElements)) parentElement.insertBefore(nodes[0], parentElement.childNodes[index] || null)
728
+ }
729
+ cached = "string number boolean".indexOf(typeof data) > -1 ? new data.constructor(data) : data;
730
+ cached.nodes = nodes
731
+ }
732
+ else if (cached.valueOf() !== data.valueOf() || shouldReattach === true) {
733
+ nodes = cached.nodes;
734
+ if (!editable || editable !== $document.activeElement) {
735
+ if (data.$trusted) {
736
+ clear(nodes, cached);
737
+ nodes = injectHTML(parentElement, index, data)
738
+ }
739
+ else {
740
+ //corner case: replacing the nodeValue of a text node that is a child of a textarea/contenteditable doesn't work
741
+ //we need to update the value property of the parent textarea or the innerHTML of the contenteditable element instead
742
+ if (parentTag === "textarea") parentElement.value = data;
743
+ else if (editable) editable.innerHTML = data;
744
+ else {
745
+ if (nodes[0].nodeType === 1 || nodes.length > 1) { //was a trusted string
746
+ clear(cached.nodes, cached);
747
+ nodes = [$document.createTextNode(data)]
748
+ }
749
+ parentElement.insertBefore(nodes[0], parentElement.childNodes[index] || null);
750
+ nodes[0].nodeValue = data
751
+ }
752
+ }
753
+ }
754
+ cached = new data.constructor(data);
755
+ cached.nodes = nodes
756
+ }
757
+ else cached.nodes.intact = true
758
+ }
759
+
760
+ return cached
761
+ }
762
+ function sortChanges(a, b) {return a.action - b.action || a.index - b.index}
763
+ function setAttributes(node, tag, dataAttrs, cachedAttrs, namespace) {
764
+ for (var attrName in dataAttrs) {
765
+ var dataAttr = dataAttrs[attrName];
766
+ var cachedAttr = cachedAttrs[attrName];
767
+ if (!(attrName in cachedAttrs) || (cachedAttr !== dataAttr)) {
768
+ cachedAttrs[attrName] = dataAttr;
769
+ try {
770
+ //`config` isn't a real attributes, so ignore it
771
+ if (attrName === "config" || attrName == "key") continue;
772
+ //hook event handlers to the auto-redrawing system
773
+ else if (typeof dataAttr === FUNCTION && attrName.indexOf("on") === 0) {
774
+ node[attrName] = autoredraw(dataAttr, node)
775
+ }
776
+ //handle `style: {...}`
777
+ else if (attrName === "style" && dataAttr != null && type.call(dataAttr) === OBJECT) {
778
+ for (var rule in dataAttr) {
779
+ if (cachedAttr == null || cachedAttr[rule] !== dataAttr[rule]) node.style[rule] = dataAttr[rule]
780
+ }
781
+ for (var rule in cachedAttr) {
782
+ if (!(rule in dataAttr)) node.style[rule] = ""
783
+ }
784
+ }
785
+ //handle SVG
786
+ else if (namespace != null) {
787
+ if (attrName === "href") node.setAttributeNS("http://www.w3.org/1999/xlink", "href", dataAttr);
788
+ else if (attrName === "className") node.setAttribute("class", dataAttr);
789
+ else node.setAttribute(attrName, dataAttr)
790
+ }
791
+ //handle cases that are properties (but ignore cases where we should use setAttribute instead)
792
+ //- list and form are typically used as strings, but are DOM element references in js
793
+ //- when using CSS selectors (e.g. `m("[style='']")`), style is used as a string, but it's an object in js
794
+ else if (attrName in node && !(attrName === "list" || attrName === "style" || attrName === "form" || attrName === "type" || attrName === "width" || attrName === "height")) {
795
+ //#348 don't set the value if not needed otherwise cursor placement breaks in Chrome
796
+ if (tag !== "input" || node[attrName] !== dataAttr) node[attrName] = dataAttr
797
+ }
798
+ else node.setAttribute(attrName, dataAttr)
799
+ }
800
+ catch (e) {
801
+ //swallow IE's invalid argument errors to mimic HTML's fallback-to-doing-nothing-on-invalid-attributes behavior
802
+ if (e.message.indexOf("Invalid argument") < 0) throw e
803
+ }
804
+ }
805
+ //#348 dataAttr may not be a string, so use loose comparison (double equal) instead of strict (triple equal)
806
+ else if (attrName === "value" && tag === "input" && node.value != dataAttr) {
807
+ node.value = dataAttr
808
+ }
809
+ }
810
+ return cachedAttrs
811
+ }
812
+ function clear(nodes, cached) {
813
+ for (var i = nodes.length - 1; i > -1; i--) {
814
+ if (nodes[i] && nodes[i].parentNode) {
815
+ try {nodes[i].parentNode.removeChild(nodes[i])}
816
+ catch (e) {} //ignore if this fails due to order of events (see http://stackoverflow.com/questions/21926083/failed-to-execute-removechild-on-node)
817
+ cached = [].concat(cached);
818
+ if (cached[i]) unload(cached[i])
819
+ }
820
+ }
821
+ if (nodes.length != 0) nodes.length = 0
822
+ }
823
+ function unload(cached) {
824
+ if (cached.configContext && typeof cached.configContext.onunload === FUNCTION) {
825
+ cached.configContext.onunload();
826
+ cached.configContext.onunload = null
827
+ }
828
+ if (cached.controllers) {
829
+ for (var i = 0, controller; controller = cached.controllers[i]; i++) {
830
+ if (typeof controller.onunload === FUNCTION) controller.onunload({preventDefault: noop});
831
+ }
832
+ }
833
+ if (cached.children) {
834
+ if (type.call(cached.children) === ARRAY) {
835
+ for (var i = 0, child; child = cached.children[i]; i++) unload(child)
836
+ }
837
+ else if (cached.children.tag) unload(cached.children)
838
+ }
839
+ }
840
+ function injectHTML(parentElement, index, data) {
841
+ var nextSibling = parentElement.childNodes[index];
842
+ if (nextSibling) {
843
+ var isElement = nextSibling.nodeType != 1;
844
+ var placeholder = $document.createElement("span");
845
+ if (isElement) {
846
+ parentElement.insertBefore(placeholder, nextSibling || null);
847
+ placeholder.insertAdjacentHTML("beforebegin", data);
848
+ parentElement.removeChild(placeholder)
849
+ }
850
+ else nextSibling.insertAdjacentHTML("beforebegin", data)
851
+ }
852
+ else parentElement.insertAdjacentHTML("beforeend", data);
853
+ var nodes = [];
854
+ while (parentElement.childNodes[index] !== nextSibling) {
855
+ nodes.push(parentElement.childNodes[index]);
856
+ index++
857
+ }
858
+ return nodes
859
+ }
860
+ function autoredraw(callback, object) {
861
+ return function(e) {
862
+ e = e || event;
863
+ m.redraw.strategy("diff");
864
+ m.startComputation();
865
+ try {return callback.call(object, e)}
866
+ finally {
867
+ endFirstComputation()
868
+ }
869
+ }
870
+ }
871
+
872
+ var html;
873
+ var documentNode = {
874
+ appendChild: function(node) {
875
+ if (html === undefined) html = $document.createElement("html");
876
+ if ($document.documentElement && $document.documentElement !== node) {
877
+ $document.replaceChild(node, $document.documentElement)
878
+ }
879
+ else $document.appendChild(node);
880
+ this.childNodes = $document.childNodes
881
+ },
882
+ insertBefore: function(node) {
883
+ this.appendChild(node)
884
+ },
885
+ childNodes: []
886
+ };
887
+ var nodeCache = [], cellCache = {};
888
+ m.render = function(root, cell, forceRecreation) {
889
+ var configs = [];
890
+ if (!root) throw new Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.");
891
+ var id = getCellCacheKey(root);
892
+ var isDocumentRoot = root === $document;
893
+ var node = isDocumentRoot || root === $document.documentElement ? documentNode : root;
894
+ if (isDocumentRoot && cell.tag != "html") cell = {tag: "html", attrs: {}, children: cell};
895
+ if (cellCache[id] === undefined) clear(node.childNodes);
896
+ if (forceRecreation === true) reset(root);
897
+ cellCache[id] = build(node, null, undefined, undefined, cell, cellCache[id], false, 0, null, undefined, configs);
898
+ for (var i = 0, len = configs.length; i < len; i++) configs[i]()
899
+ };
900
+ function getCellCacheKey(element) {
901
+ var index = nodeCache.indexOf(element);
902
+ return index < 0 ? nodeCache.push(element) - 1 : index
903
+ }
904
+
905
+ m.trust = function(value) {
906
+ value = new String(value);
907
+ value.$trusted = true;
908
+ return value
909
+ };
910
+
911
+ function gettersetter(store) {
912
+ var prop = function() {
913
+ if (arguments.length) store = arguments[0];
914
+ return store
915
+ };
916
+
917
+ prop.toJSON = function() {
918
+ return store
919
+ };
920
+
921
+ return prop
922
+ }
923
+
924
+ m.prop = function (store) {
925
+ //note: using non-strict equality check here because we're checking if store is null OR undefined
926
+ if (((store != null && type.call(store) === OBJECT) || typeof store === FUNCTION) && typeof store.then === FUNCTION) {
927
+ return propify(store)
928
+ }
929
+
930
+ return gettersetter(store)
931
+ };
932
+
933
+ var roots = [], components = [], controllers = [], lastRedrawId = null, lastRedrawCallTime = 0, computePreRedrawHook = null, computePostRedrawHook = null, prevented = false, topComponent, unloaders = [];
934
+ var FRAME_BUDGET = 16; //60 frames per second = 1 call per 16 ms
935
+ function parameterize(component, args) {
936
+ var controller = function() {
937
+ return (component.controller || noop).apply(this, args) || this
938
+ }
939
+ var view = function(ctrl) {
940
+ if (arguments.length > 1) args = args.concat([].slice.call(arguments, 1))
941
+ return component.view.apply(component, args ? [ctrl].concat(args) : [ctrl])
942
+ }
943
+ view.$original = component.view
944
+ var output = {controller: controller, view: view}
945
+ if (args[0] && args[0].key != null) output.attrs = {key: args[0].key}
946
+ return output
947
+ }
948
+ m.component = function(component) {
949
+ return parameterize(component, [].slice.call(arguments, 1))
950
+ }
951
+ m.mount = m.module = function(root, component) {
952
+ if (!root) throw new Error("Please ensure the DOM element exists before rendering a template into it.");
953
+ var index = roots.indexOf(root);
954
+ if (index < 0) index = roots.length;
955
+
956
+ var isPrevented = false;
957
+ var event = {preventDefault: function() {
958
+ isPrevented = true;
959
+ computePreRedrawHook = computePostRedrawHook = null;
960
+ }};
961
+ for (var i = 0, unloader; unloader = unloaders[i]; i++) {
962
+ unloader.handler.call(unloader.controller, event)
963
+ unloader.controller.onunload = null
964
+ }
965
+ if (isPrevented) {
966
+ for (var i = 0, unloader; unloader = unloaders[i]; i++) unloader.controller.onunload = unloader.handler
967
+ }
968
+ else unloaders = []
969
+
970
+ if (controllers[index] && typeof controllers[index].onunload === FUNCTION) {
971
+ controllers[index].onunload(event)
972
+ }
973
+
974
+ if (!isPrevented) {
975
+ m.redraw.strategy("all");
976
+ m.startComputation();
977
+ roots[index] = root;
978
+ if (arguments.length > 2) component = subcomponent(component, [].slice.call(arguments, 2))
979
+ var currentComponent = topComponent = component = component || {controller: function() {}};
980
+ var constructor = component.controller || noop
981
+ var controller = new constructor;
982
+ //controllers may call m.mount recursively (via m.route redirects, for example)
983
+ //this conditional ensures only the last recursive m.mount call is applied
984
+ if (currentComponent === topComponent) {
985
+ controllers[index] = controller;
986
+ components[index] = component
987
+ }
988
+ endFirstComputation();
989
+ return controllers[index]
990
+ }
991
+ };
992
+ var redrawing = false
993
+ m.redraw = function(force) {
994
+ if (redrawing) return
995
+ redrawing = true
996
+ //lastRedrawId is a positive number if a second redraw is requested before the next animation frame
997
+ //lastRedrawID is null if it's the first redraw and not an event handler
998
+ if (lastRedrawId && force !== true) {
999
+ //when setTimeout: only reschedule redraw if time between now and previous redraw is bigger than a frame, otherwise keep currently scheduled timeout
1000
+ //when rAF: always reschedule redraw
1001
+ if ($requestAnimationFrame === window.requestAnimationFrame || new Date - lastRedrawCallTime > FRAME_BUDGET) {
1002
+ if (lastRedrawId > 0) $cancelAnimationFrame(lastRedrawId);
1003
+ lastRedrawId = $requestAnimationFrame(redraw, FRAME_BUDGET)
1004
+ }
1005
+ }
1006
+ else {
1007
+ redraw();
1008
+ lastRedrawId = $requestAnimationFrame(function() {lastRedrawId = null}, FRAME_BUDGET)
1009
+ }
1010
+ redrawing = false
1011
+ };
1012
+ m.redraw.strategy = m.prop();
1013
+ function redraw() {
1014
+ if (computePreRedrawHook) {
1015
+ computePreRedrawHook()
1016
+ computePreRedrawHook = null
1017
+ }
1018
+ for (var i = 0, root; root = roots[i]; i++) {
1019
+ if (controllers[i]) {
1020
+ var args = components[i].controller && components[i].controller.$$args ? [controllers[i]].concat(components[i].controller.$$args) : [controllers[i]]
1021
+ m.render(root, components[i].view ? components[i].view(controllers[i], args) : "")
1022
+ }
1023
+ }
1024
+ //after rendering within a routed context, we need to scroll back to the top, and fetch the document title for history.pushState
1025
+ if (computePostRedrawHook) {
1026
+ computePostRedrawHook();
1027
+ computePostRedrawHook = null
1028
+ }
1029
+ lastRedrawId = null;
1030
+ lastRedrawCallTime = new Date;
1031
+ m.redraw.strategy("diff")
1032
+ }
1033
+
1034
+ var pendingRequests = 0;
1035
+ m.startComputation = function() {pendingRequests++};
1036
+ m.endComputation = function() {
1037
+ pendingRequests = Math.max(pendingRequests - 1, 0);
1038
+ if (pendingRequests === 0) m.redraw()
1039
+ };
1040
+ var endFirstComputation = function() {
1041
+ if (m.redraw.strategy() == "none") {
1042
+ pendingRequests--
1043
+ m.redraw.strategy("diff")
1044
+ }
1045
+ else m.endComputation();
1046
+ }
1047
+
1048
+ m.withAttr = function(prop, withAttrCallback) {
1049
+ return function(e) {
1050
+ e = e || event;
1051
+ var currentTarget = e.currentTarget || this;
1052
+ withAttrCallback(prop in currentTarget ? currentTarget[prop] : currentTarget.getAttribute(prop))
1053
+ }
1054
+ };
1055
+
1056
+ //routing
1057
+ var modes = {pathname: "", hash: "#", search: "?"};
1058
+ var redirect = noop, routeParams, currentRoute, isDefaultRoute = false;
1059
+ m.route = function() {
1060
+ //m.route()
1061
+ if (arguments.length === 0) return currentRoute;
1062
+ //m.route(el, defaultRoute, routes)
1063
+ else if (arguments.length === 3 && type.call(arguments[1]) === STRING) {
1064
+ var root = arguments[0], defaultRoute = arguments[1], router = arguments[2];
1065
+ redirect = function(source) {
1066
+ var path = currentRoute = normalizeRoute(source);
1067
+ if (!routeByValue(root, router, path)) {
1068
+ if (isDefaultRoute) throw new Error("Ensure the default route matches one of the routes defined in m.route")
1069
+ isDefaultRoute = true
1070
+ m.route(defaultRoute, true)
1071
+ isDefaultRoute = false
1072
+ }
1073
+ };
1074
+ var listener = m.route.mode === "hash" ? "onhashchange" : "onpopstate";
1075
+ window[listener] = function() {
1076
+ var path = $location[m.route.mode]
1077
+ if (m.route.mode === "pathname") path += $location.search
1078
+ if (currentRoute != normalizeRoute(path)) {
1079
+ redirect(path)
1080
+ }
1081
+ };
1082
+ computePreRedrawHook = setScroll;
1083
+ window[listener]()
1084
+ }
1085
+ //config: m.route
1086
+ else if (arguments[0].addEventListener || arguments[0].attachEvent) {
1087
+ var element = arguments[0];
1088
+ var isInitialized = arguments[1];
1089
+ var context = arguments[2];
1090
+ var vdom = arguments[3];
1091
+ element.href = (m.route.mode !== 'pathname' ? $location.pathname : '') + modes[m.route.mode] + vdom.attrs.href;
1092
+ if (element.addEventListener) {
1093
+ element.removeEventListener("click", routeUnobtrusive);
1094
+ element.addEventListener("click", routeUnobtrusive)
1095
+ }
1096
+ else {
1097
+ element.detachEvent("onclick", routeUnobtrusive);
1098
+ element.attachEvent("onclick", routeUnobtrusive)
1099
+ }
1100
+ }
1101
+ //m.route(route, params, shouldReplaceHistoryEntry)
1102
+ else if (type.call(arguments[0]) === STRING) {
1103
+ var oldRoute = currentRoute;
1104
+ currentRoute = arguments[0];
1105
+ var args = arguments[1] || {}
1106
+ var queryIndex = currentRoute.indexOf("?")
1107
+ var params = queryIndex > -1 ? parseQueryString(currentRoute.slice(queryIndex + 1)) : {}
1108
+ for (var i in args) params[i] = args[i]
1109
+ var querystring = buildQueryString(params)
1110
+ var currentPath = queryIndex > -1 ? currentRoute.slice(0, queryIndex) : currentRoute
1111
+ if (querystring) currentRoute = currentPath + (currentPath.indexOf("?") === -1 ? "?" : "&") + querystring;
1112
+
1113
+ var shouldReplaceHistoryEntry = (arguments.length === 3 ? arguments[2] : arguments[1]) === true || oldRoute === arguments[0];
1114
+
1115
+ if (window.history.pushState) {
1116
+ computePreRedrawHook = setScroll
1117
+ computePostRedrawHook = function() {
1118
+ window.history[shouldReplaceHistoryEntry ? "replaceState" : "pushState"](null, $document.title, modes[m.route.mode] + currentRoute);
1119
+ };
1120
+ redirect(modes[m.route.mode] + currentRoute)
1121
+ }
1122
+ else {
1123
+ $location[m.route.mode] = currentRoute
1124
+ redirect(modes[m.route.mode] + currentRoute)
1125
+ }
1126
+ }
1127
+ };
1128
+ m.route.param = function(key) {
1129
+ if (!routeParams) throw new Error("You must call m.route(element, defaultRoute, routes) before calling m.route.param()")
1130
+ return routeParams[key]
1131
+ };
1132
+ m.route.mode = "search";
1133
+ function normalizeRoute(route) {
1134
+ return route.slice(modes[m.route.mode].length)
1135
+ }
1136
+ function routeByValue(root, router, path) {
1137
+ routeParams = {};
1138
+
1139
+ var queryStart = path.indexOf("?");
1140
+ if (queryStart !== -1) {
1141
+ routeParams = parseQueryString(path.substr(queryStart + 1, path.length));
1142
+ path = path.substr(0, queryStart)
1143
+ }
1144
+
1145
+ // Get all routes and check if there's
1146
+ // an exact match for the current path
1147
+ var keys = Object.keys(router);
1148
+ var index = keys.indexOf(path);
1149
+ if(index !== -1){
1150
+ m.mount(root, router[keys [index]]);
1151
+ return true;
1152
+ }
1153
+
1154
+ for (var route in router) {
1155
+ if (route === path) {
1156
+ m.mount(root, router[route]);
1157
+ return true
1158
+ }
1159
+
1160
+ var matcher = new RegExp("^" + route.replace(/:[^\/]+?\.{3}/g, "(.*?)").replace(/:[^\/]+/g, "([^\\/]+)") + "\/?$");
1161
+
1162
+ if (matcher.test(path)) {
1163
+ path.replace(matcher, function() {
1164
+ var keys = route.match(/:[^\/]+/g) || [];
1165
+ var values = [].slice.call(arguments, 1, -2);
1166
+ for (var i = 0, len = keys.length; i < len; i++) routeParams[keys[i].replace(/:|\./g, "")] = decodeURIComponent(values[i])
1167
+ m.mount(root, router[route])
1168
+ });
1169
+ return true
1170
+ }
1171
+ }
1172
+ }
1173
+ function routeUnobtrusive(e) {
1174
+ e = e || event;
1175
+ if (e.ctrlKey || e.metaKey || e.which === 2) return;
1176
+ if (e.preventDefault) e.preventDefault();
1177
+ else e.returnValue = false;
1178
+ var currentTarget = e.currentTarget || e.srcElement;
1179
+ var args = m.route.mode === "pathname" && currentTarget.search ? parseQueryString(currentTarget.search.slice(1)) : {};
1180
+ while (currentTarget && currentTarget.nodeName.toUpperCase() != "A") currentTarget = currentTarget.parentNode
1181
+ m.route(currentTarget[m.route.mode].slice(modes[m.route.mode].length), args)
1182
+ }
1183
+ function setScroll() {
1184
+ if (m.route.mode != "hash" && $location.hash) $location.hash = $location.hash;
1185
+ else window.scrollTo(0, 0)
1186
+ }
1187
+ function buildQueryString(object, prefix) {
1188
+ var duplicates = {}
1189
+ var str = []
1190
+ for (var prop in object) {
1191
+ var key = prefix ? prefix + "[" + prop + "]" : prop
1192
+ var value = object[prop]
1193
+ var valueType = type.call(value)
1194
+ var pair = (value === null) ? encodeURIComponent(key) :
1195
+ valueType === OBJECT ? buildQueryString(value, key) :
1196
+ valueType === ARRAY ? value.reduce(function(memo, item) {
1197
+ if (!duplicates[key]) duplicates[key] = {}
1198
+ if (!duplicates[key][item]) {
1199
+ duplicates[key][item] = true
1200
+ return memo.concat(encodeURIComponent(key) + "=" + encodeURIComponent(item))
1201
+ }
1202
+ return memo
1203
+ }, []).join("&") :
1204
+ encodeURIComponent(key) + "=" + encodeURIComponent(value)
1205
+ if (value !== undefined) str.push(pair)
1206
+ }
1207
+ return str.join("&")
1208
+ }
1209
+ function parseQueryString(str) {
1210
+ if (str.charAt(0) === "?") str = str.substring(1);
1211
+
1212
+ var pairs = str.split("&"), params = {};
1213
+ for (var i = 0, len = pairs.length; i < len; i++) {
1214
+ var pair = pairs[i].split("=");
1215
+ var key = decodeURIComponent(pair[0])
1216
+ var value = pair.length == 2 ? decodeURIComponent(pair[1]) : null
1217
+ if (params[key] != null) {
1218
+ if (type.call(params[key]) !== ARRAY) params[key] = [params[key]]
1219
+ params[key].push(value)
1220
+ }
1221
+ else params[key] = value
1222
+ }
1223
+ return params
1224
+ }
1225
+ m.route.buildQueryString = buildQueryString
1226
+ m.route.parseQueryString = parseQueryString
1227
+
1228
+ function reset(root) {
1229
+ var cacheKey = getCellCacheKey(root);
1230
+ clear(root.childNodes, cellCache[cacheKey]);
1231
+ cellCache[cacheKey] = undefined
1232
+ }
1233
+
1234
+ m.deferred = function () {
1235
+ var deferred = new Deferred();
1236
+ deferred.promise = propify(deferred.promise);
1237
+ return deferred
1238
+ };
1239
+ function propify(promise, initialValue) {
1240
+ var prop = m.prop(initialValue);
1241
+ promise.then(prop);
1242
+ prop.then = function(resolve, reject) {
1243
+ return propify(promise.then(resolve, reject), initialValue)
1244
+ };
1245
+ return prop
1246
+ }
1247
+ //Promiz.mithril.js | Zolmeister | MIT
1248
+ //a modified version of Promiz.js, which does not conform to Promises/A+ for two reasons:
1249
+ //1) `then` callbacks are called synchronously (because setTimeout is too slow, and the setImmediate polyfill is too big
1250
+ //2) throwing subclasses of Error cause the error to be bubbled up instead of triggering rejection (because the spec does not account for the important use case of default browser error handling, i.e. message w/ line number)
1251
+ function Deferred(successCallback, failureCallback) {
1252
+ var RESOLVING = 1, REJECTING = 2, RESOLVED = 3, REJECTED = 4;
1253
+ var self = this, state = 0, promiseValue = 0, next = [];
1254
+
1255
+ self["promise"] = {};
1256
+
1257
+ self["resolve"] = function(value) {
1258
+ if (!state) {
1259
+ promiseValue = value;
1260
+ state = RESOLVING;
1261
+
1262
+ fire()
1263
+ }
1264
+ return this
1265
+ };
1266
+
1267
+ self["reject"] = function(value) {
1268
+ if (!state) {
1269
+ promiseValue = value;
1270
+ state = REJECTING;
1271
+
1272
+ fire()
1273
+ }
1274
+ return this
1275
+ };
1276
+
1277
+ self.promise["then"] = function(successCallback, failureCallback) {
1278
+ var deferred = new Deferred(successCallback, failureCallback);
1279
+ if (state === RESOLVED) {
1280
+ deferred.resolve(promiseValue)
1281
+ }
1282
+ else if (state === REJECTED) {
1283
+ deferred.reject(promiseValue)
1284
+ }
1285
+ else {
1286
+ next.push(deferred)
1287
+ }
1288
+ return deferred.promise
1289
+ };
1290
+
1291
+ function finish(type) {
1292
+ state = type || REJECTED;
1293
+ next.map(function(deferred) {
1294
+ state === RESOLVED && deferred.resolve(promiseValue) || deferred.reject(promiseValue)
1295
+ })
1296
+ }
1297
+
1298
+ function thennable(then, successCallback, failureCallback, notThennableCallback) {
1299
+ if (((promiseValue != null && type.call(promiseValue) === OBJECT) || typeof promiseValue === FUNCTION) && typeof then === FUNCTION) {
1300
+ try {
1301
+ // count protects against abuse calls from spec checker
1302
+ var count = 0;
1303
+ then.call(promiseValue, function(value) {
1304
+ if (count++) return;
1305
+ promiseValue = value;
1306
+ successCallback()
1307
+ }, function (value) {
1308
+ if (count++) return;
1309
+ promiseValue = value;
1310
+ failureCallback()
1311
+ })
1312
+ }
1313
+ catch (e) {
1314
+ m.deferred.onerror(e);
1315
+ promiseValue = e;
1316
+ failureCallback()
1317
+ }
1318
+ } else {
1319
+ notThennableCallback()
1320
+ }
1321
+ }
1322
+
1323
+ function fire() {
1324
+ // check if it's a thenable
1325
+ var then;
1326
+ try {
1327
+ then = promiseValue && promiseValue.then
1328
+ }
1329
+ catch (e) {
1330
+ m.deferred.onerror(e);
1331
+ promiseValue = e;
1332
+ state = REJECTING;
1333
+ return fire()
1334
+ }
1335
+ thennable(then, function() {
1336
+ state = RESOLVING;
1337
+ fire()
1338
+ }, function() {
1339
+ state = REJECTING;
1340
+ fire()
1341
+ }, function() {
1342
+ try {
1343
+ if (state === RESOLVING && typeof successCallback === FUNCTION) {
1344
+ promiseValue = successCallback(promiseValue)
1345
+ }
1346
+ else if (state === REJECTING && typeof failureCallback === "function") {
1347
+ promiseValue = failureCallback(promiseValue);
1348
+ state = RESOLVING
1349
+ }
1350
+ }
1351
+ catch (e) {
1352
+ m.deferred.onerror(e);
1353
+ promiseValue = e;
1354
+ return finish()
1355
+ }
1356
+
1357
+ if (promiseValue === self) {
1358
+ promiseValue = TypeError();
1359
+ finish()
1360
+ }
1361
+ else {
1362
+ thennable(then, function () {
1363
+ finish(RESOLVED)
1364
+ }, finish, function () {
1365
+ finish(state === RESOLVING && RESOLVED)
1366
+ })
1367
+ }
1368
+ })
1369
+ }
1370
+ }
1371
+ m.deferred.onerror = function(e) {
1372
+ if (type.call(e) === "[object Error]" && !e.constructor.toString().match(/ Error/)) throw e
1373
+ };
1374
+
1375
+ m.sync = function(args) {
1376
+ var method = "resolve";
1377
+ function synchronizer(pos, resolved) {
1378
+ return function(value) {
1379
+ results[pos] = value;
1380
+ if (!resolved) method = "reject";
1381
+ if (--outstanding === 0) {
1382
+ deferred.promise(results);
1383
+ deferred[method](results)
1384
+ }
1385
+ return value
1386
+ }
1387
+ }
1388
+
1389
+ var deferred = m.deferred();
1390
+ var outstanding = args.length;
1391
+ var results = new Array(outstanding);
1392
+ if (args.length > 0) {
1393
+ for (var i = 0; i < args.length; i++) {
1394
+ args[i].then(synchronizer(i, true), synchronizer(i, false))
1395
+ }
1396
+ }
1397
+ else deferred.resolve([]);
1398
+
1399
+ return deferred.promise
1400
+ };
1401
+ function identity(value) {return value}
1402
+
1403
+ function ajax(options) {
1404
+ if (options.dataType && options.dataType.toLowerCase() === "jsonp") {
1405
+ var callbackKey = "mithril_callback_" + new Date().getTime() + "_" + (Math.round(Math.random() * 1e16)).toString(36);
1406
+ var script = $document.createElement("script");
1407
+
1408
+ window[callbackKey] = function(resp) {
1409
+ script.parentNode.removeChild(script);
1410
+ options.onload({
1411
+ type: "load",
1412
+ target: {
1413
+ responseText: resp
1414
+ }
1415
+ });
1416
+ window[callbackKey] = undefined
1417
+ };
1418
+
1419
+ script.onerror = function(e) {
1420
+ script.parentNode.removeChild(script);
1421
+
1422
+ options.onerror({
1423
+ type: "error",
1424
+ target: {
1425
+ status: 500,
1426
+ responseText: JSON.stringify({error: "Error making jsonp request"})
1427
+ }
1428
+ });
1429
+ window[callbackKey] = undefined;
1430
+
1431
+ return false
1432
+ };
1433
+
1434
+ script.onload = function(e) {
1435
+ return false
1436
+ };
1437
+
1438
+ script.src = options.url
1439
+ + (options.url.indexOf("?") > 0 ? "&" : "?")
1440
+ + (options.callbackKey ? options.callbackKey : "callback")
1441
+ + "=" + callbackKey
1442
+ + "&" + buildQueryString(options.data || {});
1443
+ $document.body.appendChild(script)
1444
+ }
1445
+ else {
1446
+ var xhr = new window.XMLHttpRequest;
1447
+ xhr.open(options.method, options.url, true, options.user, options.password);
1448
+ xhr.onreadystatechange = function() {
1449
+ if (xhr.readyState === 4) {
1450
+ if (xhr.status >= 200 && xhr.status < 300) options.onload({type: "load", target: xhr});
1451
+ else options.onerror({type: "error", target: xhr})
1452
+ }
1453
+ };
1454
+ if (options.serialize === JSON.stringify && options.data && options.method !== "GET") {
1455
+ xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8")
1456
+ }
1457
+ if (options.deserialize === JSON.parse) {
1458
+ xhr.setRequestHeader("Accept", "application/json, text/*");
1459
+ }
1460
+ if (typeof options.config === FUNCTION) {
1461
+ var maybeXhr = options.config(xhr, options);
1462
+ if (maybeXhr != null) xhr = maybeXhr
1463
+ }
1464
+
1465
+ var data = options.method === "GET" || !options.data ? "" : options.data
1466
+ if (data && (type.call(data) != STRING && data.constructor != window.FormData)) {
1467
+ throw "Request data should be either be a string or FormData. Check the `serialize` option in `m.request`";
1468
+ }
1469
+ xhr.send(data);
1470
+ return xhr
1471
+ }
1472
+ }
1473
+ function bindData(xhrOptions, data, serialize) {
1474
+ if (xhrOptions.method === "GET" && xhrOptions.dataType != "jsonp") {
1475
+ var prefix = xhrOptions.url.indexOf("?") < 0 ? "?" : "&";
1476
+ var querystring = buildQueryString(data);
1477
+ xhrOptions.url = xhrOptions.url + (querystring ? prefix + querystring : "")
1478
+ }
1479
+ else xhrOptions.data = serialize(data);
1480
+ return xhrOptions
1481
+ }
1482
+ function parameterizeUrl(url, data) {
1483
+ var tokens = url.match(/:[a-z]\w+/gi);
1484
+ if (tokens && data) {
1485
+ for (var i = 0; i < tokens.length; i++) {
1486
+ var key = tokens[i].slice(1);
1487
+ url = url.replace(tokens[i], data[key]);
1488
+ delete data[key]
1489
+ }
1490
+ }
1491
+ return url
1492
+ }
1493
+
1494
+ m.request = function(xhrOptions) {
1495
+ if (xhrOptions.background !== true) m.startComputation();
1496
+ var deferred = new Deferred();
1497
+ var isJSONP = xhrOptions.dataType && xhrOptions.dataType.toLowerCase() === "jsonp";
1498
+ var serialize = xhrOptions.serialize = isJSONP ? identity : xhrOptions.serialize || JSON.stringify;
1499
+ var deserialize = xhrOptions.deserialize = isJSONP ? identity : xhrOptions.deserialize || JSON.parse;
1500
+ var extract = isJSONP ? function(jsonp) {return jsonp.responseText} : xhrOptions.extract || function(xhr) {
1501
+ return xhr.responseText.length === 0 && deserialize === JSON.parse ? null : xhr.responseText
1502
+ };
1503
+ xhrOptions.method = (xhrOptions.method || 'GET').toUpperCase();
1504
+ xhrOptions.url = parameterizeUrl(xhrOptions.url, xhrOptions.data);
1505
+ xhrOptions = bindData(xhrOptions, xhrOptions.data, serialize);
1506
+ xhrOptions.onload = xhrOptions.onerror = function(e) {
1507
+ try {
1508
+ e = e || event;
1509
+ var unwrap = (e.type === "load" ? xhrOptions.unwrapSuccess : xhrOptions.unwrapError) || identity;
1510
+ var response = unwrap(deserialize(extract(e.target, xhrOptions)), e.target);
1511
+ if (e.type === "load") {
1512
+ if (type.call(response) === ARRAY && xhrOptions.type) {
1513
+ for (var i = 0; i < response.length; i++) response[i] = new xhrOptions.type(response[i])
1514
+ }
1515
+ else if (xhrOptions.type) response = new xhrOptions.type(response)
1516
+ }
1517
+ deferred[e.type === "load" ? "resolve" : "reject"](response)
1518
+ }
1519
+ catch (e) {
1520
+ m.deferred.onerror(e);
1521
+ deferred.reject(e)
1522
+ }
1523
+ if (xhrOptions.background !== true) m.endComputation()
1524
+ };
1525
+ ajax(xhrOptions);
1526
+ deferred.promise = propify(deferred.promise, xhrOptions.initialValue);
1527
+ return deferred.promise
1528
+ };
1529
+
1530
+ //testing API
1531
+ m.deps = function(mock) {
1532
+ initialize(window = mock || window);
1533
+ return window;
1534
+ };
1535
+ //for internal testing only, do not use `m.deps.factory`
1536
+ m.deps.factory = app;
1537
+
1538
+ return m
1539
+ })(typeof window != "undefined" ? window : {});
1540
+
1541
+ if (typeof module != "undefined" && module !== null && module.exports) module.exports = m;
1542
+ else if (typeof define === "function" && define.amd) define(function() {return m});
1543
+
1544
+ },{}],7:[function(require,module,exports){
1545
+ /*!
1546
+ * EventEmitter v4.2.11 - git.io/ee
1547
+ * Unlicense - http://unlicense.org/
1548
+ * Oliver Caldwell - http://oli.me.uk/
1549
+ * @preserve
1550
+ */
1551
+
1552
+ ;(function () {
1553
+ 'use strict';
1554
+
1555
+ /**
1556
+ * Class for managing events.
1557
+ * Can be extended to provide event functionality in other classes.
1558
+ *
1559
+ * @class EventEmitter Manages event registering and emitting.
1560
+ */
1561
+ function EventEmitter() {}
1562
+
1563
+ // Shortcuts to improve speed and size
1564
+ var proto = EventEmitter.prototype;
1565
+ var exports = this;
1566
+ var originalGlobalValue = exports.EventEmitter;
1567
+
1568
+ /**
1569
+ * Finds the index of the listener for the event in its storage array.
1570
+ *
1571
+ * @param {Function[]} listeners Array of listeners to search through.
1572
+ * @param {Function} listener Method to look for.
1573
+ * @return {Number} Index of the specified listener, -1 if not found
1574
+ * @api private
1575
+ */
1576
+ function indexOfListener(listeners, listener) {
1577
+ var i = listeners.length;
1578
+ while (i--) {
1579
+ if (listeners[i].listener === listener) {
1580
+ return i;
1581
+ }
1582
+ }
1583
+
1584
+ return -1;
1585
+ }
1586
+
1587
+ /**
1588
+ * Alias a method while keeping the context correct, to allow for overwriting of target method.
1589
+ *
1590
+ * @param {String} name The name of the target method.
1591
+ * @return {Function} The aliased method
1592
+ * @api private
1593
+ */
1594
+ function alias(name) {
1595
+ return function aliasClosure() {
1596
+ return this[name].apply(this, arguments);
1597
+ };
1598
+ }
1599
+
1600
+ /**
1601
+ * Returns the listener array for the specified event.
1602
+ * Will initialise the event object and listener arrays if required.
1603
+ * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
1604
+ * Each property in the object response is an array of listener functions.
1605
+ *
1606
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
1607
+ * @return {Function[]|Object} All listener functions for the event.
1608
+ */
1609
+ proto.getListeners = function getListeners(evt) {
1610
+ var events = this._getEvents();
1611
+ var response;
1612
+ var key;
1613
+
1614
+ // Return a concatenated array of all matching events if
1615
+ // the selector is a regular expression.
1616
+ if (evt instanceof RegExp) {
1617
+ response = {};
1618
+ for (key in events) {
1619
+ if (events.hasOwnProperty(key) && evt.test(key)) {
1620
+ response[key] = events[key];
1621
+ }
1622
+ }
1623
+ }
1624
+ else {
1625
+ response = events[evt] || (events[evt] = []);
1626
+ }
1627
+
1628
+ return response;
1629
+ };
1630
+
1631
+ /**
1632
+ * Takes a list of listener objects and flattens it into a list of listener functions.
1633
+ *
1634
+ * @param {Object[]} listeners Raw listener objects.
1635
+ * @return {Function[]} Just the listener functions.
1636
+ */
1637
+ proto.flattenListeners = function flattenListeners(listeners) {
1638
+ var flatListeners = [];
1639
+ var i;
1640
+
1641
+ for (i = 0; i < listeners.length; i += 1) {
1642
+ flatListeners.push(listeners[i].listener);
1643
+ }
1644
+
1645
+ return flatListeners;
1646
+ };
1647
+
1648
+ /**
1649
+ * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
1650
+ *
1651
+ * @param {String|RegExp} evt Name of the event to return the listeners from.
1652
+ * @return {Object} All listener functions for an event in an object.
1653
+ */
1654
+ proto.getListenersAsObject = function getListenersAsObject(evt) {
1655
+ var listeners = this.getListeners(evt);
1656
+ var response;
1657
+
1658
+ if (listeners instanceof Array) {
1659
+ response = {};
1660
+ response[evt] = listeners;
1661
+ }
1662
+
1663
+ return response || listeners;
1664
+ };
1665
+
1666
+ /**
1667
+ * Adds a listener function to the specified event.
1668
+ * The listener will not be added if it is a duplicate.
1669
+ * If the listener returns true then it will be removed after it is called.
1670
+ * If you pass a regular expression as the event name then the listener will be added to all events that match it.
1671
+ *
1672
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
1673
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
1674
+ * @return {Object} Current instance of EventEmitter for chaining.
1675
+ */
1676
+ proto.addListener = function addListener(evt, listener) {
1677
+ var listeners = this.getListenersAsObject(evt);
1678
+ var listenerIsWrapped = typeof listener === 'object';
1679
+ var key;
1680
+
1681
+ for (key in listeners) {
1682
+ if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
1683
+ listeners[key].push(listenerIsWrapped ? listener : {
1684
+ listener: listener,
1685
+ once: false
1686
+ });
1687
+ }
1688
+ }
1689
+
1690
+ return this;
1691
+ };
1692
+
1693
+ /**
1694
+ * Alias of addListener
1695
+ */
1696
+ proto.on = alias('addListener');
1697
+
1698
+ /**
1699
+ * Semi-alias of addListener. It will add a listener that will be
1700
+ * automatically removed after its first execution.
1701
+ *
1702
+ * @param {String|RegExp} evt Name of the event to attach the listener to.
1703
+ * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
1704
+ * @return {Object} Current instance of EventEmitter for chaining.
1705
+ */
1706
+ proto.addOnceListener = function addOnceListener(evt, listener) {
1707
+ return this.addListener(evt, {
1708
+ listener: listener,
1709
+ once: true
1710
+ });
1711
+ };
1712
+
1713
+ /**
1714
+ * Alias of addOnceListener.
1715
+ */
1716
+ proto.once = alias('addOnceListener');
1717
+
1718
+ /**
1719
+ * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
1720
+ * You need to tell it what event names should be matched by a regex.
1721
+ *
1722
+ * @param {String} evt Name of the event to create.
1723
+ * @return {Object} Current instance of EventEmitter for chaining.
1724
+ */
1725
+ proto.defineEvent = function defineEvent(evt) {
1726
+ this.getListeners(evt);
1727
+ return this;
1728
+ };
1729
+
1730
+ /**
1731
+ * Uses defineEvent to define multiple events.
1732
+ *
1733
+ * @param {String[]} evts An array of event names to define.
1734
+ * @return {Object} Current instance of EventEmitter for chaining.
1735
+ */
1736
+ proto.defineEvents = function defineEvents(evts) {
1737
+ for (var i = 0; i < evts.length; i += 1) {
1738
+ this.defineEvent(evts[i]);
1739
+ }
1740
+ return this;
1741
+ };
1742
+
1743
+ /**
1744
+ * Removes a listener function from the specified event.
1745
+ * When passed a regular expression as the event name, it will remove the listener from all events that match it.
1746
+ *
1747
+ * @param {String|RegExp} evt Name of the event to remove the listener from.
1748
+ * @param {Function} listener Method to remove from the event.
1749
+ * @return {Object} Current instance of EventEmitter for chaining.
1750
+ */
1751
+ proto.removeListener = function removeListener(evt, listener) {
1752
+ var listeners = this.getListenersAsObject(evt);
1753
+ var index;
1754
+ var key;
1755
+
1756
+ for (key in listeners) {
1757
+ if (listeners.hasOwnProperty(key)) {
1758
+ index = indexOfListener(listeners[key], listener);
1759
+
1760
+ if (index !== -1) {
1761
+ listeners[key].splice(index, 1);
1762
+ }
1763
+ }
1764
+ }
1765
+
1766
+ return this;
1767
+ };
1768
+
1769
+ /**
1770
+ * Alias of removeListener
1771
+ */
1772
+ proto.off = alias('removeListener');
1773
+
1774
+ /**
1775
+ * Adds listeners in bulk using the manipulateListeners method.
1776
+ * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
1777
+ * You can also pass it a regular expression to add the array of listeners to all events that match it.
1778
+ * Yeah, this function does quite a bit. That's probably a bad thing.
1779
+ *
1780
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
1781
+ * @param {Function[]} [listeners] An optional array of listener functions to add.
1782
+ * @return {Object} Current instance of EventEmitter for chaining.
1783
+ */
1784
+ proto.addListeners = function addListeners(evt, listeners) {
1785
+ // Pass through to manipulateListeners
1786
+ return this.manipulateListeners(false, evt, listeners);
1787
+ };
1788
+
1789
+ /**
1790
+ * Removes listeners in bulk using the manipulateListeners method.
1791
+ * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
1792
+ * You can also pass it an event name and an array of listeners to be removed.
1793
+ * You can also pass it a regular expression to remove the listeners from all events that match it.
1794
+ *
1795
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
1796
+ * @param {Function[]} [listeners] An optional array of listener functions to remove.
1797
+ * @return {Object} Current instance of EventEmitter for chaining.
1798
+ */
1799
+ proto.removeListeners = function removeListeners(evt, listeners) {
1800
+ // Pass through to manipulateListeners
1801
+ return this.manipulateListeners(true, evt, listeners);
1802
+ };
1803
+
1804
+ /**
1805
+ * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
1806
+ * The first argument will determine if the listeners are removed (true) or added (false).
1807
+ * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
1808
+ * You can also pass it an event name and an array of listeners to be added/removed.
1809
+ * You can also pass it a regular expression to manipulate the listeners of all events that match it.
1810
+ *
1811
+ * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
1812
+ * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
1813
+ * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
1814
+ * @return {Object} Current instance of EventEmitter for chaining.
1815
+ */
1816
+ proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
1817
+ var i;
1818
+ var value;
1819
+ var single = remove ? this.removeListener : this.addListener;
1820
+ var multiple = remove ? this.removeListeners : this.addListeners;
1821
+
1822
+ // If evt is an object then pass each of its properties to this method
1823
+ if (typeof evt === 'object' && !(evt instanceof RegExp)) {
1824
+ for (i in evt) {
1825
+ if (evt.hasOwnProperty(i) && (value = evt[i])) {
1826
+ // Pass the single listener straight through to the singular method
1827
+ if (typeof value === 'function') {
1828
+ single.call(this, i, value);
1829
+ }
1830
+ else {
1831
+ // Otherwise pass back to the multiple function
1832
+ multiple.call(this, i, value);
1833
+ }
1834
+ }
1835
+ }
1836
+ }
1837
+ else {
1838
+ // So evt must be a string
1839
+ // And listeners must be an array of listeners
1840
+ // Loop over it and pass each one to the multiple method
1841
+ i = listeners.length;
1842
+ while (i--) {
1843
+ single.call(this, evt, listeners[i]);
1844
+ }
1845
+ }
1846
+
1847
+ return this;
1848
+ };
1849
+
1850
+ /**
1851
+ * Removes all listeners from a specified event.
1852
+ * If you do not specify an event then all listeners will be removed.
1853
+ * That means every event will be emptied.
1854
+ * You can also pass a regex to remove all events that match it.
1855
+ *
1856
+ * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
1857
+ * @return {Object} Current instance of EventEmitter for chaining.
1858
+ */
1859
+ proto.removeEvent = function removeEvent(evt) {
1860
+ var type = typeof evt;
1861
+ var events = this._getEvents();
1862
+ var key;
1863
+
1864
+ // Remove different things depending on the state of evt
1865
+ if (type === 'string') {
1866
+ // Remove all listeners for the specified event
1867
+ delete events[evt];
1868
+ }
1869
+ else if (evt instanceof RegExp) {
1870
+ // Remove all events matching the regex.
1871
+ for (key in events) {
1872
+ if (events.hasOwnProperty(key) && evt.test(key)) {
1873
+ delete events[key];
1874
+ }
1875
+ }
1876
+ }
1877
+ else {
1878
+ // Remove all listeners in all events
1879
+ delete this._events;
1880
+ }
1881
+
1882
+ return this;
1883
+ };
1884
+
1885
+ /**
1886
+ * Alias of removeEvent.
1887
+ *
1888
+ * Added to mirror the node API.
1889
+ */
1890
+ proto.removeAllListeners = alias('removeEvent');
1891
+
1892
+ /**
1893
+ * Emits an event of your choice.
1894
+ * When emitted, every listener attached to that event will be executed.
1895
+ * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
1896
+ * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
1897
+ * So they will not arrive within the array on the other side, they will be separate.
1898
+ * You can also pass a regular expression to emit to all events that match it.
1899
+ *
1900
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
1901
+ * @param {Array} [args] Optional array of arguments to be passed to each listener.
1902
+ * @return {Object} Current instance of EventEmitter for chaining.
1903
+ */
1904
+ proto.emitEvent = function emitEvent(evt, args) {
1905
+ var listenersMap = this.getListenersAsObject(evt);
1906
+ var listeners;
1907
+ var listener;
1908
+ var i;
1909
+ var key;
1910
+ var response;
1911
+
1912
+ for (key in listenersMap) {
1913
+ if (listenersMap.hasOwnProperty(key)) {
1914
+ listeners = listenersMap[key].slice(0);
1915
+ i = listeners.length;
1916
+
1917
+ while (i--) {
1918
+ // If the listener returns true then it shall be removed from the event
1919
+ // The function is executed either with a basic call or an apply if there is an args array
1920
+ listener = listeners[i];
1921
+
1922
+ if (listener.once === true) {
1923
+ this.removeListener(evt, listener.listener);
1924
+ }
1925
+
1926
+ response = listener.listener.apply(this, args || []);
1927
+
1928
+ if (response === this._getOnceReturnValue()) {
1929
+ this.removeListener(evt, listener.listener);
1930
+ }
1931
+ }
1932
+ }
1933
+ }
1934
+
1935
+ return this;
1936
+ };
1937
+
1938
+ /**
1939
+ * Alias of emitEvent
1940
+ */
1941
+ proto.trigger = alias('emitEvent');
1942
+
1943
+ /**
1944
+ * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
1945
+ * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
1946
+ *
1947
+ * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
1948
+ * @param {...*} Optional additional arguments to be passed to each listener.
1949
+ * @return {Object} Current instance of EventEmitter for chaining.
1950
+ */
1951
+ proto.emit = function emit(evt) {
1952
+ var args = Array.prototype.slice.call(arguments, 1);
1953
+ return this.emitEvent(evt, args);
1954
+ };
1955
+
1956
+ /**
1957
+ * Sets the current value to check against when executing listeners. If a
1958
+ * listeners return value matches the one set here then it will be removed
1959
+ * after execution. This value defaults to true.
1960
+ *
1961
+ * @param {*} value The new value to check for when executing listeners.
1962
+ * @return {Object} Current instance of EventEmitter for chaining.
1963
+ */
1964
+ proto.setOnceReturnValue = function setOnceReturnValue(value) {
1965
+ this._onceReturnValue = value;
1966
+ return this;
1967
+ };
1968
+
1969
+ /**
1970
+ * Fetches the current value to check against when executing listeners. If
1971
+ * the listeners return value matches this one then it should be removed
1972
+ * automatically. It will return true by default.
1973
+ *
1974
+ * @return {*|Boolean} The current value to check for or the default, true.
1975
+ * @api private
1976
+ */
1977
+ proto._getOnceReturnValue = function _getOnceReturnValue() {
1978
+ if (this.hasOwnProperty('_onceReturnValue')) {
1979
+ return this._onceReturnValue;
1980
+ }
1981
+ else {
1982
+ return true;
1983
+ }
1984
+ };
1985
+
1986
+ /**
1987
+ * Fetches the events object and creates one if required.
1988
+ *
1989
+ * @return {Object} The events storage object.
1990
+ * @api private
1991
+ */
1992
+ proto._getEvents = function _getEvents() {
1993
+ return this._events || (this._events = {});
1994
+ };
1995
+
1996
+ /**
1997
+ * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version.
1998
+ *
1999
+ * @return {Function} Non conflicting EventEmitter class.
2000
+ */
2001
+ EventEmitter.noConflict = function noConflict() {
2002
+ exports.EventEmitter = originalGlobalValue;
2003
+ return EventEmitter;
2004
+ };
2005
+
2006
+ // Expose the class either via AMD, CommonJS or the global object
2007
+ if (typeof define === 'function' && define.amd) {
2008
+ define(function () {
2009
+ return EventEmitter;
2010
+ });
2011
+ }
2012
+ else if (typeof module === 'object' && module.exports){
2013
+ module.exports = EventEmitter;
2014
+ }
2015
+ else {
2016
+ exports.EventEmitter = EventEmitter;
2017
+ }
2018
+ }.call(this));
2019
+
2020
+ },{}]},{},[1])
2021
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJhc3NldHMvYnJvd3NlcmlmeS9hZG1pbi5qcyIsImFzc2V0cy9icm93c2VyaWZ5L2FkbWluL2hlbHBlcnMuanMiLCJhc3NldHMvYnJvd3NlcmlmeS9hZG1pbi9zZXR0aW5ncy5qcyIsImFzc2V0cy9icm93c2VyaWZ5L2FkbWluL3RhYnMuanMiLCJhc3NldHMvYnJvd3NlcmlmeS9hZG1pbi91cmwuanMiLCJub2RlX21vZHVsZXMvbWl0aHJpbC9taXRocmlsLmpzIiwibm9kZV9tb2R1bGVzL3dvbGZ5ODctZXZlbnRlbWl0dGVyL0V2ZW50RW1pdHRlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0tBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2b0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIid1c2Ugc3RyaWN0JztcblxuLy8gZGVwZW5kZW5jaWVzXG52YXIgbSA9IHJlcXVpcmUoJ21pdGhyaWwnKTtcbnZhciBFdmVudEVtaXR0ZXIgPSByZXF1aXJlKCd3b2xmeTg3LWV2ZW50ZW1pdHRlcicpO1xuXG4vLyB2YXJzXG52YXIgY29udGV4dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtYzR3cC1hZG1pbicpO1xudmFyIGV2ZW50cyA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbnZhciB0YWJzID0gcmVxdWlyZSAoJy4vYWRtaW4vdGFicy5qcycpKGNvbnRleHQpO1xudmFyIGhlbHBlcnMgPSByZXF1aXJlKCcuL2FkbWluL2hlbHBlcnMuanMnKTtcbnZhciBzZXR0aW5ncyA9IHJlcXVpcmUoJy4vYWRtaW4vc2V0dGluZ3MuanMnKShjb250ZXh0LCBoZWxwZXJzLCBldmVudHMpO1xuXG4vLyBleHBvc2Ugc29tZSB0aGluZ3NcbndpbmRvdy5tYzR3cCA9IHdpbmRvdy5tYzR3cCB8fCB7fTtcbndpbmRvdy5tYzR3cC5kZXBzID0gd2luZG93Lm1jNHdwLmRlcHMgfHwge307XG53aW5kb3cubWM0d3AuZGVwcy5taXRocmlsID0gbTtcbndpbmRvdy5tYzR3cC5oZWxwZXJzID0gaGVscGVycztcbndpbmRvdy5tYzR3cC5ldmVudHMgPSBldmVudHM7XG53aW5kb3cubWM0d3Auc2V0dGluZ3MgPSBzZXR0aW5ncztcbndpbmRvdy5tYzR3cC50YWJzID0gdGFicztcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGhlbHBlcnMgPSB7fTtcblxuaGVscGVycy50b2dnbGVFbGVtZW50ID0gZnVuY3Rpb24oc2VsZWN0b3IpIHtcblx0dmFyIGVsZW1lbnRzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3Rvcik7XG5cdGZvciggdmFyIGk9MDsgaTxlbGVtZW50cy5sZW5ndGg7aSsrKXtcblx0XHR2YXIgc2hvdyA9IGVsZW1lbnRzW2ldLmNsaWVudEhlaWdodCA8PSAwO1xuXHRcdGVsZW1lbnRzW2ldLnN0eWxlLmRpc3BsYXkgPSBzaG93ID8gJycgOiAnbm9uZSc7XG5cdH1cbn07XG5cbmhlbHBlcnMuYmluZEV2ZW50VG9FbGVtZW50ID0gZnVuY3Rpb24oZWxlbWVudCxldmVudCxoYW5kbGVyKSB7XG5cdGlmICggZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKSB7XG5cdFx0ZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBoYW5kbGVyKTtcblx0fSBlbHNlIGlmIChlbGVtZW50LmF0dGFjaEV2ZW50KSAge1xuXHRcdGVsZW1lbnQuYXR0YWNoRXZlbnQoJ29uJyArIGV2ZW50LCBoYW5kbGVyKTtcblx0fVxufTtcblxuaGVscGVycy5iaW5kRXZlbnRUb0VsZW1lbnRzID0gZnVuY3Rpb24oIGVsZW1lbnRzLCBldmVudCwgaGFuZGxlciApIHtcblx0QXJyYXkucHJvdG90eXBlLmZvckVhY2guY2FsbCggZWxlbWVudHMsIGZ1bmN0aW9uKGVsZW1lbnQpIHtcblx0XHRoZWxwZXJzLmJpbmRFdmVudFRvRWxlbWVudChlbGVtZW50LGV2ZW50LGhhbmRsZXIpO1xuXHR9KTtcbn07XG5cbi8qKlxuICogU2hvd2lmLmpzXG4gKi9cbihmdW5jdGlvbigpIHtcblx0dmFyIHNob3dJZkVsZW1lbnRzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnW2RhdGEtc2hvd2lmXScpO1xuXG5cdC8vIGRlcGVuZGVudCBlbGVtZW50c1xuXHRBcnJheS5wcm90b3R5cGUuZm9yRWFjaC5jYWxsKCBzaG93SWZFbGVtZW50cywgZnVuY3Rpb24oZWxlbWVudCkge1xuXHRcdHZhciBjb25maWcgPSBKU09OLnBhcnNlKCBlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS1zaG93aWYnKSApO1xuXHRcdHZhciBwYXJlbnRFbGVtZW50cyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ1tuYW1lPVwiJysgY29uZmlnLmVsZW1lbnQgKydcIl0nKTtcblx0XHR2YXIgaW5wdXRzID0gZWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKCdpbnB1dCcpO1xuXG5cdFx0ZnVuY3Rpb24gdG9nZ2xlRWxlbWVudCgpIHtcblxuXHRcdFx0Ly8gZG8gbm90aGluZyB3aXRoIHVuY2hlY2tlZCBlbGVtZW50c1xuXHRcdFx0aWYoIHR5cGVvZiggdGhpcy5jaGVja2VkICkgPT09IFwiYm9vbGVhblwiICYmICEgdGhpcy5jaGVja2VkICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdC8vIGNoZWNrIGlmIGVsZW1lbnQgdmFsdWUgbWF0Y2hlcyBleHBlY3RlZCB2YWx1ZVxuXHRcdFx0dmFyIGNvbmRpdGlvbk1ldCA9ICggdGhpcy52YWx1ZSA9PSBjb25maWcudmFsdWUgKTtcblx0XHRcdGVsZW1lbnQuc3R5bGUuZGlzcGxheSA9IGNvbmRpdGlvbk1ldCA/ICcnIDogJ25vbmUnO1xuXHRcdFx0ZWxlbWVudC5zdHlsZS52aXNpYmlsaXR5ID0gY29uZGl0aW9uTWV0ID8gJycgOiAnaGlkZGVuJztcblxuXHRcdFx0Ly8gZGlzYWJsZSBpbnB1dCBmaWVsZHMgdG8gc3RvcCBzZW5kaW5nIHRoZWlyIHZhbHVlcyB0byBzZXJ2ZXJcblx0XHRcdEFycmF5LnByb3RvdHlwZS5mb3JFYWNoLmNhbGwoIGlucHV0cywgZnVuY3Rpb24oaW5wdXRFbGVtZW50KSB7XG5cdFx0XHRcdGlucHV0RWxlbWVudC5kaXNhYmxlZCA9ICFjb25kaXRpb25NZXQ7XG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHQvLyBmaW5kIGNoZWNrZWQgZWxlbWVudCBhbmQgY2FsbCB0b2dnbGVFbGVtZW50IGZ1bmN0aW9uXG5cdFx0QXJyYXkucHJvdG90eXBlLmZvckVhY2guY2FsbCggcGFyZW50RWxlbWVudHMsIGZ1bmN0aW9uKCBwYXJlbnRFbGVtZW50ICkge1xuXHRcdFx0dG9nZ2xlRWxlbWVudC5jYWxsKHBhcmVudEVsZW1lbnQpO1xuXHRcdH0pO1xuXG5cdFx0Ly8gYmluZCBvbiBhbGwgY2hhbmdlc1xuXHRcdGhlbHBlcnMuYmluZEV2ZW50VG9FbGVtZW50cyhwYXJlbnRFbGVtZW50cywgJ2NoYW5nZScsIHRvZ2dsZUVsZW1lbnQpO1xuXHR9KTtcbn0pKCk7XG5cbm1vZHVsZS5leHBvcnRzID0gaGVscGVyczsiLCJ2YXIgU2V0dGluZ3MgPSBmdW5jdGlvbihjb250ZXh0LCBoZWxwZXJzLCBldmVudHMgKSB7XG5cdCd1c2Ugc3RyaWN0JztcblxuXHQvLyB2YXJzXG5cdHZhciB1bnNhdmVkID0gZmFsc2U7XG5cdHZhciBjaGFuZ2VzID0gMDtcblx0dmFyIGZvcm0gPSBjb250ZXh0LnF1ZXJ5U2VsZWN0b3IoJ2Zvcm0nKTtcblx0dmFyIGxpc3RJbnB1dHMgPSBjb250ZXh0LnF1ZXJ5U2VsZWN0b3JBbGwoJy5tYzR3cC1saXN0LWlucHV0Jyk7XG5cdHZhciBsaXN0cyA9IG1jNHdwX3ZhcnMubWFpbGNoaW1wLmxpc3RzO1xuXHR2YXIgc2VsZWN0ZWRMaXN0cyA9IFtdO1xuXG5cdC8vIGZ1bmN0aW9uc1xuXHRmdW5jdGlvbiBnZXRTZWxlY3RlZExpc3RzV2hlcmUoc2VhcmNoS2V5LHNlYXJjaFZhbHVlKSB7XG5cdFx0cmV0dXJuIHNlbGVjdGVkTGlzdHMuZmlsdGVyKGZ1bmN0aW9uKGVsKSB7XG5cdFx0XHRyZXR1cm4gZWxbc2VhcmNoS2V5XSA9PT0gc2VhcmNoVmFsdWU7XG5cdFx0fSk7XG5cdH1cblxuXHRmdW5jdGlvbiBnZXRTZWxlY3RlZExpc3RzKCkge1xuXHRcdHJldHVybiBzZWxlY3RlZExpc3RzO1xuXHR9XG5cblx0ZnVuY3Rpb24gdXBkYXRlU2VsZWN0ZWRMaXN0cygpIHtcblx0XHRzZWxlY3RlZExpc3RzID0gW107XG5cblx0XHRBcnJheS5wcm90b3R5cGUuZm9yRWFjaC5jYWxsKGxpc3RJbnB1dHMsIGZ1bmN0aW9uKGlucHV0KSB7XG5cdFx0XHQvLyBza2lwIHVuY2hlY2tlZCBjaGVja2JveGVzXG5cdFx0XHRpZiggdHlwZW9mKCBpbnB1dC5jaGVja2VkICkgPT09IFwiYm9vbGVhblwiICYmICEgaW5wdXQuY2hlY2tlZCApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiggdHlwZW9mKCBsaXN0c1sgaW5wdXQudmFsdWUgXSApID09PSBcIm9iamVjdFwiICl7XG5cdFx0XHRcdHNlbGVjdGVkTGlzdHMucHVzaCggbGlzdHNbIGlucHV0LnZhbHVlIF0gKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdGV2ZW50cy50cmlnZ2VyKCdzZWxlY3RlZExpc3RzLmNoYW5nZScsIFsgc2VsZWN0ZWRMaXN0cyBdKTtcblx0XHRyZXR1cm4gc2VsZWN0ZWRMaXN0cztcblx0fVxuXG5cdGZ1bmN0aW9uIHRvZ2dsZVZpc2libGVMaXN0cygpIHtcblx0XHR2YXIgcm93cyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJy5saXN0cy0tb25seS1zZWxlY3RlZCA+IConKTtcblx0XHRBcnJheS5wcm90b3R5cGUuZm9yRWFjaC5jYWxsKHJvd3MsIGZ1bmN0aW9uKGVsKSB7XG5cblx0XHRcdHZhciBsaXN0SWQgPSBlbC5nZXRBdHRyaWJ1dGUoJ2RhdGEtbGlzdC1pZCcpO1xuXHRcdFx0dmFyIGlzU2VsZWN0ZWQgPSBnZXRTZWxlY3RlZExpc3RzV2hlcmUoJ2lkJywgbGlzdElkKS5sZW5ndGggPiAwO1xuXG5cdFx0XHRpZiggaXNTZWxlY3RlZCApIHtcblx0XHRcdFx0ZWwuc2V0QXR0cmlidXRlKCdjbGFzcycsIGVsLmdldEF0dHJpYnV0ZSgnY2xhc3MnKS5yZXBsYWNlKCdoaWRkZW4nLCcnKSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRlbC5zZXRBdHRyaWJ1dGUoJ2NsYXNzJywgZWwuZ2V0QXR0cmlidXRlKCdjbGFzcycpICsgXCIgaGlkZGVuXCIgKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdC8vIFRPRE86IG1ha2UgdGhpcyB0cmFuc2xhdGFibGVcblx0ZnVuY3Rpb24gY29uZmlybVBhZ2VMZWF2ZShlKSB7XG5cdFx0aWYoIXVuc2F2ZWQpIHJldHVybjtcblxuXHRcdGUgPSBlfHwgd2luZG93LmV2ZW50O1xuXHRcdHZhciBjb25maXJtYXRpb25NZXNzYWdlID0gJ0l0IGxvb2tzIGxpa2UgeW91IGhhdmUgYmVlbiBlZGl0aW5nIHNvbWV0aGluZy4gJ1xuXHRcdFx0KyAnSWYgeW91IGxlYXZlIGJlZm9yZSBzYXZpbmcsIHlvdXIgY2hhbmdlcyB3aWxsIGJlIGxvc3QuJztcblxuXHRcdGUucmV0dXJuVmFsdWUgPSBjb25maXJtYXRpb25NZXNzYWdlOyAvL0dlY2tvICsgSUVcblx0XHRyZXR1cm4gY29uZmlybWF0aW9uTWVzc2FnZTsgLy9HZWNrbyArIFdlYmtpdCwgU2FmYXJpLCBDaHJvbWUgZXRjLlxuXHR9XG5cblx0ZXZlbnRzLm9uKCdzZWxlY3RlZExpc3RzLmNoYW5nZScsIHRvZ2dsZVZpc2libGVMaXN0cyk7XG5cdGhlbHBlcnMuYmluZEV2ZW50VG9FbGVtZW50cyhsaXN0SW5wdXRzLCdjaGFuZ2UnLHVwZGF0ZVNlbGVjdGVkTGlzdHMpO1xuXG5cdC8vIG1ha2UgaXQgaGFyZCB0byBsZWF2ZSBiaWcgZm9ybXMgd2l0aCB1bnNhdmVkIGNoYW5nZXNcblx0aWYoIGZvcm0gJiYgZm9ybS5lbGVtZW50cy5sZW5ndGggPiAxMCApIHtcblx0XHRoZWxwZXJzLmJpbmRFdmVudFRvRWxlbWVudChmb3JtLCdjaGFuZ2UnLGZ1bmN0aW9uKCkgeyBjaGFuZ2VzKys7IGlmKCBjaGFuZ2VzID4gNSApIHsgdW5zYXZlZCA9IHRydWU7IH0gfSk7XG5cdFx0aGVscGVycy5iaW5kRXZlbnRUb0VsZW1lbnQoZm9ybSwnc3VibWl0JyxmdW5jdGlvbigpIHsgdW5zYXZlZCA9IGZhbHNlOyBjaGFuZ2VzID0gMDsgfSk7XG5cdFx0aGVscGVycy5iaW5kRXZlbnRUb0VsZW1lbnQod2luZG93LCdiZWZvcmV1bmxvYWQnLCBjb25maXJtUGFnZUxlYXZlKTtcblx0fVxuXG5cdHVwZGF0ZVNlbGVjdGVkTGlzdHMoKTtcblxuXHRyZXR1cm4ge1xuXHRcdGdldFNlbGVjdGVkTGlzdHM6IGdldFNlbGVjdGVkTGlzdHNcblx0fVxuXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFNldHRpbmdzOyIsIi8vIFRhYnNcbnZhciBUYWJzID0gZnVuY3Rpb24oY29udGV4dCkge1xuXHQndXNlIHN0cmljdCc7XG5cblx0Ly8gQHRvZG8gbGFzdCBwaWVjZSBvZiBqUXVlcnkuLi4gY2FuIHdlIGdldCByaWQgb2YgaXQ/XG5cdHZhciAkID0gd2luZG93LmpRdWVyeTtcblxuXHR2YXIgVVJMID0gcmVxdWlyZSgnLi91cmwuanMnKTtcblx0dmFyICRjb250ZXh0ID0gJChjb250ZXh0KTtcblx0dmFyICR0YWJzID0gJGNvbnRleHQuZmluZCgnLnRhYicpO1xuXHR2YXIgJHRhYk5hdnMgPSAkY29udGV4dC5maW5kKCcubmF2LXRhYicpO1xuXHR2YXIgcmVmZXJlckZpZWxkID0gY29udGV4dC5xdWVyeVNlbGVjdG9yKCdpbnB1dFtuYW1lPVwiX3dwX2h0dHBfcmVmZXJlclwiXScpO1xuXHR2YXIgdGFicyA9IFtdO1xuXG5cdCQuZWFjaCgkdGFicywgZnVuY3Rpb24oaSx0KSB7XG5cdFx0dmFyIGlkID0gdC5pZC5zdWJzdHJpbmcoNCk7XG5cdFx0dmFyIHRpdGxlID0gJCh0KS5maW5kKCdoMicpLmZpcnN0KCkudGV4dCgpO1xuXG5cdFx0dGFicy5wdXNoKHtcblx0XHRcdGlkOiBpZCxcblx0XHRcdHRpdGxlOiB0aXRsZSxcblx0XHRcdGVsZW1lbnQ6IHQsXG5cdFx0XHRuYXY6IGNvbnRleHQucXVlcnlTZWxlY3RvckFsbCgnLm5hdi10YWItJyArIGlkKSxcblx0XHRcdG9wZW46IGZ1bmN0aW9uKCkgeyByZXR1cm4gb3BlbihpZCk7IH1cblx0XHR9KTtcblx0fSk7XG5cblx0ZnVuY3Rpb24gZ2V0KGlkKSB7XG5cblx0XHRmb3IoIHZhciBpPTA7IGk8dGFicy5sZW5ndGg7IGkrKyl7XG5cdFx0XHRpZih0YWJzW2ldLmlkID09PSBpZCApIHtcblx0XHRcdFx0cmV0dXJuIHRhYnNbaV07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0fVxuXG5cdGZ1bmN0aW9uIG9wZW4oIHRhYiwgdXBkYXRlU3RhdGUgKSB7XG5cblx0XHQvLyBtYWtlIHN1cmUgd2UgaGF2ZSBhIHRhYiBvYmplY3Rcblx0XHRpZih0eXBlb2YodGFiKSA9PT0gXCJzdHJpbmdcIil7XG5cdFx0XHR0YWIgPSBnZXQodGFiKTtcblx0XHR9XG5cblx0XHRpZighdGFiKSB7IHJldHVybiBmYWxzZTsgfVxuXG5cdFx0Ly8gc2hvdWxkIHdlIHVwZGF0ZSBzdGF0ZT9cblx0XHRpZiggdXBkYXRlU3RhdGUgPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0dXBkYXRlU3RhdGUgPSB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIGhpZGUgYWxsIHRhYnMgJiByZW1vdmUgYWN0aXZlIGNsYXNzXG5cdFx0JHRhYnMucmVtb3ZlQ2xhc3MoJ3RhYi1hY3RpdmUnKS5jc3MoJ2Rpc3BsYXknLCAnbm9uZScpO1xuXHRcdCR0YWJOYXZzLnJlbW92ZUNsYXNzKCduYXYtdGFiLWFjdGl2ZScpO1xuXG5cdFx0Ly8gYWRkIGBuYXYtdGFiLWFjdGl2ZWAgdG8gdGhpcyB0YWJcblx0XHRBcnJheS5wcm90b3R5cGUuZm9yRWFjaC5jYWxsKHRhYi5uYXYsIGZ1bmN0aW9uKG5hdikge1xuXHRcdFx0bmF2LmNsYXNzTmFtZSArPSBcIiBuYXYtdGFiLWFjdGl2ZVwiO1xuXHRcdFx0bmF2LmJsdXIoKTtcblx0XHR9KTtcblxuXHRcdC8vIHNob3cgdGFyZ2V0IHRhYlxuXHRcdHRhYi5lbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuXHRcdHRhYi5lbGVtZW50LmNsYXNzTmFtZSArPSBcIiB0YWItYWN0aXZlXCI7XG5cblx0XHQvLyBjcmVhdGUgbmV3IFVSTFxuXHRcdHZhciB1cmwgPSBVUkwuc2V0UGFyYW1ldGVyKHdpbmRvdy5sb2NhdGlvbi5ocmVmLCBcInRhYlwiLCB0YWIuaWQgKTtcblxuXHRcdC8vIHVwZGF0ZSBoYXNoXG5cdFx0aWYoIGhpc3RvcnkucHVzaFN0YXRlICYmIHVwZGF0ZVN0YXRlICkge1xuXHRcdFx0aGlzdG9yeS5wdXNoU3RhdGUoIHRhYi5pZCwgJycsIHVybCApO1xuXHRcdH1cblxuXHRcdC8vIHVwZGF0ZSBkb2N1bWVudCB0aXRsZVxuXHRcdHRpdGxlKHRhYik7XG5cblx0XHQvLyB1cGRhdGUgcmVmZXJlciBmaWVsZFxuXHRcdHJlZmVyZXJGaWVsZC52YWx1ZSA9IHVybDtcblxuXHRcdC8vIGlmIHRoaWNrYm94IGlzIG9wZW4sIGNsb3NlIGl0LlxuXHRcdGlmKCB0eXBlb2YodGJfcmVtb3ZlKSA9PT0gXCJmdW5jdGlvblwiICkge1xuXHRcdFx0dGJfcmVtb3ZlKCk7XG5cdFx0fVxuXG5cdFx0Ly8gcmVmcmVzaCBlZGl0b3IgYWZ0ZXIgc3dpdGNoaW5nIHRhYnNcblx0XHQvLyBUT0RPOiBkZWNvdXBsZSBkZWNvdXBsZSBkZWNvdXBsZVxuXHRcdGlmKCB0YWIuaWQgPT09ICdmaWVsZHMnICYmIHdpbmRvdy5tYzR3cCAmJiB3aW5kb3cubWM0d3AuZm9ybXMgJiYgd2luZG93Lm1jNHdwLmZvcm1zLmVkaXRvciApIHtcblx0XHRcdG1jNHdwLmZvcm1zLmVkaXRvci5yZWZyZXNoKCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHRmdW5jdGlvbiB0aXRsZSh0YWIpIHtcblx0XHR2YXIgdGl0bGUgPSBkb2N1bWVudC50aXRsZS5zcGxpdCgnLScpO1xuXHRcdGRvY3VtZW50LnRpdGxlID0gZG9jdW1lbnQudGl0bGUucmVwbGFjZSh0aXRsZVswXSwgdGFiLnRpdGxlICsgXCIgXCIpO1xuXHR9XG5cblx0ZnVuY3Rpb24gc3dpdGNoVGFiKGUpIHtcblx0XHRlID0gZSB8fCB3aW5kb3cuZXZlbnQ7XG5cblx0XHQvLyBnZXQgZnJvbSBkYXRhIGF0dHJpYnV0ZVxuXHRcdHZhciB0YWJJZCA9IHRoaXMuZ2V0QXR0cmlidXRlKCdkYXRhLXRhYicpO1xuXG5cdFx0Ly8gZ2V0IGZyb20gY2xhc3NuYW1lXG5cdFx0aWYoICEgdGFiSWQgKSB7XG5cdFx0XHR2YXIgbWF0Y2ggPSB0aGlzLmNsYXNzTmFtZS5tYXRjaCgvbmF2LXRhYi0oXFx3Kyk/Lyk7XG5cdFx0XHRpZiggbWF0Y2ggKSB7XG5cdFx0XHRcdHRhYklkID0gbWF0Y2hbMV07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gZ2V0IGZyb20gaHJlZlxuXHRcdGlmKCAhIHRhYklkICkge1xuXHRcdFx0dmFyIHVybFBhcmFtcyA9IFVSTC5wYXJzZSggdGhpcy5ocmVmICk7XG5cdFx0XHRpZiggISB1cmxQYXJhbXMudGFiICkgeyByZXR1cm47IH1cblx0XHRcdHRhYklkID0gdXJsUGFyYW1zLnRhYjtcblx0XHR9XG5cblx0XHR2YXIgb3BlbmVkID0gb3BlbiggdGFiSWQgKTtcblxuXHRcdGlmKCBvcGVuZWQgKSB7XG5cdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRlLnJldHVyblZhbHVlID0gZmFsc2U7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHRmdW5jdGlvbiBpbml0KCkge1xuXG5cdFx0Ly8gY2hlY2sgZm9yIGN1cnJlbnQgdGFiXG5cdFx0aWYoISBoaXN0b3J5LnB1c2hTdGF0ZSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBhY3RpdmVUYWIgPSAkdGFicy5maWx0ZXIoJzp2aXNpYmxlJykuZ2V0KDApO1xuXHRcdGlmKCAhIGFjdGl2ZVRhYiApIHsgcmV0dXJuOyB9XG5cdFx0dmFyIHRhYiA9IGdldChhY3RpdmVUYWIuaWQuc3Vic3RyaW5nKDQpKTtcblx0XHRpZighdGFiKSByZXR1cm47XG5cblx0XHQvLyBjaGVjayBpZiB0YWIgaXMgaW4gaHRtbDUgaGlzdG9yeVxuXHRcdGlmKCBoaXN0b3J5LnJlcGxhY2VTdGF0ZSAmJiBoaXN0b3J5LnN0YXRlID09PSBudWxsKSB7XG5cdFx0XHRoaXN0b3J5LnJlcGxhY2VTdGF0ZSggdGFiLmlkLCAnJyApO1xuXHRcdH1cblxuXHRcdC8vIHVwZGF0ZSBkb2N1bWVudCB0aXRsZVxuXHRcdHRpdGxlKHRhYik7XG5cdH1cblxuXHQkdGFiTmF2cy5jbGljayhzd2l0Y2hUYWIpO1xuXHQkKGRvY3VtZW50LmJvZHkpLm9uKCdjbGljaycsICcudGFiLWxpbmsnLCBzd2l0Y2hUYWIpO1xuXHRpbml0KCk7XG5cblx0aWYod2luZG93LmFkZEV2ZW50TGlzdGVuZXIgJiYgaGlzdG9yeS5wdXNoU3RhdGUgKSB7XG5cdFx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3BvcHN0YXRlJywgZnVuY3Rpb24oZSkge1xuXHRcdFx0aWYoIWUuc3RhdGUpIHJldHVybiB0cnVlO1xuXHRcdFx0dmFyIHRhYklkID0gZS5zdGF0ZTtcblx0XHRcdHJldHVybiBvcGVuKHRhYklkLGZhbHNlKTtcblx0XHR9KTtcblx0fVxuXG5cdHJldHVybiB7XG5cdFx0b3Blbjogb3Blbixcblx0XHRnZXQ6IGdldFxuXHR9XG5cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gVGFiczsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBVUkwgPSB7XG5cdHBhcnNlOiBmdW5jdGlvbih1cmwpIHtcblx0XHR2YXIgcXVlcnkgPSB7fTtcblx0XHR2YXIgYSA9IHVybC5zcGxpdCgnJicpO1xuXHRcdGZvciAodmFyIGkgaW4gYSkge1xuXHRcdFx0aWYoIWEuaGFzT3duUHJvcGVydHkoaSkpIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHR2YXIgYiA9IGFbaV0uc3BsaXQoJz0nKTtcblx0XHRcdHF1ZXJ5W2RlY29kZVVSSUNvbXBvbmVudChiWzBdKV0gPSBkZWNvZGVVUklDb21wb25lbnQoYlsxXSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHF1ZXJ5O1xuXHR9LFxuXHRidWlsZDogZnVuY3Rpb24oZGF0YSkge1xuXHRcdHZhciByZXQgPSBbXTtcblx0XHRmb3IgKHZhciBkIGluIGRhdGEpXG5cdFx0XHRyZXQucHVzaChkICsgXCI9XCIgKyBlbmNvZGVVUklDb21wb25lbnQoZGF0YVtkXSkpO1xuXHRcdHJldHVybiByZXQuam9pbihcIiZcIik7XG5cdH0sXG5cdHNldFBhcmFtZXRlcjogZnVuY3Rpb24oIHVybCwga2V5LCB2YWx1ZSApIHtcblx0XHR2YXIgZGF0YSA9IFVSTC5wYXJzZSggdXJsICk7XG5cdFx0ZGF0YVsga2V5IF0gPSB2YWx1ZTtcblx0XHRyZXR1cm4gVVJMLmJ1aWxkKCBkYXRhICk7XG5cdH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gVVJMOyIsInZhciBtID0gKGZ1bmN0aW9uIGFwcCh3aW5kb3csIHVuZGVmaW5lZCkge1xyXG5cdHZhciBPQkpFQ1QgPSBcIltvYmplY3QgT2JqZWN0XVwiLCBBUlJBWSA9IFwiW29iamVjdCBBcnJheV1cIiwgU1RSSU5HID0gXCJbb2JqZWN0IFN0cmluZ11cIiwgRlVOQ1RJT04gPSBcImZ1bmN0aW9uXCI7XHJcblx0dmFyIHR5cGUgPSB7fS50b1N0cmluZztcclxuXHR2YXIgcGFyc2VyID0gLyg/OihefCN8XFwuKShbXiNcXC5cXFtcXF1dKykpfChcXFsuKz9cXF0pL2csIGF0dHJQYXJzZXIgPSAvXFxbKC4rPykoPzo9KFwifCd8KSguKj8pXFwyKT9cXF0vO1xyXG5cdHZhciB2b2lkRWxlbWVudHMgPSAvXihBUkVBfEJBU0V8QlJ8Q09MfENPTU1BTkR8RU1CRUR8SFJ8SU1HfElOUFVUfEtFWUdFTnxMSU5LfE1FVEF8UEFSQU18U09VUkNFfFRSQUNLfFdCUikkLztcclxuXHR2YXIgbm9vcCA9IGZ1bmN0aW9uKCkge31cclxuXHJcblx0Ly8gY2FjaGluZyBjb21tb25seSB1c2VkIHZhcmlhYmxlc1xyXG5cdHZhciAkZG9jdW1lbnQsICRsb2NhdGlvbiwgJHJlcXVlc3RBbmltYXRpb25GcmFtZSwgJGNhbmNlbEFuaW1hdGlvbkZyYW1lO1xyXG5cclxuXHQvLyBzZWxmIGludm9raW5nIGZ1bmN0aW9uIG5lZWRlZCBiZWNhdXNlIG9mIHRoZSB3YXkgbW9ja3Mgd29ya1xyXG5cdGZ1bmN0aW9uIGluaXRpYWxpemUod2luZG93KXtcclxuXHRcdCRkb2N1bWVudCA9IHdpbmRvdy5kb2N1bWVudDtcclxuXHRcdCRsb2NhdGlvbiA9IHdpbmRvdy5sb2NhdGlvbjtcclxuXHRcdCRjYW5jZWxBbmltYXRpb25GcmFtZSA9IHdpbmRvdy5jYW5jZWxBbmltYXRpb25GcmFtZSB8fCB3aW5kb3cuY2xlYXJUaW1lb3V0O1xyXG5cdFx0JHJlcXVlc3RBbmltYXRpb25GcmFtZSA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHwgd2luZG93LnNldFRpbWVvdXQ7XHJcblx0fVxyXG5cclxuXHRpbml0aWFsaXplKHdpbmRvdyk7XHJcblxyXG5cclxuXHQvKipcclxuXHQgKiBAdHlwZWRlZiB7U3RyaW5nfSBUYWdcclxuXHQgKiBBIHN0cmluZyB0aGF0IGxvb2tzIGxpa2UgLT4gZGl2LmNsYXNzbmFtZSNpZFtwYXJhbT1vbmVdW3BhcmFtMj10d29dXHJcblx0ICogV2hpY2ggZGVzY3JpYmVzIGEgRE9NIG5vZGVcclxuXHQgKi9cclxuXHJcblx0LyoqXHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge1RhZ30gVGhlIERPTSBub2RlIHRhZ1xyXG5cdCAqIEBwYXJhbSB7T2JqZWN0PVtdfSBvcHRpb25hbCBrZXktdmFsdWUgcGFpcnMgdG8gYmUgbWFwcGVkIHRvIERPTSBhdHRyc1xyXG5cdCAqIEBwYXJhbSB7Li4ubU5vZGU9W119IFplcm8gb3IgbW9yZSBNaXRocmlsIGNoaWxkIG5vZGVzLiBDYW4gYmUgYW4gYXJyYXksIG9yIHNwbGF0IChvcHRpb25hbClcclxuXHQgKlxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIG0oKSB7XHJcblx0XHR2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcclxuXHRcdHZhciBoYXNBdHRycyA9IGFyZ3NbMV0gIT0gbnVsbCAmJiB0eXBlLmNhbGwoYXJnc1sxXSkgPT09IE9CSkVDVCAmJiAhKFwidGFnXCIgaW4gYXJnc1sxXSB8fCBcInZpZXdcIiBpbiBhcmdzWzFdKSAmJiAhKFwic3VidHJlZVwiIGluIGFyZ3NbMV0pO1xyXG5cdFx0dmFyIGF0dHJzID0gaGFzQXR0cnMgPyBhcmdzWzFdIDoge307XHJcblx0XHR2YXIgY2xhc3NBdHRyTmFtZSA9IFwiY2xhc3NcIiBpbiBhdHRycyA/IFwiY2xhc3NcIiA6IFwiY2xhc3NOYW1lXCI7XHJcblx0XHR2YXIgY2VsbCA9IHt0YWc6IFwiZGl2XCIsIGF0dHJzOiB7fX07XHJcblx0XHR2YXIgbWF0Y2gsIGNsYXNzZXMgPSBbXTtcclxuXHRcdGlmICh0eXBlLmNhbGwoYXJnc1swXSkgIT0gU1RSSU5HKSB0aHJvdyBuZXcgRXJyb3IoXCJzZWxlY3RvciBpbiBtKHNlbGVjdG9yLCBhdHRycywgY2hpbGRyZW4pIHNob3VsZCBiZSBhIHN0cmluZ1wiKVxyXG5cdFx0d2hpbGUgKG1hdGNoID0gcGFyc2VyLmV4ZWMoYXJnc1swXSkpIHtcclxuXHRcdFx0aWYgKG1hdGNoWzFdID09PSBcIlwiICYmIG1hdGNoWzJdKSBjZWxsLnRhZyA9IG1hdGNoWzJdO1xyXG5cdFx0XHRlbHNlIGlmIChtYXRjaFsxXSA9PT0gXCIjXCIpIGNlbGwuYXR0cnMuaWQgPSBtYXRjaFsyXTtcclxuXHRcdFx0ZWxzZSBpZiAobWF0Y2hbMV0gPT09IFwiLlwiKSBjbGFzc2VzLnB1c2gobWF0Y2hbMl0pO1xyXG5cdFx0XHRlbHNlIGlmIChtYXRjaFszXVswXSA9PT0gXCJbXCIpIHtcclxuXHRcdFx0XHR2YXIgcGFpciA9IGF0dHJQYXJzZXIuZXhlYyhtYXRjaFszXSk7XHJcblx0XHRcdFx0Y2VsbC5hdHRyc1twYWlyWzFdXSA9IHBhaXJbM10gfHwgKHBhaXJbMl0gPyBcIlwiIDp0cnVlKVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIGNoaWxkcmVuID0gaGFzQXR0cnMgPyBhcmdzLnNsaWNlKDIpIDogYXJncy5zbGljZSgxKTtcclxuXHRcdGlmIChjaGlsZHJlbi5sZW5ndGggPT09IDEgJiYgdHlwZS5jYWxsKGNoaWxkcmVuWzBdKSA9PT0gQVJSQVkpIHtcclxuXHRcdFx0Y2VsbC5jaGlsZHJlbiA9IGNoaWxkcmVuWzBdXHJcblx0XHR9XHJcblx0XHRlbHNlIHtcclxuXHRcdFx0Y2VsbC5jaGlsZHJlbiA9IGNoaWxkcmVuXHJcblx0XHR9XHJcblx0XHRcclxuXHRcdGZvciAodmFyIGF0dHJOYW1lIGluIGF0dHJzKSB7XHJcblx0XHRcdGlmIChhdHRycy5oYXNPd25Qcm9wZXJ0eShhdHRyTmFtZSkpIHtcclxuXHRcdFx0XHRpZiAoYXR0ck5hbWUgPT09IGNsYXNzQXR0ck5hbWUgJiYgYXR0cnNbYXR0ck5hbWVdICE9IG51bGwgJiYgYXR0cnNbYXR0ck5hbWVdICE9PSBcIlwiKSB7XHJcblx0XHRcdFx0XHRjbGFzc2VzLnB1c2goYXR0cnNbYXR0ck5hbWVdKVxyXG5cdFx0XHRcdFx0Y2VsbC5hdHRyc1thdHRyTmFtZV0gPSBcIlwiIC8vY3JlYXRlIGtleSBpbiBjb3JyZWN0IGl0ZXJhdGlvbiBvcmRlclxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRlbHNlIGNlbGwuYXR0cnNbYXR0ck5hbWVdID0gYXR0cnNbYXR0ck5hbWVdXHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdGlmIChjbGFzc2VzLmxlbmd0aCA+IDApIGNlbGwuYXR0cnNbY2xhc3NBdHRyTmFtZV0gPSBjbGFzc2VzLmpvaW4oXCIgXCIpO1xyXG5cdFx0XHJcblx0XHRyZXR1cm4gY2VsbFxyXG5cdH1cclxuXHRmdW5jdGlvbiBidWlsZChwYXJlbnRFbGVtZW50LCBwYXJlbnRUYWcsIHBhcmVudENhY2hlLCBwYXJlbnRJbmRleCwgZGF0YSwgY2FjaGVkLCBzaG91bGRSZWF0dGFjaCwgaW5kZXgsIGVkaXRhYmxlLCBuYW1lc3BhY2UsIGNvbmZpZ3MpIHtcclxuXHRcdC8vYGJ1aWxkYCBpcyBhIHJlY3Vyc2l2ZSBmdW5jdGlvbiB0aGF0IG1hbmFnZXMgY3JlYXRpb24vZGlmZmluZy9yZW1vdmFsIG9mIERPTSBlbGVtZW50cyBiYXNlZCBvbiBjb21wYXJpc29uIGJldHdlZW4gYGRhdGFgIGFuZCBgY2FjaGVkYFxyXG5cdFx0Ly90aGUgZGlmZiBhbGdvcml0aG0gY2FuIGJlIHN1bW1hcml6ZWQgYXMgdGhpczpcclxuXHRcdC8vMSAtIGNvbXBhcmUgYGRhdGFgIGFuZCBgY2FjaGVkYFxyXG5cdFx0Ly8yIC0gaWYgdGhleSBhcmUgZGlmZmVyZW50LCBjb3B5IGBkYXRhYCB0byBgY2FjaGVkYCBhbmQgdXBkYXRlIHRoZSBET00gYmFzZWQgb24gd2hhdCB0aGUgZGlmZmVyZW5jZSBpc1xyXG5cdFx0Ly8zIC0gcmVjdXJzaXZlbHkgYXBwbHkgdGhpcyBhbGdvcml0aG0gZm9yIGV2ZXJ5IGFycmF5IGFuZCBmb3IgdGhlIGNoaWxkcmVuIG9mIGV2ZXJ5IHZpcnR1YWwgZWxlbWVudFxyXG5cclxuXHRcdC8vdGhlIGBjYWNoZWRgIGRhdGEgc3RydWN0dXJlIGlzIGVzc2VudGlhbGx5IHRoZSBzYW1lIGFzIHRoZSBwcmV2aW91cyByZWRyYXcncyBgZGF0YWAgZGF0YSBzdHJ1Y3R1cmUsIHdpdGggYSBmZXcgYWRkaXRpb25zOlxyXG5cdFx0Ly8tIGBjYWNoZWRgIGFsd2F5cyBoYXMgYSBwcm9wZXJ0eSBjYWxsZWQgYG5vZGVzYCwgd2hpY2ggaXMgYSBsaXN0IG9mIERPTSBlbGVtZW50cyB0aGF0IGNvcnJlc3BvbmQgdG8gdGhlIGRhdGEgcmVwcmVzZW50ZWQgYnkgdGhlIHJlc3BlY3RpdmUgdmlydHVhbCBlbGVtZW50XHJcblx0XHQvLy0gaW4gb3JkZXIgdG8gc3VwcG9ydCBhdHRhY2hpbmcgYG5vZGVzYCBhcyBhIHByb3BlcnR5IG9mIGBjYWNoZWRgLCBgY2FjaGVkYCBpcyAqYWx3YXlzKiBhIG5vbi1wcmltaXRpdmUgb2JqZWN0LCBpLmUuIGlmIHRoZSBkYXRhIHdhcyBhIHN0cmluZywgdGhlbiBjYWNoZWQgaXMgYSBTdHJpbmcgaW5zdGFuY2UuIElmIGRhdGEgd2FzIGBudWxsYCBvciBgdW5kZWZpbmVkYCwgY2FjaGVkIGlzIGBuZXcgU3RyaW5nKFwiXCIpYFxyXG5cdFx0Ly8tIGBjYWNoZWQgYWxzbyBoYXMgYSBgY29uZmlnQ29udGV4dGAgcHJvcGVydHksIHdoaWNoIGlzIHRoZSBzdGF0ZSBzdG9yYWdlIG9iamVjdCBleHBvc2VkIGJ5IGNvbmZpZyhlbGVtZW50LCBpc0luaXRpYWxpemVkLCBjb250ZXh0KVxyXG5cdFx0Ly8tIHdoZW4gYGNhY2hlZGAgaXMgYW4gT2JqZWN0LCBpdCByZXByZXNlbnRzIGEgdmlydHVhbCBlbGVtZW50OyB3aGVuIGl0J3MgYW4gQXJyYXksIGl0IHJlcHJlc2VudHMgYSBsaXN0IG9mIGVsZW1lbnRzOyB3aGVuIGl0J3MgYSBTdHJpbmcsIE51bWJlciBvciBCb29sZWFuLCBpdCByZXByZXNlbnRzIGEgdGV4dCBub2RlXHJcblxyXG5cdFx0Ly9gcGFyZW50RWxlbWVudGAgaXMgYSBET00gZWxlbWVudCB1c2VkIGZvciBXM0MgRE9NIEFQSSBjYWxsc1xyXG5cdFx0Ly9gcGFyZW50VGFnYCBpcyBvbmx5IHVzZWQgZm9yIGhhbmRsaW5nIGEgY29ybmVyIGNhc2UgZm9yIHRleHRhcmVhIHZhbHVlc1xyXG5cdFx0Ly9gcGFyZW50Q2FjaGVgIGlzIHVzZWQgdG8gcmVtb3ZlIG5vZGVzIGluIHNvbWUgbXVsdGktbm9kZSBjYXNlc1xyXG5cdFx0Ly9gcGFyZW50SW5kZXhgIGFuZCBgaW5kZXhgIGFyZSB1c2VkIHRvIGZpZ3VyZSBvdXQgdGhlIG9mZnNldCBvZiBub2Rlcy4gVGhleSdyZSBhcnRpZmFjdHMgZnJvbSBiZWZvcmUgYXJyYXlzIHN0YXJ0ZWQgYmVpbmcgZmxhdHRlbmVkIGFuZCBhcmUgbGlrZWx5IHJlZmFjdG9yYWJsZVxyXG5cdFx0Ly9gZGF0YWAgYW5kIGBjYWNoZWRgIGFyZSwgcmVzcGVjdGl2ZWx5LCB0aGUgbmV3IGFuZCBvbGQgbm9kZXMgYmVpbmcgZGlmZmVkXHJcblx0XHQvL2BzaG91bGRSZWF0dGFjaGAgaXMgYSBmbGFnIGluZGljYXRpbmcgd2hldGhlciBhIHBhcmVudCBub2RlIHdhcyByZWNyZWF0ZWQgKGlmIHNvLCBhbmQgaWYgdGhpcyBub2RlIGlzIHJldXNlZCwgdGhlbiB0aGlzIG5vZGUgbXVzdCByZWF0dGFjaCBpdHNlbGYgdG8gdGhlIG5ldyBwYXJlbnQpXHJcblx0XHQvL2BlZGl0YWJsZWAgaXMgYSBmbGFnIHRoYXQgaW5kaWNhdGVzIHdoZXRoZXIgYW4gYW5jZXN0b3IgaXMgY29udGVudGVkaXRhYmxlXHJcblx0XHQvL2BuYW1lc3BhY2VgIGluZGljYXRlcyB0aGUgY2xvc2VzdCBIVE1MIG5hbWVzcGFjZSBhcyBpdCBjYXNjYWRlcyBkb3duIGZyb20gYW4gYW5jZXN0b3JcclxuXHRcdC8vYGNvbmZpZ3NgIGlzIGEgbGlzdCBvZiBjb25maWcgZnVuY3Rpb25zIHRvIHJ1biBhZnRlciB0aGUgdG9wbW9zdCBgYnVpbGRgIGNhbGwgZmluaXNoZXMgcnVubmluZ1xyXG5cclxuXHRcdC8vdGhlcmUncyBsb2dpYyB0aGF0IHJlbGllcyBvbiB0aGUgYXNzdW1wdGlvbiB0aGF0IG51bGwgYW5kIHVuZGVmaW5lZCBkYXRhIGFyZSBlcXVpdmFsZW50IHRvIGVtcHR5IHN0cmluZ3NcclxuXHRcdC8vLSB0aGlzIHByZXZlbnRzIGxpZmVjeWNsZSBzdXJwcmlzZXMgZnJvbSBwcm9jZWR1cmFsIGhlbHBlcnMgdGhhdCBtaXggaW1wbGljaXQgYW5kIGV4cGxpY2l0IHJldHVybiBzdGF0ZW1lbnRzIChlLmcuIGZ1bmN0aW9uIGZvbygpIHtpZiAoY29uZCkgcmV0dXJuIG0oXCJkaXZcIil9XHJcblx0XHQvLy0gaXQgc2ltcGxpZmllcyBkaWZmaW5nIGNvZGVcclxuXHRcdC8vZGF0YS50b1N0cmluZygpIG1pZ2h0IHRocm93IG9yIHJldHVybiBudWxsIGlmIGRhdGEgaXMgdGhlIHJldHVybiB2YWx1ZSBvZiBDb25zb2xlLmxvZyBpbiBGaXJlZm94IChiZWhhdmlvciBkZXBlbmRzIG9uIHZlcnNpb24pXHJcblx0XHR0cnkge2lmIChkYXRhID09IG51bGwgfHwgZGF0YS50b1N0cmluZygpID09IG51bGwpIGRhdGEgPSBcIlwiO30gY2F0Y2ggKGUpIHtkYXRhID0gXCJcIn1cclxuXHRcdGlmIChkYXRhLnN1YnRyZWUgPT09IFwicmV0YWluXCIpIHJldHVybiBjYWNoZWQ7XHJcblx0XHR2YXIgY2FjaGVkVHlwZSA9IHR5cGUuY2FsbChjYWNoZWQpLCBkYXRhVHlwZSA9IHR5cGUuY2FsbChkYXRhKTtcclxuXHRcdGlmIChjYWNoZWQgPT0gbnVsbCB8fCBjYWNoZWRUeXBlICE9PSBkYXRhVHlwZSkge1xyXG5cdFx0XHRpZiAoY2FjaGVkICE9IG51bGwpIHtcclxuXHRcdFx0XHRpZiAocGFyZW50Q2FjaGUgJiYgcGFyZW50Q2FjaGUubm9kZXMpIHtcclxuXHRcdFx0XHRcdHZhciBvZmZzZXQgPSBpbmRleCAtIHBhcmVudEluZGV4O1xyXG5cdFx0XHRcdFx0dmFyIGVuZCA9IG9mZnNldCArIChkYXRhVHlwZSA9PT0gQVJSQVkgPyBkYXRhIDogY2FjaGVkLm5vZGVzKS5sZW5ndGg7XHJcblx0XHRcdFx0XHRjbGVhcihwYXJlbnRDYWNoZS5ub2Rlcy5zbGljZShvZmZzZXQsIGVuZCksIHBhcmVudENhY2hlLnNsaWNlKG9mZnNldCwgZW5kKSlcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0ZWxzZSBpZiAoY2FjaGVkLm5vZGVzKSBjbGVhcihjYWNoZWQubm9kZXMsIGNhY2hlZClcclxuXHRcdFx0fVxyXG5cdFx0XHRjYWNoZWQgPSBuZXcgZGF0YS5jb25zdHJ1Y3RvcjtcclxuXHRcdFx0aWYgKGNhY2hlZC50YWcpIGNhY2hlZCA9IHt9OyAvL2lmIGNvbnN0cnVjdG9yIGNyZWF0ZXMgYSB2aXJ0dWFsIGRvbSBlbGVtZW50LCB1c2UgYSBibGFuayBvYmplY3QgYXMgdGhlIGJhc2UgY2FjaGVkIG5vZGUgaW5zdGVhZCBvZiBjb3B5aW5nIHRoZSB2aXJ0dWFsIGVsICgjMjc3KVxyXG5cdFx0XHRjYWNoZWQubm9kZXMgPSBbXVxyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChkYXRhVHlwZSA9PT0gQVJSQVkpIHtcclxuXHRcdFx0Ly9yZWN1cnNpdmVseSBmbGF0dGVuIGFycmF5XHJcblx0XHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBkYXRhLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdFx0aWYgKHR5cGUuY2FsbChkYXRhW2ldKSA9PT0gQVJSQVkpIHtcclxuXHRcdFx0XHRcdGRhdGEgPSBkYXRhLmNvbmNhdC5hcHBseShbXSwgZGF0YSk7XHJcblx0XHRcdFx0XHRpLS0gLy9jaGVjayBjdXJyZW50IGluZGV4IGFnYWluIGFuZCBmbGF0dGVuIHVudGlsIHRoZXJlIGFyZSBubyBtb3JlIG5lc3RlZCBhcnJheXMgYXQgdGhhdCBpbmRleFxyXG5cdFx0XHRcdFx0bGVuID0gZGF0YS5sZW5ndGhcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0XHJcblx0XHRcdHZhciBub2RlcyA9IFtdLCBpbnRhY3QgPSBjYWNoZWQubGVuZ3RoID09PSBkYXRhLmxlbmd0aCwgc3ViQXJyYXlDb3VudCA9IDA7XHJcblxyXG5cdFx0XHQvL2tleXMgYWxnb3JpdGhtOiBzb3J0IGVsZW1lbnRzIHdpdGhvdXQgcmVjcmVhdGluZyB0aGVtIGlmIGtleXMgYXJlIHByZXNlbnRcclxuXHRcdFx0Ly8xKSBjcmVhdGUgYSBtYXAgb2YgYWxsIGV4aXN0aW5nIGtleXMsIGFuZCBtYXJrIGFsbCBmb3IgZGVsZXRpb25cclxuXHRcdFx0Ly8yKSBhZGQgbmV3IGtleXMgdG8gbWFwIGFuZCBtYXJrIHRoZW0gZm9yIGFkZGl0aW9uXHJcblx0XHRcdC8vMykgaWYga2V5IGV4aXN0cyBpbiBuZXcgbGlzdCwgY2hhbmdlIGFjdGlvbiBmcm9tIGRlbGV0aW9uIHRvIGEgbW92ZVxyXG5cdFx0XHQvLzQpIGZvciBlYWNoIGtleSwgaGFuZGxlIGl0cyBjb3JyZXNwb25kaW5nIGFjdGlvbiBhcyBtYXJrZWQgaW4gcHJldmlvdXMgc3RlcHNcclxuXHRcdFx0dmFyIERFTEVUSU9OID0gMSwgSU5TRVJUSU9OID0gMiAsIE1PVkUgPSAzO1xyXG5cdFx0XHR2YXIgZXhpc3RpbmcgPSB7fSwgc2hvdWxkTWFpbnRhaW5JZGVudGl0aWVzID0gZmFsc2U7XHJcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgY2FjaGVkLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdFx0aWYgKGNhY2hlZFtpXSAmJiBjYWNoZWRbaV0uYXR0cnMgJiYgY2FjaGVkW2ldLmF0dHJzLmtleSAhPSBudWxsKSB7XHJcblx0XHRcdFx0XHRzaG91bGRNYWludGFpbklkZW50aXRpZXMgPSB0cnVlO1xyXG5cdFx0XHRcdFx0ZXhpc3RpbmdbY2FjaGVkW2ldLmF0dHJzLmtleV0gPSB7YWN0aW9uOiBERUxFVElPTiwgaW5kZXg6IGl9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdFxyXG5cdFx0XHR2YXIgZ3VpZCA9IDBcclxuXHRcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IGRhdGEubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdFx0XHRpZiAoZGF0YVtpXSAmJiBkYXRhW2ldLmF0dHJzICYmIGRhdGFbaV0uYXR0cnMua2V5ICE9IG51bGwpIHtcclxuXHRcdFx0XHRcdGZvciAodmFyIGogPSAwLCBsZW4gPSBkYXRhLmxlbmd0aDsgaiA8IGxlbjsgaisrKSB7XHJcblx0XHRcdFx0XHRcdGlmIChkYXRhW2pdICYmIGRhdGFbal0uYXR0cnMgJiYgZGF0YVtqXS5hdHRycy5rZXkgPT0gbnVsbCkgZGF0YVtqXS5hdHRycy5rZXkgPSBcIl9fbWl0aHJpbF9fXCIgKyBndWlkKytcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGJyZWFrXHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdFxyXG5cdFx0XHRpZiAoc2hvdWxkTWFpbnRhaW5JZGVudGl0aWVzKSB7XHJcblx0XHRcdFx0dmFyIGtleXNEaWZmZXIgPSBmYWxzZVxyXG5cdFx0XHRcdGlmIChkYXRhLmxlbmd0aCAhPSBjYWNoZWQubGVuZ3RoKSBrZXlzRGlmZmVyID0gdHJ1ZVxyXG5cdFx0XHRcdGVsc2UgZm9yICh2YXIgaSA9IDAsIGNhY2hlZENlbGwsIGRhdGFDZWxsOyBjYWNoZWRDZWxsID0gY2FjaGVkW2ldLCBkYXRhQ2VsbCA9IGRhdGFbaV07IGkrKykge1xyXG5cdFx0XHRcdFx0aWYgKGNhY2hlZENlbGwuYXR0cnMgJiYgZGF0YUNlbGwuYXR0cnMgJiYgY2FjaGVkQ2VsbC5hdHRycy5rZXkgIT0gZGF0YUNlbGwuYXR0cnMua2V5KSB7XHJcblx0XHRcdFx0XHRcdGtleXNEaWZmZXIgPSB0cnVlXHJcblx0XHRcdFx0XHRcdGJyZWFrXHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdFxyXG5cdFx0XHRcdGlmIChrZXlzRGlmZmVyKSB7XHJcblx0XHRcdFx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gZGF0YS5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0XHRcdFx0XHRpZiAoZGF0YVtpXSAmJiBkYXRhW2ldLmF0dHJzKSB7XHJcblx0XHRcdFx0XHRcdFx0aWYgKGRhdGFbaV0uYXR0cnMua2V5ICE9IG51bGwpIHtcclxuXHRcdFx0XHRcdFx0XHRcdHZhciBrZXkgPSBkYXRhW2ldLmF0dHJzLmtleTtcclxuXHRcdFx0XHRcdFx0XHRcdGlmICghZXhpc3Rpbmdba2V5XSkgZXhpc3Rpbmdba2V5XSA9IHthY3Rpb246IElOU0VSVElPTiwgaW5kZXg6IGl9O1xyXG5cdFx0XHRcdFx0XHRcdFx0ZWxzZSBleGlzdGluZ1trZXldID0ge1xyXG5cdFx0XHRcdFx0XHRcdFx0XHRhY3Rpb246IE1PVkUsXHJcblx0XHRcdFx0XHRcdFx0XHRcdGluZGV4OiBpLFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRmcm9tOiBleGlzdGluZ1trZXldLmluZGV4LFxyXG5cdFx0XHRcdFx0XHRcdFx0XHRlbGVtZW50OiBjYWNoZWQubm9kZXNbZXhpc3Rpbmdba2V5XS5pbmRleF0gfHwgJGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIilcclxuXHRcdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdHZhciBhY3Rpb25zID0gW11cclxuXHRcdFx0XHRcdGZvciAodmFyIHByb3AgaW4gZXhpc3RpbmcpIGFjdGlvbnMucHVzaChleGlzdGluZ1twcm9wXSlcclxuXHRcdFx0XHRcdHZhciBjaGFuZ2VzID0gYWN0aW9ucy5zb3J0KHNvcnRDaGFuZ2VzKTtcclxuXHRcdFx0XHRcdHZhciBuZXdDYWNoZWQgPSBuZXcgQXJyYXkoY2FjaGVkLmxlbmd0aClcclxuXHRcdFx0XHRcdG5ld0NhY2hlZC5ub2RlcyA9IGNhY2hlZC5ub2Rlcy5zbGljZSgpXHJcblxyXG5cdFx0XHRcdFx0Zm9yICh2YXIgaSA9IDAsIGNoYW5nZTsgY2hhbmdlID0gY2hhbmdlc1tpXTsgaSsrKSB7XHJcblx0XHRcdFx0XHRcdGlmIChjaGFuZ2UuYWN0aW9uID09PSBERUxFVElPTikge1xyXG5cdFx0XHRcdFx0XHRcdGNsZWFyKGNhY2hlZFtjaGFuZ2UuaW5kZXhdLm5vZGVzLCBjYWNoZWRbY2hhbmdlLmluZGV4XSk7XHJcblx0XHRcdFx0XHRcdFx0bmV3Q2FjaGVkLnNwbGljZShjaGFuZ2UuaW5kZXgsIDEpXHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0aWYgKGNoYW5nZS5hY3Rpb24gPT09IElOU0VSVElPTikge1xyXG5cdFx0XHRcdFx0XHRcdHZhciBkdW1teSA9ICRkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xyXG5cdFx0XHRcdFx0XHRcdGR1bW15LmtleSA9IGRhdGFbY2hhbmdlLmluZGV4XS5hdHRycy5rZXk7XHJcblx0XHRcdFx0XHRcdFx0cGFyZW50RWxlbWVudC5pbnNlcnRCZWZvcmUoZHVtbXksIHBhcmVudEVsZW1lbnQuY2hpbGROb2Rlc1tjaGFuZ2UuaW5kZXhdIHx8IG51bGwpO1xyXG5cdFx0XHRcdFx0XHRcdG5ld0NhY2hlZC5zcGxpY2UoY2hhbmdlLmluZGV4LCAwLCB7YXR0cnM6IHtrZXk6IGRhdGFbY2hhbmdlLmluZGV4XS5hdHRycy5rZXl9LCBub2RlczogW2R1bW15XX0pXHJcblx0XHRcdFx0XHRcdFx0bmV3Q2FjaGVkLm5vZGVzW2NoYW5nZS5pbmRleF0gPSBkdW1teVxyXG5cdFx0XHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdFx0XHRpZiAoY2hhbmdlLmFjdGlvbiA9PT0gTU9WRSkge1xyXG5cdFx0XHRcdFx0XHRcdGlmIChwYXJlbnRFbGVtZW50LmNoaWxkTm9kZXNbY2hhbmdlLmluZGV4XSAhPT0gY2hhbmdlLmVsZW1lbnQgJiYgY2hhbmdlLmVsZW1lbnQgIT09IG51bGwpIHtcclxuXHRcdFx0XHRcdFx0XHRcdHBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKGNoYW5nZS5lbGVtZW50LCBwYXJlbnRFbGVtZW50LmNoaWxkTm9kZXNbY2hhbmdlLmluZGV4XSB8fCBudWxsKVxyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRuZXdDYWNoZWRbY2hhbmdlLmluZGV4XSA9IGNhY2hlZFtjaGFuZ2UuZnJvbV1cclxuXHRcdFx0XHRcdFx0XHRuZXdDYWNoZWQubm9kZXNbY2hhbmdlLmluZGV4XSA9IGNoYW5nZS5lbGVtZW50XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGNhY2hlZCA9IG5ld0NhY2hlZDtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0Ly9lbmQga2V5IGFsZ29yaXRobVxyXG5cclxuXHRcdFx0Zm9yICh2YXIgaSA9IDAsIGNhY2hlQ291bnQgPSAwLCBsZW4gPSBkYXRhLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdFx0Ly9kaWZmIGVhY2ggaXRlbSBpbiB0aGUgYXJyYXlcclxuXHRcdFx0XHR2YXIgaXRlbSA9IGJ1aWxkKHBhcmVudEVsZW1lbnQsIHBhcmVudFRhZywgY2FjaGVkLCBpbmRleCwgZGF0YVtpXSwgY2FjaGVkW2NhY2hlQ291bnRdLCBzaG91bGRSZWF0dGFjaCwgaW5kZXggKyBzdWJBcnJheUNvdW50IHx8IHN1YkFycmF5Q291bnQsIGVkaXRhYmxlLCBuYW1lc3BhY2UsIGNvbmZpZ3MpO1xyXG5cdFx0XHRcdGlmIChpdGVtID09PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xyXG5cdFx0XHRcdGlmICghaXRlbS5ub2Rlcy5pbnRhY3QpIGludGFjdCA9IGZhbHNlO1xyXG5cdFx0XHRcdGlmIChpdGVtLiR0cnVzdGVkKSB7XHJcblx0XHRcdFx0XHQvL2ZpeCBvZmZzZXQgb2YgbmV4dCBlbGVtZW50IGlmIGl0ZW0gd2FzIGEgdHJ1c3RlZCBzdHJpbmcgdy8gbW9yZSB0aGFuIG9uZSBodG1sIGVsZW1lbnRcclxuXHRcdFx0XHRcdC8vdGhlIGZpcnN0IGNsYXVzZSBpbiB0aGUgcmVnZXhwIG1hdGNoZXMgZWxlbWVudHNcclxuXHRcdFx0XHRcdC8vdGhlIHNlY29uZCBjbGF1c2UgKGFmdGVyIHRoZSBwaXBlKSBtYXRjaGVzIHRleHQgbm9kZXNcclxuXHRcdFx0XHRcdHN1YkFycmF5Q291bnQgKz0gKGl0ZW0ubWF0Y2goLzxbXlxcL118XFw+XFxzKltePF0vZykgfHwgWzBdKS5sZW5ndGhcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0ZWxzZSBzdWJBcnJheUNvdW50ICs9IHR5cGUuY2FsbChpdGVtKSA9PT0gQVJSQVkgPyBpdGVtLmxlbmd0aCA6IDE7XHJcblx0XHRcdFx0Y2FjaGVkW2NhY2hlQ291bnQrK10gPSBpdGVtXHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKCFpbnRhY3QpIHtcclxuXHRcdFx0XHQvL2RpZmYgdGhlIGFycmF5IGl0c2VsZlxyXG5cdFx0XHRcdFxyXG5cdFx0XHRcdC8vdXBkYXRlIHRoZSBsaXN0IG9mIERPTSBub2RlcyBieSBjb2xsZWN0aW5nIHRoZSBub2RlcyBmcm9tIGVhY2ggaXRlbVxyXG5cdFx0XHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBkYXRhLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdFx0XHRpZiAoY2FjaGVkW2ldICE9IG51bGwpIG5vZGVzLnB1c2guYXBwbHkobm9kZXMsIGNhY2hlZFtpXS5ub2RlcylcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0Ly9yZW1vdmUgaXRlbXMgZnJvbSB0aGUgZW5kIG9mIHRoZSBhcnJheSBpZiB0aGUgbmV3IGFycmF5IGlzIHNob3J0ZXIgdGhhbiB0aGUgb2xkIG9uZVxyXG5cdFx0XHRcdC8vaWYgZXJyb3JzIGV2ZXIgaGFwcGVuIGhlcmUsIHRoZSBpc3N1ZSBpcyBtb3N0IGxpa2VseSBhIGJ1ZyBpbiB0aGUgY29uc3RydWN0aW9uIG9mIHRoZSBgY2FjaGVkYCBkYXRhIHN0cnVjdHVyZSBzb21ld2hlcmUgZWFybGllciBpbiB0aGUgcHJvZ3JhbVxyXG5cdFx0XHRcdGZvciAodmFyIGkgPSAwLCBub2RlOyBub2RlID0gY2FjaGVkLm5vZGVzW2ldOyBpKyspIHtcclxuXHRcdFx0XHRcdGlmIChub2RlLnBhcmVudE5vZGUgIT0gbnVsbCAmJiBub2Rlcy5pbmRleE9mKG5vZGUpIDwgMCkgY2xlYXIoW25vZGVdLCBbY2FjaGVkW2ldXSlcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0aWYgKGRhdGEubGVuZ3RoIDwgY2FjaGVkLmxlbmd0aCkgY2FjaGVkLmxlbmd0aCA9IGRhdGEubGVuZ3RoO1xyXG5cdFx0XHRcdGNhY2hlZC5ub2RlcyA9IG5vZGVzXHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdGVsc2UgaWYgKGRhdGEgIT0gbnVsbCAmJiBkYXRhVHlwZSA9PT0gT0JKRUNUKSB7XHJcblx0XHRcdHZhciB2aWV3cyA9IFtdLCBjb250cm9sbGVycyA9IFtdXHJcblx0XHRcdHdoaWxlIChkYXRhLnZpZXcpIHtcclxuXHRcdFx0XHR2YXIgdmlldyA9IGRhdGEudmlldy4kb3JpZ2luYWwgfHwgZGF0YS52aWV3XHJcblx0XHRcdFx0dmFyIGNvbnRyb2xsZXJJbmRleCA9IG0ucmVkcmF3LnN0cmF0ZWd5KCkgPT0gXCJkaWZmXCIgJiYgY2FjaGVkLnZpZXdzID8gY2FjaGVkLnZpZXdzLmluZGV4T2YodmlldykgOiAtMVxyXG5cdFx0XHRcdHZhciBjb250cm9sbGVyID0gY29udHJvbGxlckluZGV4ID4gLTEgPyBjYWNoZWQuY29udHJvbGxlcnNbY29udHJvbGxlckluZGV4XSA6IG5ldyAoZGF0YS5jb250cm9sbGVyIHx8IG5vb3ApXHJcblx0XHRcdFx0dmFyIGtleSA9IGRhdGEgJiYgZGF0YS5hdHRycyAmJiBkYXRhLmF0dHJzLmtleVxyXG5cdFx0XHRcdGRhdGEgPSBwZW5kaW5nUmVxdWVzdHMgPT0gMCB8fCAoY2FjaGVkICYmIGNhY2hlZC5jb250cm9sbGVycyAmJiBjYWNoZWQuY29udHJvbGxlcnMuaW5kZXhPZihjb250cm9sbGVyKSA+IC0xKSA/IGRhdGEudmlldyhjb250cm9sbGVyKSA6IHt0YWc6IFwicGxhY2Vob2xkZXJcIn1cclxuXHRcdFx0XHRpZiAoZGF0YS5zdWJ0cmVlID09PSBcInJldGFpblwiKSByZXR1cm4gY2FjaGVkO1xyXG5cdFx0XHRcdGlmIChrZXkpIHtcclxuXHRcdFx0XHRcdGlmICghZGF0YS5hdHRycykgZGF0YS5hdHRycyA9IHt9XHJcblx0XHRcdFx0XHRkYXRhLmF0dHJzLmtleSA9IGtleVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRpZiAoY29udHJvbGxlci5vbnVubG9hZCkgdW5sb2FkZXJzLnB1c2goe2NvbnRyb2xsZXI6IGNvbnRyb2xsZXIsIGhhbmRsZXI6IGNvbnRyb2xsZXIub251bmxvYWR9KVxyXG5cdFx0XHRcdHZpZXdzLnB1c2godmlldylcclxuXHRcdFx0XHRjb250cm9sbGVycy5wdXNoKGNvbnRyb2xsZXIpXHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKCFkYXRhLnRhZyAmJiBjb250cm9sbGVycy5sZW5ndGgpIHRocm93IG5ldyBFcnJvcihcIkNvbXBvbmVudCB0ZW1wbGF0ZSBtdXN0IHJldHVybiBhIHZpcnR1YWwgZWxlbWVudCwgbm90IGFuIGFycmF5LCBzdHJpbmcsIGV0Yy5cIilcclxuXHRcdFx0aWYgKCFkYXRhLmF0dHJzKSBkYXRhLmF0dHJzID0ge307XHJcblx0XHRcdGlmICghY2FjaGVkLmF0dHJzKSBjYWNoZWQuYXR0cnMgPSB7fTtcclxuXHJcblx0XHRcdHZhciBkYXRhQXR0cktleXMgPSBPYmplY3Qua2V5cyhkYXRhLmF0dHJzKVxyXG5cdFx0XHR2YXIgaGFzS2V5cyA9IGRhdGFBdHRyS2V5cy5sZW5ndGggPiAoXCJrZXlcIiBpbiBkYXRhLmF0dHJzID8gMSA6IDApXHJcblx0XHRcdC8vaWYgYW4gZWxlbWVudCBpcyBkaWZmZXJlbnQgZW5vdWdoIGZyb20gdGhlIG9uZSBpbiBjYWNoZSwgcmVjcmVhdGUgaXRcclxuXHRcdFx0aWYgKGRhdGEudGFnICE9IGNhY2hlZC50YWcgfHwgZGF0YUF0dHJLZXlzLnNvcnQoKS5qb2luKCkgIT0gT2JqZWN0LmtleXMoY2FjaGVkLmF0dHJzKS5zb3J0KCkuam9pbigpIHx8IGRhdGEuYXR0cnMuaWQgIT0gY2FjaGVkLmF0dHJzLmlkIHx8IGRhdGEuYXR0cnMua2V5ICE9IGNhY2hlZC5hdHRycy5rZXkgfHwgKG0ucmVkcmF3LnN0cmF0ZWd5KCkgPT0gXCJhbGxcIiAmJiAoIWNhY2hlZC5jb25maWdDb250ZXh0IHx8IGNhY2hlZC5jb25maWdDb250ZXh0LnJldGFpbiAhPT0gdHJ1ZSkpIHx8IChtLnJlZHJhdy5zdHJhdGVneSgpID09IFwiZGlmZlwiICYmIGNhY2hlZC5jb25maWdDb250ZXh0ICYmIGNhY2hlZC5jb25maWdDb250ZXh0LnJldGFpbiA9PT0gZmFsc2UpKSB7XHJcblx0XHRcdFx0aWYgKGNhY2hlZC5ub2Rlcy5sZW5ndGgpIGNsZWFyKGNhY2hlZC5ub2Rlcyk7XHJcblx0XHRcdFx0aWYgKGNhY2hlZC5jb25maWdDb250ZXh0ICYmIHR5cGVvZiBjYWNoZWQuY29uZmlnQ29udGV4dC5vbnVubG9hZCA9PT0gRlVOQ1RJT04pIGNhY2hlZC5jb25maWdDb250ZXh0Lm9udW5sb2FkKClcclxuXHRcdFx0XHRpZiAoY2FjaGVkLmNvbnRyb2xsZXJzKSB7XHJcblx0XHRcdFx0XHRmb3IgKHZhciBpID0gMCwgY29udHJvbGxlcjsgY29udHJvbGxlciA9IGNhY2hlZC5jb250cm9sbGVyc1tpXTsgaSsrKSB7XHJcblx0XHRcdFx0XHRcdGlmICh0eXBlb2YgY29udHJvbGxlci5vbnVubG9hZCA9PT0gRlVOQ1RJT04pIGNvbnRyb2xsZXIub251bmxvYWQoe3ByZXZlbnREZWZhdWx0OiBub29wfSlcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKHR5cGUuY2FsbChkYXRhLnRhZykgIT0gU1RSSU5HKSByZXR1cm47XHJcblxyXG5cdFx0XHR2YXIgbm9kZSwgaXNOZXcgPSBjYWNoZWQubm9kZXMubGVuZ3RoID09PSAwO1xyXG5cdFx0XHRpZiAoZGF0YS5hdHRycy54bWxucykgbmFtZXNwYWNlID0gZGF0YS5hdHRycy54bWxucztcclxuXHRcdFx0ZWxzZSBpZiAoZGF0YS50YWcgPT09IFwic3ZnXCIpIG5hbWVzcGFjZSA9IFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIjtcclxuXHRcdFx0ZWxzZSBpZiAoZGF0YS50YWcgPT09IFwibWF0aFwiKSBuYW1lc3BhY2UgPSBcImh0dHA6Ly93d3cudzMub3JnLzE5OTgvTWF0aC9NYXRoTUxcIjtcclxuXHRcdFx0XHJcblx0XHRcdGlmIChpc05ldykge1xyXG5cdFx0XHRcdGlmIChkYXRhLmF0dHJzLmlzKSBub2RlID0gbmFtZXNwYWNlID09PSB1bmRlZmluZWQgPyAkZG9jdW1lbnQuY3JlYXRlRWxlbWVudChkYXRhLnRhZywgZGF0YS5hdHRycy5pcykgOiAkZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKG5hbWVzcGFjZSwgZGF0YS50YWcsIGRhdGEuYXR0cnMuaXMpO1xyXG5cdFx0XHRcdGVsc2Ugbm9kZSA9IG5hbWVzcGFjZSA9PT0gdW5kZWZpbmVkID8gJGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoZGF0YS50YWcpIDogJGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhuYW1lc3BhY2UsIGRhdGEudGFnKTtcclxuXHRcdFx0XHRjYWNoZWQgPSB7XHJcblx0XHRcdFx0XHR0YWc6IGRhdGEudGFnLFxyXG5cdFx0XHRcdFx0Ly9zZXQgYXR0cmlidXRlcyBmaXJzdCwgdGhlbiBjcmVhdGUgY2hpbGRyZW5cclxuXHRcdFx0XHRcdGF0dHJzOiBoYXNLZXlzID8gc2V0QXR0cmlidXRlcyhub2RlLCBkYXRhLnRhZywgZGF0YS5hdHRycywge30sIG5hbWVzcGFjZSkgOiBkYXRhLmF0dHJzLFxyXG5cdFx0XHRcdFx0Y2hpbGRyZW46IGRhdGEuY2hpbGRyZW4gIT0gbnVsbCAmJiBkYXRhLmNoaWxkcmVuLmxlbmd0aCA+IDAgP1xyXG5cdFx0XHRcdFx0XHRidWlsZChub2RlLCBkYXRhLnRhZywgdW5kZWZpbmVkLCB1bmRlZmluZWQsIGRhdGEuY2hpbGRyZW4sIGNhY2hlZC5jaGlsZHJlbiwgdHJ1ZSwgMCwgZGF0YS5hdHRycy5jb250ZW50ZWRpdGFibGUgPyBub2RlIDogZWRpdGFibGUsIG5hbWVzcGFjZSwgY29uZmlncykgOlxyXG5cdFx0XHRcdFx0XHRkYXRhLmNoaWxkcmVuLFxyXG5cdFx0XHRcdFx0bm9kZXM6IFtub2RlXVxyXG5cdFx0XHRcdH07XHJcblx0XHRcdFx0aWYgKGNvbnRyb2xsZXJzLmxlbmd0aCkge1xyXG5cdFx0XHRcdFx0Y2FjaGVkLnZpZXdzID0gdmlld3NcclxuXHRcdFx0XHRcdGNhY2hlZC5jb250cm9sbGVycyA9IGNvbnRyb2xsZXJzXHJcblx0XHRcdFx0XHRmb3IgKHZhciBpID0gMCwgY29udHJvbGxlcjsgY29udHJvbGxlciA9IGNvbnRyb2xsZXJzW2ldOyBpKyspIHtcclxuXHRcdFx0XHRcdFx0aWYgKGNvbnRyb2xsZXIub251bmxvYWQgJiYgY29udHJvbGxlci5vbnVubG9hZC4kb2xkKSBjb250cm9sbGVyLm9udW5sb2FkID0gY29udHJvbGxlci5vbnVubG9hZC4kb2xkXHJcblx0XHRcdFx0XHRcdGlmIChwZW5kaW5nUmVxdWVzdHMgJiYgY29udHJvbGxlci5vbnVubG9hZCkge1xyXG5cdFx0XHRcdFx0XHRcdHZhciBvbnVubG9hZCA9IGNvbnRyb2xsZXIub251bmxvYWRcclxuXHRcdFx0XHRcdFx0XHRjb250cm9sbGVyLm9udW5sb2FkID0gbm9vcFxyXG5cdFx0XHRcdFx0XHRcdGNvbnRyb2xsZXIub251bmxvYWQuJG9sZCA9IG9udW5sb2FkXHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0XHJcblx0XHRcdFx0aWYgKGNhY2hlZC5jaGlsZHJlbiAmJiAhY2FjaGVkLmNoaWxkcmVuLm5vZGVzKSBjYWNoZWQuY2hpbGRyZW4ubm9kZXMgPSBbXTtcclxuXHRcdFx0XHQvL2VkZ2UgY2FzZTogc2V0dGluZyB2YWx1ZSBvbiA8c2VsZWN0PiBkb2Vzbid0IHdvcmsgYmVmb3JlIGNoaWxkcmVuIGV4aXN0LCBzbyBzZXQgaXQgYWdhaW4gYWZ0ZXIgY2hpbGRyZW4gaGF2ZSBiZWVuIGNyZWF0ZWRcclxuXHRcdFx0XHRpZiAoZGF0YS50YWcgPT09IFwic2VsZWN0XCIgJiYgXCJ2YWx1ZVwiIGluIGRhdGEuYXR0cnMpIHNldEF0dHJpYnV0ZXMobm9kZSwgZGF0YS50YWcsIHt2YWx1ZTogZGF0YS5hdHRycy52YWx1ZX0sIHt9LCBuYW1lc3BhY2UpO1xyXG5cdFx0XHRcdHBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKG5vZGUsIHBhcmVudEVsZW1lbnQuY2hpbGROb2Rlc1tpbmRleF0gfHwgbnVsbClcclxuXHRcdFx0fVxyXG5cdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRub2RlID0gY2FjaGVkLm5vZGVzWzBdO1xyXG5cdFx0XHRcdGlmIChoYXNLZXlzKSBzZXRBdHRyaWJ1dGVzKG5vZGUsIGRhdGEudGFnLCBkYXRhLmF0dHJzLCBjYWNoZWQuYXR0cnMsIG5hbWVzcGFjZSk7XHJcblx0XHRcdFx0Y2FjaGVkLmNoaWxkcmVuID0gYnVpbGQobm9kZSwgZGF0YS50YWcsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBkYXRhLmNoaWxkcmVuLCBjYWNoZWQuY2hpbGRyZW4sIGZhbHNlLCAwLCBkYXRhLmF0dHJzLmNvbnRlbnRlZGl0YWJsZSA/IG5vZGUgOiBlZGl0YWJsZSwgbmFtZXNwYWNlLCBjb25maWdzKTtcclxuXHRcdFx0XHRjYWNoZWQubm9kZXMuaW50YWN0ID0gdHJ1ZTtcclxuXHRcdFx0XHRpZiAoY29udHJvbGxlcnMubGVuZ3RoKSB7XHJcblx0XHRcdFx0XHRjYWNoZWQudmlld3MgPSB2aWV3c1xyXG5cdFx0XHRcdFx0Y2FjaGVkLmNvbnRyb2xsZXJzID0gY29udHJvbGxlcnNcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0aWYgKHNob3VsZFJlYXR0YWNoID09PSB0cnVlICYmIG5vZGUgIT0gbnVsbCkgcGFyZW50RWxlbWVudC5pbnNlcnRCZWZvcmUobm9kZSwgcGFyZW50RWxlbWVudC5jaGlsZE5vZGVzW2luZGV4XSB8fCBudWxsKVxyXG5cdFx0XHR9XHJcblx0XHRcdC8vc2NoZWR1bGUgY29uZmlncyB0byBiZSBjYWxsZWQuIFRoZXkgYXJlIGNhbGxlZCBhZnRlciBgYnVpbGRgIGZpbmlzaGVzIHJ1bm5pbmdcclxuXHRcdFx0aWYgKHR5cGVvZiBkYXRhLmF0dHJzW1wiY29uZmlnXCJdID09PSBGVU5DVElPTikge1xyXG5cdFx0XHRcdHZhciBjb250ZXh0ID0gY2FjaGVkLmNvbmZpZ0NvbnRleHQgPSBjYWNoZWQuY29uZmlnQ29udGV4dCB8fCB7fTtcclxuXHJcblx0XHRcdFx0Ly8gYmluZFxyXG5cdFx0XHRcdHZhciBjYWxsYmFjayA9IGZ1bmN0aW9uKGRhdGEsIGFyZ3MpIHtcclxuXHRcdFx0XHRcdHJldHVybiBmdW5jdGlvbigpIHtcclxuXHRcdFx0XHRcdFx0cmV0dXJuIGRhdGEuYXR0cnNbXCJjb25maWdcIl0uYXBwbHkoZGF0YSwgYXJncylcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHR9O1xyXG5cdFx0XHRcdGNvbmZpZ3MucHVzaChjYWxsYmFjayhkYXRhLCBbbm9kZSwgIWlzTmV3LCBjb250ZXh0LCBjYWNoZWRdKSlcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0ZWxzZSBpZiAodHlwZW9mIGRhdGEgIT0gRlVOQ1RJT04pIHtcclxuXHRcdFx0Ly9oYW5kbGUgdGV4dCBub2Rlc1xyXG5cdFx0XHR2YXIgbm9kZXM7XHJcblx0XHRcdGlmIChjYWNoZWQubm9kZXMubGVuZ3RoID09PSAwKSB7XHJcblx0XHRcdFx0aWYgKGRhdGEuJHRydXN0ZWQpIHtcclxuXHRcdFx0XHRcdG5vZGVzID0gaW5qZWN0SFRNTChwYXJlbnRFbGVtZW50LCBpbmRleCwgZGF0YSlcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0XHRub2RlcyA9IFskZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoZGF0YSldO1xyXG5cdFx0XHRcdFx0aWYgKCFwYXJlbnRFbGVtZW50Lm5vZGVOYW1lLm1hdGNoKHZvaWRFbGVtZW50cykpIHBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKG5vZGVzWzBdLCBwYXJlbnRFbGVtZW50LmNoaWxkTm9kZXNbaW5kZXhdIHx8IG51bGwpXHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGNhY2hlZCA9IFwic3RyaW5nIG51bWJlciBib29sZWFuXCIuaW5kZXhPZih0eXBlb2YgZGF0YSkgPiAtMSA/IG5ldyBkYXRhLmNvbnN0cnVjdG9yKGRhdGEpIDogZGF0YTtcclxuXHRcdFx0XHRjYWNoZWQubm9kZXMgPSBub2Rlc1xyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2UgaWYgKGNhY2hlZC52YWx1ZU9mKCkgIT09IGRhdGEudmFsdWVPZigpIHx8IHNob3VsZFJlYXR0YWNoID09PSB0cnVlKSB7XHJcblx0XHRcdFx0bm9kZXMgPSBjYWNoZWQubm9kZXM7XHJcblx0XHRcdFx0aWYgKCFlZGl0YWJsZSB8fCBlZGl0YWJsZSAhPT0gJGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpIHtcclxuXHRcdFx0XHRcdGlmIChkYXRhLiR0cnVzdGVkKSB7XHJcblx0XHRcdFx0XHRcdGNsZWFyKG5vZGVzLCBjYWNoZWQpO1xyXG5cdFx0XHRcdFx0XHRub2RlcyA9IGluamVjdEhUTUwocGFyZW50RWxlbWVudCwgaW5kZXgsIGRhdGEpXHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRcdFx0Ly9jb3JuZXIgY2FzZTogcmVwbGFjaW5nIHRoZSBub2RlVmFsdWUgb2YgYSB0ZXh0IG5vZGUgdGhhdCBpcyBhIGNoaWxkIG9mIGEgdGV4dGFyZWEvY29udGVudGVkaXRhYmxlIGRvZXNuJ3Qgd29ya1xyXG5cdFx0XHRcdFx0XHQvL3dlIG5lZWQgdG8gdXBkYXRlIHRoZSB2YWx1ZSBwcm9wZXJ0eSBvZiB0aGUgcGFyZW50IHRleHRhcmVhIG9yIHRoZSBpbm5lckhUTUwgb2YgdGhlIGNvbnRlbnRlZGl0YWJsZSBlbGVtZW50IGluc3RlYWRcclxuXHRcdFx0XHRcdFx0aWYgKHBhcmVudFRhZyA9PT0gXCJ0ZXh0YXJlYVwiKSBwYXJlbnRFbGVtZW50LnZhbHVlID0gZGF0YTtcclxuXHRcdFx0XHRcdFx0ZWxzZSBpZiAoZWRpdGFibGUpIGVkaXRhYmxlLmlubmVySFRNTCA9IGRhdGE7XHJcblx0XHRcdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRcdGlmIChub2Rlc1swXS5ub2RlVHlwZSA9PT0gMSB8fCBub2Rlcy5sZW5ndGggPiAxKSB7IC8vd2FzIGEgdHJ1c3RlZCBzdHJpbmdcclxuXHRcdFx0XHRcdFx0XHRcdGNsZWFyKGNhY2hlZC5ub2RlcywgY2FjaGVkKTtcclxuXHRcdFx0XHRcdFx0XHRcdG5vZGVzID0gWyRkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShkYXRhKV1cclxuXHRcdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdFx0cGFyZW50RWxlbWVudC5pbnNlcnRCZWZvcmUobm9kZXNbMF0sIHBhcmVudEVsZW1lbnQuY2hpbGROb2Rlc1tpbmRleF0gfHwgbnVsbCk7XHJcblx0XHRcdFx0XHRcdFx0bm9kZXNbMF0ubm9kZVZhbHVlID0gZGF0YVxyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGNhY2hlZCA9IG5ldyBkYXRhLmNvbnN0cnVjdG9yKGRhdGEpO1xyXG5cdFx0XHRcdGNhY2hlZC5ub2RlcyA9IG5vZGVzXHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSBjYWNoZWQubm9kZXMuaW50YWN0ID0gdHJ1ZVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBjYWNoZWRcclxuXHR9XHJcblx0ZnVuY3Rpb24gc29ydENoYW5nZXMoYSwgYikge3JldHVybiBhLmFjdGlvbiAtIGIuYWN0aW9uIHx8IGEuaW5kZXggLSBiLmluZGV4fVxyXG5cdGZ1bmN0aW9uIHNldEF0dHJpYnV0ZXMobm9kZSwgdGFnLCBkYXRhQXR0cnMsIGNhY2hlZEF0dHJzLCBuYW1lc3BhY2UpIHtcclxuXHRcdGZvciAodmFyIGF0dHJOYW1lIGluIGRhdGFBdHRycykge1xyXG5cdFx0XHR2YXIgZGF0YUF0dHIgPSBkYXRhQXR0cnNbYXR0ck5hbWVdO1xyXG5cdFx0XHR2YXIgY2FjaGVkQXR0ciA9IGNhY2hlZEF0dHJzW2F0dHJOYW1lXTtcclxuXHRcdFx0aWYgKCEoYXR0ck5hbWUgaW4gY2FjaGVkQXR0cnMpIHx8IChjYWNoZWRBdHRyICE9PSBkYXRhQXR0cikpIHtcclxuXHRcdFx0XHRjYWNoZWRBdHRyc1thdHRyTmFtZV0gPSBkYXRhQXR0cjtcclxuXHRcdFx0XHR0cnkge1xyXG5cdFx0XHRcdFx0Ly9gY29uZmlnYCBpc24ndCBhIHJlYWwgYXR0cmlidXRlcywgc28gaWdub3JlIGl0XHJcblx0XHRcdFx0XHRpZiAoYXR0ck5hbWUgPT09IFwiY29uZmlnXCIgfHwgYXR0ck5hbWUgPT0gXCJrZXlcIikgY29udGludWU7XHJcblx0XHRcdFx0XHQvL2hvb2sgZXZlbnQgaGFuZGxlcnMgdG8gdGhlIGF1dG8tcmVkcmF3aW5nIHN5c3RlbVxyXG5cdFx0XHRcdFx0ZWxzZSBpZiAodHlwZW9mIGRhdGFBdHRyID09PSBGVU5DVElPTiAmJiBhdHRyTmFtZS5pbmRleE9mKFwib25cIikgPT09IDApIHtcclxuXHRcdFx0XHRcdFx0bm9kZVthdHRyTmFtZV0gPSBhdXRvcmVkcmF3KGRhdGFBdHRyLCBub2RlKVxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0Ly9oYW5kbGUgYHN0eWxlOiB7Li4ufWBcclxuXHRcdFx0XHRcdGVsc2UgaWYgKGF0dHJOYW1lID09PSBcInN0eWxlXCIgJiYgZGF0YUF0dHIgIT0gbnVsbCAmJiB0eXBlLmNhbGwoZGF0YUF0dHIpID09PSBPQkpFQ1QpIHtcclxuXHRcdFx0XHRcdFx0Zm9yICh2YXIgcnVsZSBpbiBkYXRhQXR0cikge1xyXG5cdFx0XHRcdFx0XHRcdGlmIChjYWNoZWRBdHRyID09IG51bGwgfHwgY2FjaGVkQXR0cltydWxlXSAhPT0gZGF0YUF0dHJbcnVsZV0pIG5vZGUuc3R5bGVbcnVsZV0gPSBkYXRhQXR0cltydWxlXVxyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdGZvciAodmFyIHJ1bGUgaW4gY2FjaGVkQXR0cikge1xyXG5cdFx0XHRcdFx0XHRcdGlmICghKHJ1bGUgaW4gZGF0YUF0dHIpKSBub2RlLnN0eWxlW3J1bGVdID0gXCJcIlxyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHQvL2hhbmRsZSBTVkdcclxuXHRcdFx0XHRcdGVsc2UgaWYgKG5hbWVzcGFjZSAhPSBudWxsKSB7XHJcblx0XHRcdFx0XHRcdGlmIChhdHRyTmFtZSA9PT0gXCJocmVmXCIpIG5vZGUuc2V0QXR0cmlidXRlTlMoXCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rXCIsIFwiaHJlZlwiLCBkYXRhQXR0cik7XHJcblx0XHRcdFx0XHRcdGVsc2UgaWYgKGF0dHJOYW1lID09PSBcImNsYXNzTmFtZVwiKSBub2RlLnNldEF0dHJpYnV0ZShcImNsYXNzXCIsIGRhdGFBdHRyKTtcclxuXHRcdFx0XHRcdFx0ZWxzZSBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgZGF0YUF0dHIpXHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHQvL2hhbmRsZSBjYXNlcyB0aGF0IGFyZSBwcm9wZXJ0aWVzIChidXQgaWdub3JlIGNhc2VzIHdoZXJlIHdlIHNob3VsZCB1c2Ugc2V0QXR0cmlidXRlIGluc3RlYWQpXHJcblx0XHRcdFx0XHQvLy0gbGlzdCBhbmQgZm9ybSBhcmUgdHlwaWNhbGx5IHVzZWQgYXMgc3RyaW5ncywgYnV0IGFyZSBET00gZWxlbWVudCByZWZlcmVuY2VzIGluIGpzXHJcblx0XHRcdFx0XHQvLy0gd2hlbiB1c2luZyBDU1Mgc2VsZWN0b3JzIChlLmcuIGBtKFwiW3N0eWxlPScnXVwiKWApLCBzdHlsZSBpcyB1c2VkIGFzIGEgc3RyaW5nLCBidXQgaXQncyBhbiBvYmplY3QgaW4ganNcclxuXHRcdFx0XHRcdGVsc2UgaWYgKGF0dHJOYW1lIGluIG5vZGUgJiYgIShhdHRyTmFtZSA9PT0gXCJsaXN0XCIgfHwgYXR0ck5hbWUgPT09IFwic3R5bGVcIiB8fCBhdHRyTmFtZSA9PT0gXCJmb3JtXCIgfHwgYXR0ck5hbWUgPT09IFwidHlwZVwiIHx8IGF0dHJOYW1lID09PSBcIndpZHRoXCIgfHwgYXR0ck5hbWUgPT09IFwiaGVpZ2h0XCIpKSB7XHJcblx0XHRcdFx0XHRcdC8vIzM0OCBkb24ndCBzZXQgdGhlIHZhbHVlIGlmIG5vdCBuZWVkZWQgb3RoZXJ3aXNlIGN1cnNvciBwbGFjZW1lbnQgYnJlYWtzIGluIENocm9tZVxyXG5cdFx0XHRcdFx0XHRpZiAodGFnICE9PSBcImlucHV0XCIgfHwgbm9kZVthdHRyTmFtZV0gIT09IGRhdGFBdHRyKSBub2RlW2F0dHJOYW1lXSA9IGRhdGFBdHRyXHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRlbHNlIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBkYXRhQXR0cilcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0Y2F0Y2ggKGUpIHtcclxuXHRcdFx0XHRcdC8vc3dhbGxvdyBJRSdzIGludmFsaWQgYXJndW1lbnQgZXJyb3JzIHRvIG1pbWljIEhUTUwncyBmYWxsYmFjay10by1kb2luZy1ub3RoaW5nLW9uLWludmFsaWQtYXR0cmlidXRlcyBiZWhhdmlvclxyXG5cdFx0XHRcdFx0aWYgKGUubWVzc2FnZS5pbmRleE9mKFwiSW52YWxpZCBhcmd1bWVudFwiKSA8IDApIHRocm93IGVcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0Ly8jMzQ4IGRhdGFBdHRyIG1heSBub3QgYmUgYSBzdHJpbmcsIHNvIHVzZSBsb29zZSBjb21wYXJpc29uIChkb3VibGUgZXF1YWwpIGluc3RlYWQgb2Ygc3RyaWN0ICh0cmlwbGUgZXF1YWwpXHJcblx0XHRcdGVsc2UgaWYgKGF0dHJOYW1lID09PSBcInZhbHVlXCIgJiYgdGFnID09PSBcImlucHV0XCIgJiYgbm9kZS52YWx1ZSAhPSBkYXRhQXR0cikge1xyXG5cdFx0XHRcdG5vZGUudmFsdWUgPSBkYXRhQXR0clxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gY2FjaGVkQXR0cnNcclxuXHR9XHJcblx0ZnVuY3Rpb24gY2xlYXIobm9kZXMsIGNhY2hlZCkge1xyXG5cdFx0Zm9yICh2YXIgaSA9IG5vZGVzLmxlbmd0aCAtIDE7IGkgPiAtMTsgaS0tKSB7XHJcblx0XHRcdGlmIChub2Rlc1tpXSAmJiBub2Rlc1tpXS5wYXJlbnROb2RlKSB7XHJcblx0XHRcdFx0dHJ5IHtub2Rlc1tpXS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGVzW2ldKX1cclxuXHRcdFx0XHRjYXRjaCAoZSkge30gLy9pZ25vcmUgaWYgdGhpcyBmYWlscyBkdWUgdG8gb3JkZXIgb2YgZXZlbnRzIChzZWUgaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMTkyNjA4My9mYWlsZWQtdG8tZXhlY3V0ZS1yZW1vdmVjaGlsZC1vbi1ub2RlKVxyXG5cdFx0XHRcdGNhY2hlZCA9IFtdLmNvbmNhdChjYWNoZWQpO1xyXG5cdFx0XHRcdGlmIChjYWNoZWRbaV0pIHVubG9hZChjYWNoZWRbaV0pXHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdGlmIChub2Rlcy5sZW5ndGggIT0gMCkgbm9kZXMubGVuZ3RoID0gMFxyXG5cdH1cclxuXHRmdW5jdGlvbiB1bmxvYWQoY2FjaGVkKSB7XHJcblx0XHRpZiAoY2FjaGVkLmNvbmZpZ0NvbnRleHQgJiYgdHlwZW9mIGNhY2hlZC5jb25maWdDb250ZXh0Lm9udW5sb2FkID09PSBGVU5DVElPTikge1xyXG5cdFx0XHRjYWNoZWQuY29uZmlnQ29udGV4dC5vbnVubG9hZCgpO1xyXG5cdFx0XHRjYWNoZWQuY29uZmlnQ29udGV4dC5vbnVubG9hZCA9IG51bGxcclxuXHRcdH1cclxuXHRcdGlmIChjYWNoZWQuY29udHJvbGxlcnMpIHtcclxuXHRcdFx0Zm9yICh2YXIgaSA9IDAsIGNvbnRyb2xsZXI7IGNvbnRyb2xsZXIgPSBjYWNoZWQuY29udHJvbGxlcnNbaV07IGkrKykge1xyXG5cdFx0XHRcdGlmICh0eXBlb2YgY29udHJvbGxlci5vbnVubG9hZCA9PT0gRlVOQ1RJT04pIGNvbnRyb2xsZXIub251bmxvYWQoe3ByZXZlbnREZWZhdWx0OiBub29wfSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdGlmIChjYWNoZWQuY2hpbGRyZW4pIHtcclxuXHRcdFx0aWYgKHR5cGUuY2FsbChjYWNoZWQuY2hpbGRyZW4pID09PSBBUlJBWSkge1xyXG5cdFx0XHRcdGZvciAodmFyIGkgPSAwLCBjaGlsZDsgY2hpbGQgPSBjYWNoZWQuY2hpbGRyZW5baV07IGkrKykgdW5sb2FkKGNoaWxkKVxyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2UgaWYgKGNhY2hlZC5jaGlsZHJlbi50YWcpIHVubG9hZChjYWNoZWQuY2hpbGRyZW4pXHJcblx0XHR9XHJcblx0fVxyXG5cdGZ1bmN0aW9uIGluamVjdEhUTUwocGFyZW50RWxlbWVudCwgaW5kZXgsIGRhdGEpIHtcclxuXHRcdHZhciBuZXh0U2libGluZyA9IHBhcmVudEVsZW1lbnQuY2hpbGROb2Rlc1tpbmRleF07XHJcblx0XHRpZiAobmV4dFNpYmxpbmcpIHtcclxuXHRcdFx0dmFyIGlzRWxlbWVudCA9IG5leHRTaWJsaW5nLm5vZGVUeXBlICE9IDE7XHJcblx0XHRcdHZhciBwbGFjZWhvbGRlciA9ICRkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcclxuXHRcdFx0aWYgKGlzRWxlbWVudCkge1xyXG5cdFx0XHRcdHBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKHBsYWNlaG9sZGVyLCBuZXh0U2libGluZyB8fCBudWxsKTtcclxuXHRcdFx0XHRwbGFjZWhvbGRlci5pbnNlcnRBZGphY2VudEhUTUwoXCJiZWZvcmViZWdpblwiLCBkYXRhKTtcclxuXHRcdFx0XHRwYXJlbnRFbGVtZW50LnJlbW92ZUNoaWxkKHBsYWNlaG9sZGVyKVxyXG5cdFx0XHR9XHJcblx0XHRcdGVsc2UgbmV4dFNpYmxpbmcuaW5zZXJ0QWRqYWNlbnRIVE1MKFwiYmVmb3JlYmVnaW5cIiwgZGF0YSlcclxuXHRcdH1cclxuXHRcdGVsc2UgcGFyZW50RWxlbWVudC5pbnNlcnRBZGphY2VudEhUTUwoXCJiZWZvcmVlbmRcIiwgZGF0YSk7XHJcblx0XHR2YXIgbm9kZXMgPSBbXTtcclxuXHRcdHdoaWxlIChwYXJlbnRFbGVtZW50LmNoaWxkTm9kZXNbaW5kZXhdICE9PSBuZXh0U2libGluZykge1xyXG5cdFx0XHRub2Rlcy5wdXNoKHBhcmVudEVsZW1lbnQuY2hpbGROb2Rlc1tpbmRleF0pO1xyXG5cdFx0XHRpbmRleCsrXHJcblx0XHR9XHJcblx0XHRyZXR1cm4gbm9kZXNcclxuXHR9XHJcblx0ZnVuY3Rpb24gYXV0b3JlZHJhdyhjYWxsYmFjaywgb2JqZWN0KSB7XHJcblx0XHRyZXR1cm4gZnVuY3Rpb24oZSkge1xyXG5cdFx0XHRlID0gZSB8fCBldmVudDtcclxuXHRcdFx0bS5yZWRyYXcuc3RyYXRlZ3koXCJkaWZmXCIpO1xyXG5cdFx0XHRtLnN0YXJ0Q29tcHV0YXRpb24oKTtcclxuXHRcdFx0dHJ5IHtyZXR1cm4gY2FsbGJhY2suY2FsbChvYmplY3QsIGUpfVxyXG5cdFx0XHRmaW5hbGx5IHtcclxuXHRcdFx0XHRlbmRGaXJzdENvbXB1dGF0aW9uKClcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0dmFyIGh0bWw7XHJcblx0dmFyIGRvY3VtZW50Tm9kZSA9IHtcclxuXHRcdGFwcGVuZENoaWxkOiBmdW5jdGlvbihub2RlKSB7XHJcblx0XHRcdGlmIChodG1sID09PSB1bmRlZmluZWQpIGh0bWwgPSAkZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImh0bWxcIik7XHJcblx0XHRcdGlmICgkZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICYmICRkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgIT09IG5vZGUpIHtcclxuXHRcdFx0XHQkZG9jdW1lbnQucmVwbGFjZUNoaWxkKG5vZGUsICRkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpXHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSAkZG9jdW1lbnQuYXBwZW5kQ2hpbGQobm9kZSk7XHJcblx0XHRcdHRoaXMuY2hpbGROb2RlcyA9ICRkb2N1bWVudC5jaGlsZE5vZGVzXHJcblx0XHR9LFxyXG5cdFx0aW5zZXJ0QmVmb3JlOiBmdW5jdGlvbihub2RlKSB7XHJcblx0XHRcdHRoaXMuYXBwZW5kQ2hpbGQobm9kZSlcclxuXHRcdH0sXHJcblx0XHRjaGlsZE5vZGVzOiBbXVxyXG5cdH07XHJcblx0dmFyIG5vZGVDYWNoZSA9IFtdLCBjZWxsQ2FjaGUgPSB7fTtcclxuXHRtLnJlbmRlciA9IGZ1bmN0aW9uKHJvb3QsIGNlbGwsIGZvcmNlUmVjcmVhdGlvbikge1xyXG5cdFx0dmFyIGNvbmZpZ3MgPSBbXTtcclxuXHRcdGlmICghcm9vdCkgdGhyb3cgbmV3IEVycm9yKFwiRW5zdXJlIHRoZSBET00gZWxlbWVudCBiZWluZyBwYXNzZWQgdG8gbS5yb3V0ZS9tLm1vdW50L20ucmVuZGVyIGlzIG5vdCB1bmRlZmluZWQuXCIpO1xyXG5cdFx0dmFyIGlkID0gZ2V0Q2VsbENhY2hlS2V5KHJvb3QpO1xyXG5cdFx0dmFyIGlzRG9jdW1lbnRSb290ID0gcm9vdCA9PT0gJGRvY3VtZW50O1xyXG5cdFx0dmFyIG5vZGUgPSBpc0RvY3VtZW50Um9vdCB8fCByb290ID09PSAkZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ID8gZG9jdW1lbnROb2RlIDogcm9vdDtcclxuXHRcdGlmIChpc0RvY3VtZW50Um9vdCAmJiBjZWxsLnRhZyAhPSBcImh0bWxcIikgY2VsbCA9IHt0YWc6IFwiaHRtbFwiLCBhdHRyczoge30sIGNoaWxkcmVuOiBjZWxsfTtcclxuXHRcdGlmIChjZWxsQ2FjaGVbaWRdID09PSB1bmRlZmluZWQpIGNsZWFyKG5vZGUuY2hpbGROb2Rlcyk7XHJcblx0XHRpZiAoZm9yY2VSZWNyZWF0aW9uID09PSB0cnVlKSByZXNldChyb290KTtcclxuXHRcdGNlbGxDYWNoZVtpZF0gPSBidWlsZChub2RlLCBudWxsLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgY2VsbCwgY2VsbENhY2hlW2lkXSwgZmFsc2UsIDAsIG51bGwsIHVuZGVmaW5lZCwgY29uZmlncyk7XHJcblx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gY29uZmlncy5sZW5ndGg7IGkgPCBsZW47IGkrKykgY29uZmlnc1tpXSgpXHJcblx0fTtcclxuXHRmdW5jdGlvbiBnZXRDZWxsQ2FjaGVLZXkoZWxlbWVudCkge1xyXG5cdFx0dmFyIGluZGV4ID0gbm9kZUNhY2hlLmluZGV4T2YoZWxlbWVudCk7XHJcblx0XHRyZXR1cm4gaW5kZXggPCAwID8gbm9kZUNhY2hlLnB1c2goZWxlbWVudCkgLSAxIDogaW5kZXhcclxuXHR9XHJcblxyXG5cdG0udHJ1c3QgPSBmdW5jdGlvbih2YWx1ZSkge1xyXG5cdFx0dmFsdWUgPSBuZXcgU3RyaW5nKHZhbHVlKTtcclxuXHRcdHZhbHVlLiR0cnVzdGVkID0gdHJ1ZTtcclxuXHRcdHJldHVybiB2YWx1ZVxyXG5cdH07XHJcblxyXG5cdGZ1bmN0aW9uIGdldHRlcnNldHRlcihzdG9yZSkge1xyXG5cdFx0dmFyIHByb3AgPSBmdW5jdGlvbigpIHtcclxuXHRcdFx0aWYgKGFyZ3VtZW50cy5sZW5ndGgpIHN0b3JlID0gYXJndW1lbnRzWzBdO1xyXG5cdFx0XHRyZXR1cm4gc3RvcmVcclxuXHRcdH07XHJcblxyXG5cdFx0cHJvcC50b0pTT04gPSBmdW5jdGlvbigpIHtcclxuXHRcdFx0cmV0dXJuIHN0b3JlXHJcblx0XHR9O1xyXG5cclxuXHRcdHJldHVybiBwcm9wXHJcblx0fVxyXG5cclxuXHRtLnByb3AgPSBmdW5jdGlvbiAoc3RvcmUpIHtcclxuXHRcdC8vbm90ZTogdXNpbmcgbm9uLXN0cmljdCBlcXVhbGl0eSBjaGVjayBoZXJlIGJlY2F1c2Ugd2UncmUgY2hlY2tpbmcgaWYgc3RvcmUgaXMgbnVsbCBPUiB1bmRlZmluZWRcclxuXHRcdGlmICgoKHN0b3JlICE9IG51bGwgJiYgdHlwZS5jYWxsKHN0b3JlKSA9PT0gT0JKRUNUKSB8fCB0eXBlb2Ygc3RvcmUgPT09IEZVTkNUSU9OKSAmJiB0eXBlb2Ygc3RvcmUudGhlbiA9PT0gRlVOQ1RJT04pIHtcclxuXHRcdFx0cmV0dXJuIHByb3BpZnkoc3RvcmUpXHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIGdldHRlcnNldHRlcihzdG9yZSlcclxuXHR9O1xyXG5cclxuXHR2YXIgcm9vdHMgPSBbXSwgY29tcG9uZW50cyA9IFtdLCBjb250cm9sbGVycyA9IFtdLCBsYXN0UmVkcmF3SWQgPSBudWxsLCBsYXN0UmVkcmF3Q2FsbFRpbWUgPSAwLCBjb21wdXRlUHJlUmVkcmF3SG9vayA9IG51bGwsIGNvbXB1dGVQb3N0UmVkcmF3SG9vayA9IG51bGwsIHByZXZlbnRlZCA9IGZhbHNlLCB0b3BDb21wb25lbnQsIHVubG9hZGVycyA9IFtdO1xyXG5cdHZhciBGUkFNRV9CVURHRVQgPSAxNjsgLy82MCBmcmFtZXMgcGVyIHNlY29uZCA9IDEgY2FsbCBwZXIgMTYgbXNcclxuXHRmdW5jdGlvbiBwYXJhbWV0ZXJpemUoY29tcG9uZW50LCBhcmdzKSB7XHJcblx0XHR2YXIgY29udHJvbGxlciA9IGZ1bmN0aW9uKCkge1xyXG5cdFx0XHRyZXR1cm4gKGNvbXBvbmVudC5jb250cm9sbGVyIHx8IG5vb3ApLmFwcGx5KHRoaXMsIGFyZ3MpIHx8IHRoaXNcclxuXHRcdH1cclxuXHRcdHZhciB2aWV3ID0gZnVuY3Rpb24oY3RybCkge1xyXG5cdFx0XHRpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIGFyZ3MgPSBhcmdzLmNvbmNhdChbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpXHJcblx0XHRcdHJldHVybiBjb21wb25lbnQudmlldy5hcHBseShjb21wb25lbnQsIGFyZ3MgPyBbY3RybF0uY29uY2F0KGFyZ3MpIDogW2N0cmxdKVxyXG5cdFx0fVxyXG5cdFx0dmlldy4kb3JpZ2luYWwgPSBjb21wb25lbnQudmlld1xyXG5cdFx0dmFyIG91dHB1dCA9IHtjb250cm9sbGVyOiBjb250cm9sbGVyLCB2aWV3OiB2aWV3fVxyXG5cdFx0aWYgKGFyZ3NbMF0gJiYgYXJnc1swXS5rZXkgIT0gbnVsbCkgb3V0cHV0LmF0dHJzID0ge2tleTogYXJnc1swXS5rZXl9XHJcblx0XHRyZXR1cm4gb3V0cHV0XHJcblx0fVxyXG5cdG0uY29tcG9uZW50ID0gZnVuY3Rpb24oY29tcG9uZW50KSB7XHJcblx0XHRyZXR1cm4gcGFyYW1ldGVyaXplKGNvbXBvbmVudCwgW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKVxyXG5cdH1cclxuXHRtLm1vdW50ID0gbS5tb2R1bGUgPSBmdW5jdGlvbihyb290LCBjb21wb25lbnQpIHtcclxuXHRcdGlmICghcm9vdCkgdGhyb3cgbmV3IEVycm9yKFwiUGxlYXNlIGVuc3VyZSB0aGUgRE9NIGVsZW1lbnQgZXhpc3RzIGJlZm9yZSByZW5kZXJpbmcgYSB0ZW1wbGF0ZSBpbnRvIGl0LlwiKTtcclxuXHRcdHZhciBpbmRleCA9IHJvb3RzLmluZGV4T2Yocm9vdCk7XHJcblx0XHRpZiAoaW5kZXggPCAwKSBpbmRleCA9IHJvb3RzLmxlbmd0aDtcclxuXHRcdFxyXG5cdFx0dmFyIGlzUHJldmVudGVkID0gZmFsc2U7XHJcblx0XHR2YXIgZXZlbnQgPSB7cHJldmVudERlZmF1bHQ6IGZ1bmN0aW9uKCkge1xyXG5cdFx0XHRpc1ByZXZlbnRlZCA9IHRydWU7XHJcblx0XHRcdGNvbXB1dGVQcmVSZWRyYXdIb29rID0gY29tcHV0ZVBvc3RSZWRyYXdIb29rID0gbnVsbDtcclxuXHRcdH19O1xyXG5cdFx0Zm9yICh2YXIgaSA9IDAsIHVubG9hZGVyOyB1bmxvYWRlciA9IHVubG9hZGVyc1tpXTsgaSsrKSB7XHJcblx0XHRcdHVubG9hZGVyLmhhbmRsZXIuY2FsbCh1bmxvYWRlci5jb250cm9sbGVyLCBldmVudClcclxuXHRcdFx0dW5sb2FkZXIuY29udHJvbGxlci5vbnVubG9hZCA9IG51bGxcclxuXHRcdH1cclxuXHRcdGlmIChpc1ByZXZlbnRlZCkge1xyXG5cdFx0XHRmb3IgKHZhciBpID0gMCwgdW5sb2FkZXI7IHVubG9hZGVyID0gdW5sb2FkZXJzW2ldOyBpKyspIHVubG9hZGVyLmNvbnRyb2xsZXIub251bmxvYWQgPSB1bmxvYWRlci5oYW5kbGVyXHJcblx0XHR9XHJcblx0XHRlbHNlIHVubG9hZGVycyA9IFtdXHJcblx0XHRcclxuXHRcdGlmIChjb250cm9sbGVyc1tpbmRleF0gJiYgdHlwZW9mIGNvbnRyb2xsZXJzW2luZGV4XS5vbnVubG9hZCA9PT0gRlVOQ1RJT04pIHtcclxuXHRcdFx0Y29udHJvbGxlcnNbaW5kZXhdLm9udW5sb2FkKGV2ZW50KVxyXG5cdFx0fVxyXG5cdFx0XHJcblx0XHRpZiAoIWlzUHJldmVudGVkKSB7XHJcblx0XHRcdG0ucmVkcmF3LnN0cmF0ZWd5KFwiYWxsXCIpO1xyXG5cdFx0XHRtLnN0YXJ0Q29tcHV0YXRpb24oKTtcclxuXHRcdFx0cm9vdHNbaW5kZXhdID0gcm9vdDtcclxuXHRcdFx0aWYgKGFyZ3VtZW50cy5sZW5ndGggPiAyKSBjb21wb25lbnQgPSBzdWJjb21wb25lbnQoY29tcG9uZW50LCBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMikpXHJcblx0XHRcdHZhciBjdXJyZW50Q29tcG9uZW50ID0gdG9wQ29tcG9uZW50ID0gY29tcG9uZW50ID0gY29tcG9uZW50IHx8IHtjb250cm9sbGVyOiBmdW5jdGlvbigpIHt9fTtcclxuXHRcdFx0dmFyIGNvbnN0cnVjdG9yID0gY29tcG9uZW50LmNvbnRyb2xsZXIgfHwgbm9vcFxyXG5cdFx0XHR2YXIgY29udHJvbGxlciA9IG5ldyBjb25zdHJ1Y3RvcjtcclxuXHRcdFx0Ly9jb250cm9sbGVycyBtYXkgY2FsbCBtLm1vdW50IHJlY3Vyc2l2ZWx5ICh2aWEgbS5yb3V0ZSByZWRpcmVjdHMsIGZvciBleGFtcGxlKVxyXG5cdFx0XHQvL3RoaXMgY29uZGl0aW9uYWwgZW5zdXJlcyBvbmx5IHRoZSBsYXN0IHJlY3Vyc2l2ZSBtLm1vdW50IGNhbGwgaXMgYXBwbGllZFxyXG5cdFx0XHRpZiAoY3VycmVudENvbXBvbmVudCA9PT0gdG9wQ29tcG9uZW50KSB7XHJcblx0XHRcdFx0Y29udHJvbGxlcnNbaW5kZXhdID0gY29udHJvbGxlcjtcclxuXHRcdFx0XHRjb21wb25lbnRzW2luZGV4XSA9IGNvbXBvbmVudFxyXG5cdFx0XHR9XHJcblx0XHRcdGVuZEZpcnN0Q29tcHV0YXRpb24oKTtcclxuXHRcdFx0cmV0dXJuIGNvbnRyb2xsZXJzW2luZGV4XVxyXG5cdFx0fVxyXG5cdH07XHJcblx0dmFyIHJlZHJhd2luZyA9IGZhbHNlXHJcblx0bS5yZWRyYXcgPSBmdW5jdGlvbihmb3JjZSkge1xyXG5cdFx0aWYgKHJlZHJhd2luZykgcmV0dXJuXHJcblx0XHRyZWRyYXdpbmcgPSB0cnVlXHJcblx0XHQvL2xhc3RSZWRyYXdJZCBpcyBhIHBvc2l0aXZlIG51bWJlciBpZiBhIHNlY29uZCByZWRyYXcgaXMgcmVxdWVzdGVkIGJlZm9yZSB0aGUgbmV4dCBhbmltYXRpb24gZnJhbWVcclxuXHRcdC8vbGFzdFJlZHJhd0lEIGlzIG51bGwgaWYgaXQncyB0aGUgZmlyc3QgcmVkcmF3IGFuZCBub3QgYW4gZXZlbnQgaGFuZGxlclxyXG5cdFx0aWYgKGxhc3RSZWRyYXdJZCAmJiBmb3JjZSAhPT0gdHJ1ZSkge1xyXG5cdFx0XHQvL3doZW4gc2V0VGltZW91dDogb25seSByZXNjaGVkdWxlIHJlZHJhdyBpZiB0aW1lIGJldHdlZW4gbm93IGFuZCBwcmV2aW91cyByZWRyYXcgaXMgYmlnZ2VyIHRoYW4gYSBmcmFtZSwgb3RoZXJ3aXNlIGtlZXAgY3VycmVudGx5IHNjaGVkdWxlZCB0aW1lb3V0XHJcblx0XHRcdC8vd2hlbiByQUY6IGFsd2F5cyByZXNjaGVkdWxlIHJlZHJhd1xyXG5cdFx0XHRpZiAoJHJlcXVlc3RBbmltYXRpb25GcmFtZSA9PT0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSB8fCBuZXcgRGF0ZSAtIGxhc3RSZWRyYXdDYWxsVGltZSA+IEZSQU1FX0JVREdFVCkge1xyXG5cdFx0XHRcdGlmIChsYXN0UmVkcmF3SWQgPiAwKSAkY2FuY2VsQW5pbWF0aW9uRnJhbWUobGFzdFJlZHJhd0lkKTtcclxuXHRcdFx0XHRsYXN0UmVkcmF3SWQgPSAkcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHJlZHJhdywgRlJBTUVfQlVER0VUKVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRlbHNlIHtcclxuXHRcdFx0cmVkcmF3KCk7XHJcblx0XHRcdGxhc3RSZWRyYXdJZCA9ICRyZXF1ZXN0QW5pbWF0aW9uRnJhbWUoZnVuY3Rpb24oKSB7bGFzdFJlZHJhd0lkID0gbnVsbH0sIEZSQU1FX0JVREdFVClcclxuXHRcdH1cclxuXHRcdHJlZHJhd2luZyA9IGZhbHNlXHJcblx0fTtcclxuXHRtLnJlZHJhdy5zdHJhdGVneSA9IG0ucHJvcCgpO1xyXG5cdGZ1bmN0aW9uIHJlZHJhdygpIHtcclxuXHRcdGlmIChjb21wdXRlUHJlUmVkcmF3SG9vaykge1xyXG5cdFx0XHRjb21wdXRlUHJlUmVkcmF3SG9vaygpXHJcblx0XHRcdGNvbXB1dGVQcmVSZWRyYXdIb29rID0gbnVsbFxyXG5cdFx0fVxyXG5cdFx0Zm9yICh2YXIgaSA9IDAsIHJvb3Q7IHJvb3QgPSByb290c1tpXTsgaSsrKSB7XHJcblx0XHRcdGlmIChjb250cm9sbGVyc1tpXSkge1xyXG5cdFx0XHRcdHZhciBhcmdzID0gY29tcG9uZW50c1tpXS5jb250cm9sbGVyICYmIGNvbXBvbmVudHNbaV0uY29udHJvbGxlci4kJGFyZ3MgPyBbY29udHJvbGxlcnNbaV1dLmNvbmNhdChjb21wb25lbnRzW2ldLmNvbnRyb2xsZXIuJCRhcmdzKSA6IFtjb250cm9sbGVyc1tpXV1cclxuXHRcdFx0XHRtLnJlbmRlcihyb290LCBjb21wb25lbnRzW2ldLnZpZXcgPyBjb21wb25lbnRzW2ldLnZpZXcoY29udHJvbGxlcnNbaV0sIGFyZ3MpIDogXCJcIilcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0Ly9hZnRlciByZW5kZXJpbmcgd2l0aGluIGEgcm91dGVkIGNvbnRleHQsIHdlIG5lZWQgdG8gc2Nyb2xsIGJhY2sgdG8gdGhlIHRvcCwgYW5kIGZldGNoIHRoZSBkb2N1bWVudCB0aXRsZSBmb3IgaGlzdG9yeS5wdXNoU3RhdGVcclxuXHRcdGlmIChjb21wdXRlUG9zdFJlZHJhd0hvb2spIHtcclxuXHRcdFx0Y29tcHV0ZVBvc3RSZWRyYXdIb29rKCk7XHJcblx0XHRcdGNvbXB1dGVQb3N0UmVkcmF3SG9vayA9IG51bGxcclxuXHRcdH1cclxuXHRcdGxhc3RSZWRyYXdJZCA9IG51bGw7XHJcblx0XHRsYXN0UmVkcmF3Q2FsbFRpbWUgPSBuZXcgRGF0ZTtcclxuXHRcdG0ucmVkcmF3LnN0cmF0ZWd5KFwiZGlmZlwiKVxyXG5cdH1cclxuXHJcblx0dmFyIHBlbmRpbmdSZXF1ZXN0cyA9IDA7XHJcblx0bS5zdGFydENvbXB1dGF0aW9uID0gZnVuY3Rpb24oKSB7cGVuZGluZ1JlcXVlc3RzKyt9O1xyXG5cdG0uZW5kQ29tcHV0YXRpb24gPSBmdW5jdGlvbigpIHtcclxuXHRcdHBlbmRpbmdSZXF1ZXN0cyA9IE1hdGgubWF4KHBlbmRpbmdSZXF1ZXN0cyAtIDEsIDApO1xyXG5cdFx0aWYgKHBlbmRpbmdSZXF1ZXN0cyA9PT0gMCkgbS5yZWRyYXcoKVxyXG5cdH07XHJcblx0dmFyIGVuZEZpcnN0Q29tcHV0YXRpb24gPSBmdW5jdGlvbigpIHtcclxuXHRcdGlmIChtLnJlZHJhdy5zdHJhdGVneSgpID09IFwibm9uZVwiKSB7XHJcblx0XHRcdHBlbmRpbmdSZXF1ZXN0cy0tXHJcblx0XHRcdG0ucmVkcmF3LnN0cmF0ZWd5KFwiZGlmZlwiKVxyXG5cdFx0fVxyXG5cdFx0ZWxzZSBtLmVuZENvbXB1dGF0aW9uKCk7XHJcblx0fVxyXG5cclxuXHRtLndpdGhBdHRyID0gZnVuY3Rpb24ocHJvcCwgd2l0aEF0dHJDYWxsYmFjaykge1xyXG5cdFx0cmV0dXJuIGZ1bmN0aW9uKGUpIHtcclxuXHRcdFx0ZSA9IGUgfHwgZXZlbnQ7XHJcblx0XHRcdHZhciBjdXJyZW50VGFyZ2V0ID0gZS5jdXJyZW50VGFyZ2V0IHx8IHRoaXM7XHJcblx0XHRcdHdpdGhBdHRyQ2FsbGJhY2socHJvcCBpbiBjdXJyZW50VGFyZ2V0ID8gY3VycmVudFRhcmdldFtwcm9wXSA6IGN1cnJlbnRUYXJnZXQuZ2V0QXR0cmlidXRlKHByb3ApKVxyXG5cdFx0fVxyXG5cdH07XHJcblxyXG5cdC8vcm91dGluZ1xyXG5cdHZhciBtb2RlcyA9IHtwYXRobmFtZTogXCJcIiwgaGFzaDogXCIjXCIsIHNlYXJjaDogXCI/XCJ9O1xyXG5cdHZhciByZWRpcmVjdCA9IG5vb3AsIHJvdXRlUGFyYW1zLCBjdXJyZW50Um91dGUsIGlzRGVmYXVsdFJvdXRlID0gZmFsc2U7XHJcblx0bS5yb3V0ZSA9IGZ1bmN0aW9uKCkge1xyXG5cdFx0Ly9tLnJvdXRlKClcclxuXHRcdGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSByZXR1cm4gY3VycmVudFJvdXRlO1xyXG5cdFx0Ly9tLnJvdXRlKGVsLCBkZWZhdWx0Um91dGUsIHJvdXRlcylcclxuXHRcdGVsc2UgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDMgJiYgdHlwZS5jYWxsKGFyZ3VtZW50c1sxXSkgPT09IFNUUklORykge1xyXG5cdFx0XHR2YXIgcm9vdCA9IGFyZ3VtZW50c1swXSwgZGVmYXVsdFJvdXRlID0gYXJndW1lbnRzWzFdLCByb3V0ZXIgPSBhcmd1bWVudHNbMl07XHJcblx0XHRcdHJlZGlyZWN0ID0gZnVuY3Rpb24oc291cmNlKSB7XHJcblx0XHRcdFx0dmFyIHBhdGggPSBjdXJyZW50Um91dGUgPSBub3JtYWxpemVSb3V0ZShzb3VyY2UpO1xyXG5cdFx0XHRcdGlmICghcm91dGVCeVZhbHVlKHJvb3QsIHJvdXRlciwgcGF0aCkpIHtcclxuXHRcdFx0XHRcdGlmIChpc0RlZmF1bHRSb3V0ZSkgdGhyb3cgbmV3IEVycm9yKFwiRW5zdXJlIHRoZSBkZWZhdWx0IHJvdXRlIG1hdGNoZXMgb25lIG9mIHRoZSByb3V0ZXMgZGVmaW5lZCBpbiBtLnJvdXRlXCIpXHJcblx0XHRcdFx0XHRpc0RlZmF1bHRSb3V0ZSA9IHRydWVcclxuXHRcdFx0XHRcdG0ucm91dGUoZGVmYXVsdFJvdXRlLCB0cnVlKVxyXG5cdFx0XHRcdFx0aXNEZWZhdWx0Um91dGUgPSBmYWxzZVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fTtcclxuXHRcdFx0dmFyIGxpc3RlbmVyID0gbS5yb3V0ZS5tb2RlID09PSBcImhhc2hcIiA/IFwib25oYXNoY2hhbmdlXCIgOiBcIm9ucG9wc3RhdGVcIjtcclxuXHRcdFx0d2luZG93W2xpc3RlbmVyXSA9IGZ1bmN0aW9uKCkge1xyXG5cdFx0XHRcdHZhciBwYXRoID0gJGxvY2F0aW9uW20ucm91dGUubW9kZV1cclxuXHRcdFx0XHRpZiAobS5yb3V0ZS5tb2RlID09PSBcInBhdGhuYW1lXCIpIHBhdGggKz0gJGxvY2F0aW9uLnNlYXJjaFxyXG5cdFx0XHRcdGlmIChjdXJyZW50Um91dGUgIT0gbm9ybWFsaXplUm91dGUocGF0aCkpIHtcclxuXHRcdFx0XHRcdHJlZGlyZWN0KHBhdGgpXHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9O1xyXG5cdFx0XHRjb21wdXRlUHJlUmVkcmF3SG9vayA9IHNldFNjcm9sbDtcclxuXHRcdFx0d2luZG93W2xpc3RlbmVyXSgpXHJcblx0XHR9XHJcblx0XHQvL2NvbmZpZzogbS5yb3V0ZVxyXG5cdFx0ZWxzZSBpZiAoYXJndW1lbnRzWzBdLmFkZEV2ZW50TGlzdGVuZXIgfHwgYXJndW1lbnRzWzBdLmF0dGFjaEV2ZW50KSB7XHJcblx0XHRcdHZhciBlbGVtZW50ID0gYXJndW1lbnRzWzBdO1xyXG5cdFx0XHR2YXIgaXNJbml0aWFsaXplZCA9IGFyZ3VtZW50c1sxXTtcclxuXHRcdFx0dmFyIGNvbnRleHQgPSBhcmd1bWVudHNbMl07XHJcblx0XHRcdHZhciB2ZG9tID0gYXJndW1lbnRzWzNdO1xyXG5cdFx0XHRlbGVtZW50LmhyZWYgPSAobS5yb3V0ZS5tb2RlICE9PSAncGF0aG5hbWUnID8gJGxvY2F0aW9uLnBhdGhuYW1lIDogJycpICsgbW9kZXNbbS5yb3V0ZS5tb2RlXSArIHZkb20uYXR0cnMuaHJlZjtcclxuXHRcdFx0aWYgKGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcikge1xyXG5cdFx0XHRcdGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIHJvdXRlVW5vYnRydXNpdmUpO1xyXG5cdFx0XHRcdGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIHJvdXRlVW5vYnRydXNpdmUpXHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0ZWxlbWVudC5kZXRhY2hFdmVudChcIm9uY2xpY2tcIiwgcm91dGVVbm9idHJ1c2l2ZSk7XHJcblx0XHRcdFx0ZWxlbWVudC5hdHRhY2hFdmVudChcIm9uY2xpY2tcIiwgcm91dGVVbm9idHJ1c2l2ZSlcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0Ly9tLnJvdXRlKHJvdXRlLCBwYXJhbXMsIHNob3VsZFJlcGxhY2VIaXN0b3J5RW50cnkpXHJcblx0XHRlbHNlIGlmICh0eXBlLmNhbGwoYXJndW1lbnRzWzBdKSA9PT0gU1RSSU5HKSB7XHJcblx0XHRcdHZhciBvbGRSb3V0ZSA9IGN1cnJlbnRSb3V0ZTtcclxuXHRcdFx0Y3VycmVudFJvdXRlID0gYXJndW1lbnRzWzBdO1xyXG5cdFx0XHR2YXIgYXJncyA9IGFyZ3VtZW50c1sxXSB8fCB7fVxyXG5cdFx0XHR2YXIgcXVlcnlJbmRleCA9IGN1cnJlbnRSb3V0ZS5pbmRleE9mKFwiP1wiKVxyXG5cdFx0XHR2YXIgcGFyYW1zID0gcXVlcnlJbmRleCA+IC0xID8gcGFyc2VRdWVyeVN0cmluZyhjdXJyZW50Um91dGUuc2xpY2UocXVlcnlJbmRleCArIDEpKSA6IHt9XHJcblx0XHRcdGZvciAodmFyIGkgaW4gYXJncykgcGFyYW1zW2ldID0gYXJnc1tpXVxyXG5cdFx0XHR2YXIgcXVlcnlzdHJpbmcgPSBidWlsZFF1ZXJ5U3RyaW5nKHBhcmFtcylcclxuXHRcdFx0dmFyIGN1cnJlbnRQYXRoID0gcXVlcnlJbmRleCA+IC0xID8gY3VycmVudFJvdXRlLnNsaWNlKDAsIHF1ZXJ5SW5kZXgpIDogY3VycmVudFJvdXRlXHJcblx0XHRcdGlmIChxdWVyeXN0cmluZykgY3VycmVudFJvdXRlID0gY3VycmVudFBhdGggKyAoY3VycmVudFBhdGguaW5kZXhPZihcIj9cIikgPT09IC0xID8gXCI/XCIgOiBcIiZcIikgKyBxdWVyeXN0cmluZztcclxuXHJcblx0XHRcdHZhciBzaG91bGRSZXBsYWNlSGlzdG9yeUVudHJ5ID0gKGFyZ3VtZW50cy5sZW5ndGggPT09IDMgPyBhcmd1bWVudHNbMl0gOiBhcmd1bWVudHNbMV0pID09PSB0cnVlIHx8IG9sZFJvdXRlID09PSBhcmd1bWVudHNbMF07XHJcblxyXG5cdFx0XHRpZiAod2luZG93Lmhpc3RvcnkucHVzaFN0YXRlKSB7XHJcblx0XHRcdFx0Y29tcHV0ZVByZVJlZHJhd0hvb2sgPSBzZXRTY3JvbGxcclxuXHRcdFx0XHRjb21wdXRlUG9zdFJlZHJhd0hvb2sgPSBmdW5jdGlvbigpIHtcclxuXHRcdFx0XHRcdHdpbmRvdy5oaXN0b3J5W3Nob3VsZFJlcGxhY2VIaXN0b3J5RW50cnkgPyBcInJlcGxhY2VTdGF0ZVwiIDogXCJwdXNoU3RhdGVcIl0obnVsbCwgJGRvY3VtZW50LnRpdGxlLCBtb2Rlc1ttLnJvdXRlLm1vZGVdICsgY3VycmVudFJvdXRlKTtcclxuXHRcdFx0XHR9O1xyXG5cdFx0XHRcdHJlZGlyZWN0KG1vZGVzW20ucm91dGUubW9kZV0gKyBjdXJyZW50Um91dGUpXHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSB7XHJcblx0XHRcdFx0JGxvY2F0aW9uW20ucm91dGUubW9kZV0gPSBjdXJyZW50Um91dGVcclxuXHRcdFx0XHRyZWRpcmVjdChtb2Rlc1ttLnJvdXRlLm1vZGVdICsgY3VycmVudFJvdXRlKVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fTtcclxuXHRtLnJvdXRlLnBhcmFtID0gZnVuY3Rpb24oa2V5KSB7XHJcblx0XHRpZiAoIXJvdXRlUGFyYW1zKSB0aHJvdyBuZXcgRXJyb3IoXCJZb3UgbXVzdCBjYWxsIG0ucm91dGUoZWxlbWVudCwgZGVmYXVsdFJvdXRlLCByb3V0ZXMpIGJlZm9yZSBjYWxsaW5nIG0ucm91dGUucGFyYW0oKVwiKVxyXG5cdFx0cmV0dXJuIHJvdXRlUGFyYW1zW2tleV1cclxuXHR9O1xyXG5cdG0ucm91dGUubW9kZSA9IFwic2VhcmNoXCI7XHJcblx0ZnVuY3Rpb24gbm9ybWFsaXplUm91dGUocm91dGUpIHtcclxuXHRcdHJldHVybiByb3V0ZS5zbGljZShtb2Rlc1ttLnJvdXRlLm1vZGVdLmxlbmd0aClcclxuXHR9XHJcblx0ZnVuY3Rpb24gcm91dGVCeVZhbHVlKHJvb3QsIHJvdXRlciwgcGF0aCkge1xyXG5cdFx0cm91dGVQYXJhbXMgPSB7fTtcclxuXHJcblx0XHR2YXIgcXVlcnlTdGFydCA9IHBhdGguaW5kZXhPZihcIj9cIik7XHJcblx0XHRpZiAocXVlcnlTdGFydCAhPT0gLTEpIHtcclxuXHRcdFx0cm91dGVQYXJhbXMgPSBwYXJzZVF1ZXJ5U3RyaW5nKHBhdGguc3Vic3RyKHF1ZXJ5U3RhcnQgKyAxLCBwYXRoLmxlbmd0aCkpO1xyXG5cdFx0XHRwYXRoID0gcGF0aC5zdWJzdHIoMCwgcXVlcnlTdGFydClcclxuXHRcdH1cclxuXHJcblx0XHQvLyBHZXQgYWxsIHJvdXRlcyBhbmQgY2hlY2sgaWYgdGhlcmUnc1xyXG5cdFx0Ly8gYW4gZXhhY3QgbWF0Y2ggZm9yIHRoZSBjdXJyZW50IHBhdGhcclxuXHRcdHZhciBrZXlzID0gT2JqZWN0LmtleXMocm91dGVyKTtcclxuXHRcdHZhciBpbmRleCA9IGtleXMuaW5kZXhPZihwYXRoKTtcclxuXHRcdGlmKGluZGV4ICE9PSAtMSl7XHJcblx0XHRcdG0ubW91bnQocm9vdCwgcm91dGVyW2tleXMgW2luZGV4XV0pO1xyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH1cclxuXHJcblx0XHRmb3IgKHZhciByb3V0ZSBpbiByb3V0ZXIpIHtcclxuXHRcdFx0aWYgKHJvdXRlID09PSBwYXRoKSB7XHJcblx0XHRcdFx0bS5tb3VudChyb290LCByb3V0ZXJbcm91dGVdKTtcclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZVxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR2YXIgbWF0Y2hlciA9IG5ldyBSZWdFeHAoXCJeXCIgKyByb3V0ZS5yZXBsYWNlKC86W15cXC9dKz9cXC57M30vZywgXCIoLio/KVwiKS5yZXBsYWNlKC86W15cXC9dKy9nLCBcIihbXlxcXFwvXSspXCIpICsgXCJcXC8/JFwiKTtcclxuXHJcblx0XHRcdGlmIChtYXRjaGVyLnRlc3QocGF0aCkpIHtcclxuXHRcdFx0XHRwYXRoLnJlcGxhY2UobWF0Y2hlciwgZnVuY3Rpb24oKSB7XHJcblx0XHRcdFx0XHR2YXIga2V5cyA9IHJvdXRlLm1hdGNoKC86W15cXC9dKy9nKSB8fCBbXTtcclxuXHRcdFx0XHRcdHZhciB2YWx1ZXMgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSwgLTIpO1xyXG5cdFx0XHRcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IGtleXMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHJvdXRlUGFyYW1zW2tleXNbaV0ucmVwbGFjZSgvOnxcXC4vZywgXCJcIildID0gZGVjb2RlVVJJQ29tcG9uZW50KHZhbHVlc1tpXSlcclxuXHRcdFx0XHRcdG0ubW91bnQocm9vdCwgcm91dGVyW3JvdXRlXSlcclxuXHRcdFx0XHR9KTtcclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cdGZ1bmN0aW9uIHJvdXRlVW5vYnRydXNpdmUoZSkge1xyXG5cdFx0ZSA9IGUgfHwgZXZlbnQ7XHJcblx0XHRpZiAoZS5jdHJsS2V5IHx8IGUubWV0YUtleSB8fCBlLndoaWNoID09PSAyKSByZXR1cm47XHJcblx0XHRpZiAoZS5wcmV2ZW50RGVmYXVsdCkgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0ZWxzZSBlLnJldHVyblZhbHVlID0gZmFsc2U7XHJcblx0XHR2YXIgY3VycmVudFRhcmdldCA9IGUuY3VycmVudFRhcmdldCB8fCBlLnNyY0VsZW1lbnQ7XHJcblx0XHR2YXIgYXJncyA9IG0ucm91dGUubW9kZSA9PT0gXCJwYXRobmFtZVwiICYmIGN1cnJlbnRUYXJnZXQuc2VhcmNoID8gcGFyc2VRdWVyeVN0cmluZyhjdXJyZW50VGFyZ2V0LnNlYXJjaC5zbGljZSgxKSkgOiB7fTtcclxuXHRcdHdoaWxlIChjdXJyZW50VGFyZ2V0ICYmIGN1cnJlbnRUYXJnZXQubm9kZU5hbWUudG9VcHBlckNhc2UoKSAhPSBcIkFcIikgY3VycmVudFRhcmdldCA9IGN1cnJlbnRUYXJnZXQucGFyZW50Tm9kZVxyXG5cdFx0bS5yb3V0ZShjdXJyZW50VGFyZ2V0W20ucm91dGUubW9kZV0uc2xpY2UobW9kZXNbbS5yb3V0ZS5tb2RlXS5sZW5ndGgpLCBhcmdzKVxyXG5cdH1cclxuXHRmdW5jdGlvbiBzZXRTY3JvbGwoKSB7XHJcblx0XHRpZiAobS5yb3V0ZS5tb2RlICE9IFwiaGFzaFwiICYmICRsb2NhdGlvbi5oYXNoKSAkbG9jYXRpb24uaGFzaCA9ICRsb2NhdGlvbi5oYXNoO1xyXG5cdFx0ZWxzZSB3aW5kb3cuc2Nyb2xsVG8oMCwgMClcclxuXHR9XHJcblx0ZnVuY3Rpb24gYnVpbGRRdWVyeVN0cmluZyhvYmplY3QsIHByZWZpeCkge1xyXG5cdFx0dmFyIGR1cGxpY2F0ZXMgPSB7fVxyXG5cdFx0dmFyIHN0ciA9IFtdXHJcblx0XHRmb3IgKHZhciBwcm9wIGluIG9iamVjdCkge1xyXG5cdFx0XHR2YXIga2V5ID0gcHJlZml4ID8gcHJlZml4ICsgXCJbXCIgKyBwcm9wICsgXCJdXCIgOiBwcm9wXHJcblx0XHRcdHZhciB2YWx1ZSA9IG9iamVjdFtwcm9wXVxyXG5cdFx0XHR2YXIgdmFsdWVUeXBlID0gdHlwZS5jYWxsKHZhbHVlKVxyXG5cdFx0XHR2YXIgcGFpciA9ICh2YWx1ZSA9PT0gbnVsbCkgPyBlbmNvZGVVUklDb21wb25lbnQoa2V5KSA6XHJcblx0XHRcdFx0dmFsdWVUeXBlID09PSBPQkpFQ1QgPyBidWlsZFF1ZXJ5U3RyaW5nKHZhbHVlLCBrZXkpIDpcclxuXHRcdFx0XHR2YWx1ZVR5cGUgPT09IEFSUkFZID8gdmFsdWUucmVkdWNlKGZ1bmN0aW9uKG1lbW8sIGl0ZW0pIHtcclxuXHRcdFx0XHRcdGlmICghZHVwbGljYXRlc1trZXldKSBkdXBsaWNhdGVzW2tleV0gPSB7fVxyXG5cdFx0XHRcdFx0aWYgKCFkdXBsaWNhdGVzW2tleV1baXRlbV0pIHtcclxuXHRcdFx0XHRcdFx0ZHVwbGljYXRlc1trZXldW2l0ZW1dID0gdHJ1ZVxyXG5cdFx0XHRcdFx0XHRyZXR1cm4gbWVtby5jb25jYXQoZW5jb2RlVVJJQ29tcG9uZW50KGtleSkgKyBcIj1cIiArIGVuY29kZVVSSUNvbXBvbmVudChpdGVtKSlcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdHJldHVybiBtZW1vXHJcblx0XHRcdFx0fSwgW10pLmpvaW4oXCImXCIpIDpcclxuXHRcdFx0XHRlbmNvZGVVUklDb21wb25lbnQoa2V5KSArIFwiPVwiICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKVxyXG5cdFx0XHRpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkgc3RyLnB1c2gocGFpcilcclxuXHRcdH1cclxuXHRcdHJldHVybiBzdHIuam9pbihcIiZcIilcclxuXHR9XHJcblx0ZnVuY3Rpb24gcGFyc2VRdWVyeVN0cmluZyhzdHIpIHtcclxuXHRcdGlmIChzdHIuY2hhckF0KDApID09PSBcIj9cIikgc3RyID0gc3RyLnN1YnN0cmluZygxKTtcclxuXHRcdFxyXG5cdFx0dmFyIHBhaXJzID0gc3RyLnNwbGl0KFwiJlwiKSwgcGFyYW1zID0ge307XHJcblx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gcGFpcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdFx0dmFyIHBhaXIgPSBwYWlyc1tpXS5zcGxpdChcIj1cIik7XHJcblx0XHRcdHZhciBrZXkgPSBkZWNvZGVVUklDb21wb25lbnQocGFpclswXSlcclxuXHRcdFx0dmFyIHZhbHVlID0gcGFpci5sZW5ndGggPT0gMiA/IGRlY29kZVVSSUNvbXBvbmVudChwYWlyWzFdKSA6IG51bGxcclxuXHRcdFx0aWYgKHBhcmFtc1trZXldICE9IG51bGwpIHtcclxuXHRcdFx0XHRpZiAodHlwZS5jYWxsKHBhcmFtc1trZXldKSAhPT0gQVJSQVkpIHBhcmFtc1trZXldID0gW3BhcmFtc1trZXldXVxyXG5cdFx0XHRcdHBhcmFtc1trZXldLnB1c2godmFsdWUpXHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSBwYXJhbXNba2V5XSA9IHZhbHVlXHJcblx0XHR9XHJcblx0XHRyZXR1cm4gcGFyYW1zXHJcblx0fVxyXG5cdG0ucm91dGUuYnVpbGRRdWVyeVN0cmluZyA9IGJ1aWxkUXVlcnlTdHJpbmdcclxuXHRtLnJvdXRlLnBhcnNlUXVlcnlTdHJpbmcgPSBwYXJzZVF1ZXJ5U3RyaW5nXHJcblx0XHJcblx0ZnVuY3Rpb24gcmVzZXQocm9vdCkge1xyXG5cdFx0dmFyIGNhY2hlS2V5ID0gZ2V0Q2VsbENhY2hlS2V5KHJvb3QpO1xyXG5cdFx0Y2xlYXIocm9vdC5jaGlsZE5vZGVzLCBjZWxsQ2FjaGVbY2FjaGVLZXldKTtcclxuXHRcdGNlbGxDYWNoZVtjYWNoZUtleV0gPSB1bmRlZmluZWRcclxuXHR9XHJcblxyXG5cdG0uZGVmZXJyZWQgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgZGVmZXJyZWQgPSBuZXcgRGVmZXJyZWQoKTtcclxuXHRcdGRlZmVycmVkLnByb21pc2UgPSBwcm9waWZ5KGRlZmVycmVkLnByb21pc2UpO1xyXG5cdFx0cmV0dXJuIGRlZmVycmVkXHJcblx0fTtcclxuXHRmdW5jdGlvbiBwcm9waWZ5KHByb21pc2UsIGluaXRpYWxWYWx1ZSkge1xyXG5cdFx0dmFyIHByb3AgPSBtLnByb3AoaW5pdGlhbFZhbHVlKTtcclxuXHRcdHByb21pc2UudGhlbihwcm9wKTtcclxuXHRcdHByb3AudGhlbiA9IGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xyXG5cdFx0XHRyZXR1cm4gcHJvcGlmeShwcm9taXNlLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KSwgaW5pdGlhbFZhbHVlKVxyXG5cdFx0fTtcclxuXHRcdHJldHVybiBwcm9wXHJcblx0fVxyXG5cdC8vUHJvbWl6Lm1pdGhyaWwuanMgfCBab2xtZWlzdGVyIHwgTUlUXHJcblx0Ly9hIG1vZGlmaWVkIHZlcnNpb24gb2YgUHJvbWl6LmpzLCB3aGljaCBkb2VzIG5vdCBjb25mb3JtIHRvIFByb21pc2VzL0ErIGZvciB0d28gcmVhc29uczpcclxuXHQvLzEpIGB0aGVuYCBjYWxsYmFja3MgYXJlIGNhbGxlZCBzeW5jaHJvbm91c2x5IChiZWNhdXNlIHNldFRpbWVvdXQgaXMgdG9vIHNsb3csIGFuZCB0aGUgc2V0SW1tZWRpYXRlIHBvbHlmaWxsIGlzIHRvbyBiaWdcclxuXHQvLzIpIHRocm93aW5nIHN1YmNsYXNzZXMgb2YgRXJyb3IgY2F1c2UgdGhlIGVycm9yIHRvIGJlIGJ1YmJsZWQgdXAgaW5zdGVhZCBvZiB0cmlnZ2VyaW5nIHJlamVjdGlvbiAoYmVjYXVzZSB0aGUgc3BlYyBkb2VzIG5vdCBhY2NvdW50IGZvciB0aGUgaW1wb3J0YW50IHVzZSBjYXNlIG9mIGRlZmF1bHQgYnJvd3NlciBlcnJvciBoYW5kbGluZywgaS5lLiBtZXNzYWdlIHcvIGxpbmUgbnVtYmVyKVxyXG5cdGZ1bmN0aW9uIERlZmVycmVkKHN1Y2Nlc3NDYWxsYmFjaywgZmFpbHVyZUNhbGxiYWNrKSB7XHJcblx0XHR2YXIgUkVTT0xWSU5HID0gMSwgUkVKRUNUSU5HID0gMiwgUkVTT0xWRUQgPSAzLCBSRUpFQ1RFRCA9IDQ7XHJcblx0XHR2YXIgc2VsZiA9IHRoaXMsIHN0YXRlID0gMCwgcHJvbWlzZVZhbHVlID0gMCwgbmV4dCA9IFtdO1xyXG5cclxuXHRcdHNlbGZbXCJwcm9taXNlXCJdID0ge307XHJcblxyXG5cdFx0c2VsZltcInJlc29sdmVcIl0gPSBmdW5jdGlvbih2YWx1ZSkge1xyXG5cdFx0XHRpZiAoIXN0YXRlKSB7XHJcblx0XHRcdFx0cHJvbWlzZVZhbHVlID0gdmFsdWU7XHJcblx0XHRcdFx0c3RhdGUgPSBSRVNPTFZJTkc7XHJcblxyXG5cdFx0XHRcdGZpcmUoKVxyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiB0aGlzXHJcblx0XHR9O1xyXG5cclxuXHRcdHNlbGZbXCJyZWplY3RcIl0gPSBmdW5jdGlvbih2YWx1ZSkge1xyXG5cdFx0XHRpZiAoIXN0YXRlKSB7XHJcblx0XHRcdFx0cHJvbWlzZVZhbHVlID0gdmFsdWU7XHJcblx0XHRcdFx0c3RhdGUgPSBSRUpFQ1RJTkc7XHJcblxyXG5cdFx0XHRcdGZpcmUoKVxyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiB0aGlzXHJcblx0XHR9O1xyXG5cclxuXHRcdHNlbGYucHJvbWlzZVtcInRoZW5cIl0gPSBmdW5jdGlvbihzdWNjZXNzQ2FsbGJhY2ssIGZhaWx1cmVDYWxsYmFjaykge1xyXG5cdFx0XHR2YXIgZGVmZXJyZWQgPSBuZXcgRGVmZXJyZWQoc3VjY2Vzc0NhbGxiYWNrLCBmYWlsdXJlQ2FsbGJhY2spO1xyXG5cdFx0XHRpZiAoc3RhdGUgPT09IFJFU09MVkVEKSB7XHJcblx0XHRcdFx0ZGVmZXJyZWQucmVzb2x2ZShwcm9taXNlVmFsdWUpXHJcblx0XHRcdH1cclxuXHRcdFx0ZWxzZSBpZiAoc3RhdGUgPT09IFJFSkVDVEVEKSB7XHJcblx0XHRcdFx0ZGVmZXJyZWQucmVqZWN0KHByb21pc2VWYWx1ZSlcclxuXHRcdFx0fVxyXG5cdFx0XHRlbHNlIHtcclxuXHRcdFx0XHRuZXh0LnB1c2goZGVmZXJyZWQpXHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIGRlZmVycmVkLnByb21pc2VcclxuXHRcdH07XHJcblxyXG5cdFx0ZnVuY3Rpb24gZmluaXNoKHR5cGUpIHtcclxuXHRcdFx0c3RhdGUgPSB0eXBlIHx8IFJFSkVDVEVEO1xyXG5cdFx0XHRuZXh0Lm1hcChmdW5jdGlvbihkZWZlcnJlZCkge1xyXG5cdFx0XHRcdHN0YXRlID09PSBSRVNPTFZFRCAmJiBkZWZlcnJlZC5yZXNvbHZlKHByb21pc2VWYWx1ZSkgfHwgZGVmZXJyZWQucmVqZWN0KHByb21pc2VWYWx1ZSlcclxuXHRcdFx0fSlcclxuXHRcdH1cclxuXHJcblx0XHRmdW5jdGlvbiB0aGVubmFibGUodGhlbiwgc3VjY2Vzc0NhbGxiYWNrLCBmYWlsdXJlQ2FsbGJhY2ssIG5vdFRoZW5uYWJsZUNhbGxiYWNrKSB7XHJcblx0XHRcdGlmICgoKHByb21pc2VWYWx1ZSAhPSBudWxsICYmIHR5cGUuY2FsbChwcm9taXNlVmFsdWUpID09PSBPQkpFQ1QpIHx8IHR5cGVvZiBwcm9taXNlVmFsdWUgPT09IEZVTkNUSU9OKSAmJiB0eXBlb2YgdGhlbiA9PT0gRlVOQ1RJT04pIHtcclxuXHRcdFx0XHR0cnkge1xyXG5cdFx0XHRcdFx0Ly8gY291bnQgcHJvdGVjdHMgYWdhaW5zdCBhYnVzZSBjYWxscyBmcm9tIHNwZWMgY2hlY2tlclxyXG5cdFx0XHRcdFx0dmFyIGNvdW50ID0gMDtcclxuXHRcdFx0XHRcdHRoZW4uY2FsbChwcm9taXNlVmFsdWUsIGZ1bmN0aW9uKHZhbHVlKSB7XHJcblx0XHRcdFx0XHRcdGlmIChjb3VudCsrKSByZXR1cm47XHJcblx0XHRcdFx0XHRcdHByb21pc2VWYWx1ZSA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRzdWNjZXNzQ2FsbGJhY2soKVxyXG5cdFx0XHRcdFx0fSwgZnVuY3Rpb24gKHZhbHVlKSB7XHJcblx0XHRcdFx0XHRcdGlmIChjb3VudCsrKSByZXR1cm47XHJcblx0XHRcdFx0XHRcdHByb21pc2VWYWx1ZSA9IHZhbHVlO1xyXG5cdFx0XHRcdFx0XHRmYWlsdXJlQ2FsbGJhY2soKVxyXG5cdFx0XHRcdFx0fSlcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0Y2F0Y2ggKGUpIHtcclxuXHRcdFx0XHRcdG0uZGVmZXJyZWQub25lcnJvcihlKTtcclxuXHRcdFx0XHRcdHByb21pc2VWYWx1ZSA9IGU7XHJcblx0XHRcdFx0XHRmYWlsdXJlQ2FsbGJhY2soKVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRub3RUaGVubmFibGVDYWxsYmFjaygpXHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRmdW5jdGlvbiBmaXJlKCkge1xyXG5cdFx0XHQvLyBjaGVjayBpZiBpdCdzIGEgdGhlbmFibGVcclxuXHRcdFx0dmFyIHRoZW47XHJcblx0XHRcdHRyeSB7XHJcblx0XHRcdFx0dGhlbiA9IHByb21pc2VWYWx1ZSAmJiBwcm9taXNlVmFsdWUudGhlblxyXG5cdFx0XHR9XHJcblx0XHRcdGNhdGNoIChlKSB7XHJcblx0XHRcdFx0bS5kZWZlcnJlZC5vbmVycm9yKGUpO1xyXG5cdFx0XHRcdHByb21pc2VWYWx1ZSA9IGU7XHJcblx0XHRcdFx0c3RhdGUgPSBSRUpFQ1RJTkc7XHJcblx0XHRcdFx0cmV0dXJuIGZpcmUoKVxyXG5cdFx0XHR9XHJcblx0XHRcdHRoZW5uYWJsZSh0aGVuLCBmdW5jdGlvbigpIHtcclxuXHRcdFx0XHRzdGF0ZSA9IFJFU09MVklORztcclxuXHRcdFx0XHRmaXJlKClcclxuXHRcdFx0fSwgZnVuY3Rpb24oKSB7XHJcblx0XHRcdFx0c3RhdGUgPSBSRUpFQ1RJTkc7XHJcblx0XHRcdFx0ZmlyZSgpXHJcblx0XHRcdH0sIGZ1bmN0aW9uKCkge1xyXG5cdFx0XHRcdHRyeSB7XHJcblx0XHRcdFx0XHRpZiAoc3RhdGUgPT09IFJFU09MVklORyAmJiB0eXBlb2Ygc3VjY2Vzc0NhbGxiYWNrID09PSBGVU5DVElPTikge1xyXG5cdFx0XHRcdFx0XHRwcm9taXNlVmFsdWUgPSBzdWNjZXNzQ2FsbGJhY2socHJvbWlzZVZhbHVlKVxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0ZWxzZSBpZiAoc3RhdGUgPT09IFJFSkVDVElORyAmJiB0eXBlb2YgZmFpbHVyZUNhbGxiYWNrID09PSBcImZ1bmN0aW9uXCIpIHtcclxuXHRcdFx0XHRcdFx0cHJvbWlzZVZhbHVlID0gZmFpbHVyZUNhbGxiYWNrKHByb21pc2VWYWx1ZSk7XHJcblx0XHRcdFx0XHRcdHN0YXRlID0gUkVTT0xWSU5HXHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGNhdGNoIChlKSB7XHJcblx0XHRcdFx0XHRtLmRlZmVycmVkLm9uZXJyb3IoZSk7XHJcblx0XHRcdFx0XHRwcm9taXNlVmFsdWUgPSBlO1xyXG5cdFx0XHRcdFx0cmV0dXJuIGZpbmlzaCgpXHJcblx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRpZiAocHJvbWlzZVZhbHVlID09PSBzZWxmKSB7XHJcblx0XHRcdFx0XHRwcm9taXNlVmFsdWUgPSBUeXBlRXJyb3IoKTtcclxuXHRcdFx0XHRcdGZpbmlzaCgpXHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGVsc2Uge1xyXG5cdFx0XHRcdFx0dGhlbm5hYmxlKHRoZW4sIGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0XHRcdFx0ZmluaXNoKFJFU09MVkVEKVxyXG5cdFx0XHRcdFx0fSwgZmluaXNoLCBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRcdGZpbmlzaChzdGF0ZSA9PT0gUkVTT0xWSU5HICYmIFJFU09MVkVEKVxyXG5cdFx0XHRcdFx0fSlcclxuXHRcdFx0XHR9XHJcblx0XHRcdH0pXHJcblx0XHR9XHJcblx0fVxyXG5cdG0uZGVmZXJyZWQub25lcnJvciA9IGZ1bmN0aW9uKGUpIHtcclxuXHRcdGlmICh0eXBlLmNhbGwoZSkgPT09IFwiW29iamVjdCBFcnJvcl1cIiAmJiAhZS5jb25zdHJ1Y3Rvci50b1N0cmluZygpLm1hdGNoKC8gRXJyb3IvKSkgdGhyb3cgZVxyXG5cdH07XHJcblxyXG5cdG0uc3luYyA9IGZ1bmN0aW9uKGFyZ3MpIHtcclxuXHRcdHZhciBtZXRob2QgPSBcInJlc29sdmVcIjtcclxuXHRcdGZ1bmN0aW9uIHN5bmNocm9uaXplcihwb3MsIHJlc29sdmVkKSB7XHJcblx0XHRcdHJldHVybiBmdW5jdGlvbih2YWx1ZSkge1xyXG5cdFx0XHRcdHJlc3VsdHNbcG9zXSA9IHZhbHVlO1xyXG5cdFx0XHRcdGlmICghcmVzb2x2ZWQpIG1ldGhvZCA9IFwicmVqZWN0XCI7XHJcblx0XHRcdFx0aWYgKC0tb3V0c3RhbmRpbmcgPT09IDApIHtcclxuXHRcdFx0XHRcdGRlZmVycmVkLnByb21pc2UocmVzdWx0cyk7XHJcblx0XHRcdFx0XHRkZWZlcnJlZFttZXRob2RdKHJlc3VsdHMpXHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybiB2YWx1ZVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIGRlZmVycmVkID0gbS5kZWZlcnJlZCgpO1xyXG5cdFx0dmFyIG91dHN0YW5kaW5nID0gYXJncy5sZW5ndGg7XHJcblx0XHR2YXIgcmVzdWx0cyA9IG5ldyBBcnJheShvdXRzdGFuZGluZyk7XHJcblx0XHRpZiAoYXJncy5sZW5ndGggPiAwKSB7XHJcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRcdGFyZ3NbaV0udGhlbihzeW5jaHJvbml6ZXIoaSwgdHJ1ZSksIHN5bmNocm9uaXplcihpLCBmYWxzZSkpXHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdGVsc2UgZGVmZXJyZWQucmVzb2x2ZShbXSk7XHJcblxyXG5cdFx0cmV0dXJuIGRlZmVycmVkLnByb21pc2VcclxuXHR9O1xyXG5cdGZ1bmN0aW9uIGlkZW50aXR5KHZhbHVlKSB7cmV0dXJuIHZhbHVlfVxyXG5cclxuXHRmdW5jdGlvbiBhamF4KG9wdGlvbnMpIHtcclxuXHRcdGlmIChvcHRpb25zLmRhdGFUeXBlICYmIG9wdGlvbnMuZGF0YVR5cGUudG9Mb3dlckNhc2UoKSA9PT0gXCJqc29ucFwiKSB7XHJcblx0XHRcdHZhciBjYWxsYmFja0tleSA9IFwibWl0aHJpbF9jYWxsYmFja19cIiArIG5ldyBEYXRlKCkuZ2V0VGltZSgpICsgXCJfXCIgKyAoTWF0aC5yb3VuZChNYXRoLnJhbmRvbSgpICogMWUxNikpLnRvU3RyaW5nKDM2KTtcclxuXHRcdFx0dmFyIHNjcmlwdCA9ICRkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic2NyaXB0XCIpO1xyXG5cclxuXHRcdFx0d2luZG93W2NhbGxiYWNrS2V5XSA9IGZ1bmN0aW9uKHJlc3ApIHtcclxuXHRcdFx0XHRzY3JpcHQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChzY3JpcHQpO1xyXG5cdFx0XHRcdG9wdGlvbnMub25sb2FkKHtcclxuXHRcdFx0XHRcdHR5cGU6IFwibG9hZFwiLFxyXG5cdFx0XHRcdFx0dGFyZ2V0OiB7XHJcblx0XHRcdFx0XHRcdHJlc3BvbnNlVGV4dDogcmVzcFxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH0pO1xyXG5cdFx0XHRcdHdpbmRvd1tjYWxsYmFja0tleV0gPSB1bmRlZmluZWRcclxuXHRcdFx0fTtcclxuXHJcblx0XHRcdHNjcmlwdC5vbmVycm9yID0gZnVuY3Rpb24oZSkge1xyXG5cdFx0XHRcdHNjcmlwdC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHNjcmlwdCk7XHJcblxyXG5cdFx0XHRcdG9wdGlvbnMub25lcnJvcih7XHJcblx0XHRcdFx0XHR0eXBlOiBcImVycm9yXCIsXHJcblx0XHRcdFx0XHR0YXJnZXQ6IHtcclxuXHRcdFx0XHRcdFx0c3RhdHVzOiA1MDAsXHJcblx0XHRcdFx0XHRcdHJlc3BvbnNlVGV4dDogSlNPTi5zdHJpbmdpZnkoe2Vycm9yOiBcIkVycm9yIG1ha2luZyBqc29ucCByZXF1ZXN0XCJ9KVxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH0pO1xyXG5cdFx0XHRcdHdpbmRvd1tjYWxsYmFja0tleV0gPSB1bmRlZmluZWQ7XHJcblxyXG5cdFx0XHRcdHJldHVybiBmYWxzZVxyXG5cdFx0XHR9O1xyXG5cclxuXHRcdFx0c2NyaXB0Lm9ubG9hZCA9IGZ1bmN0aW9uKGUpIHtcclxuXHRcdFx0XHRyZXR1cm4gZmFsc2VcclxuXHRcdFx0fTtcclxuXHJcblx0XHRcdHNjcmlwdC5zcmMgPSBvcHRpb25zLnVybFxyXG5cdFx0XHRcdCsgKG9wdGlvbnMudXJsLmluZGV4T2YoXCI/XCIpID4gMCA/IFwiJlwiIDogXCI/XCIpXHJcblx0XHRcdFx0KyAob3B0aW9ucy5jYWxsYmFja0tleSA/IG9wdGlvbnMuY2FsbGJhY2tLZXkgOiBcImNhbGxiYWNrXCIpXHJcblx0XHRcdFx0KyBcIj1cIiArIGNhbGxiYWNrS2V5XHJcblx0XHRcdFx0KyBcIiZcIiArIGJ1aWxkUXVlcnlTdHJpbmcob3B0aW9ucy5kYXRhIHx8IHt9KTtcclxuXHRcdFx0JGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoc2NyaXB0KVxyXG5cdFx0fVxyXG5cdFx0ZWxzZSB7XHJcblx0XHRcdHZhciB4aHIgPSBuZXcgd2luZG93LlhNTEh0dHBSZXF1ZXN0O1xyXG5cdFx0XHR4aHIub3BlbihvcHRpb25zLm1ldGhvZCwgb3B0aW9ucy51cmwsIHRydWUsIG9wdGlvbnMudXNlciwgb3B0aW9ucy5wYXNzd29yZCk7XHJcblx0XHRcdHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcclxuXHRcdFx0XHRpZiAoeGhyLnJlYWR5U3RhdGUgPT09IDQpIHtcclxuXHRcdFx0XHRcdGlmICh4aHIuc3RhdHVzID49IDIwMCAmJiB4aHIuc3RhdHVzIDwgMzAwKSBvcHRpb25zLm9ubG9hZCh7dHlwZTogXCJsb2FkXCIsIHRhcmdldDogeGhyfSk7XHJcblx0XHRcdFx0XHRlbHNlIG9wdGlvbnMub25lcnJvcih7dHlwZTogXCJlcnJvclwiLCB0YXJnZXQ6IHhocn0pXHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9O1xyXG5cdFx0XHRpZiAob3B0aW9ucy5zZXJpYWxpemUgPT09IEpTT04uc3RyaW5naWZ5ICYmIG9wdGlvbnMuZGF0YSAmJiBvcHRpb25zLm1ldGhvZCAhPT0gXCJHRVRcIikge1xyXG5cdFx0XHRcdHhoci5zZXRSZXF1ZXN0SGVhZGVyKFwiQ29udGVudC1UeXBlXCIsIFwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD11dGYtOFwiKVxyXG5cdFx0XHR9XHJcblx0XHRcdGlmIChvcHRpb25zLmRlc2VyaWFsaXplID09PSBKU09OLnBhcnNlKSB7XHJcblx0XHRcdFx0eGhyLnNldFJlcXVlc3RIZWFkZXIoXCJBY2NlcHRcIiwgXCJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0LypcIik7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKHR5cGVvZiBvcHRpb25zLmNvbmZpZyA9PT0gRlVOQ1RJT04pIHtcclxuXHRcdFx0XHR2YXIgbWF5YmVYaHIgPSBvcHRpb25zLmNvbmZpZyh4aHIsIG9wdGlvbnMpO1xyXG5cdFx0XHRcdGlmIChtYXliZVhociAhPSBudWxsKSB4aHIgPSBtYXliZVhoclxyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR2YXIgZGF0YSA9IG9wdGlvbnMubWV0aG9kID09PSBcIkdFVFwiIHx8ICFvcHRpb25zLmRhdGEgPyBcIlwiIDogb3B0aW9ucy5kYXRhXHJcblx0XHRcdGlmIChkYXRhICYmICh0eXBlLmNhbGwoZGF0YSkgIT0gU1RSSU5HICYmIGRhdGEuY29uc3RydWN0b3IgIT0gd2luZG93LkZvcm1EYXRhKSkge1xyXG5cdFx0XHRcdHRocm93IFwiUmVxdWVzdCBkYXRhIHNob3VsZCBiZSBlaXRoZXIgYmUgYSBzdHJpbmcgb3IgRm9ybURhdGEuIENoZWNrIHRoZSBgc2VyaWFsaXplYCBvcHRpb24gaW4gYG0ucmVxdWVzdGBcIjtcclxuXHRcdFx0fVxyXG5cdFx0XHR4aHIuc2VuZChkYXRhKTtcclxuXHRcdFx0cmV0dXJuIHhoclxyXG5cdFx0fVxyXG5cdH1cclxuXHRmdW5jdGlvbiBiaW5kRGF0YSh4aHJPcHRpb25zLCBkYXRhLCBzZXJpYWxpemUpIHtcclxuXHRcdGlmICh4aHJPcHRpb25zLm1ldGhvZCA9PT0gXCJHRVRcIiAmJiB4aHJPcHRpb25zLmRhdGFUeXBlICE9IFwianNvbnBcIikge1xyXG5cdFx0XHR2YXIgcHJlZml4ID0geGhyT3B0aW9ucy51cmwuaW5kZXhPZihcIj9cIikgPCAwID8gXCI/XCIgOiBcIiZcIjtcclxuXHRcdFx0dmFyIHF1ZXJ5c3RyaW5nID0gYnVpbGRRdWVyeVN0cmluZyhkYXRhKTtcclxuXHRcdFx0eGhyT3B0aW9ucy51cmwgPSB4aHJPcHRpb25zLnVybCArIChxdWVyeXN0cmluZyA/IHByZWZpeCArIHF1ZXJ5c3RyaW5nIDogXCJcIilcclxuXHRcdH1cclxuXHRcdGVsc2UgeGhyT3B0aW9ucy5kYXRhID0gc2VyaWFsaXplKGRhdGEpO1xyXG5cdFx0cmV0dXJuIHhock9wdGlvbnNcclxuXHR9XHJcblx0ZnVuY3Rpb24gcGFyYW1ldGVyaXplVXJsKHVybCwgZGF0YSkge1xyXG5cdFx0dmFyIHRva2VucyA9IHVybC5tYXRjaCgvOlthLXpdXFx3Ky9naSk7XHJcblx0XHRpZiAodG9rZW5zICYmIGRhdGEpIHtcclxuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0b2tlbnMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0XHR2YXIga2V5ID0gdG9rZW5zW2ldLnNsaWNlKDEpO1xyXG5cdFx0XHRcdHVybCA9IHVybC5yZXBsYWNlKHRva2Vuc1tpXSwgZGF0YVtrZXldKTtcclxuXHRcdFx0XHRkZWxldGUgZGF0YVtrZXldXHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdHJldHVybiB1cmxcclxuXHR9XHJcblxyXG5cdG0ucmVxdWVzdCA9IGZ1bmN0aW9uKHhock9wdGlvbnMpIHtcclxuXHRcdGlmICh4aHJPcHRpb25zLmJhY2tncm91bmQgIT09IHRydWUpIG0uc3RhcnRDb21wdXRhdGlvbigpO1xyXG5cdFx0dmFyIGRlZmVycmVkID0gbmV3IERlZmVycmVkKCk7XHJcblx0XHR2YXIgaXNKU09OUCA9IHhock9wdGlvbnMuZGF0YVR5cGUgJiYgeGhyT3B0aW9ucy5kYXRhVHlwZS50b0xvd2VyQ2FzZSgpID09PSBcImpzb25wXCI7XHJcblx0XHR2YXIgc2VyaWFsaXplID0geGhyT3B0aW9ucy5zZXJpYWxpemUgPSBpc0pTT05QID8gaWRlbnRpdHkgOiB4aHJPcHRpb25zLnNlcmlhbGl6ZSB8fCBKU09OLnN0cmluZ2lmeTtcclxuXHRcdHZhciBkZXNlcmlhbGl6ZSA9IHhock9wdGlvbnMuZGVzZXJpYWxpemUgPSBpc0pTT05QID8gaWRlbnRpdHkgOiB4aHJPcHRpb25zLmRlc2VyaWFsaXplIHx8IEpTT04ucGFyc2U7XHJcblx0XHR2YXIgZXh0cmFjdCA9IGlzSlNPTlAgPyBmdW5jdGlvbihqc29ucCkge3JldHVybiBqc29ucC5yZXNwb25zZVRleHR9IDogeGhyT3B0aW9ucy5leHRyYWN0IHx8IGZ1bmN0aW9uKHhocikge1xyXG5cdFx0XHRyZXR1cm4geGhyLnJlc3BvbnNlVGV4dC5sZW5ndGggPT09IDAgJiYgZGVzZXJpYWxpemUgPT09IEpTT04ucGFyc2UgPyBudWxsIDogeGhyLnJlc3BvbnNlVGV4dFxyXG5cdFx0fTtcclxuXHRcdHhock9wdGlvbnMubWV0aG9kID0gKHhock9wdGlvbnMubWV0aG9kIHx8ICdHRVQnKS50b1VwcGVyQ2FzZSgpO1xyXG5cdFx0eGhyT3B0aW9ucy51cmwgPSBwYXJhbWV0ZXJpemVVcmwoeGhyT3B0aW9ucy51cmwsIHhock9wdGlvbnMuZGF0YSk7XHJcblx0XHR4aHJPcHRpb25zID0gYmluZERhdGEoeGhyT3B0aW9ucywgeGhyT3B0aW9ucy5kYXRhLCBzZXJpYWxpemUpO1xyXG5cdFx0eGhyT3B0aW9ucy5vbmxvYWQgPSB4aHJPcHRpb25zLm9uZXJyb3IgPSBmdW5jdGlvbihlKSB7XHJcblx0XHRcdHRyeSB7XHJcblx0XHRcdFx0ZSA9IGUgfHwgZXZlbnQ7XHJcblx0XHRcdFx0dmFyIHVud3JhcCA9IChlLnR5cGUgPT09IFwibG9hZFwiID8geGhyT3B0aW9ucy51bndyYXBTdWNjZXNzIDogeGhyT3B0aW9ucy51bndyYXBFcnJvcikgfHwgaWRlbnRpdHk7XHJcblx0XHRcdFx0dmFyIHJlc3BvbnNlID0gdW53cmFwKGRlc2VyaWFsaXplKGV4dHJhY3QoZS50YXJnZXQsIHhock9wdGlvbnMpKSwgZS50YXJnZXQpO1xyXG5cdFx0XHRcdGlmIChlLnR5cGUgPT09IFwibG9hZFwiKSB7XHJcblx0XHRcdFx0XHRpZiAodHlwZS5jYWxsKHJlc3BvbnNlKSA9PT0gQVJSQVkgJiYgeGhyT3B0aW9ucy50eXBlKSB7XHJcblx0XHRcdFx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcmVzcG9uc2UubGVuZ3RoOyBpKyspIHJlc3BvbnNlW2ldID0gbmV3IHhock9wdGlvbnMudHlwZShyZXNwb25zZVtpXSlcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdGVsc2UgaWYgKHhock9wdGlvbnMudHlwZSkgcmVzcG9uc2UgPSBuZXcgeGhyT3B0aW9ucy50eXBlKHJlc3BvbnNlKVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRkZWZlcnJlZFtlLnR5cGUgPT09IFwibG9hZFwiID8gXCJyZXNvbHZlXCIgOiBcInJlamVjdFwiXShyZXNwb25zZSlcclxuXHRcdFx0fVxyXG5cdFx0XHRjYXRjaCAoZSkge1xyXG5cdFx0XHRcdG0uZGVmZXJyZWQub25lcnJvcihlKTtcclxuXHRcdFx0XHRkZWZlcnJlZC5yZWplY3QoZSlcclxuXHRcdFx0fVxyXG5cdFx0XHRpZiAoeGhyT3B0aW9ucy5iYWNrZ3JvdW5kICE9PSB0cnVlKSBtLmVuZENvbXB1dGF0aW9uKClcclxuXHRcdH07XHJcblx0XHRhamF4KHhock9wdGlvbnMpO1xyXG5cdFx0ZGVmZXJyZWQucHJvbWlzZSA9IHByb3BpZnkoZGVmZXJyZWQucHJvbWlzZSwgeGhyT3B0aW9ucy5pbml0aWFsVmFsdWUpO1xyXG5cdFx0cmV0dXJuIGRlZmVycmVkLnByb21pc2VcclxuXHR9O1xyXG5cclxuXHQvL3Rlc3RpbmcgQVBJXHJcblx0bS5kZXBzID0gZnVuY3Rpb24obW9jaykge1xyXG5cdFx0aW5pdGlhbGl6ZSh3aW5kb3cgPSBtb2NrIHx8IHdpbmRvdyk7XHJcblx0XHRyZXR1cm4gd2luZG93O1xyXG5cdH07XHJcblx0Ly9mb3IgaW50ZXJuYWwgdGVzdGluZyBvbmx5LCBkbyBub3QgdXNlIGBtLmRlcHMuZmFjdG9yeWBcclxuXHRtLmRlcHMuZmFjdG9yeSA9IGFwcDtcclxuXHJcblx0cmV0dXJuIG1cclxufSkodHlwZW9mIHdpbmRvdyAhPSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xyXG5cclxuaWYgKHR5cGVvZiBtb2R1bGUgIT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUgIT09IG51bGwgJiYgbW9kdWxlLmV4cG9ydHMpIG1vZHVsZS5leHBvcnRzID0gbTtcclxuZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIGRlZmluZShmdW5jdGlvbigpIHtyZXR1cm4gbX0pO1xyXG4iLCIvKiFcbiAqIEV2ZW50RW1pdHRlciB2NC4yLjExIC0gZ2l0LmlvL2VlXG4gKiBVbmxpY2Vuc2UgLSBodHRwOi8vdW5saWNlbnNlLm9yZy9cbiAqIE9saXZlciBDYWxkd2VsbCAtIGh0dHA6Ly9vbGkubWUudWsvXG4gKiBAcHJlc2VydmVcbiAqL1xuXG47KGZ1bmN0aW9uICgpIHtcbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICAvKipcbiAgICAgKiBDbGFzcyBmb3IgbWFuYWdpbmcgZXZlbnRzLlxuICAgICAqIENhbiBiZSBleHRlbmRlZCB0byBwcm92aWRlIGV2ZW50IGZ1bmN0aW9uYWxpdHkgaW4gb3RoZXIgY2xhc3Nlcy5cbiAgICAgKlxuICAgICAqIEBjbGFzcyBFdmVudEVtaXR0ZXIgTWFuYWdlcyBldmVudCByZWdpc3RlcmluZyBhbmQgZW1pdHRpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCkge31cblxuICAgIC8vIFNob3J0Y3V0cyB0byBpbXByb3ZlIHNwZWVkIGFuZCBzaXplXG4gICAgdmFyIHByb3RvID0gRXZlbnRFbWl0dGVyLnByb3RvdHlwZTtcbiAgICB2YXIgZXhwb3J0cyA9IHRoaXM7XG4gICAgdmFyIG9yaWdpbmFsR2xvYmFsVmFsdWUgPSBleHBvcnRzLkV2ZW50RW1pdHRlcjtcblxuICAgIC8qKlxuICAgICAqIEZpbmRzIHRoZSBpbmRleCBvZiB0aGUgbGlzdGVuZXIgZm9yIHRoZSBldmVudCBpbiBpdHMgc3RvcmFnZSBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gbGlzdGVuZXJzIEFycmF5IG9mIGxpc3RlbmVycyB0byBzZWFyY2ggdGhyb3VnaC5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBsaXN0ZW5lciBNZXRob2QgdG8gbG9vayBmb3IuXG4gICAgICogQHJldHVybiB7TnVtYmVyfSBJbmRleCBvZiB0aGUgc3BlY2lmaWVkIGxpc3RlbmVyLCAtMSBpZiBub3QgZm91bmRcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbmRleE9mTGlzdGVuZXIobGlzdGVuZXJzLCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0ubGlzdGVuZXIgPT09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgYSBtZXRob2Qgd2hpbGUga2VlcGluZyB0aGUgY29udGV4dCBjb3JyZWN0LCB0byBhbGxvdyBmb3Igb3ZlcndyaXRpbmcgb2YgdGFyZ2V0IG1ldGhvZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSB0YXJnZXQgbWV0aG9kLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9ufSBUaGUgYWxpYXNlZCBtZXRob2RcbiAgICAgKiBAYXBpIHByaXZhdGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhbGlhcyhuYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBhbGlhc0Nsb3N1cmUoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1tuYW1lXS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGxpc3RlbmVyIGFycmF5IGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIFdpbGwgaW5pdGlhbGlzZSB0aGUgZXZlbnQgb2JqZWN0IGFuZCBsaXN0ZW5lciBhcnJheXMgaWYgcmVxdWlyZWQuXG4gICAgICogV2lsbCByZXR1cm4gYW4gb2JqZWN0IGlmIHlvdSB1c2UgYSByZWdleCBzZWFyY2guIFRoZSBvYmplY3QgY29udGFpbnMga2V5cyBmb3IgZWFjaCBtYXRjaGVkIGV2ZW50LiBTbyAvYmFbcnpdLyBtaWdodCByZXR1cm4gYW4gb2JqZWN0IGNvbnRhaW5pbmcgYmFyIGFuZCBiYXouIEJ1dCBvbmx5IGlmIHlvdSBoYXZlIGVpdGhlciBkZWZpbmVkIHRoZW0gd2l0aCBkZWZpbmVFdmVudCBvciBhZGRlZCBzb21lIGxpc3RlbmVycyB0byB0aGVtLlxuICAgICAqIEVhY2ggcHJvcGVydHkgaW4gdGhlIG9iamVjdCByZXNwb25zZSBpcyBhbiBhcnJheSBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byByZXR1cm4gdGhlIGxpc3RlbmVycyBmcm9tLlxuICAgICAqIEByZXR1cm4ge0Z1bmN0aW9uW118T2JqZWN0fSBBbGwgbGlzdGVuZXIgZnVuY3Rpb25zIGZvciB0aGUgZXZlbnQuXG4gICAgICovXG4gICAgcHJvdG8uZ2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gZ2V0TGlzdGVuZXJzKGV2dCkge1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciByZXNwb25zZTtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICAvLyBSZXR1cm4gYSBjb25jYXRlbmF0ZWQgYXJyYXkgb2YgYWxsIG1hdGNoaW5nIGV2ZW50cyBpZlxuICAgICAgICAvLyB0aGUgc2VsZWN0b3IgaXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAgICAgIGlmIChldnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge307XG4gICAgICAgICAgICBmb3IgKGtleSBpbiBldmVudHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnRzLmhhc093blByb3BlcnR5KGtleSkgJiYgZXZ0LnRlc3Qoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXNwb25zZVtrZXldID0gZXZlbnRzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBldmVudHNbZXZ0XSB8fCAoZXZlbnRzW2V2dF0gPSBbXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFRha2VzIGEgbGlzdCBvZiBsaXN0ZW5lciBvYmplY3RzIGFuZCBmbGF0dGVucyBpdCBpbnRvIGEgbGlzdCBvZiBsaXN0ZW5lciBmdW5jdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdFtdfSBsaXN0ZW5lcnMgUmF3IGxpc3RlbmVyIG9iamVjdHMuXG4gICAgICogQHJldHVybiB7RnVuY3Rpb25bXX0gSnVzdCB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxuICAgICAqL1xuICAgIHByb3RvLmZsYXR0ZW5MaXN0ZW5lcnMgPSBmdW5jdGlvbiBmbGF0dGVuTGlzdGVuZXJzKGxpc3RlbmVycykge1xuICAgICAgICB2YXIgZmxhdExpc3RlbmVycyA9IFtdO1xuICAgICAgICB2YXIgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBmbGF0TGlzdGVuZXJzLnB1c2gobGlzdGVuZXJzW2ldLmxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmbGF0TGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSByZXF1ZXN0ZWQgbGlzdGVuZXJzIHZpYSBnZXRMaXN0ZW5lcnMgYnV0IHdpbGwgYWx3YXlzIHJldHVybiB0aGUgcmVzdWx0cyBpbnNpZGUgYW4gb2JqZWN0LiBUaGlzIGlzIG1haW5seSBmb3IgaW50ZXJuYWwgdXNlIGJ1dCBvdGhlcnMgbWF5IGZpbmQgaXQgdXNlZnVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmV0dXJuIHRoZSBsaXN0ZW5lcnMgZnJvbS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEFsbCBsaXN0ZW5lciBmdW5jdGlvbnMgZm9yIGFuIGV2ZW50IGluIGFuIG9iamVjdC5cbiAgICAgKi9cbiAgICBwcm90by5nZXRMaXN0ZW5lcnNBc09iamVjdCA9IGZ1bmN0aW9uIGdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCkge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgdmFyIHJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChsaXN0ZW5lcnMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSB7fTtcbiAgICAgICAgICAgIHJlc3BvbnNlW2V2dF0gPSBsaXN0ZW5lcnM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgbGlzdGVuZXJzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGEgbGlzdGVuZXIgZnVuY3Rpb24gdG8gdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBUaGUgbGlzdGVuZXIgd2lsbCBub3QgYmUgYWRkZWQgaWYgaXQgaXMgYSBkdXBsaWNhdGUuXG4gICAgICogSWYgdGhlIGxpc3RlbmVyIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBpdCBpcyBjYWxsZWQuXG4gICAgICogSWYgeW91IHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gYXMgdGhlIGV2ZW50IG5hbWUgdGhlbiB0aGUgbGlzdGVuZXIgd2lsbCBiZSBhZGRlZCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBhdHRhY2ggdGhlIGxpc3RlbmVyIHRvLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBjYWxsaW5nLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZExpc3RlbmVyID0gZnVuY3Rpb24gYWRkTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5nZXRMaXN0ZW5lcnNBc09iamVjdChldnQpO1xuICAgICAgICB2YXIgbGlzdGVuZXJJc1dyYXBwZWQgPSB0eXBlb2YgbGlzdGVuZXIgPT09ICdvYmplY3QnO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIGxpc3RlbmVycykge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGluZGV4T2ZMaXN0ZW5lcihsaXN0ZW5lcnNba2V5XSwgbGlzdGVuZXIpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVyc1trZXldLnB1c2gobGlzdGVuZXJJc1dyYXBwZWQgPyBsaXN0ZW5lciA6IHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXI6IGxpc3RlbmVyLFxuICAgICAgICAgICAgICAgICAgICBvbmNlOiBmYWxzZVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIGFkZExpc3RlbmVyXG4gICAgICovXG4gICAgcHJvdG8ub24gPSBhbGlhcygnYWRkTGlzdGVuZXInKTtcblxuICAgIC8qKlxuICAgICAqIFNlbWktYWxpYXMgb2YgYWRkTGlzdGVuZXIuIEl0IHdpbGwgYWRkIGEgbGlzdGVuZXIgdGhhdCB3aWxsIGJlXG4gICAgICogYXV0b21hdGljYWxseSByZW1vdmVkIGFmdGVyIGl0cyBmaXJzdCBleGVjdXRpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBhdHRhY2ggdGhlIGxpc3RlbmVyIHRvLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgZW1pdHRlZC4gSWYgdGhlIGZ1bmN0aW9uIHJldHVybnMgdHJ1ZSB0aGVuIGl0IHdpbGwgYmUgcmVtb3ZlZCBhZnRlciBjYWxsaW5nLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmFkZE9uY2VMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZE9uY2VMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFkZExpc3RlbmVyKGV2dCwge1xuICAgICAgICAgICAgbGlzdGVuZXI6IGxpc3RlbmVyLFxuICAgICAgICAgICAgb25jZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgYWRkT25jZUxpc3RlbmVyLlxuICAgICAqL1xuICAgIHByb3RvLm9uY2UgPSBhbGlhcygnYWRkT25jZUxpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBEZWZpbmVzIGFuIGV2ZW50IG5hbWUuIFRoaXMgaXMgcmVxdWlyZWQgaWYgeW91IHdhbnQgdG8gdXNlIGEgcmVnZXggdG8gYWRkIGEgbGlzdGVuZXIgdG8gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIElmIHlvdSBkb24ndCBkbyB0aGlzIHRoZW4gaG93IGRvIHlvdSBleHBlY3QgaXQgdG8ga25vdyB3aGF0IGV2ZW50IHRvIGFkZCB0bz8gU2hvdWxkIGl0IGp1c3QgYWRkIHRvIGV2ZXJ5IHBvc3NpYmxlIG1hdGNoIGZvciBhIHJlZ2V4PyBOby4gVGhhdCBpcyBzY2FyeSBhbmQgYmFkLlxuICAgICAqIFlvdSBuZWVkIHRvIHRlbGwgaXQgd2hhdCBldmVudCBuYW1lcyBzaG91bGQgYmUgbWF0Y2hlZCBieSBhIHJlZ2V4LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBjcmVhdGUuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uZGVmaW5lRXZlbnQgPSBmdW5jdGlvbiBkZWZpbmVFdmVudChldnQpIHtcbiAgICAgICAgdGhpcy5nZXRMaXN0ZW5lcnMoZXZ0KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFVzZXMgZGVmaW5lRXZlbnQgdG8gZGVmaW5lIG11bHRpcGxlIGV2ZW50cy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nW119IGV2dHMgQW4gYXJyYXkgb2YgZXZlbnQgbmFtZXMgdG8gZGVmaW5lLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLmRlZmluZUV2ZW50cyA9IGZ1bmN0aW9uIGRlZmluZUV2ZW50cyhldnRzKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZXZ0cy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgdGhpcy5kZWZpbmVFdmVudChldnRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIGZyb20gdGhlIHNwZWNpZmllZCBldmVudC5cbiAgICAgKiBXaGVuIHBhc3NlZCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBhcyB0aGUgZXZlbnQgbmFtZSwgaXQgd2lsbCByZW1vdmUgdGhlIGxpc3RlbmVyIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8UmVnRXhwfSBldnQgTmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lciBmcm9tLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyIE1ldGhvZCB0byByZW1vdmUgZnJvbSB0aGUgZXZlbnQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlTGlzdGVuZXIgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcihldnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBpbmRleDtcbiAgICAgICAgdmFyIGtleTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gaW5kZXhPZkxpc3RlbmVyKGxpc3RlbmVyc1trZXldLCBsaXN0ZW5lcik7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyc1trZXldLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHJlbW92ZUxpc3RlbmVyXG4gICAgICovXG4gICAgcHJvdG8ub2ZmID0gYWxpYXMoJ3JlbW92ZUxpc3RlbmVyJyk7XG5cbiAgICAvKipcbiAgICAgKiBBZGRzIGxpc3RlbmVycyBpbiBidWxrIHVzaW5nIHRoZSBtYW5pcHVsYXRlTGlzdGVuZXJzIG1ldGhvZC5cbiAgICAgKiBJZiB5b3UgcGFzcyBhbiBvYmplY3QgYXMgdGhlIHNlY29uZCBhcmd1bWVudCB5b3UgY2FuIGFkZCB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgaXQgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gYWRkIHRoZSBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqIFllYWgsIHRoaXMgZnVuY3Rpb24gZG9lcyBxdWl0ZSBhIGJpdC4gVGhhdCdzIHByb2JhYmx5IGEgYmFkIHRoaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZCB0byBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8uYWRkTGlzdGVuZXJzID0gZnVuY3Rpb24gYWRkTGlzdGVuZXJzKGV2dCwgbGlzdGVuZXJzKSB7XG4gICAgICAgIC8vIFBhc3MgdGhyb3VnaCB0byBtYW5pcHVsYXRlTGlzdGVuZXJzXG4gICAgICAgIHJldHVybiB0aGlzLm1hbmlwdWxhdGVMaXN0ZW5lcnMoZmFsc2UsIGV2dCwgbGlzdGVuZXJzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBsaXN0ZW5lcnMgaW4gYnVsayB1c2luZyB0aGUgbWFuaXB1bGF0ZUxpc3RlbmVycyBtZXRob2QuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiByZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS4gVGhlIG9iamVjdCBzaG91bGQgY29udGFpbiBrZXkgdmFsdWUgcGFpcnMgb2YgZXZlbnRzIGFuZCBsaXN0ZW5lcnMgb3IgbGlzdGVuZXIgYXJyYXlzLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGFuIGV2ZW50IG5hbWUgYW5kIGFuIGFycmF5IG9mIGxpc3RlbmVycyB0byBiZSByZW1vdmVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGl0IGEgcmVndWxhciBleHByZXNzaW9uIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXJzIGZyb20gYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIHJlbW92ZSBmcm9tIG11bHRpcGxlIGV2ZW50cyBhdCBvbmNlLlxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb25bXX0gW2xpc3RlbmVyc10gQW4gb3B0aW9uYWwgYXJyYXkgb2YgbGlzdGVuZXIgZnVuY3Rpb25zIHRvIHJlbW92ZS5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5yZW1vdmVMaXN0ZW5lcnMgPSBmdW5jdGlvbiByZW1vdmVMaXN0ZW5lcnMoZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgLy8gUGFzcyB0aHJvdWdoIHRvIG1hbmlwdWxhdGVMaXN0ZW5lcnNcbiAgICAgICAgcmV0dXJuIHRoaXMubWFuaXB1bGF0ZUxpc3RlbmVycyh0cnVlLCBldnQsIGxpc3RlbmVycyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEVkaXRzIGxpc3RlbmVycyBpbiBidWxrLiBUaGUgYWRkTGlzdGVuZXJzIGFuZCByZW1vdmVMaXN0ZW5lcnMgbWV0aG9kcyBib3RoIHVzZSB0aGlzIHRvIGRvIHRoZWlyIGpvYi4gWW91IHNob3VsZCByZWFsbHkgdXNlIHRob3NlIGluc3RlYWQsIHRoaXMgaXMgYSBsaXR0bGUgbG93ZXIgbGV2ZWwuXG4gICAgICogVGhlIGZpcnN0IGFyZ3VtZW50IHdpbGwgZGV0ZXJtaW5lIGlmIHRoZSBsaXN0ZW5lcnMgYXJlIHJlbW92ZWQgKHRydWUpIG9yIGFkZGVkIChmYWxzZSkuXG4gICAgICogSWYgeW91IHBhc3MgYW4gb2JqZWN0IGFzIHRoZSBzZWNvbmQgYXJndW1lbnQgeW91IGNhbiBhZGQvcmVtb3ZlIGZyb20gbXVsdGlwbGUgZXZlbnRzIGF0IG9uY2UuIFRoZSBvYmplY3Qgc2hvdWxkIGNvbnRhaW4ga2V5IHZhbHVlIHBhaXJzIG9mIGV2ZW50cyBhbmQgbGlzdGVuZXJzIG9yIGxpc3RlbmVyIGFycmF5cy5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhbiBldmVudCBuYW1lIGFuZCBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgdG8gYmUgYWRkZWQvcmVtb3ZlZC5cbiAgICAgKiBZb3UgY2FuIGFsc28gcGFzcyBpdCBhIHJlZ3VsYXIgZXhwcmVzc2lvbiB0byBtYW5pcHVsYXRlIHRoZSBsaXN0ZW5lcnMgb2YgYWxsIGV2ZW50cyB0aGF0IG1hdGNoIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtCb29sZWFufSByZW1vdmUgVHJ1ZSBpZiB5b3Ugd2FudCB0byByZW1vdmUgbGlzdGVuZXJzLCBmYWxzZSBpZiB5b3Ugd2FudCB0byBhZGQuXG4gICAgICogQHBhcmFtIHtTdHJpbmd8T2JqZWN0fFJlZ0V4cH0gZXZ0IEFuIGV2ZW50IG5hbWUgaWYgeW91IHdpbGwgcGFzcyBhbiBhcnJheSBvZiBsaXN0ZW5lcnMgbmV4dC4gQW4gb2JqZWN0IGlmIHlvdSB3aXNoIHRvIGFkZC9yZW1vdmUgZnJvbSBtdWx0aXBsZSBldmVudHMgYXQgb25jZS5cbiAgICAgKiBAcGFyYW0ge0Z1bmN0aW9uW119IFtsaXN0ZW5lcnNdIEFuIG9wdGlvbmFsIGFycmF5IG9mIGxpc3RlbmVyIGZ1bmN0aW9ucyB0byBhZGQvcmVtb3ZlLlxuICAgICAqIEByZXR1cm4ge09iamVjdH0gQ3VycmVudCBpbnN0YW5jZSBvZiBFdmVudEVtaXR0ZXIgZm9yIGNoYWluaW5nLlxuICAgICAqL1xuICAgIHByb3RvLm1hbmlwdWxhdGVMaXN0ZW5lcnMgPSBmdW5jdGlvbiBtYW5pcHVsYXRlTGlzdGVuZXJzKHJlbW92ZSwgZXZ0LCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciB2YWx1ZTtcbiAgICAgICAgdmFyIHNpbmdsZSA9IHJlbW92ZSA/IHRoaXMucmVtb3ZlTGlzdGVuZXIgOiB0aGlzLmFkZExpc3RlbmVyO1xuICAgICAgICB2YXIgbXVsdGlwbGUgPSByZW1vdmUgPyB0aGlzLnJlbW92ZUxpc3RlbmVycyA6IHRoaXMuYWRkTGlzdGVuZXJzO1xuXG4gICAgICAgIC8vIElmIGV2dCBpcyBhbiBvYmplY3QgdGhlbiBwYXNzIGVhY2ggb2YgaXRzIHByb3BlcnRpZXMgdG8gdGhpcyBtZXRob2RcbiAgICAgICAgaWYgKHR5cGVvZiBldnQgPT09ICdvYmplY3QnICYmICEoZXZ0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgZm9yIChpIGluIGV2dCkge1xuICAgICAgICAgICAgICAgIGlmIChldnQuaGFzT3duUHJvcGVydHkoaSkgJiYgKHZhbHVlID0gZXZ0W2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQYXNzIHRoZSBzaW5nbGUgbGlzdGVuZXIgc3RyYWlnaHQgdGhyb3VnaCB0byB0aGUgc2luZ3VsYXIgbWV0aG9kXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBwYXNzIGJhY2sgdG8gdGhlIG11bHRpcGxlIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZS5jYWxsKHRoaXMsIGksIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNvIGV2dCBtdXN0IGJlIGEgc3RyaW5nXG4gICAgICAgICAgICAvLyBBbmQgbGlzdGVuZXJzIG11c3QgYmUgYW4gYXJyYXkgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAvLyBMb29wIG92ZXIgaXQgYW5kIHBhc3MgZWFjaCBvbmUgdG8gdGhlIG11bHRpcGxlIG1ldGhvZFxuICAgICAgICAgICAgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgc2luZ2xlLmNhbGwodGhpcywgZXZ0LCBsaXN0ZW5lcnNbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyBmcm9tIGEgc3BlY2lmaWVkIGV2ZW50LlxuICAgICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhbiBldmVudCB0aGVuIGFsbCBsaXN0ZW5lcnMgd2lsbCBiZSByZW1vdmVkLlxuICAgICAqIFRoYXQgbWVhbnMgZXZlcnkgZXZlbnQgd2lsbCBiZSBlbXB0aWVkLlxuICAgICAqIFlvdSBjYW4gYWxzbyBwYXNzIGEgcmVnZXggdG8gcmVtb3ZlIGFsbCBldmVudHMgdGhhdCBtYXRjaCBpdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gW2V2dF0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGFsbCBsaXN0ZW5lcnMgZm9yLiBXaWxsIHJlbW92ZSBmcm9tIGV2ZXJ5IGV2ZW50IGlmIG5vdCBwYXNzZWQuXG4gICAgICogQHJldHVybiB7T2JqZWN0fSBDdXJyZW50IGluc3RhbmNlIG9mIEV2ZW50RW1pdHRlciBmb3IgY2hhaW5pbmcuXG4gICAgICovXG4gICAgcHJvdG8ucmVtb3ZlRXZlbnQgPSBmdW5jdGlvbiByZW1vdmVFdmVudChldnQpIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgZXZ0O1xuICAgICAgICB2YXIgZXZlbnRzID0gdGhpcy5fZ2V0RXZlbnRzKCk7XG4gICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGRpZmZlcmVudCB0aGluZ3MgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZSBvZiBldnRcbiAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgYWxsIGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudFxuICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1tldnRdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGV2dCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBldmVudHMgbWF0Y2hpbmcgdGhlIHJlZ2V4LlxuICAgICAgICAgICAgZm9yIChrZXkgaW4gZXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50cy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIGV2dC50ZXN0KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGV2ZW50c1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgbGlzdGVuZXJzIGluIGFsbCBldmVudHNcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgcmVtb3ZlRXZlbnQuXG4gICAgICpcbiAgICAgKiBBZGRlZCB0byBtaXJyb3IgdGhlIG5vZGUgQVBJLlxuICAgICAqL1xuICAgIHByb3RvLnJlbW92ZUFsbExpc3RlbmVycyA9IGFsaWFzKCdyZW1vdmVFdmVudCcpO1xuXG4gICAgLyoqXG4gICAgICogRW1pdHMgYW4gZXZlbnQgb2YgeW91ciBjaG9pY2UuXG4gICAgICogV2hlbiBlbWl0dGVkLCBldmVyeSBsaXN0ZW5lciBhdHRhY2hlZCB0byB0aGF0IGV2ZW50IHdpbGwgYmUgZXhlY3V0ZWQuXG4gICAgICogSWYgeW91IHBhc3MgdGhlIG9wdGlvbmFsIGFyZ3VtZW50IGFycmF5IHRoZW4gdGhvc2UgYXJndW1lbnRzIHdpbGwgYmUgcGFzc2VkIHRvIGV2ZXJ5IGxpc3RlbmVyIHVwb24gZXhlY3V0aW9uLlxuICAgICAqIEJlY2F1c2UgaXQgdXNlcyBgYXBwbHlgLCB5b3VyIGFycmF5IG9mIGFyZ3VtZW50cyB3aWxsIGJlIHBhc3NlZCBhcyBpZiB5b3Ugd3JvdGUgdGhlbSBvdXQgc2VwYXJhdGVseS5cbiAgICAgKiBTbyB0aGV5IHdpbGwgbm90IGFycml2ZSB3aXRoaW4gdGhlIGFycmF5IG9uIHRoZSBvdGhlciBzaWRlLCB0aGV5IHdpbGwgYmUgc2VwYXJhdGUuXG4gICAgICogWW91IGNhbiBhbHNvIHBhc3MgYSByZWd1bGFyIGV4cHJlc3Npb24gdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHtBcnJheX0gW2FyZ3NdIE9wdGlvbmFsIGFycmF5IG9mIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0RXZlbnQgPSBmdW5jdGlvbiBlbWl0RXZlbnQoZXZ0LCBhcmdzKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnNNYXAgPSB0aGlzLmdldExpc3RlbmVyc0FzT2JqZWN0KGV2dCk7XG4gICAgICAgIHZhciBsaXN0ZW5lcnM7XG4gICAgICAgIHZhciBsaXN0ZW5lcjtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIHZhciBrZXk7XG4gICAgICAgIHZhciByZXNwb25zZTtcblxuICAgICAgICBmb3IgKGtleSBpbiBsaXN0ZW5lcnNNYXApIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNNYXAuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVyc01hcFtrZXldLnNsaWNlKDApO1xuICAgICAgICAgICAgICAgIGkgPSBsaXN0ZW5lcnMubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbGlzdGVuZXIgcmV0dXJucyB0cnVlIHRoZW4gaXQgc2hhbGwgYmUgcmVtb3ZlZCBmcm9tIHRoZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgZnVuY3Rpb24gaXMgZXhlY3V0ZWQgZWl0aGVyIHdpdGggYSBiYXNpYyBjYWxsIG9yIGFuIGFwcGx5IGlmIHRoZXJlIGlzIGFuIGFyZ3MgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyLm9uY2UgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGxpc3RlbmVyLmxpc3RlbmVyLmFwcGx5KHRoaXMsIGFyZ3MgfHwgW10pO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSA9PT0gdGhpcy5fZ2V0T25jZVJldHVyblZhbHVlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIoZXZ0LCBsaXN0ZW5lci5saXN0ZW5lcik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgZW1pdEV2ZW50XG4gICAgICovXG4gICAgcHJvdG8udHJpZ2dlciA9IGFsaWFzKCdlbWl0RXZlbnQnKTtcblxuICAgIC8qKlxuICAgICAqIFN1YnRseSBkaWZmZXJlbnQgZnJvbSBlbWl0RXZlbnQgaW4gdGhhdCBpdCB3aWxsIHBhc3MgaXRzIGFyZ3VtZW50cyBvbiB0byB0aGUgbGlzdGVuZXJzLCBhcyBvcHBvc2VkIHRvIHRha2luZyBhIHNpbmdsZSBhcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyBvbi5cbiAgICAgKiBBcyB3aXRoIGVtaXRFdmVudCwgeW91IGNhbiBwYXNzIGEgcmVnZXggaW4gcGxhY2Ugb2YgdGhlIGV2ZW50IG5hbWUgdG8gZW1pdCB0byBhbGwgZXZlbnRzIHRoYXQgbWF0Y2ggaXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV2dCBOYW1lIG9mIHRoZSBldmVudCB0byBlbWl0IGFuZCBleGVjdXRlIGxpc3RlbmVycyBmb3IuXG4gICAgICogQHBhcmFtIHsuLi4qfSBPcHRpb25hbCBhZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBiZSBwYXNzZWQgdG8gZWFjaCBsaXN0ZW5lci5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5lbWl0ID0gZnVuY3Rpb24gZW1pdChldnQpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5lbWl0RXZlbnQoZXZ0LCBhcmdzKTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSB0byBjaGVjayBhZ2FpbnN0IHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy4gSWYgYVxuICAgICAqIGxpc3RlbmVycyByZXR1cm4gdmFsdWUgbWF0Y2hlcyB0aGUgb25lIHNldCBoZXJlIHRoZW4gaXQgd2lsbCBiZSByZW1vdmVkXG4gICAgICogYWZ0ZXIgZXhlY3V0aW9uLiBUaGlzIHZhbHVlIGRlZmF1bHRzIHRvIHRydWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gY2hlY2sgZm9yIHdoZW4gZXhlY3V0aW5nIGxpc3RlbmVycy5cbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IEN1cnJlbnQgaW5zdGFuY2Ugb2YgRXZlbnRFbWl0dGVyIGZvciBjaGFpbmluZy5cbiAgICAgKi9cbiAgICBwcm90by5zZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBzZXRPbmNlUmV0dXJuVmFsdWUodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fb25jZVJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBGZXRjaGVzIHRoZSBjdXJyZW50IHZhbHVlIHRvIGNoZWNrIGFnYWluc3Qgd2hlbiBleGVjdXRpbmcgbGlzdGVuZXJzLiBJZlxuICAgICAqIHRoZSBsaXN0ZW5lcnMgcmV0dXJuIHZhbHVlIG1hdGNoZXMgdGhpcyBvbmUgdGhlbiBpdCBzaG91bGQgYmUgcmVtb3ZlZFxuICAgICAqIGF1dG9tYXRpY2FsbHkuIEl0IHdpbGwgcmV0dXJuIHRydWUgYnkgZGVmYXVsdC5cbiAgICAgKlxuICAgICAqIEByZXR1cm4geyp8Qm9vbGVhbn0gVGhlIGN1cnJlbnQgdmFsdWUgdG8gY2hlY2sgZm9yIG9yIHRoZSBkZWZhdWx0LCB0cnVlLlxuICAgICAqIEBhcGkgcHJpdmF0ZVxuICAgICAqL1xuICAgIHByb3RvLl9nZXRPbmNlUmV0dXJuVmFsdWUgPSBmdW5jdGlvbiBfZ2V0T25jZVJldHVyblZhbHVlKCkge1xuICAgICAgICBpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eSgnX29uY2VSZXR1cm5WYWx1ZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb25jZVJldHVyblZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogRmV0Y2hlcyB0aGUgZXZlbnRzIG9iamVjdCBhbmQgY3JlYXRlcyBvbmUgaWYgcmVxdWlyZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBldmVudHMgc3RvcmFnZSBvYmplY3QuXG4gICAgICogQGFwaSBwcml2YXRlXG4gICAgICovXG4gICAgcHJvdG8uX2dldEV2ZW50cyA9IGZ1bmN0aW9uIF9nZXRFdmVudHMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ldmVudHMgfHwgKHRoaXMuX2V2ZW50cyA9IHt9KTtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogUmV2ZXJ0cyB0aGUgZ2xvYmFsIHtAbGluayBFdmVudEVtaXR0ZXJ9IHRvIGl0cyBwcmV2aW91cyB2YWx1ZSBhbmQgcmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGlzIHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gTm9uIGNvbmZsaWN0aW5nIEV2ZW50RW1pdHRlciBjbGFzcy5cbiAgICAgKi9cbiAgICBFdmVudEVtaXR0ZXIubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gb3JpZ2luYWxHbG9iYWxWYWx1ZTtcbiAgICAgICAgcmV0dXJuIEV2ZW50RW1pdHRlcjtcbiAgICB9O1xuXG4gICAgLy8gRXhwb3NlIHRoZSBjbGFzcyBlaXRoZXIgdmlhIEFNRCwgQ29tbW9uSlMgb3IgdGhlIGdsb2JhbCBvYmplY3RcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gRXZlbnRFbWl0dGVyO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpe1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGV4cG9ydHMuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuICAgIH1cbn0uY2FsbCh0aGlzKSk7XG4iXX0=
assets/js/admin.min.js CHANGED
@@ -1 +1 @@
1
- !function(a){"use strict";function b(){"boolean"==typeof this.checked&&(this.checked=!1),alert(mc4wp.strings.proOnlyNotice),event.stopPropagation()}function c(){var b=a(document.getElementById("mc4wp-send-welcome"));0==a(this).val()?b.removeClass("hidden").find(":input").removeAttr("disabled"):b.addClass("hidden").find(":input").attr("disabled","disabled").prop("checked",!1)}function d(){var b=a(document.getElementById("woocommerce-settings"));b.toggle(this.checked)}function e(){var b=i.filter(":checked").length>0;a(".mc4wp-notice.no-lists-selected").toggle(!b),a(document.getElementById("mc4wp-fw-mailchimp-fields")).toggle(b)}function f(b){var c=b.keyCode||b.which;if(9===c){b.preventDefault();var d=this.selectionStart,e=this.selectionEnd;a(this).val(a(this).val().substring(0,d)+" "+a(this).val().substring(e)),this.selectionStart=this.selectionEnd=d+1}}function g(){"undefined"!=typeof QTags&&(QTags.addButton("mc4wp_paragraph","<p>","<p>","</p>","paragraph","Paragraph tag",1),QTags.addButton("mc4wp_label","label","<label>","</label>","label","Label tag",2),QTags.addButton("mc4wp_response","form response","{response}","","response","Shows the form response"),QTags.addButton("mc4wp_subscriber_count","# of subscribers","{subscriber_count}","","subscribers","Shows number of subscribers of selected list(s)"),window.mc4wp.hasCaptchaPlugin===!0&&QTags.addButton("mc4wp_captcha","CAPTCHA","{captcha}","","captcha","Display a CAPTCHA field"))}var h=a(document.getElementById("mc4wp-admin")),i=a(document.getElementById("mc4wp-lists")).find(":input"),j=a(document.getElementById("mc4wpformmarkup")),k=a(document.getElementById("missing-fields-notice")),l=a(document.getElementById("missing-fields-list"));h.find(".pro-feature, .pro-feature label, .pro-feature :radio").click(b),h.find('input[name$="[double_optin]"]').change(c),h.find('input[name$="[show_at_woocommerce_checkout]"]').change(d),i.change(e),a(document).delegate("#mc4wpformmarkup","keydown",f),g(),function(){function b(){for(var b={},c=0;c<H.length;c++){var d='name="'+H[c].tag.toLowerCase();-1==j.val().toLowerCase().indexOf(d)&&(b[H[c].tag]=H[c])}if(a.isEmptyObject(b))return void k.hide();l.html("");for(var e in b){var f=b[e],g=a("<li></li>");g.html(f.name+" (<code>"+f.tag+"</code>)"),g.appendTo(l)}k.show()}function c(){u.find("option").not(".default").remove(),H=[],t.filter(":checked").each(function(){for(var b=a(this).val(),c=mc4wp.mailchimpLists[b],d=0,e=c.merge_vars.length;e>d;d++){var f=c.merge_vars[d];if(f.req&&H.push(f),0===v.children("option[value='"+f.tag+"']").length){var g=f.name.length>25?f.name.substring(0,25)+"..":f.name;f.req&&(g+="*");var h=a("<option />").text(g).val(f.tag).data("list-field",f);v.append(h)}}for(var d=0,i=c.interest_groupings.length;i>d;d++){var j=c.interest_groupings[d];if(0===w.children("option[value='"+j.id+"']").length){var g=j.name.length>25?j.name.substring(0,25)+"..":j.name,h=a("<option />").text(g).val(j.id).data("list-grouping",j);d>=1&&h.text(G.proOnly+" "+g).attr("disabled","disabled").data("list-grouping",null),w.append(h)}}}),b()}function d(){e();var b=a(this).find(":selected");switch(b.val()){case"_action":r="action",x.find(".wrap-p").show();break;case"submit":r="submit",z.text(G.buttonText),y.val(G.subscribe),x.find("p.row").filter(".value, .wrap-p").show();break;case"lists":r="lists",x.find(".wrap-p").show();break;default:var c=b.data("list-field");if(c)return m(c);var c=b.data("list-grouping");if(c)return g(c)}o()}function e(){x.find(".row :input").each(function(){a(this).is(":checkbox")?this.checked=!0:this.value=""}),x.find("p.row").hide(),A.find(":input").remove(),x.show(),r="text",s="",z.html(G.initialValue+" <small>"+G.optional+"</small>")}function f(b){for(var c=0,d=b.length;d>c;c++)a("<input />").attr("type","text").addClass("widefat").data("value",b[c].name).attr("placeholder",G.labelFor+' "'+b[c].name+'" '+G.orLeaveEmpty).attr("value",b[c].name).appendTo(A)}function g(a){switch(x.find("p.row").filter(".values, .label, .wrap-p").show(),B.val(a.name+":"),s="GROUPINGS["+a.id+"]",f(a.groups),a.form_field){case"radio":r="radio";break;case"hidden":x.find("p.row").filter(".values, .label, .wrap-p").hide(),x.find("p.row.value").show();for(var b=0,c=a.groups.length;c>b;b++)y.val(y.val()+a.groups[b].name+",");r="hidden";break;case"dropdown":r="select";break;default:r="checkbox",s+="[]"}o()}function h(){var b="";return t.each(function(){var c=a(this).val(),d=a(this).parent("label").text(),e="";a(this).is(":checked")&&(e+="checked "),b+="<label>\n",b+=' <input type="checkbox" name="_mc4wp_lists[]" value="'+c+'" '+e+" /> "+d+"\n",b+="</label>\n"}),b}function i(){for(var a=[{name:"subscribe",label:G.subscribe,checked:!0},{name:"unsubscribe",label:G.unsubscribe,checked:!1}],b="",c=0;c<a.length;c++){var d=a[c];b+="<label>\n",b+=' <input type="radio" name="_mc4wp_action" value="'+d.name+'" '+(d.checked?"checked":"")+" > "+d.label+"\n",b+="</label>\n"}return b}function m(b){var c={"default":["label","value","placeholder","required","wrap-p"],select:["label","required","wrap-p","values"],radio:["label","required","wrap-p","values"],date:["label","required","wrap-p","value"]},d={text:"text",email:"email",phone:"tel",address:"text",number:"number",dropdown:"select",date:"date",birthday:"date",radio:"radio",checkbox:"checkbox",url:"url"};if(r="undefined"!=typeof d[b.field_type]?d[b.field_type]:"text","undefined"!=typeof c[r])var e=c[r];else var e=c["default"];for(var f=0;f<e.length;f++)x.find("p.row."+e[f]).show();if(r=r,s=b.tag,C.val("Your "+b.name.toLowerCase()),B.val(b.name+":"),D.prop("checked",b.req),A.is(":visible")&&b.choices)for(var f=0;f<b.choices.length;f++)a("<input />").attr("type","text").addClass("widefat").data("value",b.choices[f]).attr("placeholder",G.labelFor+' "'+b.choices[f]+'" '+G.orLeaveEmpty).attr("value",b.choices[f]).appendTo(A);o()}function n(a){a=html_beautify(a),F.val(a)}function o(){var b,c=a("<div></div>");switch(r){case"action":var d=i();return q()&&(d="<p>"+d+"</p>"),n(d);case"lists":var d=h();return q()&&(d="<p>"+d+"</p>"),n(d);case"select":b=a("<select />"),A.find(":input").each(function(){a(this).val().length>0&&a("<option />").val(a(this).data("value")).text(a(this).val()).appendTo(b)});break;case"radio":case"checkbox":A.find(":input").each(function(){a(this).val().length>0&&(b=a("<input />").attr("type",r).attr("name",s).val(a(this).data("value")),D.is(":visible:checked")&&b.attr("required",!0),c.append(b),b.wrap("<label />"),a("<span />").text(a(this).val()+" ").insertAfter(b))});break;case"textarea":b=a("<textarea />");break;default:b=a("<input />").attr("type",r)}"radio"!==r&&"checkbox"!==r&&(s.length>0&&b.attr("name",s),y.is(":visible")&&y.val().length>0&&("textarea"===r?b.text(y.val()):b.attr("value",y.val())),C.is(":visible")&&C.val().length>0&&b.attr("placeholder",C.val()),D.is(":visible:checked")&&b.attr("required",!0),c.append(b)),B.is(":visible")&&B.val().length>0&&a("<label />").text(B.val()).prependTo(c),q()&&c.wrapInner(a("<p />")),n(c.html())}function p(){var a=!1;"undefined"!=typeof wpActiveEditor&&"undefined"!=typeof QTags&&QTags.insertContent&&(a=QTags.insertContent(F.val())),a||j.val(j.val()+"\n"+F.val()),j.change()}function q(){return E.is(":visible:checked")?!0:!1}var r,s,t=a("#mc4wp-lists :input"),u=a("#mc4wp-fw-mailchimp-fields"),v=u.find(".merge-fields"),w=u.find(".groupings"),x=a("#mc4wp-fw-fields"),y=a("#mc4wp-fw-value"),z=a("#mc4wp-fw-value-label"),A=a("#mc4wp-fw-values"),B=a("#mc4wp-fw-label"),C=a("#mc4wp-fw-placeholder"),D=a("#mc4wp-fw-required"),E=a("#mc4wp-fw-wrap-p"),F=a("#mc4wp-fw-preview"),G=mc4wp.strings.fieldWizard,H=[];t.change(c),u.change(d),x.change(o),a("#mc4wp-fw-add-to-form").click(p),j.bind({input:function(){j.unbind("keydown"),b.call(this)},keydown:b}),c()}()}(jQuery);
1
+ !function e(t,n,r){function o(a,l){if(!n[a]){if(!t[a]){var s="function"==typeof require&&require;if(!l&&s)return s(a,!0);if(i)return i(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var c=n[a]={exports:{}};t[a][0].call(c.exports,function(e){var n=t[a][1][e];return o(n?n:e)},c,c.exports,e,t,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(e,t,n){"use strict";var r=e("mithril"),o=e("wolfy87-eventemitter"),i=document.getElementById("mc4wp-admin"),a=new o,l=e("./admin/tabs.js")(i),s=e("./admin/helpers.js"),u=e("./admin/settings.js")(i,s,a);window.mc4wp=window.mc4wp||{},window.mc4wp.deps=window.mc4wp.deps||{},window.mc4wp.deps.mithril=r,window.mc4wp.helpers=s,window.mc4wp.events=a,window.mc4wp.settings=u,window.mc4wp.tabs=l},{"./admin/helpers.js":2,"./admin/settings.js":3,"./admin/tabs.js":4,mithril:6,"wolfy87-eventemitter":7}],2:[function(e,t,n){"use strict";var r={};r.toggleElement=function(e){for(var t=document.querySelectorAll(e),n=0;n<t.length;n++){var r=t[n].clientHeight<=0;t[n].style.display=r?"":"none"}},r.bindEventToElement=function(e,t,n){e.addEventListener?e.addEventListener(t,n):e.attachEvent&&e.attachEvent("on"+t,n)},r.bindEventToElements=function(e,t,n){Array.prototype.forEach.call(e,function(e){r.bindEventToElement(e,t,n)})},function(){var e=document.querySelectorAll("[data-showif]");Array.prototype.forEach.call(e,function(e){function t(){if("boolean"!=typeof this.checked||this.checked){var t=this.value==n.value;e.style.display=t?"":"none",e.style.visibility=t?"":"hidden",Array.prototype.forEach.call(i,function(e){e.disabled=!t})}}var n=JSON.parse(e.getAttribute("data-showif")),o=document.querySelectorAll('[name="'+n.element+'"]'),i=e.querySelectorAll("input");Array.prototype.forEach.call(o,function(e){t.call(e)}),r.bindEventToElements(o,"change",t)})}(),t.exports=r},{}],3:[function(e,t,n){var r=function(e,t,n){"use strict";function r(e,t){return h.filter(function(n){return n[e]===t})}function o(){return h}function i(){return h=[],Array.prototype.forEach.call(f,function(e){("boolean"!=typeof e.checked||e.checked)&&"object"==typeof d[e.value]&&h.push(d[e.value])}),n.trigger("selectedLists.change",[h]),h}function a(){var e=document.querySelectorAll(".lists--only-selected > *");Array.prototype.forEach.call(e,function(e){var t=e.getAttribute("data-list-id"),n=r("id",t).length>0;n?e.setAttribute("class",e.getAttribute("class").replace("hidden","")):e.setAttribute("class",e.getAttribute("class")+" hidden")})}function l(e){if(s){e=e||window.event;var t="It looks like you have been editing something. If you leave before saving, your changes will be lost.";return e.returnValue=t,t}}var s=!1,u=0,c=e.querySelector("form"),f=e.querySelectorAll(".mc4wp-list-input"),d=mc4wp_vars.mailchimp.lists,h=[];return n.on("selectedLists.change",a),t.bindEventToElements(f,"change",i),c&&c.elements.length>10&&(t.bindEventToElement(c,"change",function(){u++,u>5&&(s=!0)}),t.bindEventToElement(c,"submit",function(){s=!1,u=0}),t.bindEventToElement(window,"beforeunload",l)),i(),{getSelectedLists:o}};t.exports=r},{}],4:[function(e,t,n){var r=function(t){"use strict";function n(e){for(var t=0;t<h.length;t++)if(h[t].id===e)return h[t]}function r(e,t){if("string"==typeof e&&(e=n(e)),!e)return!1;void 0==t&&(t=!0),c.removeClass("tab-active").css("display","none"),f.removeClass("nav-tab-active"),Array.prototype.forEach.call(e.nav,function(e){e.className+=" nav-tab-active",e.blur()}),e.element.style.display="block",e.element.className+=" tab-active";var r=s.setParameter(window.location.href,"tab",e.id);return history.pushState&&t&&history.pushState(e.id,"",r),o(e),d.value=r,"function"==typeof tb_remove&&tb_remove(),"fields"===e.id&&window.mc4wp&&window.mc4wp.forms&&window.mc4wp.forms.editor&&mc4wp.forms.editor.refresh(),!0}function o(e){var t=document.title.split("-");document.title=document.title.replace(t[0],e.title+" ")}function i(e){e=e||window.event;var t=this.getAttribute("data-tab");if(!t){var n=this.className.match(/nav-tab-(\w+)?/);n&&(t=n[1])}if(!t){var o=s.parse(this.href);if(!o.tab)return;t=o.tab}var i=r(t);return i?(e.preventDefault(),e.returnValue=!1,!1):!0}function a(){if(history.pushState){var e=c.filter(":visible").get(0);if(e){var t=n(e.id.substring(4));t&&(history.replaceState&&null===history.state&&history.replaceState(t.id,""),o(t))}}}var l=window.jQuery,s=e("./url.js"),u=l(t),c=u.find(".tab"),f=u.find(".nav-tab"),d=t.querySelector('input[name="_wp_http_referer"]'),h=[];return l.each(c,function(e,n){var o=n.id.substring(4),i=l(n).find("h2").first().text();h.push({id:o,title:i,element:n,nav:t.querySelectorAll(".nav-tab-"+o),open:function(){return r(o)}})}),f.click(i),l(document.body).on("click",".tab-link",i),a(),window.addEventListener&&history.pushState&&window.addEventListener("popstate",function(e){if(!e.state)return!0;var t=e.state;return r(t,!1)}),{open:r,get:n}};t.exports=r},{"./url.js":5}],5:[function(e,t,n){"use strict";var r={parse:function(e){var t={},n=e.split("&");for(var r in n)if(n.hasOwnProperty(r)){var o=n[r].split("=");t[decodeURIComponent(o[0])]=decodeURIComponent(o[1])}return t},build:function(e){var t=[];for(var n in e)t.push(n+"="+encodeURIComponent(e[n]));return t.join("&")},setParameter:function(e,t,n){var o=r.parse(e);return o[t]=n,r.build(o)}};t.exports=r},{}],6:[function(e,t,n){var r=function o(e,t){function n(e){j=e.document,S=e.location,R=e.cancelAnimationFrame||e.clearTimeout,T=e.requestAnimationFrame||e.setTimeout}function r(){var e,t=[].slice.call(arguments),n=!(null==t[1]||D.call(t[1])!==_||"tag"in t[1]||"view"in t[1]||"subtree"in t[1]),r=n?t[1]:{},o="class"in r?"class":"className",i={tag:"div",attrs:{}},a=[];if(D.call(t[0])!=M)throw new Error("selector in m(selector, attrs, children) should be a string");for(;e=U.exec(t[0]);)if(""===e[1]&&e[2])i.tag=e[2];else if("#"===e[1])i.attrs.id=e[2];else if("."===e[1])a.push(e[2]);else if("["===e[3][0]){var l=$.exec(e[3]);i.attrs[l[1]]=l[3]||(l[2]?"":!0)}var s=n?t.slice(2):t.slice(1);1===s.length&&D.call(s[0])===q?i.children=s[0]:i.children=s;for(var u in r)r.hasOwnProperty(u)&&(u===o&&null!=r[u]&&""!==r[u]?(a.push(r[u]),i.attrs[u]=""):i.attrs[u]=r[u]);return a.length>0&&(i.attrs[o]=a.join(" ")),i}function i(e,n,o,u,f,d,h,p,v,m,g){try{(null==f||null==f.toString())&&(f="")}catch(y){f=""}if("retain"===f.subtree)return d;var w=D.call(d),b=D.call(f);if(null==d||w!==b){if(null!=d)if(o&&o.nodes){var E=p-u,x=E+(b===q?f:d.nodes).length;s(o.nodes.slice(E,x),o.slice(E,x))}else d.nodes&&s(d.nodes,d);d=new f.constructor,d.tag&&(d={}),d.nodes=[]}if(b===q){for(var C=0,A=f.length;A>C;C++)D.call(f[C])===q&&(f=f.concat.apply([],f),C--,A=f.length);for(var O=[],k=d.length===f.length,L=0,N=1,S=2,T=3,R={},U=!1,C=0;C<d.length;C++)d[C]&&d[C].attrs&&null!=d[C].attrs.key&&(U=!0,R[d[C].attrs.key]={action:N,index:C});for(var $=0,C=0,A=f.length;A>C;C++)if(f[C]&&f[C].attrs&&null!=f[C].attrs.key){for(var V=0,A=f.length;A>V;V++)f[V]&&f[V].attrs&&null==f[V].attrs.key&&(f[V].attrs.key="__mithril__"+$++);break}if(U){var H=!1;if(f.length!=d.length)H=!0;else for(var z,J,C=0;z=d[C],J=f[C];C++)if(z.attrs&&J.attrs&&z.attrs.key!=J.attrs.key){H=!0;break}if(H){for(var C=0,A=f.length;A>C;C++)if(f[C]&&f[C].attrs&&null!=f[C].attrs.key){var K=f[C].attrs.key;R[K]?R[K]={action:T,index:C,from:R[K].index,element:d.nodes[R[K].index]||j.createElement("div")}:R[K]={action:S,index:C}}var F=[];for(var G in R)F.push(R[G]);var Q=F.sort(a),Y=new Array(d.length);Y.nodes=d.nodes.slice();for(var W,C=0;W=Q[C];C++){if(W.action===N&&(s(d[W.index].nodes,d[W.index]),Y.splice(W.index,1)),W.action===S){var X=j.createElement("div");X.key=f[W.index].attrs.key,e.insertBefore(X,e.childNodes[W.index]||null),Y.splice(W.index,0,{attrs:{key:f[W.index].attrs.key},nodes:[X]}),Y.nodes[W.index]=X}W.action===T&&(e.childNodes[W.index]!==W.element&&null!==W.element&&e.insertBefore(W.element,e.childNodes[W.index]||null),Y[W.index]=d[W.from],Y.nodes[W.index]=W.element)}d=Y}}for(var C=0,Z=0,A=f.length;A>C;C++){var te=i(e,n,d,p,f[C],d[Z],h,p+L||L,v,m,g);te!==t&&(te.nodes.intact||(k=!1),L+=te.$trusted?(te.match(/<[^\/]|\>\s*[^<]/g)||[0]).length:D.call(te)===q?te.length:1,d[Z++]=te)}if(!k){for(var C=0,A=f.length;A>C;C++)null!=d[C]&&O.push.apply(O,d[C].nodes);for(var ne,C=0;ne=d.nodes[C];C++)null!=ne.parentNode&&O.indexOf(ne)<0&&s([ne],[d[C]]);f.length<d.length&&(d.length=f.length),d.nodes=O}}else if(null!=f&&b===_){for(var oe=[],ie=[];f.view;){var ae=f.view.$original||f.view,le="diff"==r.redraw.strategy()&&d.views?d.views.indexOf(ae):-1,se=le>-1?d.controllers[le]:new(f.controller||B),K=f&&f.attrs&&f.attrs.key;if(f=0==re||d&&d.controllers&&d.controllers.indexOf(se)>-1?f.view(se):{tag:"placeholder"},"retain"===f.subtree)return d;K&&(f.attrs||(f.attrs={}),f.attrs.key=K),se.onunload&&ee.push({controller:se,handler:se.onunload}),oe.push(ae),ie.push(se)}if(!f.tag&&ie.length)throw new Error("Component template must return a virtual element, not an array, string, etc.");f.attrs||(f.attrs={}),d.attrs||(d.attrs={});var ue=Object.keys(f.attrs),ce=ue.length>("key"in f.attrs?1:0);if((f.tag!=d.tag||ue.sort().join()!=Object.keys(d.attrs).sort().join()||f.attrs.id!=d.attrs.id||f.attrs.key!=d.attrs.key||"all"==r.redraw.strategy()&&(!d.configContext||d.configContext.retain!==!0)||"diff"==r.redraw.strategy()&&d.configContext&&d.configContext.retain===!1)&&(d.nodes.length&&s(d.nodes),d.configContext&&typeof d.configContext.onunload===I&&d.configContext.onunload(),d.controllers))for(var se,C=0;se=d.controllers[C];C++)typeof se.onunload===I&&se.onunload({preventDefault:B});if(D.call(f.tag)!=M)return;var ne,fe=0===d.nodes.length;if(f.attrs.xmlns?m=f.attrs.xmlns:"svg"===f.tag?m="http://www.w3.org/2000/svg":"math"===f.tag&&(m="http://www.w3.org/1998/Math/MathML"),fe){if(ne=f.attrs.is?m===t?j.createElement(f.tag,f.attrs.is):j.createElementNS(m,f.tag,f.attrs.is):m===t?j.createElement(f.tag):j.createElementNS(m,f.tag),d={tag:f.tag,attrs:ce?l(ne,f.tag,f.attrs,{},m):f.attrs,children:null!=f.children&&f.children.length>0?i(ne,f.tag,t,t,f.children,d.children,!0,0,f.attrs.contenteditable?ne:v,m,g):f.children,nodes:[ne]},ie.length){d.views=oe,d.controllers=ie;for(var se,C=0;se=ie[C];C++)if(se.onunload&&se.onunload.$old&&(se.onunload=se.onunload.$old),re&&se.onunload){var de=se.onunload;se.onunload=B,se.onunload.$old=de}}d.children&&!d.children.nodes&&(d.children.nodes=[]),"select"===f.tag&&"value"in f.attrs&&l(ne,f.tag,{value:f.attrs.value},{},m),e.insertBefore(ne,e.childNodes[p]||null)}else ne=d.nodes[0],ce&&l(ne,f.tag,f.attrs,d.attrs,m),d.children=i(ne,f.tag,t,t,f.children,d.children,!1,0,f.attrs.contenteditable?ne:v,m,g),d.nodes.intact=!0,ie.length&&(d.views=oe,d.controllers=ie),h===!0&&null!=ne&&e.insertBefore(ne,e.childNodes[p]||null);if(typeof f.attrs.config===I){var he=d.configContext=d.configContext||{},pe=function(e,t){return function(){return e.attrs.config.apply(e,t)}};g.push(pe(f,[ne,!fe,he,d]))}}else if(typeof f!=I){var O;0===d.nodes.length?(f.$trusted?O=c(e,p,f):(O=[j.createTextNode(f)],e.nodeName.match(P)||e.insertBefore(O[0],e.childNodes[p]||null)),d="string number boolean".indexOf(typeof f)>-1?new f.constructor(f):f,d.nodes=O):d.valueOf()!==f.valueOf()||h===!0?(O=d.nodes,v&&v===j.activeElement||(f.$trusted?(s(O,d),O=c(e,p,f)):"textarea"===n?e.value=f:v?v.innerHTML=f:((1===O[0].nodeType||O.length>1)&&(s(d.nodes,d),O=[j.createTextNode(f)]),e.insertBefore(O[0],e.childNodes[p]||null),O[0].nodeValue=f)),d=new f.constructor(f),d.nodes=O):d.nodes.intact=!0}return d}function a(e,t){return e.action-t.action||e.index-t.index}function l(e,t,n,r,o){for(var i in n){var a=n[i],l=r[i];if(i in r&&l===a)"value"===i&&"input"===t&&e.value!=a&&(e.value=a);else{r[i]=a;try{if("config"===i||"key"==i)continue;if(typeof a===I&&0===i.indexOf("on"))e[i]=f(a,e);else if("style"===i&&null!=a&&D.call(a)===_){for(var s in a)(null==l||l[s]!==a[s])&&(e.style[s]=a[s]);for(var s in l)s in a||(e.style[s]="")}else null!=o?"href"===i?e.setAttributeNS("http://www.w3.org/1999/xlink","href",a):"className"===i?e.setAttribute("class",a):e.setAttribute(i,a):i in e&&"list"!==i&&"style"!==i&&"form"!==i&&"type"!==i&&"width"!==i&&"height"!==i?("input"!==t||e[i]!==a)&&(e[i]=a):e.setAttribute(i,a)}catch(u){if(u.message.indexOf("Invalid argument")<0)throw u}}}return r}function s(e,t){for(var n=e.length-1;n>-1;n--)if(e[n]&&e[n].parentNode){try{e[n].parentNode.removeChild(e[n])}catch(r){}t=[].concat(t),t[n]&&u(t[n])}0!=e.length&&(e.length=0)}function u(e){if(e.configContext&&typeof e.configContext.onunload===I&&(e.configContext.onunload(),e.configContext.onunload=null),e.controllers)for(var t,n=0;t=e.controllers[n];n++)typeof t.onunload===I&&t.onunload({preventDefault:B});if(e.children)if(D.call(e.children)===q)for(var r,n=0;r=e.children[n];n++)u(r);else e.children.tag&&u(e.children)}function c(e,t,n){var r=e.childNodes[t];if(r){var o=1!=r.nodeType,i=j.createElement("span");o?(e.insertBefore(i,r||null),i.insertAdjacentHTML("beforebegin",n),e.removeChild(i)):r.insertAdjacentHTML("beforebegin",n)}else e.insertAdjacentHTML("beforeend",n);for(var a=[];e.childNodes[t]!==r;)a.push(e.childNodes[t]),t++;return a}function f(e,t){return function(n){n=n||event,r.redraw.strategy("diff"),r.startComputation();try{return e.call(t,n)}finally{oe()}}}function d(e){var t=z.indexOf(e);return 0>t?z.push(e)-1:t}function h(e){var t=function(){return arguments.length&&(e=arguments[0]),e};return t.toJSON=function(){return e},t}function p(e,t){var n=function(){return(e.controller||B).apply(this,t)||this},r=function(n){return arguments.length>1&&(t=t.concat([].slice.call(arguments,1))),e.view.apply(e,t?[n].concat(t):[n])};r.$original=e.view;var o={controller:n,view:r};return t[0]&&null!=t[0].key&&(o.attrs={key:t[0].key}),o}function v(){X&&(X(),X=null);for(var e,t=0;e=F[t];t++)if(Q[t]){var n=G[t].controller&&G[t].controller.$$args?[Q[t]].concat(G[t].controller.$$args):[Q[t]];r.render(e,G[t].view?G[t].view(Q[t],n):"")}Z&&(Z(),Z=null),Y=null,W=new Date,r.redraw.strategy("diff")}function m(e){return e.slice(le[r.route.mode].length)}function g(e,t,n){ie={};var o=n.indexOf("?");-1!==o&&(ie=E(n.substr(o+1,n.length)),n=n.substr(0,o));var i=Object.keys(t),a=i.indexOf(n);if(-1!==a)return r.mount(e,t[i[a]]),!0;for(var l in t){if(l===n)return r.mount(e,t[l]),!0;var s=new RegExp("^"+l.replace(/:[^\/]+?\.{3}/g,"(.*?)").replace(/:[^\/]+/g,"([^\\/]+)")+"/?$");if(s.test(n))return n.replace(s,function(){for(var n=l.match(/:[^\/]+/g)||[],o=[].slice.call(arguments,1,-2),i=0,a=n.length;a>i;i++)ie[n[i].replace(/:|\./g,"")]=decodeURIComponent(o[i]);r.mount(e,t[l])}),!0}}function y(e){if(e=e||event,!e.ctrlKey&&!e.metaKey&&2!==e.which){e.preventDefault?e.preventDefault():e.returnValue=!1;for(var t=e.currentTarget||e.srcElement,n="pathname"===r.route.mode&&t.search?E(t.search.slice(1)):{};t&&"A"!=t.nodeName.toUpperCase();)t=t.parentNode;r.route(t[r.route.mode].slice(le[r.route.mode].length),n)}}function w(){"hash"!=r.route.mode&&S.hash?S.hash=S.hash:e.scrollTo(0,0)}function b(e,n){var r={},o=[];for(var i in e){var a=n?n+"["+i+"]":i,l=e[i],s=D.call(l),u=null===l?encodeURIComponent(a):s===_?b(l,a):s===q?l.reduce(function(e,t){return r[a]||(r[a]={}),r[a][t]?e:(r[a][t]=!0,e.concat(encodeURIComponent(a)+"="+encodeURIComponent(t)))},[]).join("&"):encodeURIComponent(a)+"="+encodeURIComponent(l);l!==t&&o.push(u)}return o.join("&")}function E(e){"?"===e.charAt(0)&&(e=e.substring(1));for(var t=e.split("&"),n={},r=0,o=t.length;o>r;r++){var i=t[r].split("="),a=decodeURIComponent(i[0]),l=2==i.length?decodeURIComponent(i[1]):null;null!=n[a]?(D.call(n[a])!==q&&(n[a]=[n[a]]),n[a].push(l)):n[a]=l}return n}function x(e){var n=d(e);s(e.childNodes,J[n]),J[n]=t}function C(e,t){var n=r.prop(t);return e.then(n),n.then=function(n,r){return C(e.then(n,r),t)},n}function A(e,t){function n(e){f=e||u,h.map(function(e){f===s&&e.resolve(d)||e.reject(d)})}function o(e,t,n,o){if((null!=d&&D.call(d)===_||typeof d===I)&&typeof e===I)try{var i=0;e.call(d,function(e){i++||(d=e,t())},function(e){i++||(d=e,n())})}catch(a){r.deferred.onerror(a),d=a,n()}else o()}function i(){var u;try{u=d&&d.then}catch(h){return r.deferred.onerror(h),d=h,f=l,i()}o(u,function(){f=a,i()},function(){f=l,i()},function(){try{f===a&&typeof e===I?d=e(d):f===l&&"function"==typeof t&&(d=t(d),f=a)}catch(i){return r.deferred.onerror(i),d=i,n()}d===c?(d=TypeError(),n()):o(u,function(){n(s)},n,function(){n(f===a&&s)})})}var a=1,l=2,s=3,u=4,c=this,f=0,d=0,h=[];c.promise={},c.resolve=function(e){return f||(d=e,f=a,i()),this},c.reject=function(e){return f||(d=e,f=l,i()),this},c.promise.then=function(e,t){var n=new A(e,t);return f===s?n.resolve(d):f===u?n.reject(d):h.push(n),n.promise}}function O(e){return e}function k(n){if(!n.dataType||"jsonp"!==n.dataType.toLowerCase()){var r=new e.XMLHttpRequest;if(r.open(n.method,n.url,!0,n.user,n.password),r.onreadystatechange=function(){4===r.readyState&&(r.status>=200&&r.status<300?n.onload({type:"load",target:r}):n.onerror({type:"error",target:r}))},n.serialize===JSON.stringify&&n.data&&"GET"!==n.method&&r.setRequestHeader("Content-Type","application/json; charset=utf-8"),n.deserialize===JSON.parse&&r.setRequestHeader("Accept","application/json, text/*"),typeof n.config===I){var o=n.config(r,n);null!=o&&(r=o)}var i="GET"!==n.method&&n.data?n.data:"";if(i&&D.call(i)!=M&&i.constructor!=e.FormData)throw"Request data should be either be a string or FormData. Check the `serialize` option in `m.request`";return r.send(i),r}var a="mithril_callback_"+(new Date).getTime()+"_"+Math.round(1e16*Math.random()).toString(36),l=j.createElement("script");e[a]=function(r){l.parentNode.removeChild(l),n.onload({type:"load",target:{responseText:r}}),e[a]=t},l.onerror=function(r){return l.parentNode.removeChild(l),n.onerror({type:"error",target:{status:500,responseText:JSON.stringify({error:"Error making jsonp request"})}}),e[a]=t,!1},l.onload=function(e){return!1},l.src=n.url+(n.url.indexOf("?")>0?"&":"?")+(n.callbackKey?n.callbackKey:"callback")+"="+a+"&"+b(n.data||{}),j.body.appendChild(l)}function L(e,t,n){if("GET"===e.method&&"jsonp"!=e.dataType){var r=e.url.indexOf("?")<0?"?":"&",o=b(t);e.url=e.url+(o?r+o:"")}else e.data=n(t);return e}function N(e,t){var n=e.match(/:[a-z]\w+/gi);if(n&&t)for(var r=0;r<n.length;r++){var o=n[r].slice(1);e=e.replace(n[r],t[o]),delete t[o]}return e}var j,S,T,R,_="[object Object]",q="[object Array]",M="[object String]",I="function",D={}.toString,U=/(?:(^|#|\.)([^#\.\[\]]+))|(\[.+?\])/g,$=/\[(.+?)(?:=("|'|)(.*?)\2)?\]/,P=/^(AREA|BASE|BR|COL|COMMAND|EMBED|HR|IMG|INPUT|KEYGEN|LINK|META|PARAM|SOURCE|TRACK|WBR)$/,B=function(){};n(e);var V,H={appendChild:function(e){V===t&&(V=j.createElement("html")),j.documentElement&&j.documentElement!==e?j.replaceChild(e,j.documentElement):j.appendChild(e),this.childNodes=j.childNodes},insertBefore:function(e){this.appendChild(e)},childNodes:[]},z=[],J={};r.render=function(e,n,r){var o=[];if(!e)throw new Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.");var a=d(e),l=e===j,u=l||e===j.documentElement?H:e;l&&"html"!=n.tag&&(n={tag:"html",attrs:{},children:n}),J[a]===t&&s(u.childNodes),r===!0&&x(e),J[a]=i(u,null,t,t,n,J[a],!1,0,null,t,o);for(var c=0,f=o.length;f>c;c++)o[c]()},r.trust=function(e){return e=new String(e),e.$trusted=!0,e},r.prop=function(e){return(null!=e&&D.call(e)===_||typeof e===I)&&typeof e.then===I?C(e):h(e)};var K,F=[],G=[],Q=[],Y=null,W=0,X=null,Z=null,ee=[],te=16;r.component=function(e){return p(e,[].slice.call(arguments,1))},r.mount=r.module=function(e,t){if(!e)throw new Error("Please ensure the DOM element exists before rendering a template into it.");var n=F.indexOf(e);0>n&&(n=F.length);for(var o,i=!1,a={preventDefault:function(){i=!0,X=Z=null}},l=0;o=ee[l];l++)o.handler.call(o.controller,a),o.controller.onunload=null;if(i)for(var o,l=0;o=ee[l];l++)o.controller.onunload=o.handler;else ee=[];if(Q[n]&&typeof Q[n].onunload===I&&Q[n].onunload(a),!i){r.redraw.strategy("all"),r.startComputation(),F[n]=e,arguments.length>2&&(t=subcomponent(t,[].slice.call(arguments,2)));var s=K=t=t||{controller:function(){}},u=t.controller||B,c=new u;return s===K&&(Q[n]=c,G[n]=t),oe(),Q[n]}};var ne=!1;r.redraw=function(t){ne||(ne=!0,Y&&t!==!0?(T===e.requestAnimationFrame||new Date-W>te)&&(Y>0&&R(Y),Y=T(v,te)):(v(),Y=T(function(){Y=null},te)),ne=!1)},r.redraw.strategy=r.prop();var re=0;r.startComputation=function(){re++},r.endComputation=function(){re=Math.max(re-1,0),0===re&&r.redraw()};var oe=function(){"none"==r.redraw.strategy()?(re--,r.redraw.strategy("diff")):r.endComputation()};r.withAttr=function(e,t){return function(n){n=n||event;var r=n.currentTarget||this;t(e in r?r[e]:r.getAttribute(e))}};var ie,ae,le={pathname:"",hash:"#",search:"?"},se=B,ue=!1;return r.route=function(){if(0===arguments.length)return ae;if(3===arguments.length&&D.call(arguments[1])===M){var t=arguments[0],n=arguments[1],o=arguments[2];se=function(e){var i=ae=m(e);if(!g(t,o,i)){if(ue)throw new Error("Ensure the default route matches one of the routes defined in m.route");ue=!0,r.route(n,!0),ue=!1}};var i="hash"===r.route.mode?"onhashchange":"onpopstate";e[i]=function(){var e=S[r.route.mode];"pathname"===r.route.mode&&(e+=S.search),ae!=m(e)&&se(e)},X=w,e[i]()}else if(arguments[0].addEventListener||arguments[0].attachEvent){var a=arguments[0],l=(arguments[1],arguments[2],arguments[3]);a.href=("pathname"!==r.route.mode?S.pathname:"")+le[r.route.mode]+l.attrs.href,a.addEventListener?(a.removeEventListener("click",y),a.addEventListener("click",y)):(a.detachEvent("onclick",y),a.attachEvent("onclick",y))}else if(D.call(arguments[0])===M){var s=ae;ae=arguments[0];var u=arguments[1]||{},c=ae.indexOf("?"),f=c>-1?E(ae.slice(c+1)):{};for(var d in u)f[d]=u[d];var h=b(f),p=c>-1?ae.slice(0,c):ae;h&&(ae=p+(-1===p.indexOf("?")?"?":"&")+h);var v=(3===arguments.length?arguments[2]:arguments[1])===!0||s===arguments[0];e.history.pushState?(X=w,Z=function(){e.history[v?"replaceState":"pushState"](null,j.title,le[r.route.mode]+ae)},se(le[r.route.mode]+ae)):(S[r.route.mode]=ae,se(le[r.route.mode]+ae))}},r.route.param=function(e){if(!ie)throw new Error("You must call m.route(element, defaultRoute, routes) before calling m.route.param()");return ie[e]},r.route.mode="search",r.route.buildQueryString=b,r.route.parseQueryString=E,r.deferred=function(){var e=new A;return e.promise=C(e.promise),e},r.deferred.onerror=function(e){if("[object Error]"===D.call(e)&&!e.constructor.toString().match(/ Error/))throw e},r.sync=function(e){function t(e,t){return function(r){return a[e]=r,t||(n="reject"),0===--i&&(o.promise(a),o[n](a)),r}}var n="resolve",o=r.deferred(),i=e.length,a=new Array(i);if(e.length>0)for(var l=0;l<e.length;l++)e[l].then(t(l,!0),t(l,!1));else o.resolve([]);return o.promise},r.request=function(e){e.background!==!0&&r.startComputation();var t=new A,n=e.dataType&&"jsonp"===e.dataType.toLowerCase(),o=e.serialize=n?O:e.serialize||JSON.stringify,i=e.deserialize=n?O:e.deserialize||JSON.parse,a=n?function(e){return e.responseText}:e.extract||function(e){return 0===e.responseText.length&&i===JSON.parse?null:e.responseText};return e.method=(e.method||"GET").toUpperCase(),e.url=N(e.url,e.data),e=L(e,e.data,o),e.onload=e.onerror=function(n){try{n=n||event;var o=("load"===n.type?e.unwrapSuccess:e.unwrapError)||O,l=o(i(a(n.target,e)),n.target);if("load"===n.type)if(D.call(l)===q&&e.type)for(var s=0;s<l.length;s++)l[s]=new e.type(l[s]);else e.type&&(l=new e.type(l));t["load"===n.type?"resolve":"reject"](l)}catch(n){r.deferred.onerror(n),t.reject(n)}e.background!==!0&&r.endComputation()},k(e),t.promise=C(t.promise,e.initialValue),t.promise},r.deps=function(t){return n(e=t||e),e},r.deps.factory=o,r}("undefined"!=typeof window?window:{});"undefined"!=typeof t&&null!==t&&t.exports?t.exports=r:"function"==typeof define&&define.amd&&define(function(){return r})},{}],7:[function(e,t,n){(function(){"use strict";function e(){}function n(e,t){for(var n=e.length;n--;)if(e[n].listener===t)return n;return-1}function r(e){return function(){return this[e].apply(this,arguments)}}var o=e.prototype,i=this,a=i.EventEmitter;o.getListeners=function(e){var t,n,r=this._getEvents();if(e instanceof RegExp){t={};for(n in r)r.hasOwnProperty(n)&&e.test(n)&&(t[n]=r[n])}else t=r[e]||(r[e]=[]);return t},o.flattenListeners=function(e){var t,n=[];for(t=0;t<e.length;t+=1)n.push(e[t].listener);return n},o.getListenersAsObject=function(e){var t,n=this.getListeners(e);return n instanceof Array&&(t={},t[e]=n),t||n},o.addListener=function(e,t){var r,o=this.getListenersAsObject(e),i="object"==typeof t;for(r in o)o.hasOwnProperty(r)&&-1===n(o[r],t)&&o[r].push(i?t:{listener:t,once:!1});return this},o.on=r("addListener"),o.addOnceListener=function(e,t){return this.addListener(e,{listener:t,once:!0})},o.once=r("addOnceListener"),o.defineEvent=function(e){return this.getListeners(e),this},o.defineEvents=function(e){for(var t=0;t<e.length;t+=1)this.defineEvent(e[t]);return this},o.removeListener=function(e,t){var r,o,i=this.getListenersAsObject(e);for(o in i)i.hasOwnProperty(o)&&(r=n(i[o],t),-1!==r&&i[o].splice(r,1));return this},o.off=r("removeListener"),o.addListeners=function(e,t){return this.manipulateListeners(!1,e,t)},o.removeListeners=function(e,t){return this.manipulateListeners(!0,e,t)},o.manipulateListeners=function(e,t,n){var r,o,i=e?this.removeListener:this.addListener,a=e?this.removeListeners:this.addListeners;if("object"!=typeof t||t instanceof RegExp)for(r=n.length;r--;)i.call(this,t,n[r]);else for(r in t)t.hasOwnProperty(r)&&(o=t[r])&&("function"==typeof o?i.call(this,r,o):a.call(this,r,o));return this},o.removeEvent=function(e){var t,n=typeof e,r=this._getEvents();if("string"===n)delete r[e];else if(e instanceof RegExp)for(t in r)r.hasOwnProperty(t)&&e.test(t)&&delete r[t];else delete this._events;return this},o.removeAllListeners=r("removeEvent"),o.emitEvent=function(e,t){var n,r,o,i,a,l=this.getListenersAsObject(e);for(i in l)if(l.hasOwnProperty(i))for(n=l[i].slice(0),o=n.length;o--;)r=n[o],r.once===!0&&this.removeListener(e,r.listener),a=r.listener.apply(this,t||[]),a===this._getOnceReturnValue()&&this.removeListener(e,r.listener);return this},o.trigger=r("emitEvent"),o.emit=function(e){var t=Array.prototype.slice.call(arguments,1);return this.emitEvent(e,t)},o.setOnceReturnValue=function(e){return this._onceReturnValue=e,this},o._getOnceReturnValue=function(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},o._getEvents=function(){return this._events||(this._events={})},e.noConflict=function(){return i.EventEmitter=a,e},"function"==typeof define&&define.amd?define(function(){return e}):"object"==typeof t&&t.exports?t.exports=e:i.EventEmitter=e}).call(this)},{}]},{},[1]);
assets/js/form-request.js DELETED
@@ -1,182 +0,0 @@
1
- (function() {
2
-
3
- /**
4
- * A formrequest. Should be passed an array of data in the following format.
5
- *
6
- * {
7
- * formElementId: 0,
8
- * success: 1,
9
- * data: {}
10
- * }
11
- *
12
- * @param request
13
- */
14
- var formRequest = function( request ) {
15
-
16
- // vars
17
- var self = this;
18
-
19
- // Functions
20
- function init() {
21
-
22
- self.element = document.getElementById( request.formElementId );
23
-
24
- if( ! self.element ) {
25
- return false;
26
- }
27
-
28
- if( request.success != 1 ) {
29
- self.repopulate();
30
- }
31
-
32
- self.scrollTo();
33
- }
34
-
35
- /**
36
- * Scrolls to the form element
37
- */
38
- this.scrollTo = function() {
39
- // Scroll to form element
40
- var formElement = self.element;
41
- var scrollToHeight = 0;
42
- var obj = formElement;
43
- var windowHeight = window.innerHeight;
44
-
45
- if (obj.offsetParent) {
46
- do {
47
- scrollToHeight += obj.offsetTop;
48
- } while (obj = obj.offsetParent);
49
- } else {
50
- scrollToHeight = formElement.offsetTop;
51
- }
52
-
53
- if((windowHeight - 80) > formElement.clientHeight) {
54
- // vertically center the form, but only if there's enough space for a decent margin
55
- scrollToHeight = scrollToHeight - ((windowHeight - formElement.clientHeight) / 2);
56
- } else {
57
- // the form doesn't fit, scroll a little above the form
58
- scrollToHeight = scrollToHeight - 80;
59
- }
60
-
61
- // scroll there. if jQuery is loaded, do it with an animation.
62
- if( request.animate_scroll && window.jQuery !== undefined) {
63
- jQuery('html, body').animate({ scrollTop: scrollToHeight }, 800);
64
- } else {
65
- window.scrollTo(0, scrollToHeight);
66
- }
67
- };
68
-
69
- /**
70
- * Repopulates the form fields
71
- */
72
- this.repopulate = function() {
73
- populate( self.element.querySelector('form'), request.data );
74
- };
75
-
76
- // Call "init" on window.load event
77
- addEvent( window, 'load', init );
78
- };
79
-
80
- window.mc4wpFormRequest = new formRequest( mc4wpFormRequestData );
81
-
82
- /**
83
- * Adds a browser event, IE compatible.
84
- *
85
- * @param element
86
- * @param eventName
87
- * @param callback
88
- */
89
- function addEvent( element, eventName, callback ) {
90
- if (element.addEventListener) {
91
- element.addEventListener(eventName, callback, false);
92
- } else {
93
- element.attachEvent("on" + eventName, callback);
94
- }
95
- }
96
-
97
- /*! populate.js v1.0 by @dannyvankooten | MIT license */
98
- ;(function(root) {
99
-
100
- /**
101
- * Populate form fields from a JSON object.
102
- *
103
- * @param form object The form element containing your input fields.
104
- * @param data array JSON data to populate the fields with.
105
- * @param basename string Optional basename which is added to `name` attributes
106
- */
107
- var populate = function( form, data, basename) {
108
-
109
- for(var key in data) {
110
-
111
- if( ! data.hasOwnProperty( key ) ) {
112
- continue;
113
- }
114
-
115
- var name = key;
116
- var value = data[key];
117
-
118
- // handle array name attributes
119
- if(typeof(basename) !== "undefined") {
120
- name = basename + "[" + key + "]";
121
- }
122
-
123
- if(value.constructor === Array) {
124
- name += '[]';
125
- } else if(typeof value == "object") {
126
- populate( form, value, name);
127
- continue;
128
- }
129
-
130
- // only proceed if element is set
131
- var element = form.elements.namedItem( name );
132
- if( ! element ) {
133
- continue;
134
- }
135
-
136
- // check element type
137
- switch(element.type || element.constructor ) {
138
- default:
139
- element.value = value;
140
- break;
141
-
142
- case RadioNodeList:
143
- for( var j=0; j < element.length; j++ ) {
144
- element[j].checked = ( value.indexOf(element[j].value) > -1 );
145
- }
146
- break;
147
-
148
- case 'select-multiple':
149
- var values = value.constructor == Array ? value : [value];
150
-
151
- for(var k = 0; k < element.options.length; k++) {
152
- element.options[k].selected |= (values.indexOf(element.options[k].value) > -1 );
153
- }
154
- break;
155
-
156
- case 'select':
157
- case 'select-one':
158
- element.value = value.toString() || value;
159
- break;
160
-
161
- }
162
-
163
-
164
-
165
- }
166
-
167
- };
168
-
169
- // Play nice with AMD, CommonJS or a plain global object.
170
- if ( typeof define == 'function' && typeof define.amd == 'object' && define.amd ) {
171
- define(function() {
172
- return populate;
173
- });
174
- } else if ( typeof exports === 'object' ) {
175
- exports.populate = populate;
176
- } else {
177
- root.populate = populate;
178
- }
179
-
180
- }(this));
181
-
182
- })();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/js/form-request.min.js DELETED
@@ -1 +0,0 @@
1
- !function(){function a(a,b,c){a.addEventListener?a.addEventListener(b,c,!1):a.attachEvent("on"+b,c)}var b=function(b){function c(){return d.element=document.getElementById(b.formElementId),d.element?(1!=b.success&&d.repopulate(),void d.scrollTo()):!1}var d=this;this.scrollTo=function(){var a=d.element,c=0,e=a,f=window.innerHeight;if(e.offsetParent){do c+=e.offsetTop;while(e=e.offsetParent)}else c=a.offsetTop;c-=f-80>a.clientHeight?(f-a.clientHeight)/2:80,b.animate_scroll&&void 0!==window.jQuery?jQuery("html, body").animate({scrollTop:c},800):window.scrollTo(0,c)},this.repopulate=function(){populate(d.element.querySelector("form"),b.data)},a(window,"load",c)};window.mc4wpFormRequest=new b(mc4wpFormRequestData),function(a){var b=function(a,c,d){for(var e in c)if(c.hasOwnProperty(e)){var f=e,g=c[e];if("undefined"!=typeof d&&(f=d+"["+e+"]"),g.constructor===Array)f+="[]";else if("object"==typeof g){b(a,g,f);continue}var h=a.elements.namedItem(f);if(h)switch(h.type||h.constructor){default:h.value=g;break;case RadioNodeList:for(var i=0;i<h.length;i++)h[i].checked=g.indexOf(h[i].value)>-1;break;case"select-multiple":for(var j=g.constructor==Array?g:[g],k=0;k<h.options.length;k++)h.options[k].selected|=j.indexOf(h.options[k].value)>-1;break;case"select":case"select-one":h.value=g.toString()||g}}};"function"==typeof define&&"object"==typeof define.amd&&define.amd?define(function(){return b}):"object"==typeof exports?exports.populate=b:a.populate=b}(this)}();
 
assets/js/forms-admin.js ADDED
@@ -0,0 +1,13487 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
+ var rows = function(m) {
3
+ 'use strict';
4
+
5
+ var r = {};
6
+
7
+ r.label = function (config) {
8
+ // label row
9
+ return m("div", [
10
+ m("label", "Field Label"),
11
+ m("input.widefat", {
12
+ type : "text",
13
+ value : config.label(),
14
+ onchange : m.withAttr('value', config.label),
15
+ placeholder: config.title()
16
+ })
17
+ ]);
18
+ };
19
+
20
+ r.defaultValue = function (config) {
21
+ return m("div", [
22
+ m("label", "Default Value"),
23
+ m("input.widefat", {
24
+ type : "text",
25
+ value : config.value(),
26
+ onkeyup: m.withAttr('value', config.value)
27
+ })
28
+ ]);
29
+ };
30
+
31
+ r.numberMinMax = function (config) {
32
+ return m('div', [
33
+ m('div.row', [
34
+ m('div.col.col-3', [
35
+ m('label', "Min"),
36
+ m('input', {type: 'number', onchange: m.withAttr('value', config.min)})
37
+ ]),
38
+ m('div.col.col-3', [
39
+ m('label', 'Max'),
40
+ m('input', {type: 'number', onchange: m.withAttr('value', config.max)})
41
+ ])
42
+ ])
43
+ ])
44
+ };
45
+
46
+
47
+ r.isRequired = function (config) {
48
+ return m('div', [
49
+ m('label.cb-wrap', [
50
+ m('input', {
51
+ type : 'checkbox',
52
+ checked : config.required(),
53
+ onchange: m.withAttr('checked', config.required)
54
+ }),
55
+ "Is this field required?"
56
+ ])
57
+ ]);
58
+ };
59
+
60
+ r.usePlaceholder = function (config) {
61
+
62
+ if (config.value().length > 0) {
63
+ return m("div", [
64
+ m("label.cb-wrap", [
65
+ m("input", {
66
+ type : 'checkbox',
67
+ checked : config.placeholder(),
68
+ onchange: m.withAttr('checked', config.placeholder)
69
+ }),
70
+ "Use \"" + config.value() + "\" as placeholder for the field."
71
+ ])
72
+ ]);
73
+ }
74
+ };
75
+
76
+ r.useParagraphs = function (config) {
77
+ return m('div', [
78
+ m('label.cb-wrap', [
79
+ m('input', {
80
+ type : 'checkbox',
81
+ checked : config.wrap(),
82
+ onchange: m.withAttr('checked', config.wrap)
83
+ }),
84
+ "Wrap in paragraph tags?"
85
+ ])
86
+ ]);
87
+ };
88
+
89
+ r.choiceType = function (config) {
90
+ return m('div', [
91
+ m('label', "Choice Type"),
92
+ m('select', {
93
+ value : config.type(),
94
+ onchange: m.withAttr('value', config.type)
95
+ }, [
96
+ m('option', {
97
+ value : 'select',
98
+ selected: config.type() === 'select' ? 'selected' : false
99
+ }, 'Dropdown'),
100
+ m('option', {
101
+ value : 'radio',
102
+ selected: config.type() === 'radio' ? 'selected' : false
103
+ }, 'Radio Button'),
104
+ m('option', {
105
+ value : 'checkbox',
106
+ selected: config.type() === 'checkbox' ? 'selected' : false
107
+ }, 'Checkboxes')
108
+ ])
109
+ ]);
110
+ };
111
+
112
+ r.choices = function (config) {
113
+
114
+
115
+ return m('div', [
116
+ m('label', "Choices"),
117
+ m('div.limit-height', [
118
+ m("table", [
119
+
120
+ // table body
121
+ config.choices().map(function (choice, index) {
122
+ return m('tr', {
123
+ 'data-id': index
124
+ }, [
125
+ m('td.cb', m('input', {
126
+ name : 'selected',
127
+ type : (config.type() === 'checkbox' ) ? 'checkbox' : 'radio',
128
+ onchange: m.withAttr('value', config.selectChoice.bind(config)),
129
+ checked: choice.selected(),
130
+ value: choice.value()
131
+ })
132
+ ),
133
+ m('td.stretch', m('input.widefat', {
134
+ type : 'text',
135
+ value : choice.label(),
136
+ placeholder: choice.title(),
137
+ onchange : m.withAttr('value', choice.label)
138
+ })),
139
+ m('td', m('span', {
140
+ "class": 'dashicons dashicons-no-alt hover-activated',
141
+ onclick: function (key) {
142
+ this.choices().splice(key, 1);
143
+ }.bind(config, index)
144
+ }, ''))
145
+ ])
146
+ })
147
+ ]) // end of table
148
+ ]) // end of limit-height div
149
+ ]);
150
+ };
151
+
152
+ return r;
153
+ };
154
+
155
+ module.exports = rows;
156
+ },{}],2:[function(require,module,exports){
157
+ var forms = function(m) {
158
+ var forms = {};
159
+ var rows = require('./field-forms-rows.js')(m);
160
+
161
+ // route to one of the other form configs, default to "text"
162
+ forms.render = function(config) {
163
+
164
+ var type = config.type();
165
+
166
+ if( typeof( forms[type] ) === "function" ) {
167
+ return forms[ type ](config);
168
+ }
169
+
170
+ switch( type ) {
171
+ case 'select':
172
+ case 'radio':
173
+ case 'checkbox':
174
+ return forms.choice(config);
175
+ break;
176
+ }
177
+
178
+ // fallback to good old text field
179
+ return forms.text(config);
180
+ };
181
+
182
+
183
+ forms.text = function(config) {
184
+ return [
185
+ rows.label(config),
186
+ rows.defaultValue(config),
187
+ rows.usePlaceholder(config),
188
+ rows.isRequired(config),
189
+ rows.useParagraphs(config)
190
+ ]
191
+ };
192
+
193
+ forms.choice = function(config) {
194
+ return [
195
+ rows.label(config),
196
+ rows.choiceType(config),
197
+ rows.choices(config),
198
+ rows.useParagraphs(config)
199
+ ]
200
+ };
201
+
202
+ forms.hidden = function( config ) {
203
+ return [
204
+ rows.defaultValue(config)
205
+ ]
206
+ };
207
+
208
+ forms.submit = function(config) {
209
+
210
+ config.label('');
211
+ config.placeholder(false);
212
+
213
+ return [
214
+ rows.defaultValue(config),
215
+ rows.useParagraphs(config)
216
+ ]
217
+ };
218
+
219
+ forms.number = function(config) {
220
+
221
+ return [
222
+ forms.text(config),
223
+ rows.numberMinMax(config)
224
+ ];
225
+ };
226
+
227
+ return forms;
228
+ };
229
+
230
+
231
+
232
+ module.exports = forms;
233
+ },{"./field-forms-rows.js":1}],3:[function(require,module,exports){
234
+ var g = function(m) {
235
+ 'use strict';
236
+
237
+ var render = require('../third-party/render.js');
238
+ var html_beautify = require('../third-party/beautify-html.js');
239
+ var generators = {};
240
+
241
+ /**
242
+ * Generates a <select> field
243
+ * @param config
244
+ * @returns {*}
245
+ */
246
+ generators.select = function (config) {
247
+ var field = m('select', {name: config.name()}, [
248
+ config.choices().map(function (choice) {
249
+ return m('option', {
250
+ value : ( choice.value() !== choice.label() ) ? choice.value() : undefined,
251
+ "selected": choice.selected()
252
+ }, choice.label())
253
+ })
254
+ ]);
255
+ return field;
256
+ };
257
+
258
+ /**
259
+ * Generates a checkbox or radio type input field.
260
+ *
261
+ * @param config
262
+ * @returns {*}
263
+ */
264
+ generators.checkbox = function (config) {
265
+
266
+
267
+ var field = config.choices().map(function (choice) {
268
+ return m('label', [
269
+ m('input', {
270
+ name : config.name() + ( config.type() === 'checkbox' ? '[]' : '' ),
271
+ type : config.type(),
272
+ value : choice.value(),
273
+ checked : choice.selected()
274
+ }),
275
+ m('span', choice.label())
276
+ ]
277
+ )
278
+ });
279
+ return field;
280
+ };
281
+ generators.radio = generators.checkbox;
282
+
283
+ /**
284
+ * Generates a default field
285
+ *
286
+ * - text, url, number, email, date
287
+ *
288
+ * @param config
289
+ * @returns {*}
290
+ */
291
+ generators['default'] = function (config) {
292
+
293
+ var attributes = {
294
+ type: config.type()
295
+ };
296
+ var field;
297
+
298
+ if (config.name()) {
299
+ attributes.name = config.name();
300
+ }
301
+
302
+ if (config.min()) {
303
+ attributes.min = config.min();
304
+ }
305
+
306
+ if (config.max()) {
307
+ attributes.max = config.max();
308
+ }
309
+
310
+ if (config.value().length > 0) {
311
+ if (config.placeholder()) {
312
+ attributes.placeholder = config.value();
313
+ } else {
314
+ attributes.value = config.value();
315
+ }
316
+ }
317
+
318
+ attributes.required = config.required();
319
+
320
+ field = m('input', attributes);
321
+ return field;
322
+ };
323
+
324
+ /**
325
+ * Generates an HTML string based on a field (config) object
326
+ *
327
+ * @param config
328
+ * @returns {*}
329
+ */
330
+ function generate(config) {
331
+ var label, field, htmlTemplate, html;
332
+
333
+ label = config.label().length ? m("label", config.label()) : '';
334
+ field = typeof(generators[config.type()]) === "function" ? generators[config.type()](config) : generators['default'](config);
335
+
336
+ htmlTemplate = config.wrap() ? m('p', [label, field]) : [label, field];
337
+
338
+ // render HTML on memory node
339
+ html = render(htmlTemplate);
340
+
341
+ // prettify html
342
+ html = html_beautify(html);
343
+
344
+ return html + "\n";
345
+ }
346
+
347
+ return generate;
348
+ };
349
+
350
+ module.exports = g;
351
+ },{"../third-party/beautify-html.js":11,"../third-party/render.js":12}],4:[function(require,module,exports){
352
+ var FieldHelper = function(m, tabs, editor, fields) {
353
+ 'use strict';
354
+
355
+ var generate = require('./field-generator.js')(m);
356
+ var overlay = require('./overlay.js')(m);
357
+ var forms = require('./field-forms.js')(m);
358
+ var fieldConfig;
359
+
360
+ editor.on('blur', m.redraw);
361
+
362
+ /**
363
+ * Choose a field to open the helper form for
364
+ *
365
+ * @param index
366
+ * @returns {*}
367
+ */
368
+ function setActiveField(index) {
369
+ fieldConfig = fields.get(index);
370
+ m.redraw();
371
+ }
372
+
373
+
374
+ /**
375
+ * Controller
376
+ */
377
+ function controller() {
378
+
379
+ }
380
+
381
+ /**
382
+ * Create HTML based on current config object
383
+ */
384
+ function createFieldHTMLAndAddToForm() {
385
+
386
+ // generate html
387
+ var html = generate(fieldConfig);
388
+
389
+ // add to editor
390
+ editor.insert( html );
391
+
392
+ // reset field form
393
+ setActiveField('');
394
+
395
+ // redraw
396
+ m.redraw();
397
+ }
398
+
399
+ /**
400
+ * View
401
+ * @returns {*}
402
+ */
403
+ function view() {
404
+
405
+ // build DOM for fields choice
406
+ var availableFields = fields.getAll();
407
+
408
+ var fieldsChoice = m( "div.available-fields.small-margin", [
409
+ m("strong", "Choose a MailChimp field to add to the form"),
410
+
411
+ (availableFields.length) ?
412
+
413
+ // render fields
414
+ availableFields.map(function(field, index) {
415
+
416
+ var className = "button";
417
+ if( field.required() ) {
418
+ className += " is-required";
419
+ }
420
+
421
+ var inForm = field.inFormContent();
422
+ if( inForm !== null ) {
423
+ className += " " + ( inForm ? 'in-form' : 'not-in-form' );
424
+ }
425
+
426
+ return m("button", {
427
+ "class": className,
428
+ type : 'button',
429
+ onclick: m.withAttr("value", setActiveField),
430
+ value : index
431
+ }, field.title() );
432
+ })
433
+
434
+ :
435
+
436
+ // no fields
437
+ m( "p", [
438
+ "No fields, did you ",
439
+ m("a", {
440
+ onclick: function() { tabs.open('settings'); }
441
+ }, "select a MailChimp list in the form settings?")
442
+ ])
443
+ ]);
444
+
445
+ // build DOM for overlay
446
+ var form = null;
447
+ if( fieldConfig ) {
448
+ form = overlay(
449
+ // field wizard
450
+ m("div.field-wizard", [
451
+
452
+ //heading
453
+ m("h3", [
454
+ fieldConfig.title(),
455
+ fieldConfig.required() ? m('span.red', '*' ) : '',
456
+ fieldConfig.name().length ? m("code", fieldConfig.name()) : ''
457
+ ]),
458
+
459
+ // help text
460
+ ( fieldConfig.help().length ) ? m('p', m.trust( fieldConfig.help() ) ) : '',
461
+
462
+ // actual form
463
+ forms.render(fieldConfig),
464
+
465
+ // add to form button
466
+ m("p", [
467
+ m("button", {
468
+ "class": "button-primary",
469
+ type: "button",
470
+ onclick: createFieldHTMLAndAddToForm
471
+ }, "Add to form" )
472
+ ])
473
+ ]), setActiveField);
474
+ }
475
+
476
+ return [
477
+ fieldsChoice,
478
+ form
479
+ ];
480
+ }
481
+
482
+ // expose some variables
483
+ return {
484
+ view: view,
485
+ controller: controller
486
+ }
487
+ };
488
+
489
+ module.exports = FieldHelper;
490
+ },{"./field-forms.js":2,"./field-generator.js":3,"./overlay.js":9}],5:[function(require,module,exports){
491
+ var FieldFactory = function(settings, fields) {
492
+ 'use strict';
493
+
494
+ /**
495
+ * Array of registered fields
496
+ *
497
+ * @type {Array}
498
+ */
499
+ var registeredFields = [];
500
+
501
+ /**
502
+ * Reset all previously registered fields
503
+ */
504
+ function reset() {
505
+ // clear all of our fields
506
+ registeredFields.forEach(function(field) {
507
+ fields.deregister(field);
508
+ });
509
+ }
510
+
511
+ /**
512
+ * Helper function to quickly register a field and store it in local scope
513
+ *
514
+ * @param data
515
+ */
516
+ function register(data) {
517
+ var field = fields.register(data);
518
+ registeredFields.push(field);
519
+ }
520
+
521
+ /**
522
+ * Normalizes the field type which is passed by MailChimp
523
+ *
524
+ * @todo Maybe do this server-side?
525
+ *
526
+ * @param type
527
+ * @returns {*}
528
+ */
529
+ function getFieldType(type) {
530
+ switch(type) {
531
+ case 'phone':
532
+ return 'tel';
533
+ break;
534
+
535
+ case 'dropdown':
536
+ return 'select';
537
+
538
+ case 'checkboxes':
539
+ return 'checkbox';
540
+ }
541
+
542
+ return type;
543
+ }
544
+
545
+ /**
546
+ * Register the various fields for a merge var
547
+ *
548
+ * @param mergeVar
549
+ * @returns {boolean}
550
+ */
551
+ function registerMergeVar(mergeVar) {
552
+
553
+ // only register merge var field if it's public
554
+ if( ! mergeVar.public ) {
555
+ return false;
556
+ }
557
+
558
+ // name, type, title, value, required, label, placeholder, choices, wrap
559
+ var data = {
560
+ name: mergeVar.tag,
561
+ title: mergeVar.name,
562
+ required: mergeVar.required,
563
+ type: getFieldType(mergeVar.field_type),
564
+ choices: mergeVar.choices
565
+ };
566
+
567
+ if( data.type !== 'address' ) {
568
+ register(data);
569
+ } else {
570
+ register({ name: data.name + '[addr1]', type: 'text', title: 'Street Address' });
571
+ register({ name: data.name + '[city]', type: 'text', title: 'City' });
572
+ register({ name: data.name + '[state]', type: 'text', title: 'State' });
573
+ register({ name: data.name + '[zip]', type: 'text', title: 'ZIP' });
574
+ register({ name: data.name + '[country]', type: 'select', title: 'Country', choices: mc4wp_vars.countries });
575
+ }
576
+
577
+ return true;
578
+ }
579
+
580
+ /**
581
+ * Register a field for a MailChimp grouping
582
+ *
583
+ * @param grouping
584
+ */
585
+ function registerGrouping(grouping){
586
+
587
+ var data = {
588
+ title: grouping.name,
589
+ name: 'GROUPINGS[' + grouping.id + ']',
590
+ type: getFieldType(grouping.field_type),
591
+ choices: grouping.groups
592
+ };
593
+ register(data);
594
+ }
595
+
596
+ /**
597
+ * Register all fields belonging to a list
598
+ *
599
+ * @param list
600
+ */
601
+ function registerListFields(list) {
602
+ // loop through merge vars
603
+ list.merge_vars.forEach(registerMergeVar);
604
+
605
+ // loop through groupings
606
+ list.groupings.forEach(registerGrouping);
607
+ }
608
+
609
+ function registerCustomFields(lists) {
610
+
611
+ var choices;
612
+
613
+ // register submit button
614
+ register({
615
+ name: '',
616
+ value: "Subscribe",
617
+ type: "submit",
618
+ title: "Submit Button"
619
+ });
620
+
621
+ // register lists choice field
622
+ choices = {};
623
+ lists.forEach(function(list) {
624
+ choices[list.id] = list.name;
625
+ });
626
+ register({
627
+ name: '_mc4wp_lists',
628
+ type: 'checkbox',
629
+ title: "List Choice",
630
+ choices: choices,
631
+ help: 'This field will allow your visitors to choose a list to subscribe to. <a href="#" data-tab="settings" class="tab-link">Click here to select more lists to show</a>.'
632
+ });
633
+
634
+ choices = {
635
+ 'subscribe': "Subscribe",
636
+ 'unsubscribe': "Unsubscribe"
637
+ };
638
+ register({
639
+ name: '_mc4wp_action',
640
+ type: 'radio',
641
+ title: "Subscribe / Unsubscribe",
642
+ choices: choices,
643
+ value: 'subscribe',
644
+ help: 'This field will allow your visitors to choose whether they would like to subscribe or unsubscribe'
645
+ });
646
+ }
647
+
648
+ /**
649
+ * Update list fields
650
+ *
651
+ * @param lists
652
+ */
653
+ function work(lists) {
654
+
655
+ // clear our fields
656
+ reset();
657
+
658
+ // register list specific fields
659
+ lists.forEach(registerListFields);
660
+
661
+ // register global fields like "submit" & "list choice"
662
+ registerCustomFields(lists);
663
+ }
664
+
665
+ /**
666
+ * Expose some methods
667
+ */
668
+ return {
669
+ 'work': work
670
+ }
671
+
672
+ };
673
+
674
+ module.exports = FieldFactory;
675
+ },{}],6:[function(require,module,exports){
676
+ module.exports = function(m, events) {
677
+ 'use strict';
678
+
679
+ /**
680
+ * @internal
681
+ *
682
+ *
683
+ * @param data
684
+ * @constructor
685
+ */
686
+ var Field = function (data) {
687
+ this.name = m.prop(data.name);
688
+ this.title = m.prop(data.title || data.name);
689
+
690
+ this.type = m.prop(data.type);
691
+ this.label = m.prop(data.title || '');
692
+ this.value = m.prop(data.value || '');
693
+ this.placeholder = m.prop(data.placeholder || true);
694
+ this.required = m.prop(data.required || false);
695
+ this.wrap = m.prop(data.wrap || true);
696
+ this.min = m.prop(data.min || null);
697
+ this.max = m.prop(data.max || null);
698
+ this.help = m.prop(data.help || '');
699
+ this.choices = m.prop(data.choices || []);
700
+ this.inFormContent = m.prop(null);
701
+
702
+ this.selectChoice = function(value) {
703
+ var field = this;
704
+
705
+ this.choices(this.choices().map(function(choice) {
706
+
707
+ if( choice.value() === value ) {
708
+ choice.selected(true);
709
+ } else {
710
+ // only checkboxes allow for multiple selections
711
+ if(field.type() !== 'checkbox' ) {
712
+ choice.selected(false);
713
+ }
714
+ }
715
+
716
+ return choice;
717
+
718
+ }) );
719
+ }
720
+ };
721
+
722
+ /**
723
+ * @internal
724
+ *
725
+ * @param data
726
+ * @constructor
727
+ */
728
+ var FieldChoice = function (data) {
729
+ this.label = m.prop(data.label);
730
+ this.title = m.prop(data.title || data.label);
731
+ this.selected = m.prop(data.selected || false);
732
+ this.value = m.prop(data.value || data.label);
733
+ };
734
+
735
+
736
+ /**
737
+ * @api
738
+ *
739
+ * @returns {{fields: {}, get: get, getAll: getAll, deregister: deregister, register: register}}
740
+ * @constructor
741
+ */
742
+ var fields = [];
743
+
744
+ /**
745
+ * Creates FieldChoice objects from an (associative) array of data objects
746
+ *
747
+ * @param data
748
+ * @returns {Array}
749
+ */
750
+ function createChoices(data) {
751
+ var choices = [];
752
+ if (typeof( data.map ) === "function") {
753
+ choices = data.map(function (choiceLabel) {
754
+ return new FieldChoice({label: choiceLabel});
755
+ });
756
+ } else {
757
+ choices = Object.keys(data).map(function (key) {
758
+ var choiceLabel = data[key];
759
+ return new FieldChoice({label: choiceLabel, value: key});
760
+ });
761
+ }
762
+
763
+ return choices;
764
+ }
765
+
766
+ /**
767
+ * Factory method
768
+ *
769
+ * @api
770
+ *
771
+ * @param data
772
+ * @returns {Field}
773
+ */
774
+ function register(data) {
775
+ var field;
776
+ var existingField = getAllWhere('name', data.name).shift();
777
+
778
+ // a field with the same "name" already exists
779
+ if(existingField) {
780
+
781
+ // update "required" status
782
+ if( ! existingField.required() && data.required ) {
783
+ existingField.required(true);
784
+ }
785
+
786
+ // bail
787
+ return undefined;
788
+ }
789
+
790
+ // array of choices given? convert to FieldChoice objects
791
+ if (data.choices) {
792
+ data.choices = createChoices(data.choices);
793
+
794
+ if( data.value) {
795
+ data.choices = data.choices.map(function(choice) {
796
+ if(choice.value() === data.value) {
797
+ choice.selected(true);
798
+ }
799
+ return choice;
800
+ });
801
+ }
802
+ }
803
+
804
+ // create Field object
805
+ field = new Field(data);
806
+ fields.push(field);
807
+
808
+ // redraw view
809
+ m.redraw();
810
+
811
+ // trigger event
812
+ events.trigger('fields.change');
813
+
814
+ return field;
815
+ }
816
+
817
+ /**
818
+ * @api
819
+ *
820
+ * @param field
821
+ */
822
+ function deregister(field) {
823
+ var index = fields.indexOf(field);
824
+ if (index > -1) {
825
+ delete fields[index];
826
+ m.redraw();
827
+ }
828
+ }
829
+
830
+ /**
831
+ * Get a field config object
832
+ *
833
+ * @param name
834
+ * @returns {*}
835
+ */
836
+ function get(name) {
837
+ return fields[name];
838
+ }
839
+
840
+ /**
841
+ * Get all field config objects
842
+ *
843
+ * @returns {Array|*}
844
+ */
845
+ function getAll() {
846
+ return fields;
847
+ }
848
+
849
+ /**
850
+ * Get all fields where a property matches the given value
851
+ *
852
+ * @param searchKey
853
+ * @param searchValue
854
+ * @returns {Array|*}
855
+ */
856
+ function getAllWhere(searchKey, searchValue) {
857
+ return fields.filter(function (field) {
858
+ return field[searchKey]() === searchValue;
859
+ });
860
+ }
861
+
862
+
863
+ /**
864
+ * Exposed methods
865
+ */
866
+ return {
867
+ 'fields' : fields,
868
+ 'get' : get,
869
+ 'getAll' : getAll,
870
+ 'deregister' : deregister,
871
+ 'register' : register,
872
+ 'getAllWhere': getAllWhere
873
+ };
874
+ };
875
+ },{}],7:[function(require,module,exports){
876
+ /* Editor */
877
+ var FormEditor = function(element) {
878
+
879
+ // create dom representation of form
880
+ var _dom = document.createElement('form')
881
+ , domDirty = false,
882
+ r = {},
883
+ editor;
884
+ _dom.innerHTML = element.value.toLowerCase();
885
+
886
+ // load CodeMirror & plugins
887
+ var CodeMirror = require('codemirror');
888
+ require('codemirror/mode/xml/xml');
889
+ require('codemirror/mode/javascript/javascript');
890
+ require('codemirror/mode/css/css');
891
+ require('codemirror/mode/htmlmixed/htmlmixed');
892
+ require('codemirror/addon/fold/xml-fold');
893
+ require('codemirror/addon/edit/matchtags');
894
+ require('codemirror/addon/edit/closetag.js');
895
+
896
+ if( CodeMirror ) {
897
+ editor = CodeMirror.fromTextArea(element, {
898
+ selectionPointer: true,
899
+ matchTags: { bothTags: true },
900
+ mode: "htmlmixed",
901
+ htmlMode: true,
902
+ autoCloseTags: true,
903
+ autoRefresh: true
904
+ });
905
+
906
+ // dispatch regular "change" on element event every time editor changes (IE9+ only)
907
+ window.dispatchEvent && editor.on('change',function() {
908
+ if(typeof(Event) === "function") {
909
+ // Create a new 'change' event
910
+ var event = new Event('change', { bubbles: true });
911
+ element.dispatchEvent(event);
912
+ }
913
+ });
914
+ }
915
+
916
+ // set domDirty to true everytime the "change" event fires (a lot..)
917
+ element.addEventListener && element.addEventListener('change',function() {
918
+ domDirty = true;
919
+ });
920
+
921
+ function dom() {
922
+ if( domDirty ) {
923
+ _dom.innerHTML = r.getValue().toLowerCase();
924
+ domDirty = false;
925
+ }
926
+
927
+ return _dom;
928
+ }
929
+
930
+ r.getValue = function() {
931
+ if( editor ) {
932
+ return editor.getValue();
933
+ }
934
+
935
+ return element.value;
936
+ };
937
+
938
+ r.query = function(query) {
939
+ return dom().querySelectorAll(query);
940
+ };
941
+
942
+ r.containsField = function(fieldName){
943
+ return r.query('[name^="'+ fieldName.toLowerCase() +'"]').length > 0;
944
+ };
945
+
946
+ r.insert = function( html ) {
947
+ if( editor ) {
948
+ editor.replaceSelection( html );
949
+ editor.focus();
950
+ }
951
+
952
+ element.value += html;
953
+ };
954
+
955
+ r.on = function(event,callback) {
956
+ if( editor ) {
957
+
958
+ // translate "input" event for CodeMirror
959
+ if( event === 'input' ) {
960
+ event = 'changes';
961
+ }
962
+
963
+ return editor.on(event,callback);
964
+ }
965
+
966
+ return element.addEventListener(event,callback);
967
+ };
968
+
969
+ r.refresh = function() {
970
+ if( editor ) {
971
+ editor.refresh();
972
+ }
973
+ };
974
+
975
+ return r;
976
+ };
977
+
978
+ module.exports = FormEditor;
979
+ },{"codemirror":16,"codemirror/addon/edit/closetag.js":13,"codemirror/addon/edit/matchtags":14,"codemirror/addon/fold/xml-fold":15,"codemirror/mode/css/css":17,"codemirror/mode/htmlmixed/htmlmixed":18,"codemirror/mode/javascript/javascript":19,"codemirror/mode/xml/xml":20}],8:[function(require,module,exports){
980
+ var FormWatcher = function(m, editor, settings, fields, events) {
981
+ 'use strict';
982
+
983
+ var missingFieldsNotice = document.getElementById('missing-fields-notice');
984
+ var missingFieldsNoticeList = missingFieldsNotice.querySelector('ul');
985
+ var requiredFieldsInput = document.getElementById('required-fields');
986
+
987
+ // polling
988
+ function debounce(func, wait, immediate) {
989
+ var timeout;
990
+ return function() {
991
+ var context = this, args = arguments;
992
+ var later = function() {
993
+ timeout = null;
994
+ if (!immediate) func.apply(context, args);
995
+ };
996
+ var callNow = immediate && !timeout;
997
+ clearTimeout(timeout);
998
+ timeout = setTimeout(later, wait);
999
+ if (callNow) func.apply(context, args);
1000
+ };
1001
+ }
1002
+
1003
+ function updateFields() {
1004
+ fields.getAll().forEach(function(field) {
1005
+ // don't run for empty field names
1006
+ if(field.name().length <= 0) return;
1007
+
1008
+ var inForm = editor.containsField( field.name() );
1009
+ field.inFormContent( inForm );
1010
+ });
1011
+
1012
+ checkRequiredFields();
1013
+
1014
+ m.redraw();
1015
+ }
1016
+
1017
+ // functions
1018
+ function checkRequiredFields() {
1019
+
1020
+ var requiredFields = fields.getAllWhere('required', true);
1021
+
1022
+ // check presence for each required field
1023
+ var missingFields = [];
1024
+ requiredFields.forEach(function(field) {
1025
+ if( ! field.inFormContent() ) {
1026
+ missingFields.push(field);
1027
+ }
1028
+ });
1029
+
1030
+ // do nothing if no fields are missing
1031
+ if( missingFields.length === 0 ) {
1032
+ missingFieldsNotice.style.display = 'none';
1033
+ return;
1034
+ }
1035
+
1036
+ // show notice
1037
+ var listItems = '';
1038
+ missingFields.forEach(function( field ) {
1039
+ listItems += "<li>" + field.label() + " (<code>" + field.name() + "</code>)</li>";
1040
+ });
1041
+
1042
+ missingFieldsNoticeList.innerHTML = listItems;
1043
+ missingFieldsNotice.style.display = 'block';
1044
+ }
1045
+
1046
+ function findRequiredFields() {
1047
+
1048
+ // query fields required by MailChimp
1049
+ var requiredFields = fields.getAllWhere('required', true).map(function(f) {
1050
+ return f.name().toUpperCase();
1051
+ });
1052
+
1053
+ // query fields with [required] attribute
1054
+ var requiredFieldElements = editor.query('[required]');
1055
+ Array.prototype.forEach.call(requiredFieldElements, function(el) {
1056
+ var name = el.name.toUpperCase();
1057
+
1058
+ // only add field if it's not already in it
1059
+ if( requiredFields.indexOf(name) === -1 ) {
1060
+ requiredFields.push(name);
1061
+ }
1062
+ });
1063
+
1064
+ // update meta
1065
+ requiredFieldsInput.value = requiredFields.join(',');
1066
+ }
1067
+
1068
+ // events
1069
+ editor.on('change', debounce(updateFields,334));
1070
+ editor.on('blur', findRequiredFields );
1071
+ events.on('fields.change', debounce(updateFields, 500));
1072
+
1073
+ };
1074
+
1075
+ module.exports = FormWatcher;
1076
+ },{}],9:[function(require,module,exports){
1077
+ var overlay = function( m ) {
1078
+ 'use strict';
1079
+
1080
+ var _element,
1081
+ _onCloseCallback;
1082
+
1083
+ function onKeyDown(e) {
1084
+ e = e || window.event;
1085
+
1086
+ if (e.keyCode == 27 && _onCloseCallback ) {
1087
+ _onCloseCallback();
1088
+ }
1089
+ }
1090
+
1091
+ function position() {
1092
+ if( ! _element ) return;
1093
+
1094
+ // fix for window width in IE8
1095
+ var windowWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
1096
+ var windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
1097
+
1098
+ var marginLeft = ( windowWidth - _element.clientWidth - 40 ) / 2;
1099
+ var marginTop = ( windowHeight - _element.clientHeight - 40 ) / 2;
1100
+
1101
+ _element.style.left = ( marginLeft > 0 ? marginLeft : 0 ) + "px";
1102
+ _element.style.top = ( marginTop > 0 ? marginTop : 0 ) + "px";
1103
+ }
1104
+
1105
+ // bind events (IE8 compatible)
1106
+ if (document.addEventListener) {
1107
+ document.addEventListener('keydown', onKeyDown);
1108
+ window.addEventListener('resize', position);
1109
+ } else if(document.attachEvent) {
1110
+ document.attachEvent('onkeydown', onKeyDown);
1111
+ window.attachEvent('onresize', position);
1112
+ }
1113
+
1114
+ return function (content, onCloseCallback) {
1115
+ _onCloseCallback = onCloseCallback;
1116
+
1117
+ return [
1118
+ m('div.overlay-wrap',
1119
+ m("div.overlay", {
1120
+ config: function (el) {
1121
+ _element = el;
1122
+ position();
1123
+ }
1124
+ },[
1125
+
1126
+ // close icon
1127
+ m('span', {
1128
+ "class": 'close dashicons dashicons-no',
1129
+ title : "Click to close the overlay.",
1130
+ onclick: onCloseCallback
1131
+ }),
1132
+
1133
+ content
1134
+ ])
1135
+ )
1136
+ ,
1137
+ m('div.overlay-background', {
1138
+ title : "Click to close the overlay.",
1139
+ onclick: onCloseCallback
1140
+ })
1141
+ ];
1142
+ };
1143
+ };
1144
+
1145
+ module.exports = overlay;
1146
+ },{}],10:[function(require,module,exports){
1147
+ 'use strict';
1148
+
1149
+ // deps
1150
+ var m = window.mc4wp.deps.mithril;
1151
+ var events = mc4wp.events;
1152
+ var settings = mc4wp.settings;
1153
+ var tabs = mc4wp.tabs;
1154
+ var FormWatcher = require('./admin/form-watcher.js');
1155
+ var FormEditor = require('./admin/form-editor.js');
1156
+ var FieldHelper = require('./admin/field-helper.js');
1157
+ var FieldsFactory = require('./admin/fields-factory.js');
1158
+ var fields = require('./admin/fields.js')(m, events);
1159
+
1160
+ // vars
1161
+ var textareaElement = document.getElementById('mc4wp-form-content');
1162
+ var editor = window.formEditor = new FormEditor( textareaElement );
1163
+ var watcher = new FormWatcher( m, formEditor, settings, fields, events );
1164
+ var fieldHelper = new FieldHelper( m, tabs, formEditor, fields );
1165
+
1166
+ // mount field helper on element
1167
+ m.mount( document.getElementById( 'mc4wp-field-wizard'), fieldHelper );
1168
+
1169
+ // register fields and redraw screen in 2 seconds (fixes IE8 bug)
1170
+ var fieldsFactory = new FieldsFactory(settings,fields);
1171
+ events.on('selectedLists.change', fieldsFactory.work);
1172
+ fieldsFactory.work(settings.getSelectedLists());
1173
+ window.setTimeout( function() {m.redraw();}, 2000 );
1174
+
1175
+ // expose some methods
1176
+ window.mc4wp = window.mc4wp || {};
1177
+ window.mc4wp.forms = window.mc4wp.forms || {};
1178
+ window.mc4wp.forms.editor = editor;
1179
+ window.mc4wp.forms.fields = fields;
1180
+
1181
+ },{"./admin/field-helper.js":4,"./admin/fields-factory.js":5,"./admin/fields.js":6,"./admin/form-editor.js":7,"./admin/form-watcher.js":8}],11:[function(require,module,exports){
1182
+ /*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
1183
+ /*
1184
+
1185
+ The MIT License (MIT)
1186
+
1187
+ Copyright (c) 2007-2013 Einar Lielmanis and contributors.
1188
+
1189
+ Permission is hereby granted, free of charge, to any person
1190
+ obtaining a copy of this software and associated documentation files
1191
+ (the "Software"), to deal in the Software without restriction,
1192
+ including without limitation the rights to use, copy, modify, merge,
1193
+ publish, distribute, sublicense, and/or sell copies of the Software,
1194
+ and to permit persons to whom the Software is furnished to do so,
1195
+ subject to the following conditions:
1196
+
1197
+ The above copyright notice and this permission notice shall be
1198
+ included in all copies or substantial portions of the Software.
1199
+
1200
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1201
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1202
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1203
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1204
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1205
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1206
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1207
+ SOFTWARE.
1208
+
1209
+
1210
+ Style HTML
1211
+ ---------------
1212
+
1213
+ Written by Nochum Sossonko, (nsossonko@hotmail.com)
1214
+
1215
+ Based on code initially developed by: Einar Lielmanis, <elfz@laacz.lv>
1216
+ http://jsbeautifier.org/
1217
+
1218
+ Usage:
1219
+ style_html(html_source);
1220
+
1221
+ style_html(html_source, options);
1222
+
1223
+ The options are:
1224
+ indent_inner_html (default false) — indent <head> and <body> sections,
1225
+ indent_size (default 4) — indentation size,
1226
+ indent_char (default space) — character to indent with,
1227
+ wrap_line_length (default 250) - maximum amount of characters per line (0 = disable)
1228
+ brace_style (default "collapse") - "collapse" | "expand" | "end-expand"
1229
+ put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line.
1230
+ unformatted (defaults to inline tags) - list of tags, that shouldn't be reformatted
1231
+ indent_scripts (default normal) - "keep"|"separate"|"normal"
1232
+ preserve_newlines (default true) - whether existing line breaks before elements should be preserved
1233
+ Only works before elements, not inside tags or for text.
1234
+ max_preserve_newlines (default unlimited) - maximum number of line breaks to be preserved in one chunk
1235
+ indent_handlebars (default false) - format and indent {{#foo}} and {{/foo}}
1236
+
1237
+ e.g.
1238
+
1239
+ style_html(html_source, {
1240
+ 'indent_inner_html': false,
1241
+ 'indent_size': 2,
1242
+ 'indent_char': ' ',
1243
+ 'wrap_line_length': 78,
1244
+ 'brace_style': 'expand',
1245
+ 'unformatted': ['a', 'sub', 'sup', 'b', 'i', 'u'],
1246
+ 'preserve_newlines': true,
1247
+ 'max_preserve_newlines': 5,
1248
+ 'indent_handlebars': false
1249
+ });
1250
+ */
1251
+
1252
+ (function() {
1253
+
1254
+ function trim(s) {
1255
+ return s.replace(/^\s+|\s+$/g, '');
1256
+ }
1257
+
1258
+ function ltrim(s) {
1259
+ return s.replace(/^\s+/g, '');
1260
+ }
1261
+
1262
+ function style_html(html_source, options, js_beautify, css_beautify) {
1263
+ //Wrapper function to invoke all the necessary constructors and deal with the output.
1264
+
1265
+ var multi_parser,
1266
+ indent_inner_html,
1267
+ indent_size,
1268
+ indent_character,
1269
+ wrap_line_length,
1270
+ brace_style,
1271
+ unformatted,
1272
+ preserve_newlines,
1273
+ max_preserve_newlines;
1274
+
1275
+ options = options || {};
1276
+
1277
+ // backwards compatibility to 1.3.4
1278
+ if ((options.wrap_line_length === undefined || parseInt(options.wrap_line_length, 10) === 0) &&
1279
+ (options.max_char === undefined || parseInt(options.max_char, 10) === 0)) {
1280
+ options.wrap_line_length = options.max_char;
1281
+ }
1282
+
1283
+ indent_inner_html = options.indent_inner_html || false;
1284
+ indent_size = parseInt(options.indent_size || 4, 10);
1285
+ indent_character = options.indent_char || ' ';
1286
+ brace_style = options.brace_style || 'collapse';
1287
+ wrap_line_length = parseInt(options.wrap_line_length, 10) === 0 ? 32786 : parseInt(options.wrap_line_length || 250, 10);
1288
+ unformatted = options.unformatted || ['a', 'span', 'bdo', 'em', 'strong', 'dfn', 'code', 'samp', 'kbd', 'var', 'cite', 'abbr', 'acronym', 'q', 'sub', 'sup', 'tt', 'i', 'b', 'big', 'small', 'u', 's', 'strike', 'font', 'ins', 'del', 'pre', 'address', 'dt', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
1289
+ preserve_newlines = options.preserve_newlines || true;
1290
+ max_preserve_newlines = preserve_newlines ? parseInt(options.max_preserve_newlines || 32786, 10) : 0;
1291
+ indent_handlebars = options.indent_handlebars || false;
1292
+
1293
+ function Parser() {
1294
+
1295
+ this.pos = 0; //Parser position
1296
+ this.token = '';
1297
+ this.current_mode = 'CONTENT'; //reflects the current Parser mode: TAG/CONTENT
1298
+ this.tags = { //An object to hold tags, their position, and their parent-tags, initiated with default values
1299
+ parent: 'parent1',
1300
+ parentcount: 1,
1301
+ parent1: ''
1302
+ };
1303
+ this.tag_type = '';
1304
+ this.token_text = this.last_token = this.last_text = this.token_type = '';
1305
+ this.newlines = 0;
1306
+ this.indent_content = indent_inner_html;
1307
+
1308
+ this.Utils = { //Uilities made available to the various functions
1309
+ whitespace: "\n\r\t ".split(''),
1310
+ single_token: 'br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed,?php,?,?='.split(','), //all the single tags for HTML
1311
+ extra_liners: 'head,body,/html'.split(','), //for tags that need a line of whitespace before them
1312
+ in_array: function(what, arr) {
1313
+ for (var i = 0; i < arr.length; i++) {
1314
+ if (what === arr[i]) {
1315
+ return true;
1316
+ }
1317
+ }
1318
+ return false;
1319
+ }
1320
+ };
1321
+
1322
+ this.traverse_whitespace = function() {
1323
+ var input_char = '';
1324
+
1325
+ input_char = this.input.charAt(this.pos);
1326
+ if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
1327
+ this.newlines = 0;
1328
+ while (this.Utils.in_array(input_char, this.Utils.whitespace)) {
1329
+ if (preserve_newlines && input_char === '\n' && this.newlines <= max_preserve_newlines) {
1330
+ this.newlines += 1;
1331
+ }
1332
+
1333
+ this.pos++;
1334
+ input_char = this.input.charAt(this.pos);
1335
+ }
1336
+ return true;
1337
+ }
1338
+ return false;
1339
+ };
1340
+
1341
+ this.get_content = function() { //function to capture regular content between tags
1342
+
1343
+ var input_char = '',
1344
+ content = [],
1345
+ space = false; //if a space is needed
1346
+
1347
+ while (this.input.charAt(this.pos) !== '<') {
1348
+ if (this.pos >= this.input.length) {
1349
+ return content.length ? content.join('') : ['', 'TK_EOF'];
1350
+ }
1351
+
1352
+ if (this.traverse_whitespace()) {
1353
+ if (content.length) {
1354
+ space = true;
1355
+ }
1356
+ continue; //don't want to insert unnecessary space
1357
+ }
1358
+
1359
+ if (indent_handlebars) {
1360
+ // Handlebars parsing is complicated.
1361
+ // {{#foo}} and {{/foo}} are formatted tags.
1362
+ // {{something}} should get treated as content, except:
1363
+ // {{else}} specifically behaves like {{#if}} and {{/if}}
1364
+ var peek3 = this.input.substr(this.pos, 3);
1365
+ if (peek3 === '{{#' || peek3 === '{{/') {
1366
+ // These are tags and not content.
1367
+ break;
1368
+ } else if (this.input.substr(this.pos, 2) === '{{') {
1369
+ if (this.get_tag(true) === '{{else}}') {
1370
+ break;
1371
+ }
1372
+ }
1373
+ }
1374
+
1375
+ input_char = this.input.charAt(this.pos);
1376
+ this.pos++;
1377
+
1378
+ if (space) {
1379
+ if (this.line_char_count >= this.wrap_line_length) { //insert a line when the wrap_line_length is reached
1380
+ this.print_newline(false, content);
1381
+ this.print_indentation(content);
1382
+ } else {
1383
+ this.line_char_count++;
1384
+ content.push(' ');
1385
+ }
1386
+ space = false;
1387
+ }
1388
+ this.line_char_count++;
1389
+ content.push(input_char); //letter at-a-time (or string) inserted to an array
1390
+ }
1391
+ return content.length ? content.join('') : '';
1392
+ };
1393
+
1394
+ this.get_contents_to = function(name) { //get the full content of a script or style to pass to js_beautify
1395
+ if (this.pos === this.input.length) {
1396
+ return ['', 'TK_EOF'];
1397
+ }
1398
+ var input_char = '';
1399
+ var content = '';
1400
+ var reg_match = new RegExp('</' + name + '\\s*>', 'igm');
1401
+ reg_match.lastIndex = this.pos;
1402
+ var reg_array = reg_match.exec(this.input);
1403
+ var end_script = reg_array ? reg_array.index : this.input.length; //absolute end of script
1404
+ if (this.pos < end_script) { //get everything in between the script tags
1405
+ content = this.input.substring(this.pos, end_script);
1406
+ this.pos = end_script;
1407
+ }
1408
+ return content;
1409
+ };
1410
+
1411
+ this.record_tag = function(tag) { //function to record a tag and its parent in this.tags Object
1412
+ if (this.tags[tag + 'count']) { //check for the existence of this tag type
1413
+ this.tags[tag + 'count']++;
1414
+ this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
1415
+ } else { //otherwise initialize this tag type
1416
+ this.tags[tag + 'count'] = 1;
1417
+ this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
1418
+ }
1419
+ this.tags[tag + this.tags[tag + 'count'] + 'parent'] = this.tags.parent; //set the parent (i.e. in the case of a div this.tags.div1parent)
1420
+ this.tags.parent = tag + this.tags[tag + 'count']; //and make this the current parent (i.e. in the case of a div 'div1')
1421
+ };
1422
+
1423
+ this.retrieve_tag = function(tag) { //function to retrieve the opening tag to the corresponding closer
1424
+ if (this.tags[tag + 'count']) { //if the openener is not in the Object we ignore it
1425
+ var temp_parent = this.tags.parent; //check to see if it's a closable tag.
1426
+ while (temp_parent) { //till we reach '' (the initial value);
1427
+ if (tag + this.tags[tag + 'count'] === temp_parent) { //if this is it use it
1428
+ break;
1429
+ }
1430
+ temp_parent = this.tags[temp_parent + 'parent']; //otherwise keep on climbing up the DOM Tree
1431
+ }
1432
+ if (temp_parent) { //if we caught something
1433
+ this.indent_level = this.tags[tag + this.tags[tag + 'count']]; //set the indent_level accordingly
1434
+ this.tags.parent = this.tags[temp_parent + 'parent']; //and set the current parent
1435
+ }
1436
+ delete this.tags[tag + this.tags[tag + 'count'] + 'parent']; //delete the closed tags parent reference...
1437
+ delete this.tags[tag + this.tags[tag + 'count']]; //...and the tag itself
1438
+ if (this.tags[tag + 'count'] === 1) {
1439
+ delete this.tags[tag + 'count'];
1440
+ } else {
1441
+ this.tags[tag + 'count']--;
1442
+ }
1443
+ }
1444
+ };
1445
+
1446
+ this.indent_to_tag = function(tag) {
1447
+ // Match the indentation level to the last use of this tag, but don't remove it.
1448
+ if (!this.tags[tag + 'count']) {
1449
+ return;
1450
+ }
1451
+ var temp_parent = this.tags.parent;
1452
+ while (temp_parent) {
1453
+ if (tag + this.tags[tag + 'count'] === temp_parent) {
1454
+ break;
1455
+ }
1456
+ temp_parent = this.tags[temp_parent + 'parent'];
1457
+ }
1458
+ if (temp_parent) {
1459
+ this.indent_level = this.tags[tag + this.tags[tag + 'count']];
1460
+ }
1461
+ };
1462
+
1463
+ this.get_tag = function(peek) { //function to get a full tag and parse its type
1464
+ var input_char = '',
1465
+ content = [],
1466
+ comment = '',
1467
+ space = false,
1468
+ tag_start, tag_end,
1469
+ tag_start_char,
1470
+ orig_pos = this.pos,
1471
+ orig_line_char_count = this.line_char_count;
1472
+
1473
+ peek = peek !== undefined ? peek : false;
1474
+
1475
+ do {
1476
+ if (this.pos >= this.input.length) {
1477
+ if (peek) {
1478
+ this.pos = orig_pos;
1479
+ this.line_char_count = orig_line_char_count;
1480
+ }
1481
+ return content.length ? content.join('') : ['', 'TK_EOF'];
1482
+ }
1483
+
1484
+ input_char = this.input.charAt(this.pos);
1485
+ this.pos++;
1486
+
1487
+ if (this.Utils.in_array(input_char, this.Utils.whitespace)) { //don't want to insert unnecessary space
1488
+ space = true;
1489
+ continue;
1490
+ }
1491
+
1492
+ if (input_char === "'" || input_char === '"') {
1493
+ input_char += this.get_unformatted(input_char);
1494
+ space = true;
1495
+
1496
+ }
1497
+
1498
+ if (input_char === '=') { //no space before =
1499
+ space = false;
1500
+ }
1501
+
1502
+ if (content.length && content[content.length - 1] !== '=' && input_char !== '>' && space) {
1503
+ //no space after = or before >
1504
+ if (this.line_char_count >= this.wrap_line_length) {
1505
+ this.print_newline(false, content);
1506
+ this.print_indentation(content);
1507
+ } else {
1508
+ content.push(' ');
1509
+ this.line_char_count++;
1510
+ }
1511
+ space = false;
1512
+ }
1513
+
1514
+ if (indent_handlebars && tag_start_char === '<') {
1515
+ // When inside an angle-bracket tag, put spaces around
1516
+ // handlebars not inside of strings.
1517
+ if ((input_char + this.input.charAt(this.pos)) === '{{') {
1518
+ input_char += this.get_unformatted('}}');
1519
+ if (content.length && content[content.length - 1] !== ' ' && content[content.length - 1] !== '<') {
1520
+ input_char = ' ' + input_char;
1521
+ }
1522
+ space = true;
1523
+ }
1524
+ }
1525
+
1526
+ if (input_char === '<' && !tag_start_char) {
1527
+ tag_start = this.pos - 1;
1528
+ tag_start_char = '<';
1529
+ }
1530
+
1531
+ if (indent_handlebars && !tag_start_char) {
1532
+ if (content.length >= 2 && content[content.length - 1] === '{' && content[content.length - 2] == '{') {
1533
+ if (input_char === '#' || input_char === '/') {
1534
+ tag_start = this.pos - 3;
1535
+ } else {
1536
+ tag_start = this.pos - 2;
1537
+ }
1538
+ tag_start_char = '{';
1539
+ }
1540
+ }
1541
+
1542
+ this.line_char_count++;
1543
+ content.push(input_char); //inserts character at-a-time (or string)
1544
+
1545
+ if (content[1] && content[1] === '!') { //if we're in a comment, do something special
1546
+ // We treat all comments as literals, even more than preformatted tags
1547
+ // we just look for the appropriate close tag
1548
+ content = [this.get_comment(tag_start)];
1549
+ break;
1550
+ }
1551
+
1552
+ if (indent_handlebars && tag_start_char === '{' && content.length > 2 && content[content.length - 2] === '}' && content[content.length - 1] === '}') {
1553
+ break;
1554
+ }
1555
+ } while (input_char !== '>');
1556
+
1557
+ var tag_complete = content.join('');
1558
+ var tag_index;
1559
+ var tag_offset;
1560
+
1561
+ if (tag_complete.indexOf(' ') !== -1) { //if there's whitespace, thats where the tag name ends
1562
+ tag_index = tag_complete.indexOf(' ');
1563
+ } else if (tag_complete[0] === '{') {
1564
+ tag_index = tag_complete.indexOf('}');
1565
+ } else { //otherwise go with the tag ending
1566
+ tag_index = tag_complete.indexOf('>');
1567
+ }
1568
+ if (tag_complete[0] === '<' || !indent_handlebars) {
1569
+ tag_offset = 1;
1570
+ } else {
1571
+ tag_offset = tag_complete[2] === '#' ? 3 : 2;
1572
+ }
1573
+ var tag_check = tag_complete.substring(tag_offset, tag_index).toLowerCase();
1574
+ if (tag_complete.charAt(tag_complete.length - 2) === '/' ||
1575
+ this.Utils.in_array(tag_check, this.Utils.single_token)) { //if this tag name is a single tag type (either in the list or has a closing /)
1576
+ if (!peek) {
1577
+ this.tag_type = 'SINGLE';
1578
+ }
1579
+ } else if (indent_handlebars && tag_complete[0] === '{' && tag_check === 'else') {
1580
+ if (!peek) {
1581
+ this.indent_to_tag('if');
1582
+ this.tag_type = 'HANDLEBARS_ELSE';
1583
+ this.indent_content = true;
1584
+ this.traverse_whitespace();
1585
+ }
1586
+ } else if (tag_check === 'script') { //for later script handling
1587
+ if (!peek) {
1588
+ this.record_tag(tag_check);
1589
+ this.tag_type = 'SCRIPT';
1590
+ }
1591
+ } else if (tag_check === 'style') { //for future style handling (for now it justs uses get_content)
1592
+ if (!peek) {
1593
+ this.record_tag(tag_check);
1594
+ this.tag_type = 'STYLE';
1595
+ }
1596
+ } else if (this.is_unformatted(tag_check, unformatted)) { // do not reformat the "unformatted" tags
1597
+ comment = this.get_unformatted('</' + tag_check + '>', tag_complete); //...delegate to get_unformatted function
1598
+ content.push(comment);
1599
+ // Preserve collapsed whitespace either before or after this tag.
1600
+ if (tag_start > 0 && this.Utils.in_array(this.input.charAt(tag_start - 1), this.Utils.whitespace)) {
1601
+ content.splice(0, 0, this.input.charAt(tag_start - 1));
1602
+ }
1603
+ tag_end = this.pos - 1;
1604
+ if (this.Utils.in_array(this.input.charAt(tag_end + 1), this.Utils.whitespace)) {
1605
+ content.push(this.input.charAt(tag_end + 1));
1606
+ }
1607
+ this.tag_type = 'SINGLE';
1608
+ } else if (tag_check.charAt(0) === '!') { //peek for <! comment
1609
+ // for comments content is already correct.
1610
+ if (!peek) {
1611
+ this.tag_type = 'SINGLE';
1612
+ this.traverse_whitespace();
1613
+ }
1614
+ } else if (!peek) {
1615
+ if (tag_check.charAt(0) === '/') { //this tag is a double tag so check for tag-ending
1616
+ this.retrieve_tag(tag_check.substring(1)); //remove it and all ancestors
1617
+ this.tag_type = 'END';
1618
+ this.traverse_whitespace();
1619
+ } else { //otherwise it's a start-tag
1620
+ this.record_tag(tag_check); //push it on the tag stack
1621
+ if (tag_check.toLowerCase() !== 'html') {
1622
+ this.indent_content = true;
1623
+ }
1624
+ this.tag_type = 'START';
1625
+
1626
+ // Allow preserving of newlines after a start tag
1627
+ this.traverse_whitespace();
1628
+ }
1629
+ if (this.Utils.in_array(tag_check, this.Utils.extra_liners)) { //check if this double needs an extra line
1630
+ this.print_newline(false, this.output);
1631
+ if (this.output.length && this.output[this.output.length - 2] !== '\n') {
1632
+ this.print_newline(true, this.output);
1633
+ }
1634
+ }
1635
+ }
1636
+
1637
+ if (peek) {
1638
+ this.pos = orig_pos;
1639
+ this.line_char_count = orig_line_char_count;
1640
+ }
1641
+
1642
+ return content.join(''); //returns fully formatted tag
1643
+ };
1644
+
1645
+ this.get_comment = function(start_pos) { //function to return comment content in its entirety
1646
+ // this is will have very poor perf, but will work for now.
1647
+ var comment = '',
1648
+ delimiter = '>',
1649
+ matched = false;
1650
+
1651
+ this.pos = start_pos;
1652
+ input_char = this.input.charAt(this.pos);
1653
+ this.pos++;
1654
+
1655
+ while (this.pos <= this.input.length) {
1656
+ comment += input_char;
1657
+
1658
+ // only need to check for the delimiter if the last chars match
1659
+ if (comment[comment.length - 1] === delimiter[delimiter.length - 1] &&
1660
+ comment.indexOf(delimiter) !== -1) {
1661
+ break;
1662
+ }
1663
+
1664
+ // only need to search for custom delimiter for the first few characters
1665
+ if (!matched && comment.length < 10) {
1666
+ if (comment.indexOf('<![if') === 0) { //peek for <![if conditional comment
1667
+ delimiter = '<![endif]>';
1668
+ matched = true;
1669
+ } else if (comment.indexOf('<![cdata[') === 0) { //if it's a <[cdata[ comment...
1670
+ delimiter = ']]>';
1671
+ matched = true;
1672
+ } else if (comment.indexOf('<![') === 0) { // some other ![ comment? ...
1673
+ delimiter = ']>';
1674
+ matched = true;
1675
+ } else if (comment.indexOf('<!--') === 0) { // <!-- comment ...
1676
+ delimiter = '-->';
1677
+ matched = true;
1678
+ }
1679
+ }
1680
+
1681
+ input_char = this.input.charAt(this.pos);
1682
+ this.pos++;
1683
+ }
1684
+
1685
+ return comment;
1686
+ };
1687
+
1688
+ this.get_unformatted = function(delimiter, orig_tag) { //function to return unformatted content in its entirety
1689
+
1690
+ if (orig_tag && orig_tag.toLowerCase().indexOf(delimiter) !== -1) {
1691
+ return '';
1692
+ }
1693
+ var input_char = '';
1694
+ var content = '';
1695
+ var min_index = 0;
1696
+ var space = true;
1697
+ do {
1698
+
1699
+ if (this.pos >= this.input.length) {
1700
+ return content;
1701
+ }
1702
+
1703
+ input_char = this.input.charAt(this.pos);
1704
+ this.pos++;
1705
+
1706
+ if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
1707
+ if (!space) {
1708
+ this.line_char_count--;
1709
+ continue;
1710
+ }
1711
+ if (input_char === '\n' || input_char === '\r') {
1712
+ content += '\n';
1713
+ /* Don't change tab indention for unformatted blocks. If using code for html editing, this will greatly affect <pre> tags if they are specified in the 'unformatted array'
1714
+ for (var i=0; i<this.indent_level; i++) {
1715
+ content += this.indent_string;
1716
+ }
1717
+ space = false; //...and make sure other indentation is erased
1718
+ */
1719
+ this.line_char_count = 0;
1720
+ continue;
1721
+ }
1722
+ }
1723
+ content += input_char;
1724
+ this.line_char_count++;
1725
+ space = true;
1726
+
1727
+ if (indent_handlebars && input_char === '{' && content.length && content[content.length - 2] === '{') {
1728
+ // Handlebars expressions in strings should also be unformatted.
1729
+ content += this.get_unformatted('}}');
1730
+ // These expressions are opaque. Ignore delimiters found in them.
1731
+ min_index = content.length;
1732
+ }
1733
+ } while (content.toLowerCase().indexOf(delimiter, min_index) === -1);
1734
+ return content;
1735
+ };
1736
+
1737
+ this.get_token = function() { //initial handler for token-retrieval
1738
+ var token;
1739
+
1740
+ if (this.last_token === 'TK_TAG_SCRIPT' || this.last_token === 'TK_TAG_STYLE') { //check if we need to format javascript
1741
+ var type = this.last_token.substr(7);
1742
+ token = this.get_contents_to(type);
1743
+ if (typeof token !== 'string') {
1744
+ return token;
1745
+ }
1746
+ return [token, 'TK_' + type];
1747
+ }
1748
+ if (this.current_mode === 'CONTENT') {
1749
+ token = this.get_content();
1750
+ if (typeof token !== 'string') {
1751
+ return token;
1752
+ } else {
1753
+ return [token, 'TK_CONTENT'];
1754
+ }
1755
+ }
1756
+
1757
+ if (this.current_mode === 'TAG') {
1758
+ token = this.get_tag();
1759
+ if (typeof token !== 'string') {
1760
+ return token;
1761
+ } else {
1762
+ var tag_name_type = 'TK_TAG_' + this.tag_type;
1763
+ return [token, tag_name_type];
1764
+ }
1765
+ }
1766
+ };
1767
+
1768
+ this.get_full_indent = function(level) {
1769
+ level = this.indent_level + level || 0;
1770
+ if (level < 1) {
1771
+ return '';
1772
+ }
1773
+
1774
+ return Array(level + 1).join(this.indent_string);
1775
+ };
1776
+
1777
+ this.is_unformatted = function(tag_check, unformatted) {
1778
+ //is this an HTML5 block-level link?
1779
+ if (!this.Utils.in_array(tag_check, unformatted)) {
1780
+ return false;
1781
+ }
1782
+
1783
+ if (tag_check.toLowerCase() !== 'a' || !this.Utils.in_array('a', unformatted)) {
1784
+ return true;
1785
+ }
1786
+
1787
+ //at this point we have an tag; is its first child something we want to remain
1788
+ //unformatted?
1789
+ var next_tag = this.get_tag(true /* peek. */ );
1790
+
1791
+ // test next_tag to see if it is just html tag (no external content)
1792
+ var tag = (next_tag || "").match(/^\s*<\s*\/?([a-z]*)\s*[^>]*>\s*$/);
1793
+
1794
+ // if next_tag comes back but is not an isolated tag, then
1795
+ // let's treat the 'a' tag as having content
1796
+ // and respect the unformatted option
1797
+ if (!tag || this.Utils.in_array(tag, unformatted)) {
1798
+ return true;
1799
+ } else {
1800
+ return false;
1801
+ }
1802
+ };
1803
+
1804
+ this.printer = function(js_source, indent_character, indent_size, wrap_line_length, brace_style) { //handles input/output and some other printing functions
1805
+
1806
+ this.input = js_source || ''; //gets the input for the Parser
1807
+ this.output = [];
1808
+ this.indent_character = indent_character;
1809
+ this.indent_string = '';
1810
+ this.indent_size = indent_size;
1811
+ this.brace_style = brace_style;
1812
+ this.indent_level = 0;
1813
+ this.wrap_line_length = wrap_line_length;
1814
+ this.line_char_count = 0; //count to see if wrap_line_length was exceeded
1815
+
1816
+ for (var i = 0; i < this.indent_size; i++) {
1817
+ this.indent_string += this.indent_character;
1818
+ }
1819
+
1820
+ this.print_newline = function(force, arr) {
1821
+ this.line_char_count = 0;
1822
+ if (!arr || !arr.length) {
1823
+ return;
1824
+ }
1825
+ if (force || (arr[arr.length - 1] !== '\n')) { //we might want the extra line
1826
+ arr.push('\n');
1827
+ }
1828
+ };
1829
+
1830
+ this.print_indentation = function(arr) {
1831
+ for (var i = 0; i < this.indent_level; i++) {
1832
+ arr.push(this.indent_string);
1833
+ this.line_char_count += this.indent_string.length;
1834
+ }
1835
+ };
1836
+
1837
+ this.print_token = function(text) {
1838
+ if (text || text !== '') {
1839
+ if (this.output.length && this.output[this.output.length - 1] === '\n') {
1840
+ this.print_indentation(this.output);
1841
+ text = ltrim(text);
1842
+ }
1843
+ }
1844
+ this.print_token_raw(text);
1845
+ };
1846
+
1847
+ this.print_token_raw = function(text) {
1848
+ if (text && text !== '') {
1849
+ if (text.length > 1 && text[text.length - 1] === '\n') {
1850
+ // unformatted tags can grab newlines as their last character
1851
+ this.output.push(text.slice(0, -1));
1852
+ this.print_newline(false, this.output);
1853
+ } else {
1854
+ this.output.push(text);
1855
+ }
1856
+ }
1857
+
1858
+ for (var n = 0; n < this.newlines; n++) {
1859
+ this.print_newline(n > 0, this.output);
1860
+ }
1861
+ this.newlines = 0;
1862
+ };
1863
+
1864
+ this.indent = function() {
1865
+ this.indent_level++;
1866
+ };
1867
+
1868
+ this.unindent = function() {
1869
+ if (this.indent_level > 0) {
1870
+ this.indent_level--;
1871
+ }
1872
+ };
1873
+ };
1874
+ return this;
1875
+ }
1876
+
1877
+ /*_____________________--------------------_____________________*/
1878
+
1879
+ multi_parser = new Parser(); //wrapping functions Parser
1880
+ multi_parser.printer(html_source, indent_character, indent_size, wrap_line_length, brace_style); //initialize starting values
1881
+
1882
+ while (true) {
1883
+ var t = multi_parser.get_token();
1884
+ multi_parser.token_text = t[0];
1885
+ multi_parser.token_type = t[1];
1886
+
1887
+ if (multi_parser.token_type === 'TK_EOF') {
1888
+ break;
1889
+ }
1890
+
1891
+ switch (multi_parser.token_type) {
1892
+ case 'TK_TAG_START':
1893
+ multi_parser.print_newline(false, multi_parser.output);
1894
+ multi_parser.print_token(multi_parser.token_text);
1895
+ if (multi_parser.indent_content) {
1896
+ multi_parser.indent();
1897
+ multi_parser.indent_content = false;
1898
+ }
1899
+ multi_parser.current_mode = 'CONTENT';
1900
+ break;
1901
+ case 'TK_TAG_STYLE':
1902
+ case 'TK_TAG_SCRIPT':
1903
+ multi_parser.print_newline(false, multi_parser.output);
1904
+ multi_parser.print_token(multi_parser.token_text);
1905
+ multi_parser.current_mode = 'CONTENT';
1906
+ break;
1907
+ case 'TK_TAG_END':
1908
+ //Print new line only if the tag has no content and has child
1909
+ if (multi_parser.last_token === 'TK_CONTENT' && multi_parser.last_text === '') {
1910
+ var tag_name = multi_parser.token_text.match(/\w+/)[0];
1911
+ var tag_extracted_from_last_output = null;
1912
+ if (multi_parser.output.length) {
1913
+ tag_extracted_from_last_output = multi_parser.output[multi_parser.output.length - 1].match(/(?:<|{{#)\s*(\w+)/);
1914
+ }
1915
+ if (tag_extracted_from_last_output === null ||
1916
+ tag_extracted_from_last_output[1] !== tag_name) {
1917
+ multi_parser.print_newline(false, multi_parser.output);
1918
+ }
1919
+ }
1920
+ multi_parser.print_token(multi_parser.token_text);
1921
+ multi_parser.current_mode = 'CONTENT';
1922
+ break;
1923
+ case 'TK_TAG_SINGLE':
1924
+ // Don't add a newline before elements that should remain unformatted.
1925
+ var tag_check = multi_parser.token_text.match(/^\s*<([a-z]+)/i);
1926
+ if (!tag_check || !multi_parser.Utils.in_array(tag_check[1], unformatted)) {
1927
+ multi_parser.print_newline(false, multi_parser.output);
1928
+ }
1929
+ multi_parser.print_token(multi_parser.token_text);
1930
+ multi_parser.current_mode = 'CONTENT';
1931
+ break;
1932
+ case 'TK_TAG_HANDLEBARS_ELSE':
1933
+ multi_parser.print_token(multi_parser.token_text);
1934
+ if (multi_parser.indent_content) {
1935
+ multi_parser.indent();
1936
+ multi_parser.indent_content = false;
1937
+ }
1938
+ multi_parser.current_mode = 'CONTENT';
1939
+ break;
1940
+ case 'TK_CONTENT':
1941
+ multi_parser.print_token(multi_parser.token_text);
1942
+ multi_parser.current_mode = 'TAG';
1943
+ break;
1944
+ case 'TK_STYLE':
1945
+ case 'TK_SCRIPT':
1946
+ if (multi_parser.token_text !== '') {
1947
+ multi_parser.print_newline(false, multi_parser.output);
1948
+ var text = multi_parser.token_text,
1949
+ _beautifier,
1950
+ script_indent_level = 1;
1951
+ if (multi_parser.token_type === 'TK_SCRIPT') {
1952
+ _beautifier = typeof js_beautify === 'function' && js_beautify;
1953
+ } else if (multi_parser.token_type === 'TK_STYLE') {
1954
+ _beautifier = typeof css_beautify === 'function' && css_beautify;
1955
+ }
1956
+
1957
+ if (options.indent_scripts === "keep") {
1958
+ script_indent_level = 0;
1959
+ } else if (options.indent_scripts === "separate") {
1960
+ script_indent_level = -multi_parser.indent_level;
1961
+ }
1962
+
1963
+ var indentation = multi_parser.get_full_indent(script_indent_level);
1964
+ if (_beautifier) {
1965
+ // call the Beautifier if avaliable
1966
+ text = _beautifier(text.replace(/^\s*/, indentation), options);
1967
+ } else {
1968
+ // simply indent the string otherwise
1969
+ var white = text.match(/^\s*/)[0];
1970
+ var _level = white.match(/[^\n\r]*$/)[0].split(multi_parser.indent_string).length - 1;
1971
+ var reindent = multi_parser.get_full_indent(script_indent_level - _level);
1972
+ text = text.replace(/^\s*/, indentation)
1973
+ .replace(/\r\n|\r|\n/g, '\n' + reindent)
1974
+ .replace(/\s+$/, '');
1975
+ }
1976
+ if (text) {
1977
+ multi_parser.print_token_raw(indentation + trim(text));
1978
+ multi_parser.print_newline(false, multi_parser.output);
1979
+ }
1980
+ }
1981
+ multi_parser.current_mode = 'TAG';
1982
+ break;
1983
+ }
1984
+ multi_parser.last_token = multi_parser.token_type;
1985
+ multi_parser.last_text = multi_parser.token_text;
1986
+ }
1987
+ return multi_parser.output.join('');
1988
+ }
1989
+
1990
+ if (typeof module !== "undefined" && typeof( module.exports ) !== "undefined" ) {
1991
+ module.exports = style_html;
1992
+ } else if (typeof window !== "undefined") {
1993
+ // If we're running a web page and don't have either of the above, add our one global
1994
+ window.html_beautify = style_html;
1995
+ }
1996
+
1997
+ }());
1998
+ },{}],12:[function(require,module,exports){
1999
+ 'use strict';
2000
+
2001
+ var VOID_TAGS = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr',
2002
+ 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track',
2003
+ 'wbr', '!doctype'];
2004
+
2005
+ function isArray(thing) {
2006
+ return Object.prototype.toString.call(thing) === '[object Array]';
2007
+ }
2008
+
2009
+ function camelToDash(str) {
2010
+ return str.replace(/\W+/g, '-')
2011
+ .replace(/([a-z\d])([A-Z])/g, '$1-$2');
2012
+ }
2013
+
2014
+ function removeEmpties(n) {
2015
+ return n != '';
2016
+ }
2017
+
2018
+ // shameless stolen from https://github.com/punkave/sanitize-html
2019
+ function escapeHtml(s, replaceDoubleQuote) {
2020
+ if (s === 'undefined') {
2021
+ s = '';
2022
+ }
2023
+ if (typeof(s) !== 'string') {
2024
+ s = s + '';
2025
+ }
2026
+ s = s.replace(/\&/g, '&amp;').replace(/</g, '&lt;').replace(/\>/g, '&gt;');
2027
+ if (replaceDoubleQuote) {
2028
+ return s.replace(/\"/g, '&quot;');
2029
+ }
2030
+ return s;
2031
+ }
2032
+
2033
+ function createAttrString(attrs) {
2034
+ if (!attrs || !Object.keys(attrs).length) {
2035
+ return '';
2036
+ }
2037
+
2038
+ return Object.keys(attrs).map(function(name) {
2039
+ var value = attrs[name];
2040
+ if (typeof value === 'undefined' || value === null || typeof value === 'function') {
2041
+ return;
2042
+ }
2043
+ if (typeof value === 'boolean') {
2044
+ return value ? ' ' + name : '';
2045
+ }
2046
+ if (name === 'style') {
2047
+ if (!value) {
2048
+ return;
2049
+ }
2050
+ var styles = attrs.style;
2051
+ if (typeof styles === 'object') {
2052
+ styles = Object.keys(styles).map(function(property) {
2053
+ return styles[property] != '' ? [camelToDash(property).toLowerCase(), styles[property]].join(':') : '';
2054
+ }).filter(removeEmpties).join(';');
2055
+ }
2056
+ return styles != '' ? ' style="' + escapeHtml(styles, true) + '"' : '';
2057
+ }
2058
+ return ' ' + escapeHtml(name === 'className' ? 'class' : name) + '="' + escapeHtml(value, true) + '"';
2059
+ }).join('');
2060
+ }
2061
+
2062
+ function createChildrenContent(view) {
2063
+ if(isArray(view.children) && !view.children.length) {
2064
+ return '';
2065
+ }
2066
+
2067
+ return render(view.children);
2068
+ }
2069
+
2070
+ function render(view) {
2071
+ var type = typeof view;
2072
+
2073
+ if (type === 'string') {
2074
+ return escapeHtml(view);
2075
+ }
2076
+
2077
+ if(type === 'number' || type === 'boolean') {
2078
+ return view;
2079
+ }
2080
+
2081
+ if (!view) {
2082
+ return '';
2083
+ }
2084
+
2085
+ if (isArray(view)) {
2086
+ return view.map(render).join('');
2087
+ }
2088
+
2089
+ //compontent
2090
+ if (view.view) {
2091
+ var scope = view.controller ? new view.controller : {};
2092
+ var result = render(view.view(scope));
2093
+ if (scope.onunload) {
2094
+ scope.onunload();
2095
+ }
2096
+ return result;
2097
+ }
2098
+
2099
+ if (view.$trusted) {
2100
+ return '' + view;
2101
+ }
2102
+ var children = createChildrenContent(view);
2103
+ if (!children && VOID_TAGS.indexOf(view.tag.toLowerCase()) >= 0) {
2104
+ return '<' + view.tag + createAttrString(view.attrs) + '>';
2105
+ }
2106
+ return [
2107
+ '<', view.tag, createAttrString(view.attrs), '>',
2108
+ children,
2109
+ '</', view.tag, '>',
2110
+ ].join('');
2111
+ }
2112
+
2113
+ module.exports = render;
2114
+ },{}],13:[function(require,module,exports){
2115
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2116
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
2117
+
2118
+ /**
2119
+ * Tag-closer extension for CodeMirror.
2120
+ *
2121
+ * This extension adds an "autoCloseTags" option that can be set to
2122
+ * either true to get the default behavior, or an object to further
2123
+ * configure its behavior.
2124
+ *
2125
+ * These are supported options:
2126
+ *
2127
+ * `whenClosing` (default true)
2128
+ * Whether to autoclose when the '/' of a closing tag is typed.
2129
+ * `whenOpening` (default true)
2130
+ * Whether to autoclose the tag when the final '>' of an opening
2131
+ * tag is typed.
2132
+ * `dontCloseTags` (default is empty tags for HTML, none for XML)
2133
+ * An array of tag names that should not be autoclosed.
2134
+ * `indentTags` (default is block tags for HTML, none for XML)
2135
+ * An array of tag names that should, when opened, cause a
2136
+ * blank line to be added inside the tag, and the blank line and
2137
+ * closing line to be indented.
2138
+ *
2139
+ * See demos/closetag.html for a usage example.
2140
+ */
2141
+
2142
+ (function(mod) {
2143
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
2144
+ mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
2145
+ else if (typeof define == "function" && define.amd) // AMD
2146
+ define(["../../lib/codemirror", "../fold/xml-fold"], mod);
2147
+ else // Plain browser env
2148
+ mod(CodeMirror);
2149
+ })(function(CodeMirror) {
2150
+ CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) {
2151
+ if (old != CodeMirror.Init && old)
2152
+ cm.removeKeyMap("autoCloseTags");
2153
+ if (!val) return;
2154
+ var map = {name: "autoCloseTags"};
2155
+ if (typeof val != "object" || val.whenClosing)
2156
+ map["'/'"] = function(cm) { return autoCloseSlash(cm); };
2157
+ if (typeof val != "object" || val.whenOpening)
2158
+ map["'>'"] = function(cm) { return autoCloseGT(cm); };
2159
+ cm.addKeyMap(map);
2160
+ });
2161
+
2162
+ var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
2163
+ "source", "track", "wbr"];
2164
+ var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4",
2165
+ "h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"];
2166
+
2167
+ function autoCloseGT(cm) {
2168
+ if (cm.getOption("disableInput")) return CodeMirror.Pass;
2169
+ var ranges = cm.listSelections(), replacements = [];
2170
+ for (var i = 0; i < ranges.length; i++) {
2171
+ if (!ranges[i].empty()) return CodeMirror.Pass;
2172
+ var pos = ranges[i].head, tok = cm.getTokenAt(pos);
2173
+ var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
2174
+ if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass;
2175
+
2176
+ var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html";
2177
+ var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
2178
+ var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
2179
+
2180
+ var tagName = state.tagName;
2181
+ if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
2182
+ var lowerTagName = tagName.toLowerCase();
2183
+ // Don't process the '>' at the end of an end-tag or self-closing tag
2184
+ if (!tagName ||
2185
+ tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||
2186
+ tok.type == "tag" && state.type == "closeTag" ||
2187
+ tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName />
2188
+ dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||
2189
+ closingTagExists(cm, tagName, pos, state, true))
2190
+ return CodeMirror.Pass;
2191
+
2192
+ var indent = indentTags && indexOf(indentTags, lowerTagName) > -1;
2193
+ replacements[i] = {indent: indent,
2194
+ text: ">" + (indent ? "\n\n" : "") + "</" + tagName + ">",
2195
+ newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)};
2196
+ }
2197
+
2198
+ for (var i = ranges.length - 1; i >= 0; i--) {
2199
+ var info = replacements[i];
2200
+ cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert");
2201
+ var sel = cm.listSelections().slice(0);
2202
+ sel[i] = {head: info.newPos, anchor: info.newPos};
2203
+ cm.setSelections(sel);
2204
+ if (info.indent) {
2205
+ cm.indentLine(info.newPos.line, null, true);
2206
+ cm.indentLine(info.newPos.line + 1, null, true);
2207
+ }
2208
+ }
2209
+ }
2210
+
2211
+ function autoCloseCurrent(cm, typingSlash) {
2212
+ var ranges = cm.listSelections(), replacements = [];
2213
+ var head = typingSlash ? "/" : "</";
2214
+ for (var i = 0; i < ranges.length; i++) {
2215
+ if (!ranges[i].empty()) return CodeMirror.Pass;
2216
+ var pos = ranges[i].head, tok = cm.getTokenAt(pos);
2217
+ var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
2218
+ if (typingSlash && (tok.type == "string" || tok.string.charAt(0) != "<" ||
2219
+ tok.start != pos.ch - 1))
2220
+ return CodeMirror.Pass;
2221
+ // Kludge to get around the fact that we are not in XML mode
2222
+ // when completing in JS/CSS snippet in htmlmixed mode. Does not
2223
+ // work for other XML embedded languages (there is no general
2224
+ // way to go from a mixed mode to its current XML state).
2225
+ var replacement;
2226
+ if (inner.mode.name != "xml") {
2227
+ if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript")
2228
+ replacement = head + "script";
2229
+ else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css")
2230
+ replacement = head + "style";
2231
+ else
2232
+ return CodeMirror.Pass;
2233
+ } else {
2234
+ if (!state.context || !state.context.tagName ||
2235
+ closingTagExists(cm, state.context.tagName, pos, state))
2236
+ return CodeMirror.Pass;
2237
+ replacement = head + state.context.tagName;
2238
+ }
2239
+ if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">";
2240
+ replacements[i] = replacement;
2241
+ }
2242
+ cm.replaceSelections(replacements);
2243
+ ranges = cm.listSelections();
2244
+ for (var i = 0; i < ranges.length; i++)
2245
+ if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
2246
+ cm.indentLine(ranges[i].head.line);
2247
+ }
2248
+
2249
+ function autoCloseSlash(cm) {
2250
+ if (cm.getOption("disableInput")) return CodeMirror.Pass;
2251
+ return autoCloseCurrent(cm, true);
2252
+ }
2253
+
2254
+ CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); };
2255
+
2256
+ function indexOf(collection, elt) {
2257
+ if (collection.indexOf) return collection.indexOf(elt);
2258
+ for (var i = 0, e = collection.length; i < e; ++i)
2259
+ if (collection[i] == elt) return i;
2260
+ return -1;
2261
+ }
2262
+
2263
+ // If xml-fold is loaded, we use its functionality to try and verify
2264
+ // whether a given tag is actually unclosed.
2265
+ function closingTagExists(cm, tagName, pos, state, newTag) {
2266
+ if (!CodeMirror.scanForClosingTag) return false;
2267
+ var end = Math.min(cm.lastLine() + 1, pos.line + 500);
2268
+ var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);
2269
+ if (!nextClose || nextClose.tag != tagName) return false;
2270
+ var cx = state.context;
2271
+ // If the immediate wrapping context contains onCx instances of
2272
+ // the same tag, a closing tag only exists if there are at least
2273
+ // that many closing tags of that type following.
2274
+ for (var onCx = newTag ? 1 : 0; cx && cx.tagName == tagName; cx = cx.prev) ++onCx;
2275
+ pos = nextClose.to;
2276
+ for (var i = 1; i < onCx; i++) {
2277
+ var next = CodeMirror.scanForClosingTag(cm, pos, null, end);
2278
+ if (!next || next.tag != tagName) return false;
2279
+ pos = next.to;
2280
+ }
2281
+ return true;
2282
+ }
2283
+ });
2284
+
2285
+ },{"../../lib/codemirror":16,"../fold/xml-fold":15}],14:[function(require,module,exports){
2286
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2287
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
2288
+
2289
+ (function(mod) {
2290
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
2291
+ mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
2292
+ else if (typeof define == "function" && define.amd) // AMD
2293
+ define(["../../lib/codemirror", "../fold/xml-fold"], mod);
2294
+ else // Plain browser env
2295
+ mod(CodeMirror);
2296
+ })(function(CodeMirror) {
2297
+ "use strict";
2298
+
2299
+ CodeMirror.defineOption("matchTags", false, function(cm, val, old) {
2300
+ if (old && old != CodeMirror.Init) {
2301
+ cm.off("cursorActivity", doMatchTags);
2302
+ cm.off("viewportChange", maybeUpdateMatch);
2303
+ clear(cm);
2304
+ }
2305
+ if (val) {
2306
+ cm.state.matchBothTags = typeof val == "object" && val.bothTags;
2307
+ cm.on("cursorActivity", doMatchTags);
2308
+ cm.on("viewportChange", maybeUpdateMatch);
2309
+ doMatchTags(cm);
2310
+ }
2311
+ });
2312
+
2313
+ function clear(cm) {
2314
+ if (cm.state.tagHit) cm.state.tagHit.clear();
2315
+ if (cm.state.tagOther) cm.state.tagOther.clear();
2316
+ cm.state.tagHit = cm.state.tagOther = null;
2317
+ }
2318
+
2319
+ function doMatchTags(cm) {
2320
+ cm.state.failedTagMatch = false;
2321
+ cm.operation(function() {
2322
+ clear(cm);
2323
+ if (cm.somethingSelected()) return;
2324
+ var cur = cm.getCursor(), range = cm.getViewport();
2325
+ range.from = Math.min(range.from, cur.line); range.to = Math.max(cur.line + 1, range.to);
2326
+ var match = CodeMirror.findMatchingTag(cm, cur, range);
2327
+ if (!match) return;
2328
+ if (cm.state.matchBothTags) {
2329
+ var hit = match.at == "open" ? match.open : match.close;
2330
+ if (hit) cm.state.tagHit = cm.markText(hit.from, hit.to, {className: "CodeMirror-matchingtag"});
2331
+ }
2332
+ var other = match.at == "close" ? match.open : match.close;
2333
+ if (other)
2334
+ cm.state.tagOther = cm.markText(other.from, other.to, {className: "CodeMirror-matchingtag"});
2335
+ else
2336
+ cm.state.failedTagMatch = true;
2337
+ });
2338
+ }
2339
+
2340
+ function maybeUpdateMatch(cm) {
2341
+ if (cm.state.failedTagMatch) doMatchTags(cm);
2342
+ }
2343
+
2344
+ CodeMirror.commands.toMatchingTag = function(cm) {
2345
+ var found = CodeMirror.findMatchingTag(cm, cm.getCursor());
2346
+ if (found) {
2347
+ var other = found.at == "close" ? found.open : found.close;
2348
+ if (other) cm.extendSelection(other.to, other.from);
2349
+ }
2350
+ };
2351
+ });
2352
+
2353
+ },{"../../lib/codemirror":16,"../fold/xml-fold":15}],15:[function(require,module,exports){
2354
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2355
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
2356
+
2357
+ (function(mod) {
2358
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
2359
+ mod(require("../../lib/codemirror"));
2360
+ else if (typeof define == "function" && define.amd) // AMD
2361
+ define(["../../lib/codemirror"], mod);
2362
+ else // Plain browser env
2363
+ mod(CodeMirror);
2364
+ })(function(CodeMirror) {
2365
+ "use strict";
2366
+
2367
+ var Pos = CodeMirror.Pos;
2368
+ function cmp(a, b) { return a.line - b.line || a.ch - b.ch; }
2369
+
2370
+ var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
2371
+ var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
2372
+ var xmlTagStart = new RegExp("<(/?)([" + nameStartChar + "][" + nameChar + "]*)", "g");
2373
+
2374
+ function Iter(cm, line, ch, range) {
2375
+ this.line = line; this.ch = ch;
2376
+ this.cm = cm; this.text = cm.getLine(line);
2377
+ this.min = range ? range.from : cm.firstLine();
2378
+ this.max = range ? range.to - 1 : cm.lastLine();
2379
+ }
2380
+
2381
+ function tagAt(iter, ch) {
2382
+ var type = iter.cm.getTokenTypeAt(Pos(iter.line, ch));
2383
+ return type && /\btag\b/.test(type);
2384
+ }
2385
+
2386
+ function nextLine(iter) {
2387
+ if (iter.line >= iter.max) return;
2388
+ iter.ch = 0;
2389
+ iter.text = iter.cm.getLine(++iter.line);
2390
+ return true;
2391
+ }
2392
+ function prevLine(iter) {
2393
+ if (iter.line <= iter.min) return;
2394
+ iter.text = iter.cm.getLine(--iter.line);
2395
+ iter.ch = iter.text.length;
2396
+ return true;
2397
+ }
2398
+
2399
+ function toTagEnd(iter) {
2400
+ for (;;) {
2401
+ var gt = iter.text.indexOf(">", iter.ch);
2402
+ if (gt == -1) { if (nextLine(iter)) continue; else return; }
2403
+ if (!tagAt(iter, gt + 1)) { iter.ch = gt + 1; continue; }
2404
+ var lastSlash = iter.text.lastIndexOf("/", gt);
2405
+ var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
2406
+ iter.ch = gt + 1;
2407
+ return selfClose ? "selfClose" : "regular";
2408
+ }
2409
+ }
2410
+ function toTagStart(iter) {
2411
+ for (;;) {
2412
+ var lt = iter.ch ? iter.text.lastIndexOf("<", iter.ch - 1) : -1;
2413
+ if (lt == -1) { if (prevLine(iter)) continue; else return; }
2414
+ if (!tagAt(iter, lt + 1)) { iter.ch = lt; continue; }
2415
+ xmlTagStart.lastIndex = lt;
2416
+ iter.ch = lt;
2417
+ var match = xmlTagStart.exec(iter.text);
2418
+ if (match && match.index == lt) return match;
2419
+ }
2420
+ }
2421
+
2422
+ function toNextTag(iter) {
2423
+ for (;;) {
2424
+ xmlTagStart.lastIndex = iter.ch;
2425
+ var found = xmlTagStart.exec(iter.text);
2426
+ if (!found) { if (nextLine(iter)) continue; else return; }
2427
+ if (!tagAt(iter, found.index + 1)) { iter.ch = found.index + 1; continue; }
2428
+ iter.ch = found.index + found[0].length;
2429
+ return found;
2430
+ }
2431
+ }
2432
+ function toPrevTag(iter) {
2433
+ for (;;) {
2434
+ var gt = iter.ch ? iter.text.lastIndexOf(">", iter.ch - 1) : -1;
2435
+ if (gt == -1) { if (prevLine(iter)) continue; else return; }
2436
+ if (!tagAt(iter, gt + 1)) { iter.ch = gt; continue; }
2437
+ var lastSlash = iter.text.lastIndexOf("/", gt);
2438
+ var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
2439
+ iter.ch = gt + 1;
2440
+ return selfClose ? "selfClose" : "regular";
2441
+ }
2442
+ }
2443
+
2444
+ function findMatchingClose(iter, tag) {
2445
+ var stack = [];
2446
+ for (;;) {
2447
+ var next = toNextTag(iter), end, startLine = iter.line, startCh = iter.ch - (next ? next[0].length : 0);
2448
+ if (!next || !(end = toTagEnd(iter))) return;
2449
+ if (end == "selfClose") continue;
2450
+ if (next[1]) { // closing tag
2451
+ for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == next[2]) {
2452
+ stack.length = i;
2453
+ break;
2454
+ }
2455
+ if (i < 0 && (!tag || tag == next[2])) return {
2456
+ tag: next[2],
2457
+ from: Pos(startLine, startCh),
2458
+ to: Pos(iter.line, iter.ch)
2459
+ };
2460
+ } else { // opening tag
2461
+ stack.push(next[2]);
2462
+ }
2463
+ }
2464
+ }
2465
+ function findMatchingOpen(iter, tag) {
2466
+ var stack = [];
2467
+ for (;;) {
2468
+ var prev = toPrevTag(iter);
2469
+ if (!prev) return;
2470
+ if (prev == "selfClose") { toTagStart(iter); continue; }
2471
+ var endLine = iter.line, endCh = iter.ch;
2472
+ var start = toTagStart(iter);
2473
+ if (!start) return;
2474
+ if (start[1]) { // closing tag
2475
+ stack.push(start[2]);
2476
+ } else { // opening tag
2477
+ for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == start[2]) {
2478
+ stack.length = i;
2479
+ break;
2480
+ }
2481
+ if (i < 0 && (!tag || tag == start[2])) return {
2482
+ tag: start[2],
2483
+ from: Pos(iter.line, iter.ch),
2484
+ to: Pos(endLine, endCh)
2485
+ };
2486
+ }
2487
+ }
2488
+ }
2489
+
2490
+ CodeMirror.registerHelper("fold", "xml", function(cm, start) {
2491
+ var iter = new Iter(cm, start.line, 0);
2492
+ for (;;) {
2493
+ var openTag = toNextTag(iter), end;
2494
+ if (!openTag || iter.line != start.line || !(end = toTagEnd(iter))) return;
2495
+ if (!openTag[1] && end != "selfClose") {
2496
+ var start = Pos(iter.line, iter.ch);
2497
+ var close = findMatchingClose(iter, openTag[2]);
2498
+ return close && {from: start, to: close.from};
2499
+ }
2500
+ }
2501
+ });
2502
+ CodeMirror.findMatchingTag = function(cm, pos, range) {
2503
+ var iter = new Iter(cm, pos.line, pos.ch, range);
2504
+ if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return;
2505
+ var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch);
2506
+ var start = end && toTagStart(iter);
2507
+ if (!end || !start || cmp(iter, pos) > 0) return;
2508
+ var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]};
2509
+ if (end == "selfClose") return {open: here, close: null, at: "open"};
2510
+
2511
+ if (start[1]) { // closing tag
2512
+ return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"};
2513
+ } else { // opening tag
2514
+ iter = new Iter(cm, to.line, to.ch, range);
2515
+ return {open: here, close: findMatchingClose(iter, start[2]), at: "open"};
2516
+ }
2517
+ };
2518
+
2519
+ CodeMirror.findEnclosingTag = function(cm, pos, range) {
2520
+ var iter = new Iter(cm, pos.line, pos.ch, range);
2521
+ for (;;) {
2522
+ var open = findMatchingOpen(iter);
2523
+ if (!open) break;
2524
+ var forward = new Iter(cm, pos.line, pos.ch, range);
2525
+ var close = findMatchingClose(forward, open.tag);
2526
+ if (close) return {open: open, close: close};
2527
+ }
2528
+ };
2529
+
2530
+ // Used by addon/edit/closetag.js
2531
+ CodeMirror.scanForClosingTag = function(cm, pos, name, end) {
2532
+ var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null);
2533
+ return findMatchingClose(iter, name);
2534
+ };
2535
+ });
2536
+
2537
+ },{"../../lib/codemirror":16}],16:[function(require,module,exports){
2538
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2539
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
2540
+
2541
+ // This is CodeMirror (http://codemirror.net), a code editor
2542
+ // implemented in JavaScript on top of the browser's DOM.
2543
+ //
2544
+ // You can find some technical background for some of the code below
2545
+ // at http://marijnhaverbeke.nl/blog/#cm-internals .
2546
+
2547
+ (function(mod) {
2548
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
2549
+ module.exports = mod();
2550
+ else if (typeof define == "function" && define.amd) // AMD
2551
+ return define([], mod);
2552
+ else // Plain browser env
2553
+ this.CodeMirror = mod();
2554
+ })(function() {
2555
+ "use strict";
2556
+
2557
+ // BROWSER SNIFFING
2558
+
2559
+ // Kludges for bugs and behavior differences that can't be feature
2560
+ // detected are enabled based on userAgent etc sniffing.
2561
+ var userAgent = navigator.userAgent;
2562
+ var platform = navigator.platform;
2563
+
2564
+ var gecko = /gecko\/\d/i.test(userAgent);
2565
+ var ie_upto10 = /MSIE \d/.test(userAgent);
2566
+ var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent);
2567
+ var ie = ie_upto10 || ie_11up;
2568
+ var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);
2569
+ var webkit = /WebKit\//.test(userAgent);
2570
+ var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent);
2571
+ var chrome = /Chrome\//.test(userAgent);
2572
+ var presto = /Opera\//.test(userAgent);
2573
+ var safari = /Apple Computer/.test(navigator.vendor);
2574
+ var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
2575
+ var phantom = /PhantomJS/.test(userAgent);
2576
+
2577
+ var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent);
2578
+ // This is woefully incomplete. Suggestions for alternative methods welcome.
2579
+ var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
2580
+ var mac = ios || /Mac/.test(platform);
2581
+ var windows = /win/i.test(platform);
2582
+
2583
+ var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/);
2584
+ if (presto_version) presto_version = Number(presto_version[1]);
2585
+ if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
2586
+ // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
2587
+ var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));
2588
+ var captureRightClick = gecko || (ie && ie_version >= 9);
2589
+
2590
+ // Optimize some code when these features are not used.
2591
+ var sawReadOnlySpans = false, sawCollapsedSpans = false;
2592
+
2593
+ // EDITOR CONSTRUCTOR
2594
+
2595
+ // A CodeMirror instance represents an editor. This is the object
2596
+ // that user code is usually dealing with.
2597
+
2598
+ function CodeMirror(place, options) {
2599
+ if (!(this instanceof CodeMirror)) return new CodeMirror(place, options);
2600
+
2601
+ this.options = options = options ? copyObj(options) : {};
2602
+ // Determine effective options based on given values and defaults.
2603
+ copyObj(defaults, options, false);
2604
+ setGuttersForLineNumbers(options);
2605
+
2606
+ var doc = options.value;
2607
+ if (typeof doc == "string") doc = new Doc(doc, options.mode, null, options.lineSeparator);
2608
+ this.doc = doc;
2609
+
2610
+ var input = new CodeMirror.inputStyles[options.inputStyle](this);
2611
+ var display = this.display = new Display(place, doc, input);
2612
+ display.wrapper.CodeMirror = this;
2613
+ updateGutters(this);
2614
+ themeChanged(this);
2615
+ if (options.lineWrapping)
2616
+ this.display.wrapper.className += " CodeMirror-wrap";
2617
+ if (options.autofocus && !mobile) display.input.focus();
2618
+ initScrollbars(this);
2619
+
2620
+ this.state = {
2621
+ keyMaps: [], // stores maps added by addKeyMap
2622
+ overlays: [], // highlighting overlays, as added by addOverlay
2623
+ modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info
2624
+ overwrite: false,
2625
+ delayingBlurEvent: false,
2626
+ focused: false,
2627
+ suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
2628
+ pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
2629
+ selectingText: false,
2630
+ draggingText: false,
2631
+ highlight: new Delayed(), // stores highlight worker timeout
2632
+ keySeq: null, // Unfinished key sequence
2633
+ specialChars: null
2634
+ };
2635
+
2636
+ var cm = this;
2637
+
2638
+ // Override magic textarea content restore that IE sometimes does
2639
+ // on our hidden textarea on reload
2640
+ if (ie && ie_version < 11) setTimeout(function() { cm.display.input.reset(true); }, 20);
2641
+
2642
+ registerEventHandlers(this);
2643
+ ensureGlobalHandlers();
2644
+
2645
+ startOperation(this);
2646
+ this.curOp.forceUpdate = true;
2647
+ attachDoc(this, doc);
2648
+
2649
+ if ((options.autofocus && !mobile) || cm.hasFocus())
2650
+ setTimeout(bind(onFocus, this), 20);
2651
+ else
2652
+ onBlur(this);
2653
+
2654
+ for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))
2655
+ optionHandlers[opt](this, options[opt], Init);
2656
+ maybeUpdateLineNumberWidth(this);
2657
+ if (options.finishInit) options.finishInit(this);
2658
+ for (var i = 0; i < initHooks.length; ++i) initHooks[i](this);
2659
+ endOperation(this);
2660
+ // Suppress optimizelegibility in Webkit, since it breaks text
2661
+ // measuring on line wrapping boundaries.
2662
+ if (webkit && options.lineWrapping &&
2663
+ getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
2664
+ display.lineDiv.style.textRendering = "auto";
2665
+ }
2666
+
2667
+ // DISPLAY CONSTRUCTOR
2668
+
2669
+ // The display handles the DOM integration, both for input reading
2670
+ // and content drawing. It holds references to DOM nodes and
2671
+ // display-related state.
2672
+
2673
+ function Display(place, doc, input) {
2674
+ var d = this;
2675
+ this.input = input;
2676
+
2677
+ // Covers bottom-right square when both scrollbars are present.
2678
+ d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
2679
+ d.scrollbarFiller.setAttribute("cm-not-content", "true");
2680
+ // Covers bottom of gutter when coverGutterNextToScrollbar is on
2681
+ // and h scrollbar is present.
2682
+ d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
2683
+ d.gutterFiller.setAttribute("cm-not-content", "true");
2684
+ // Will contain the actual code, positioned to cover the viewport.
2685
+ d.lineDiv = elt("div", null, "CodeMirror-code");
2686
+ // Elements are added to these to represent selection and cursors.
2687
+ d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
2688
+ d.cursorDiv = elt("div", null, "CodeMirror-cursors");
2689
+ // A visibility: hidden element used to find the size of things.
2690
+ d.measure = elt("div", null, "CodeMirror-measure");
2691
+ // When lines outside of the viewport are measured, they are drawn in this.
2692
+ d.lineMeasure = elt("div", null, "CodeMirror-measure");
2693
+ // Wraps everything that needs to exist inside the vertically-padded coordinate system
2694
+ d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
2695
+ null, "position: relative; outline: none");
2696
+ // Moved around its parent to cover visible view.
2697
+ d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative");
2698
+ // Set to the height of the document, allowing scrolling.
2699
+ d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
2700
+ d.sizerWidth = null;
2701
+ // Behavior of elts with overflow: auto and padding is
2702
+ // inconsistent across browsers. This is used to ensure the
2703
+ // scrollable area is big enough.
2704
+ d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;");
2705
+ // Will contain the gutters, if any.
2706
+ d.gutters = elt("div", null, "CodeMirror-gutters");
2707
+ d.lineGutter = null;
2708
+ // Actual scrollable element.
2709
+ d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
2710
+ d.scroller.setAttribute("tabIndex", "-1");
2711
+ // The element in which the editor lives.
2712
+ d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
2713
+
2714
+ // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
2715
+ if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
2716
+ if (!webkit && !(gecko && mobile)) d.scroller.draggable = true;
2717
+
2718
+ if (place) {
2719
+ if (place.appendChild) place.appendChild(d.wrapper);
2720
+ else place(d.wrapper);
2721
+ }
2722
+
2723
+ // Current rendered range (may be bigger than the view window).
2724
+ d.viewFrom = d.viewTo = doc.first;
2725
+ d.reportedViewFrom = d.reportedViewTo = doc.first;
2726
+ // Information about the rendered lines.
2727
+ d.view = [];
2728
+ d.renderedView = null;
2729
+ // Holds info about a single rendered line when it was rendered
2730
+ // for measurement, while not in view.
2731
+ d.externalMeasured = null;
2732
+ // Empty space (in pixels) above the view
2733
+ d.viewOffset = 0;
2734
+ d.lastWrapHeight = d.lastWrapWidth = 0;
2735
+ d.updateLineNumbers = null;
2736
+
2737
+ d.nativeBarWidth = d.barHeight = d.barWidth = 0;
2738
+ d.scrollbarsClipped = false;
2739
+
2740
+ // Used to only resize the line number gutter when necessary (when
2741
+ // the amount of lines crosses a boundary that makes its width change)
2742
+ d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
2743
+ // Set to true when a non-horizontal-scrolling line widget is
2744
+ // added. As an optimization, line widget aligning is skipped when
2745
+ // this is false.
2746
+ d.alignWidgets = false;
2747
+
2748
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
2749
+
2750
+ // Tracks the maximum line length so that the horizontal scrollbar
2751
+ // can be kept static when scrolling.
2752
+ d.maxLine = null;
2753
+ d.maxLineLength = 0;
2754
+ d.maxLineChanged = false;
2755
+
2756
+ // Used for measuring wheel scrolling granularity
2757
+ d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
2758
+
2759
+ // True when shift is held down.
2760
+ d.shift = false;
2761
+
2762
+ // Used to track whether anything happened since the context menu
2763
+ // was opened.
2764
+ d.selForContextMenu = null;
2765
+
2766
+ d.activeTouch = null;
2767
+
2768
+ input.init(d);
2769
+ }
2770
+
2771
+ // STATE UPDATES
2772
+
2773
+ // Used to get the editor into a consistent state again when options change.
2774
+
2775
+ function loadMode(cm) {
2776
+ cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption);
2777
+ resetModeState(cm);
2778
+ }
2779
+
2780
+ function resetModeState(cm) {
2781
+ cm.doc.iter(function(line) {
2782
+ if (line.stateAfter) line.stateAfter = null;
2783
+ if (line.styles) line.styles = null;
2784
+ });
2785
+ cm.doc.frontier = cm.doc.first;
2786
+ startWorker(cm, 100);
2787
+ cm.state.modeGen++;
2788
+ if (cm.curOp) regChange(cm);
2789
+ }
2790
+
2791
+ function wrappingChanged(cm) {
2792
+ if (cm.options.lineWrapping) {
2793
+ addClass(cm.display.wrapper, "CodeMirror-wrap");
2794
+ cm.display.sizer.style.minWidth = "";
2795
+ cm.display.sizerWidth = null;
2796
+ } else {
2797
+ rmClass(cm.display.wrapper, "CodeMirror-wrap");
2798
+ findMaxLine(cm);
2799
+ }
2800
+ estimateLineHeights(cm);
2801
+ regChange(cm);
2802
+ clearCaches(cm);
2803
+ setTimeout(function(){updateScrollbars(cm);}, 100);
2804
+ }
2805
+
2806
+ // Returns a function that estimates the height of a line, to use as
2807
+ // first approximation until the line becomes visible (and is thus
2808
+ // properly measurable).
2809
+ function estimateHeight(cm) {
2810
+ var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
2811
+ var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
2812
+ return function(line) {
2813
+ if (lineIsHidden(cm.doc, line)) return 0;
2814
+
2815
+ var widgetsHeight = 0;
2816
+ if (line.widgets) for (var i = 0; i < line.widgets.length; i++) {
2817
+ if (line.widgets[i].height) widgetsHeight += line.widgets[i].height;
2818
+ }
2819
+
2820
+ if (wrapping)
2821
+ return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th;
2822
+ else
2823
+ return widgetsHeight + th;
2824
+ };
2825
+ }
2826
+
2827
+ function estimateLineHeights(cm) {
2828
+ var doc = cm.doc, est = estimateHeight(cm);
2829
+ doc.iter(function(line) {
2830
+ var estHeight = est(line);
2831
+ if (estHeight != line.height) updateLineHeight(line, estHeight);
2832
+ });
2833
+ }
2834
+
2835
+ function themeChanged(cm) {
2836
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
2837
+ cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
2838
+ clearCaches(cm);
2839
+ }
2840
+
2841
+ function guttersChanged(cm) {
2842
+ updateGutters(cm);
2843
+ regChange(cm);
2844
+ setTimeout(function(){alignHorizontally(cm);}, 20);
2845
+ }
2846
+
2847
+ // Rebuild the gutter elements, ensure the margin to the left of the
2848
+ // code matches their width.
2849
+ function updateGutters(cm) {
2850
+ var gutters = cm.display.gutters, specs = cm.options.gutters;
2851
+ removeChildren(gutters);
2852
+ for (var i = 0; i < specs.length; ++i) {
2853
+ var gutterClass = specs[i];
2854
+ var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass));
2855
+ if (gutterClass == "CodeMirror-linenumbers") {
2856
+ cm.display.lineGutter = gElt;
2857
+ gElt.style.width = (cm.display.lineNumWidth || 1) + "px";
2858
+ }
2859
+ }
2860
+ gutters.style.display = i ? "" : "none";
2861
+ updateGutterSpace(cm);
2862
+ }
2863
+
2864
+ function updateGutterSpace(cm) {
2865
+ var width = cm.display.gutters.offsetWidth;
2866
+ cm.display.sizer.style.marginLeft = width + "px";
2867
+ }
2868
+
2869
+ // Compute the character length of a line, taking into account
2870
+ // collapsed ranges (see markText) that might hide parts, and join
2871
+ // other lines onto it.
2872
+ function lineLength(line) {
2873
+ if (line.height == 0) return 0;
2874
+ var len = line.text.length, merged, cur = line;
2875
+ while (merged = collapsedSpanAtStart(cur)) {
2876
+ var found = merged.find(0, true);
2877
+ cur = found.from.line;
2878
+ len += found.from.ch - found.to.ch;
2879
+ }
2880
+ cur = line;
2881
+ while (merged = collapsedSpanAtEnd(cur)) {
2882
+ var found = merged.find(0, true);
2883
+ len -= cur.text.length - found.from.ch;
2884
+ cur = found.to.line;
2885
+ len += cur.text.length - found.to.ch;
2886
+ }
2887
+ return len;
2888
+ }
2889
+
2890
+ // Find the longest line in the document.
2891
+ function findMaxLine(cm) {
2892
+ var d = cm.display, doc = cm.doc;
2893
+ d.maxLine = getLine(doc, doc.first);
2894
+ d.maxLineLength = lineLength(d.maxLine);
2895
+ d.maxLineChanged = true;
2896
+ doc.iter(function(line) {
2897
+ var len = lineLength(line);
2898
+ if (len > d.maxLineLength) {
2899
+ d.maxLineLength = len;
2900
+ d.maxLine = line;
2901
+ }
2902
+ });
2903
+ }
2904
+
2905
+ // Make sure the gutters options contains the element
2906
+ // "CodeMirror-linenumbers" when the lineNumbers option is true.
2907
+ function setGuttersForLineNumbers(options) {
2908
+ var found = indexOf(options.gutters, "CodeMirror-linenumbers");
2909
+ if (found == -1 && options.lineNumbers) {
2910
+ options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]);
2911
+ } else if (found > -1 && !options.lineNumbers) {
2912
+ options.gutters = options.gutters.slice(0);
2913
+ options.gutters.splice(found, 1);
2914
+ }
2915
+ }
2916
+
2917
+ // SCROLLBARS
2918
+
2919
+ // Prepare DOM reads needed to update the scrollbars. Done in one
2920
+ // shot to minimize update/measure roundtrips.
2921
+ function measureForScrollbars(cm) {
2922
+ var d = cm.display, gutterW = d.gutters.offsetWidth;
2923
+ var docH = Math.round(cm.doc.height + paddingVert(cm.display));
2924
+ return {
2925
+ clientHeight: d.scroller.clientHeight,
2926
+ viewHeight: d.wrapper.clientHeight,
2927
+ scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
2928
+ viewWidth: d.wrapper.clientWidth,
2929
+ barLeft: cm.options.fixedGutter ? gutterW : 0,
2930
+ docHeight: docH,
2931
+ scrollHeight: docH + scrollGap(cm) + d.barHeight,
2932
+ nativeBarWidth: d.nativeBarWidth,
2933
+ gutterWidth: gutterW
2934
+ };
2935
+ }
2936
+
2937
+ function NativeScrollbars(place, scroll, cm) {
2938
+ this.cm = cm;
2939
+ var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
2940
+ var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
2941
+ place(vert); place(horiz);
2942
+
2943
+ on(vert, "scroll", function() {
2944
+ if (vert.clientHeight) scroll(vert.scrollTop, "vertical");
2945
+ });
2946
+ on(horiz, "scroll", function() {
2947
+ if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal");
2948
+ });
2949
+
2950
+ this.checkedOverlay = false;
2951
+ // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
2952
+ if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px";
2953
+ }
2954
+
2955
+ NativeScrollbars.prototype = copyObj({
2956
+ update: function(measure) {
2957
+ var needsH = measure.scrollWidth > measure.clientWidth + 1;
2958
+ var needsV = measure.scrollHeight > measure.clientHeight + 1;
2959
+ var sWidth = measure.nativeBarWidth;
2960
+
2961
+ if (needsV) {
2962
+ this.vert.style.display = "block";
2963
+ this.vert.style.bottom = needsH ? sWidth + "px" : "0";
2964
+ var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
2965
+ // A bug in IE8 can cause this value to be negative, so guard it.
2966
+ this.vert.firstChild.style.height =
2967
+ Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
2968
+ } else {
2969
+ this.vert.style.display = "";
2970
+ this.vert.firstChild.style.height = "0";
2971
+ }
2972
+
2973
+ if (needsH) {
2974
+ this.horiz.style.display = "block";
2975
+ this.horiz.style.right = needsV ? sWidth + "px" : "0";
2976
+ this.horiz.style.left = measure.barLeft + "px";
2977
+ var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);
2978
+ this.horiz.firstChild.style.width =
2979
+ (measure.scrollWidth - measure.clientWidth + totalWidth) + "px";
2980
+ } else {
2981
+ this.horiz.style.display = "";
2982
+ this.horiz.firstChild.style.width = "0";
2983
+ }
2984
+
2985
+ if (!this.checkedOverlay && measure.clientHeight > 0) {
2986
+ if (sWidth == 0) this.overlayHack();
2987
+ this.checkedOverlay = true;
2988
+ }
2989
+
2990
+ return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0};
2991
+ },
2992
+ setScrollLeft: function(pos) {
2993
+ if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos;
2994
+ },
2995
+ setScrollTop: function(pos) {
2996
+ if (this.vert.scrollTop != pos) this.vert.scrollTop = pos;
2997
+ },
2998
+ overlayHack: function() {
2999
+ var w = mac && !mac_geMountainLion ? "12px" : "18px";
3000
+ this.horiz.style.minHeight = this.vert.style.minWidth = w;
3001
+ var self = this;
3002
+ var barMouseDown = function(e) {
3003
+ if (e_target(e) != self.vert && e_target(e) != self.horiz)
3004
+ operation(self.cm, onMouseDown)(e);
3005
+ };
3006
+ on(this.vert, "mousedown", barMouseDown);
3007
+ on(this.horiz, "mousedown", barMouseDown);
3008
+ },
3009
+ clear: function() {
3010
+ var parent = this.horiz.parentNode;
3011
+ parent.removeChild(this.horiz);
3012
+ parent.removeChild(this.vert);
3013
+ }
3014
+ }, NativeScrollbars.prototype);
3015
+
3016
+ function NullScrollbars() {}
3017
+
3018
+ NullScrollbars.prototype = copyObj({
3019
+ update: function() { return {bottom: 0, right: 0}; },
3020
+ setScrollLeft: function() {},
3021
+ setScrollTop: function() {},
3022
+ clear: function() {}
3023
+ }, NullScrollbars.prototype);
3024
+
3025
+ CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars};
3026
+
3027
+ function initScrollbars(cm) {
3028
+ if (cm.display.scrollbars) {
3029
+ cm.display.scrollbars.clear();
3030
+ if (cm.display.scrollbars.addClass)
3031
+ rmClass(cm.display.wrapper, cm.display.scrollbars.addClass);
3032
+ }
3033
+
3034
+ cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) {
3035
+ cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);
3036
+ // Prevent clicks in the scrollbars from killing focus
3037
+ on(node, "mousedown", function() {
3038
+ if (cm.state.focused) setTimeout(function() { cm.display.input.focus(); }, 0);
3039
+ });
3040
+ node.setAttribute("cm-not-content", "true");
3041
+ }, function(pos, axis) {
3042
+ if (axis == "horizontal") setScrollLeft(cm, pos);
3043
+ else setScrollTop(cm, pos);
3044
+ }, cm);
3045
+ if (cm.display.scrollbars.addClass)
3046
+ addClass(cm.display.wrapper, cm.display.scrollbars.addClass);
3047
+ }
3048
+
3049
+ function updateScrollbars(cm, measure) {
3050
+ if (!measure) measure = measureForScrollbars(cm);
3051
+ var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;
3052
+ updateScrollbarsInner(cm, measure);
3053
+ for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
3054
+ if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
3055
+ updateHeightsInViewport(cm);
3056
+ updateScrollbarsInner(cm, measureForScrollbars(cm));
3057
+ startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;
3058
+ }
3059
+ }
3060
+
3061
+ // Re-synchronize the fake scrollbars with the actual size of the
3062
+ // content.
3063
+ function updateScrollbarsInner(cm, measure) {
3064
+ var d = cm.display;
3065
+ var sizes = d.scrollbars.update(measure);
3066
+
3067
+ d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";
3068
+ d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";
3069
+
3070
+ if (sizes.right && sizes.bottom) {
3071
+ d.scrollbarFiller.style.display = "block";
3072
+ d.scrollbarFiller.style.height = sizes.bottom + "px";
3073
+ d.scrollbarFiller.style.width = sizes.right + "px";
3074
+ } else d.scrollbarFiller.style.display = "";
3075
+ if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
3076
+ d.gutterFiller.style.display = "block";
3077
+ d.gutterFiller.style.height = sizes.bottom + "px";
3078
+ d.gutterFiller.style.width = measure.gutterWidth + "px";
3079
+ } else d.gutterFiller.style.display = "";
3080
+ }
3081
+
3082
+ // Compute the lines that are visible in a given viewport (defaults
3083
+ // the the current scroll position). viewport may contain top,
3084
+ // height, and ensure (see op.scrollToPos) properties.
3085
+ function visibleLines(display, doc, viewport) {
3086
+ var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;
3087
+ top = Math.floor(top - paddingTop(display));
3088
+ var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;
3089
+
3090
+ var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
3091
+ // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
3092
+ // forces those lines into the viewport (if possible).
3093
+ if (viewport && viewport.ensure) {
3094
+ var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;
3095
+ if (ensureFrom < from) {
3096
+ from = ensureFrom;
3097
+ to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);
3098
+ } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
3099
+ from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);
3100
+ to = ensureTo;
3101
+ }
3102
+ }
3103
+ return {from: from, to: Math.max(to, from + 1)};
3104
+ }
3105
+
3106
+ // LINE NUMBERS
3107
+
3108
+ // Re-align line numbers and gutter marks to compensate for
3109
+ // horizontal scrolling.
3110
+ function alignHorizontally(cm) {
3111
+ var display = cm.display, view = display.view;
3112
+ if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return;
3113
+ var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
3114
+ var gutterW = display.gutters.offsetWidth, left = comp + "px";
3115
+ for (var i = 0; i < view.length; i++) if (!view[i].hidden) {
3116
+ if (cm.options.fixedGutter && view[i].gutter)
3117
+ view[i].gutter.style.left = left;
3118
+ var align = view[i].alignable;
3119
+ if (align) for (var j = 0; j < align.length; j++)
3120
+ align[j].style.left = left;
3121
+ }
3122
+ if (cm.options.fixedGutter)
3123
+ display.gutters.style.left = (comp + gutterW) + "px";
3124
+ }
3125
+
3126
+ // Used to ensure that the line number gutter is still the right
3127
+ // size for the current document size. Returns true when an update
3128
+ // is needed.
3129
+ function maybeUpdateLineNumberWidth(cm) {
3130
+ if (!cm.options.lineNumbers) return false;
3131
+ var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
3132
+ if (last.length != display.lineNumChars) {
3133
+ var test = display.measure.appendChild(elt("div", [elt("div", last)],
3134
+ "CodeMirror-linenumber CodeMirror-gutter-elt"));
3135
+ var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
3136
+ display.lineGutter.style.width = "";
3137
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
3138
+ display.lineNumWidth = display.lineNumInnerWidth + padding;
3139
+ display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
3140
+ display.lineGutter.style.width = display.lineNumWidth + "px";
3141
+ updateGutterSpace(cm);
3142
+ return true;
3143
+ }
3144
+ return false;
3145
+ }
3146
+
3147
+ function lineNumberFor(options, i) {
3148
+ return String(options.lineNumberFormatter(i + options.firstLineNumber));
3149
+ }
3150
+
3151
+ // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
3152
+ // but using getBoundingClientRect to get a sub-pixel-accurate
3153
+ // result.
3154
+ function compensateForHScroll(display) {
3155
+ return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left;
3156
+ }
3157
+
3158
+ // DISPLAY DRAWING
3159
+
3160
+ function DisplayUpdate(cm, viewport, force) {
3161
+ var display = cm.display;
3162
+
3163
+ this.viewport = viewport;
3164
+ // Store some values that we'll need later (but don't want to force a relayout for)
3165
+ this.visible = visibleLines(display, cm.doc, viewport);
3166
+ this.editorIsHidden = !display.wrapper.offsetWidth;
3167
+ this.wrapperHeight = display.wrapper.clientHeight;
3168
+ this.wrapperWidth = display.wrapper.clientWidth;
3169
+ this.oldDisplayWidth = displayWidth(cm);
3170
+ this.force = force;
3171
+ this.dims = getDimensions(cm);
3172
+ this.events = [];
3173
+ }
3174
+
3175
+ DisplayUpdate.prototype.signal = function(emitter, type) {
3176
+ if (hasHandler(emitter, type))
3177
+ this.events.push(arguments);
3178
+ };
3179
+ DisplayUpdate.prototype.finish = function() {
3180
+ for (var i = 0; i < this.events.length; i++)
3181
+ signal.apply(null, this.events[i]);
3182
+ };
3183
+
3184
+ function maybeClipScrollbars(cm) {
3185
+ var display = cm.display;
3186
+ if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
3187
+ display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;
3188
+ display.heightForcer.style.height = scrollGap(cm) + "px";
3189
+ display.sizer.style.marginBottom = -display.nativeBarWidth + "px";
3190
+ display.sizer.style.borderRightWidth = scrollGap(cm) + "px";
3191
+ display.scrollbarsClipped = true;
3192
+ }
3193
+ }
3194
+
3195
+ // Does the actual updating of the line display. Bails out
3196
+ // (returning false) when there is nothing to be done and forced is
3197
+ // false.
3198
+ function updateDisplayIfNeeded(cm, update) {
3199
+ var display = cm.display, doc = cm.doc;
3200
+
3201
+ if (update.editorIsHidden) {
3202
+ resetView(cm);
3203
+ return false;
3204
+ }
3205
+
3206
+ // Bail out if the visible area is already rendered and nothing changed.
3207
+ if (!update.force &&
3208
+ update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
3209
+ (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
3210
+ display.renderedView == display.view && countDirtyView(cm) == 0)
3211
+ return false;
3212
+
3213
+ if (maybeUpdateLineNumberWidth(cm)) {
3214
+ resetView(cm);
3215
+ update.dims = getDimensions(cm);
3216
+ }
3217
+
3218
+ // Compute a suitable new viewport (from & to)
3219
+ var end = doc.first + doc.size;
3220
+ var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);
3221
+ var to = Math.min(end, update.visible.to + cm.options.viewportMargin);
3222
+ if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom);
3223
+ if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo);
3224
+ if (sawCollapsedSpans) {
3225
+ from = visualLineNo(cm.doc, from);
3226
+ to = visualLineEndNo(cm.doc, to);
3227
+ }
3228
+
3229
+ var different = from != display.viewFrom || to != display.viewTo ||
3230
+ display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;
3231
+ adjustView(cm, from, to);
3232
+
3233
+ display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
3234
+ // Position the mover div to align with the current scroll position
3235
+ cm.display.mover.style.top = display.viewOffset + "px";
3236
+
3237
+ var toUpdate = countDirtyView(cm);
3238
+ if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
3239
+ (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
3240
+ return false;
3241
+
3242
+ // For big changes, we hide the enclosing element during the
3243
+ // update, since that speeds up the operations on most browsers.
3244
+ var focused = activeElt();
3245
+ if (toUpdate > 4) display.lineDiv.style.display = "none";
3246
+ patchDisplay(cm, display.updateLineNumbers, update.dims);
3247
+ if (toUpdate > 4) display.lineDiv.style.display = "";
3248
+ display.renderedView = display.view;
3249
+ // There might have been a widget with a focused element that got
3250
+ // hidden or updated, if so re-focus it.
3251
+ if (focused && activeElt() != focused && focused.offsetHeight) focused.focus();
3252
+
3253
+ // Prevent selection and cursors from interfering with the scroll
3254
+ // width and height.
3255
+ removeChildren(display.cursorDiv);
3256
+ removeChildren(display.selectionDiv);
3257
+ display.gutters.style.height = display.sizer.style.minHeight = 0;
3258
+
3259
+ if (different) {
3260
+ display.lastWrapHeight = update.wrapperHeight;
3261
+ display.lastWrapWidth = update.wrapperWidth;
3262
+ startWorker(cm, 400);
3263
+ }
3264
+
3265
+ display.updateLineNumbers = null;
3266
+
3267
+ return true;
3268
+ }
3269
+
3270
+ function postUpdateDisplay(cm, update) {
3271
+ var viewport = update.viewport;
3272
+ for (var first = true;; first = false) {
3273
+ if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
3274
+ // Clip forced viewport to actual scrollable area.
3275
+ if (viewport && viewport.top != null)
3276
+ viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)};
3277
+ // Updated line heights might result in the drawn area not
3278
+ // actually covering the viewport. Keep looping until it does.
3279
+ update.visible = visibleLines(cm.display, cm.doc, viewport);
3280
+ if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
3281
+ break;
3282
+ }
3283
+ if (!updateDisplayIfNeeded(cm, update)) break;
3284
+ updateHeightsInViewport(cm);
3285
+ var barMeasure = measureForScrollbars(cm);
3286
+ updateSelection(cm);
3287
+ setDocumentHeight(cm, barMeasure);
3288
+ updateScrollbars(cm, barMeasure);
3289
+ }
3290
+
3291
+ update.signal(cm, "update", cm);
3292
+ if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
3293
+ update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
3294
+ cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;
3295
+ }
3296
+ }
3297
+
3298
+ function updateDisplaySimple(cm, viewport) {
3299
+ var update = new DisplayUpdate(cm, viewport);
3300
+ if (updateDisplayIfNeeded(cm, update)) {
3301
+ updateHeightsInViewport(cm);
3302
+ postUpdateDisplay(cm, update);
3303
+ var barMeasure = measureForScrollbars(cm);
3304
+ updateSelection(cm);
3305
+ setDocumentHeight(cm, barMeasure);
3306
+ updateScrollbars(cm, barMeasure);
3307
+ update.finish();
3308
+ }
3309
+ }
3310
+
3311
+ function setDocumentHeight(cm, measure) {
3312
+ cm.display.sizer.style.minHeight = measure.docHeight + "px";
3313
+ var total = measure.docHeight + cm.display.barHeight;
3314
+ cm.display.heightForcer.style.top = total + "px";
3315
+ cm.display.gutters.style.height = Math.max(total + scrollGap(cm), measure.clientHeight) + "px";
3316
+ }
3317
+
3318
+ // Read the actual heights of the rendered lines, and update their
3319
+ // stored heights to match.
3320
+ function updateHeightsInViewport(cm) {
3321
+ var display = cm.display;
3322
+ var prevBottom = display.lineDiv.offsetTop;
3323
+ for (var i = 0; i < display.view.length; i++) {
3324
+ var cur = display.view[i], height;
3325
+ if (cur.hidden) continue;
3326
+ if (ie && ie_version < 8) {
3327
+ var bot = cur.node.offsetTop + cur.node.offsetHeight;
3328
+ height = bot - prevBottom;
3329
+ prevBottom = bot;
3330
+ } else {
3331
+ var box = cur.node.getBoundingClientRect();
3332
+ height = box.bottom - box.top;
3333
+ }
3334
+ var diff = cur.line.height - height;
3335
+ if (height < 2) height = textHeight(display);
3336
+ if (diff > .001 || diff < -.001) {
3337
+ updateLineHeight(cur.line, height);
3338
+ updateWidgetHeight(cur.line);
3339
+ if (cur.rest) for (var j = 0; j < cur.rest.length; j++)
3340
+ updateWidgetHeight(cur.rest[j]);
3341
+ }
3342
+ }
3343
+ }
3344
+
3345
+ // Read and store the height of line widgets associated with the
3346
+ // given line.
3347
+ function updateWidgetHeight(line) {
3348
+ if (line.widgets) for (var i = 0; i < line.widgets.length; ++i)
3349
+ line.widgets[i].height = line.widgets[i].node.offsetHeight;
3350
+ }
3351
+
3352
+ // Do a bulk-read of the DOM positions and sizes needed to draw the
3353
+ // view, so that we don't interleave reading and writing to the DOM.
3354
+ function getDimensions(cm) {
3355
+ var d = cm.display, left = {}, width = {};
3356
+ var gutterLeft = d.gutters.clientLeft;
3357
+ for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
3358
+ left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft;
3359
+ width[cm.options.gutters[i]] = n.clientWidth;
3360
+ }
3361
+ return {fixedPos: compensateForHScroll(d),
3362
+ gutterTotalWidth: d.gutters.offsetWidth,
3363
+ gutterLeft: left,
3364
+ gutterWidth: width,
3365
+ wrapperWidth: d.wrapper.clientWidth};
3366
+ }
3367
+
3368
+ // Sync the actual display DOM structure with display.view, removing
3369
+ // nodes for lines that are no longer in view, and creating the ones
3370
+ // that are not there yet, and updating the ones that are out of
3371
+ // date.
3372
+ function patchDisplay(cm, updateNumbersFrom, dims) {
3373
+ var display = cm.display, lineNumbers = cm.options.lineNumbers;
3374
+ var container = display.lineDiv, cur = container.firstChild;
3375
+
3376
+ function rm(node) {
3377
+ var next = node.nextSibling;
3378
+ // Works around a throw-scroll bug in OS X Webkit
3379
+ if (webkit && mac && cm.display.currentWheelTarget == node)
3380
+ node.style.display = "none";
3381
+ else
3382
+ node.parentNode.removeChild(node);
3383
+ return next;
3384
+ }
3385
+
3386
+ var view = display.view, lineN = display.viewFrom;
3387
+ // Loop over the elements in the view, syncing cur (the DOM nodes
3388
+ // in display.lineDiv) with the view as we go.
3389
+ for (var i = 0; i < view.length; i++) {
3390
+ var lineView = view[i];
3391
+ if (lineView.hidden) {
3392
+ } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
3393
+ var node = buildLineElement(cm, lineView, lineN, dims);
3394
+ container.insertBefore(node, cur);
3395
+ } else { // Already drawn
3396
+ while (cur != lineView.node) cur = rm(cur);
3397
+ var updateNumber = lineNumbers && updateNumbersFrom != null &&
3398
+ updateNumbersFrom <= lineN && lineView.lineNumber;
3399
+ if (lineView.changes) {
3400
+ if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false;
3401
+ updateLineForChanges(cm, lineView, lineN, dims);
3402
+ }
3403
+ if (updateNumber) {
3404
+ removeChildren(lineView.lineNumber);
3405
+ lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));
3406
+ }
3407
+ cur = lineView.node.nextSibling;
3408
+ }
3409
+ lineN += lineView.size;
3410
+ }
3411
+ while (cur) cur = rm(cur);
3412
+ }
3413
+
3414
+ // When an aspect of a line changes, a string is added to
3415
+ // lineView.changes. This updates the relevant part of the line's
3416
+ // DOM structure.
3417
+ function updateLineForChanges(cm, lineView, lineN, dims) {
3418
+ for (var j = 0; j < lineView.changes.length; j++) {
3419
+ var type = lineView.changes[j];
3420
+ if (type == "text") updateLineText(cm, lineView);
3421
+ else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims);
3422
+ else if (type == "class") updateLineClasses(lineView);
3423
+ else if (type == "widget") updateLineWidgets(cm, lineView, dims);
3424
+ }
3425
+ lineView.changes = null;
3426
+ }
3427
+
3428
+ // Lines with gutter elements, widgets or a background class need to
3429
+ // be wrapped, and have the extra elements added to the wrapper div
3430
+ function ensureLineWrapped(lineView) {
3431
+ if (lineView.node == lineView.text) {
3432
+ lineView.node = elt("div", null, null, "position: relative");
3433
+ if (lineView.text.parentNode)
3434
+ lineView.text.parentNode.replaceChild(lineView.node, lineView.text);
3435
+ lineView.node.appendChild(lineView.text);
3436
+ if (ie && ie_version < 8) lineView.node.style.zIndex = 2;
3437
+ }
3438
+ return lineView.node;
3439
+ }
3440
+
3441
+ function updateLineBackground(lineView) {
3442
+ var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;
3443
+ if (cls) cls += " CodeMirror-linebackground";
3444
+ if (lineView.background) {
3445
+ if (cls) lineView.background.className = cls;
3446
+ else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }
3447
+ } else if (cls) {
3448
+ var wrap = ensureLineWrapped(lineView);
3449
+ lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);
3450
+ }
3451
+ }
3452
+
3453
+ // Wrapper around buildLineContent which will reuse the structure
3454
+ // in display.externalMeasured when possible.
3455
+ function getLineContent(cm, lineView) {
3456
+ var ext = cm.display.externalMeasured;
3457
+ if (ext && ext.line == lineView.line) {
3458
+ cm.display.externalMeasured = null;
3459
+ lineView.measure = ext.measure;
3460
+ return ext.built;
3461
+ }
3462
+ return buildLineContent(cm, lineView);
3463
+ }
3464
+
3465
+ // Redraw the line's text. Interacts with the background and text
3466
+ // classes because the mode may output tokens that influence these
3467
+ // classes.
3468
+ function updateLineText(cm, lineView) {
3469
+ var cls = lineView.text.className;
3470
+ var built = getLineContent(cm, lineView);
3471
+ if (lineView.text == lineView.node) lineView.node = built.pre;
3472
+ lineView.text.parentNode.replaceChild(built.pre, lineView.text);
3473
+ lineView.text = built.pre;
3474
+ if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
3475
+ lineView.bgClass = built.bgClass;
3476
+ lineView.textClass = built.textClass;
3477
+ updateLineClasses(lineView);
3478
+ } else if (cls) {
3479
+ lineView.text.className = cls;
3480
+ }
3481
+ }
3482
+
3483
+ function updateLineClasses(lineView) {
3484
+ updateLineBackground(lineView);
3485
+ if (lineView.line.wrapClass)
3486
+ ensureLineWrapped(lineView).className = lineView.line.wrapClass;
3487
+ else if (lineView.node != lineView.text)
3488
+ lineView.node.className = "";
3489
+ var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;
3490
+ lineView.text.className = textClass || "";
3491
+ }
3492
+
3493
+ function updateLineGutter(cm, lineView, lineN, dims) {
3494
+ if (lineView.gutter) {
3495
+ lineView.node.removeChild(lineView.gutter);
3496
+ lineView.gutter = null;
3497
+ }
3498
+ if (lineView.gutterBackground) {
3499
+ lineView.node.removeChild(lineView.gutterBackground);
3500
+ lineView.gutterBackground = null;
3501
+ }
3502
+ if (lineView.line.gutterClass) {
3503
+ var wrap = ensureLineWrapped(lineView);
3504
+ lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass,
3505
+ "left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +
3506
+ "px; width: " + dims.gutterTotalWidth + "px");
3507
+ wrap.insertBefore(lineView.gutterBackground, lineView.text);
3508
+ }
3509
+ var markers = lineView.line.gutterMarkers;
3510
+ if (cm.options.lineNumbers || markers) {
3511
+ var wrap = ensureLineWrapped(lineView);
3512
+ var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " +
3513
+ (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px");
3514
+ cm.display.input.setUneditable(gutterWrap);
3515
+ wrap.insertBefore(gutterWrap, lineView.text);
3516
+ if (lineView.line.gutterClass)
3517
+ gutterWrap.className += " " + lineView.line.gutterClass;
3518
+ if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
3519
+ lineView.lineNumber = gutterWrap.appendChild(
3520
+ elt("div", lineNumberFor(cm.options, lineN),
3521
+ "CodeMirror-linenumber CodeMirror-gutter-elt",
3522
+ "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: "
3523
+ + cm.display.lineNumInnerWidth + "px"));
3524
+ if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) {
3525
+ var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id];
3526
+ if (found)
3527
+ gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " +
3528
+ dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px"));
3529
+ }
3530
+ }
3531
+ }
3532
+
3533
+ function updateLineWidgets(cm, lineView, dims) {
3534
+ if (lineView.alignable) lineView.alignable = null;
3535
+ for (var node = lineView.node.firstChild, next; node; node = next) {
3536
+ var next = node.nextSibling;
3537
+ if (node.className == "CodeMirror-linewidget")
3538
+ lineView.node.removeChild(node);
3539
+ }
3540
+ insertLineWidgets(cm, lineView, dims);
3541
+ }
3542
+
3543
+ // Build a line's DOM representation from scratch
3544
+ function buildLineElement(cm, lineView, lineN, dims) {
3545
+ var built = getLineContent(cm, lineView);
3546
+ lineView.text = lineView.node = built.pre;
3547
+ if (built.bgClass) lineView.bgClass = built.bgClass;
3548
+ if (built.textClass) lineView.textClass = built.textClass;
3549
+
3550
+ updateLineClasses(lineView);
3551
+ updateLineGutter(cm, lineView, lineN, dims);
3552
+ insertLineWidgets(cm, lineView, dims);
3553
+ return lineView.node;
3554
+ }
3555
+
3556
+ // A lineView may contain multiple logical lines (when merged by
3557
+ // collapsed spans). The widgets for all of them need to be drawn.
3558
+ function insertLineWidgets(cm, lineView, dims) {
3559
+ insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);
3560
+ if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
3561
+ insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false);
3562
+ }
3563
+
3564
+ function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
3565
+ if (!line.widgets) return;
3566
+ var wrap = ensureLineWrapped(lineView);
3567
+ for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
3568
+ var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget");
3569
+ if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true");
3570
+ positionLineWidget(widget, node, lineView, dims);
3571
+ cm.display.input.setUneditable(node);
3572
+ if (allowAbove && widget.above)
3573
+ wrap.insertBefore(node, lineView.gutter || lineView.text);
3574
+ else
3575
+ wrap.appendChild(node);
3576
+ signalLater(widget, "redraw");
3577
+ }
3578
+ }
3579
+
3580
+ function positionLineWidget(widget, node, lineView, dims) {
3581
+ if (widget.noHScroll) {
3582
+ (lineView.alignable || (lineView.alignable = [])).push(node);
3583
+ var width = dims.wrapperWidth;
3584
+ node.style.left = dims.fixedPos + "px";
3585
+ if (!widget.coverGutter) {
3586
+ width -= dims.gutterTotalWidth;
3587
+ node.style.paddingLeft = dims.gutterTotalWidth + "px";
3588
+ }
3589
+ node.style.width = width + "px";
3590
+ }
3591
+ if (widget.coverGutter) {
3592
+ node.style.zIndex = 5;
3593
+ node.style.position = "relative";
3594
+ if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px";
3595
+ }
3596
+ }
3597
+
3598
+ // POSITION OBJECT
3599
+
3600
+ // A Pos instance represents a position within the text.
3601
+ var Pos = CodeMirror.Pos = function(line, ch) {
3602
+ if (!(this instanceof Pos)) return new Pos(line, ch);
3603
+ this.line = line; this.ch = ch;
3604
+ };
3605
+
3606
+ // Compare two positions, return 0 if they are the same, a negative
3607
+ // number when a is less, and a positive number otherwise.
3608
+ var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; };
3609
+
3610
+ function copyPos(x) {return Pos(x.line, x.ch);}
3611
+ function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; }
3612
+ function minPos(a, b) { return cmp(a, b) < 0 ? a : b; }
3613
+
3614
+ // INPUT HANDLING
3615
+
3616
+ function ensureFocus(cm) {
3617
+ if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }
3618
+ }
3619
+
3620
+ function isReadOnly(cm) {
3621
+ return cm.options.readOnly || cm.doc.cantEdit;
3622
+ }
3623
+
3624
+ // This will be set to an array of strings when copying, so that,
3625
+ // when pasting, we know what kind of selections the copied text
3626
+ // was made out of.
3627
+ var lastCopied = null;
3628
+
3629
+ function applyTextInput(cm, inserted, deleted, sel, origin) {
3630
+ var doc = cm.doc;
3631
+ cm.display.shift = false;
3632
+ if (!sel) sel = doc.sel;
3633
+
3634
+ var paste = cm.state.pasteIncoming || origin == "paste";
3635
+ var textLines = doc.splitLines(inserted), multiPaste = null;
3636
+ // When pasing N lines into N selections, insert one line per selection
3637
+ if (paste && sel.ranges.length > 1) {
3638
+ if (lastCopied && lastCopied.join("\n") == inserted) {
3639
+ if (sel.ranges.length % lastCopied.length == 0) {
3640
+ multiPaste = [];
3641
+ for (var i = 0; i < lastCopied.length; i++)
3642
+ multiPaste.push(doc.splitLines(lastCopied[i]));
3643
+ }
3644
+ } else if (textLines.length == sel.ranges.length) {
3645
+ multiPaste = map(textLines, function(l) { return [l]; });
3646
+ }
3647
+ }
3648
+
3649
+ // Normal behavior is to insert the new text into every selection
3650
+ for (var i = sel.ranges.length - 1; i >= 0; i--) {
3651
+ var range = sel.ranges[i];
3652
+ var from = range.from(), to = range.to();
3653
+ if (range.empty()) {
3654
+ if (deleted && deleted > 0) // Handle deletion
3655
+ from = Pos(from.line, from.ch - deleted);
3656
+ else if (cm.state.overwrite && !paste) // Handle overwrite
3657
+ to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length));
3658
+ }
3659
+ var updateInput = cm.curOp.updateInput;
3660
+ var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
3661
+ origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")};
3662
+ makeChange(cm.doc, changeEvent);
3663
+ signalLater(cm, "inputRead", cm, changeEvent);
3664
+ }
3665
+ if (inserted && !paste)
3666
+ triggerElectric(cm, inserted);
3667
+
3668
+ ensureCursorVisible(cm);
3669
+ cm.curOp.updateInput = updateInput;
3670
+ cm.curOp.typing = true;
3671
+ cm.state.pasteIncoming = cm.state.cutIncoming = false;
3672
+ }
3673
+
3674
+ function handlePaste(e, cm) {
3675
+ var pasted = e.clipboardData && e.clipboardData.getData("text/plain");
3676
+ if (pasted) {
3677
+ e.preventDefault();
3678
+ if (!isReadOnly(cm) && !cm.options.disableInput)
3679
+ runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, "paste"); });
3680
+ return true;
3681
+ }
3682
+ }
3683
+
3684
+ function triggerElectric(cm, inserted) {
3685
+ // When an 'electric' character is inserted, immediately trigger a reindent
3686
+ if (!cm.options.electricChars || !cm.options.smartIndent) return;
3687
+ var sel = cm.doc.sel;
3688
+
3689
+ for (var i = sel.ranges.length - 1; i >= 0; i--) {
3690
+ var range = sel.ranges[i];
3691
+ if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue;
3692
+ var mode = cm.getModeAt(range.head);
3693
+ var indented = false;
3694
+ if (mode.electricChars) {
3695
+ for (var j = 0; j < mode.electricChars.length; j++)
3696
+ if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
3697
+ indented = indentLine(cm, range.head.line, "smart");
3698
+ break;
3699
+ }
3700
+ } else if (mode.electricInput) {
3701
+ if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
3702
+ indented = indentLine(cm, range.head.line, "smart");
3703
+ }
3704
+ if (indented) signalLater(cm, "electricInput", cm, range.head.line);
3705
+ }
3706
+ }
3707
+
3708
+ function copyableRanges(cm) {
3709
+ var text = [], ranges = [];
3710
+ for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
3711
+ var line = cm.doc.sel.ranges[i].head.line;
3712
+ var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
3713
+ ranges.push(lineRange);
3714
+ text.push(cm.getRange(lineRange.anchor, lineRange.head));
3715
+ }
3716
+ return {text: text, ranges: ranges};
3717
+ }
3718
+
3719
+ function disableBrowserMagic(field) {
3720
+ field.setAttribute("autocorrect", "off");
3721
+ field.setAttribute("autocapitalize", "off");
3722
+ field.setAttribute("spellcheck", "false");
3723
+ }
3724
+
3725
+ // TEXTAREA INPUT STYLE
3726
+
3727
+ function TextareaInput(cm) {
3728
+ this.cm = cm;
3729
+ // See input.poll and input.reset
3730
+ this.prevInput = "";
3731
+
3732
+ // Flag that indicates whether we expect input to appear real soon
3733
+ // now (after some event like 'keypress' or 'input') and are
3734
+ // polling intensively.
3735
+ this.pollingFast = false;
3736
+ // Self-resetting timeout for the poller
3737
+ this.polling = new Delayed();
3738
+ // Tracks when input.reset has punted to just putting a short
3739
+ // string into the textarea instead of the full selection.
3740
+ this.inaccurateSelection = false;
3741
+ // Used to work around IE issue with selection being forgotten when focus moves away from textarea
3742
+ this.hasSelection = false;
3743
+ this.composing = null;
3744
+ };
3745
+
3746
+ function hiddenTextarea() {
3747
+ var te = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none");
3748
+ var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
3749
+ // The textarea is kept positioned near the cursor to prevent the
3750
+ // fact that it'll be scrolled into view on input from scrolling
3751
+ // our fake cursor out of view. On webkit, when wrap=off, paste is
3752
+ // very slow. So make the area wide instead.
3753
+ if (webkit) te.style.width = "1000px";
3754
+ else te.setAttribute("wrap", "off");
3755
+ // If border: 0; -- iOS fails to open keyboard (issue #1287)
3756
+ if (ios) te.style.border = "1px solid black";
3757
+ disableBrowserMagic(te);
3758
+ return div;
3759
+ }
3760
+
3761
+ TextareaInput.prototype = copyObj({
3762
+ init: function(display) {
3763
+ var input = this, cm = this.cm;
3764
+
3765
+ // Wraps and hides input textarea
3766
+ var div = this.wrapper = hiddenTextarea();
3767
+ // The semihidden textarea that is focused when the editor is
3768
+ // focused, and receives input.
3769
+ var te = this.textarea = div.firstChild;
3770
+ display.wrapper.insertBefore(div, display.wrapper.firstChild);
3771
+
3772
+ // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
3773
+ if (ios) te.style.width = "0px";
3774
+
3775
+ on(te, "input", function() {
3776
+ if (ie && ie_version >= 9 && input.hasSelection) input.hasSelection = null;
3777
+ input.poll();
3778
+ });
3779
+
3780
+ on(te, "paste", function(e) {
3781
+ if (handlePaste(e, cm)) return true;
3782
+
3783
+ cm.state.pasteIncoming = true;
3784
+ input.fastPoll();
3785
+ });
3786
+
3787
+ function prepareCopyCut(e) {
3788
+ if (cm.somethingSelected()) {
3789
+ lastCopied = cm.getSelections();
3790
+ if (input.inaccurateSelection) {
3791
+ input.prevInput = "";
3792
+ input.inaccurateSelection = false;
3793
+ te.value = lastCopied.join("\n");
3794
+ selectInput(te);
3795
+ }
3796
+ } else if (!cm.options.lineWiseCopyCut) {
3797
+ return;
3798
+ } else {
3799
+ var ranges = copyableRanges(cm);
3800
+ lastCopied = ranges.text;
3801
+ if (e.type == "cut") {
3802
+ cm.setSelections(ranges.ranges, null, sel_dontScroll);
3803
+ } else {
3804
+ input.prevInput = "";
3805
+ te.value = ranges.text.join("\n");
3806
+ selectInput(te);
3807
+ }
3808
+ }
3809
+ if (e.type == "cut") cm.state.cutIncoming = true;
3810
+ }
3811
+ on(te, "cut", prepareCopyCut);
3812
+ on(te, "copy", prepareCopyCut);
3813
+
3814
+ on(display.scroller, "paste", function(e) {
3815
+ if (eventInWidget(display, e)) return;
3816
+ cm.state.pasteIncoming = true;
3817
+ input.focus();
3818
+ });
3819
+
3820
+ // Prevent normal selection in the editor (we handle our own)
3821
+ on(display.lineSpace, "selectstart", function(e) {
3822
+ if (!eventInWidget(display, e)) e_preventDefault(e);
3823
+ });
3824
+
3825
+ on(te, "compositionstart", function() {
3826
+ var start = cm.getCursor("from");
3827
+ if (input.composing) input.composing.range.clear()
3828
+ input.composing = {
3829
+ start: start,
3830
+ range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
3831
+ };
3832
+ });
3833
+ on(te, "compositionend", function() {
3834
+ if (input.composing) {
3835
+ input.poll();
3836
+ input.composing.range.clear();
3837
+ input.composing = null;
3838
+ }
3839
+ });
3840
+ },
3841
+
3842
+ prepareSelection: function() {
3843
+ // Redraw the selection and/or cursor
3844
+ var cm = this.cm, display = cm.display, doc = cm.doc;
3845
+ var result = prepareSelection(cm);
3846
+
3847
+ // Move the hidden textarea near the cursor to prevent scrolling artifacts
3848
+ if (cm.options.moveInputWithCursor) {
3849
+ var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
3850
+ var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
3851
+ result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
3852
+ headPos.top + lineOff.top - wrapOff.top));
3853
+ result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
3854
+ headPos.left + lineOff.left - wrapOff.left));
3855
+ }
3856
+
3857
+ return result;
3858
+ },
3859
+
3860
+ showSelection: function(drawn) {
3861
+ var cm = this.cm, display = cm.display;
3862
+ removeChildrenAndAdd(display.cursorDiv, drawn.cursors);
3863
+ removeChildrenAndAdd(display.selectionDiv, drawn.selection);
3864
+ if (drawn.teTop != null) {
3865
+ this.wrapper.style.top = drawn.teTop + "px";
3866
+ this.wrapper.style.left = drawn.teLeft + "px";
3867
+ }
3868
+ },
3869
+
3870
+ // Reset the input to correspond to the selection (or to be empty,
3871
+ // when not typing and nothing is selected)
3872
+ reset: function(typing) {
3873
+ if (this.contextMenuPending) return;
3874
+ var minimal, selected, cm = this.cm, doc = cm.doc;
3875
+ if (cm.somethingSelected()) {
3876
+ this.prevInput = "";
3877
+ var range = doc.sel.primary();
3878
+ minimal = hasCopyEvent &&
3879
+ (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000);
3880
+ var content = minimal ? "-" : selected || cm.getSelection();
3881
+ this.textarea.value = content;
3882
+ if (cm.state.focused) selectInput(this.textarea);
3883
+ if (ie && ie_version >= 9) this.hasSelection = content;
3884
+ } else if (!typing) {
3885
+ this.prevInput = this.textarea.value = "";
3886
+ if (ie && ie_version >= 9) this.hasSelection = null;
3887
+ }
3888
+ this.inaccurateSelection = minimal;
3889
+ },
3890
+
3891
+ getField: function() { return this.textarea; },
3892
+
3893
+ supportsTouch: function() { return false; },
3894
+
3895
+ focus: function() {
3896
+ if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
3897
+ try { this.textarea.focus(); }
3898
+ catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
3899
+ }
3900
+ },
3901
+
3902
+ blur: function() { this.textarea.blur(); },
3903
+
3904
+ resetPosition: function() {
3905
+ this.wrapper.style.top = this.wrapper.style.left = 0;
3906
+ },
3907
+
3908
+ receivedFocus: function() { this.slowPoll(); },
3909
+
3910
+ // Poll for input changes, using the normal rate of polling. This
3911
+ // runs as long as the editor is focused.
3912
+ slowPoll: function() {
3913
+ var input = this;
3914
+ if (input.pollingFast) return;
3915
+ input.polling.set(this.cm.options.pollInterval, function() {
3916
+ input.poll();
3917
+ if (input.cm.state.focused) input.slowPoll();
3918
+ });
3919
+ },
3920
+
3921
+ // When an event has just come in that is likely to add or change
3922
+ // something in the input textarea, we poll faster, to ensure that
3923
+ // the change appears on the screen quickly.
3924
+ fastPoll: function() {
3925
+ var missed = false, input = this;
3926
+ input.pollingFast = true;
3927
+ function p() {
3928
+ var changed = input.poll();
3929
+ if (!changed && !missed) {missed = true; input.polling.set(60, p);}
3930
+ else {input.pollingFast = false; input.slowPoll();}
3931
+ }
3932
+ input.polling.set(20, p);
3933
+ },
3934
+
3935
+ // Read input from the textarea, and update the document to match.
3936
+ // When something is selected, it is present in the textarea, and
3937
+ // selected (unless it is huge, in which case a placeholder is
3938
+ // used). When nothing is selected, the cursor sits after previously
3939
+ // seen text (can be empty), which is stored in prevInput (we must
3940
+ // not reset the textarea when typing, because that breaks IME).
3941
+ poll: function() {
3942
+ var cm = this.cm, input = this.textarea, prevInput = this.prevInput;
3943
+ // Since this is called a *lot*, try to bail out as cheaply as
3944
+ // possible when it is clear that nothing happened. hasSelection
3945
+ // will be the case when there is a lot of text in the textarea,
3946
+ // in which case reading its value would be expensive.
3947
+ if (this.contextMenuPending || !cm.state.focused ||
3948
+ (hasSelection(input) && !prevInput && !this.composing) ||
3949
+ isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq)
3950
+ return false;
3951
+
3952
+ var text = input.value;
3953
+ // If nothing changed, bail.
3954
+ if (text == prevInput && !cm.somethingSelected()) return false;
3955
+ // Work around nonsensical selection resetting in IE9/10, and
3956
+ // inexplicable appearance of private area unicode characters on
3957
+ // some key combos in Mac (#2689).
3958
+ if (ie && ie_version >= 9 && this.hasSelection === text ||
3959
+ mac && /[\uf700-\uf7ff]/.test(text)) {
3960
+ cm.display.input.reset();
3961
+ return false;
3962
+ }
3963
+
3964
+ if (cm.doc.sel == cm.display.selForContextMenu) {
3965
+ var first = text.charCodeAt(0);
3966
+ if (first == 0x200b && !prevInput) prevInput = "\u200b";
3967
+ if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo"); }
3968
+ }
3969
+ // Find the part of the input that is actually new
3970
+ var same = 0, l = Math.min(prevInput.length, text.length);
3971
+ while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same;
3972
+
3973
+ var self = this;
3974
+ runInOp(cm, function() {
3975
+ applyTextInput(cm, text.slice(same), prevInput.length - same,
3976
+ null, self.composing ? "*compose" : null);
3977
+
3978
+ // Don't leave long text in the textarea, since it makes further polling slow
3979
+ if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = "";
3980
+ else self.prevInput = text;
3981
+
3982
+ if (self.composing) {
3983
+ self.composing.range.clear();
3984
+ self.composing.range = cm.markText(self.composing.start, cm.getCursor("to"),
3985
+ {className: "CodeMirror-composing"});
3986
+ }
3987
+ });
3988
+ return true;
3989
+ },
3990
+
3991
+ ensurePolled: function() {
3992
+ if (this.pollingFast && this.poll()) this.pollingFast = false;
3993
+ },
3994
+
3995
+ onKeyPress: function() {
3996
+ if (ie && ie_version >= 9) this.hasSelection = null;
3997
+ this.fastPoll();
3998
+ },
3999
+
4000
+ onContextMenu: function(e) {
4001
+ var input = this, cm = input.cm, display = cm.display, te = input.textarea;
4002
+ var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
4003
+ if (!pos || presto) return; // Opera is difficult.
4004
+
4005
+ // Reset the current text selection only if the click is done outside of the selection
4006
+ // and 'resetSelectionOnContextMenu' option is true.
4007
+ var reset = cm.options.resetSelectionOnContextMenu;
4008
+ if (reset && cm.doc.sel.contains(pos) == -1)
4009
+ operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll);
4010
+
4011
+ var oldCSS = te.style.cssText;
4012
+ input.wrapper.style.position = "absolute";
4013
+ te.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) +
4014
+ "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " +
4015
+ (ie ? "rgba(255, 255, 255, .05)" : "transparent") +
4016
+ "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
4017
+ if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712)
4018
+ display.input.focus();
4019
+ if (webkit) window.scrollTo(null, oldScrollY);
4020
+ display.input.reset();
4021
+ // Adds "Select all" to context menu in FF
4022
+ if (!cm.somethingSelected()) te.value = input.prevInput = " ";
4023
+ input.contextMenuPending = true;
4024
+ display.selForContextMenu = cm.doc.sel;
4025
+ clearTimeout(display.detectingSelectAll);
4026
+
4027
+ // Select-all will be greyed out if there's nothing to select, so
4028
+ // this adds a zero-width space so that we can later check whether
4029
+ // it got selected.
4030
+ function prepareSelectAllHack() {
4031
+ if (te.selectionStart != null) {
4032
+ var selected = cm.somethingSelected();
4033
+ var extval = "\u200b" + (selected ? te.value : "");
4034
+ te.value = "\u21da"; // Used to catch context-menu undo
4035
+ te.value = extval;
4036
+ input.prevInput = selected ? "" : "\u200b";
4037
+ te.selectionStart = 1; te.selectionEnd = extval.length;
4038
+ // Re-set this, in case some other handler touched the
4039
+ // selection in the meantime.
4040
+ display.selForContextMenu = cm.doc.sel;
4041
+ }
4042
+ }
4043
+ function rehide() {
4044
+ input.contextMenuPending = false;
4045
+ input.wrapper.style.position = "relative";
4046
+ te.style.cssText = oldCSS;
4047
+ if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos);
4048
+
4049
+ // Try to detect the user choosing select-all
4050
+ if (te.selectionStart != null) {
4051
+ if (!ie || (ie && ie_version < 9)) prepareSelectAllHack();
4052
+ var i = 0, poll = function() {
4053
+ if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
4054
+ te.selectionEnd > 0 && input.prevInput == "\u200b")
4055
+ operation(cm, commands.selectAll)(cm);
4056
+ else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500);
4057
+ else display.input.reset();
4058
+ };
4059
+ display.detectingSelectAll = setTimeout(poll, 200);
4060
+ }
4061
+ }
4062
+
4063
+ if (ie && ie_version >= 9) prepareSelectAllHack();
4064
+ if (captureRightClick) {
4065
+ e_stop(e);
4066
+ var mouseup = function() {
4067
+ off(window, "mouseup", mouseup);
4068
+ setTimeout(rehide, 20);
4069
+ };
4070
+ on(window, "mouseup", mouseup);
4071
+ } else {
4072
+ setTimeout(rehide, 50);
4073
+ }
4074
+ },
4075
+
4076
+ readOnlyChanged: function(val) {
4077
+ if (!val) this.reset();
4078
+ },
4079
+
4080
+ setUneditable: nothing,
4081
+
4082
+ needsContentAttribute: false
4083
+ }, TextareaInput.prototype);
4084
+
4085
+ // CONTENTEDITABLE INPUT STYLE
4086
+
4087
+ function ContentEditableInput(cm) {
4088
+ this.cm = cm;
4089
+ this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
4090
+ this.polling = new Delayed();
4091
+ this.gracePeriod = false;
4092
+ }
4093
+
4094
+ ContentEditableInput.prototype = copyObj({
4095
+ init: function(display) {
4096
+ var input = this, cm = input.cm;
4097
+ var div = input.div = display.lineDiv;
4098
+ disableBrowserMagic(div);
4099
+
4100
+ on(div, "paste", function(e) { handlePaste(e, cm); })
4101
+
4102
+ on(div, "compositionstart", function(e) {
4103
+ var data = e.data;
4104
+ input.composing = {sel: cm.doc.sel, data: data, startData: data};
4105
+ if (!data) return;
4106
+ var prim = cm.doc.sel.primary();
4107
+ var line = cm.getLine(prim.head.line);
4108
+ var found = line.indexOf(data, Math.max(0, prim.head.ch - data.length));
4109
+ if (found > -1 && found <= prim.head.ch)
4110
+ input.composing.sel = simpleSelection(Pos(prim.head.line, found),
4111
+ Pos(prim.head.line, found + data.length));
4112
+ });
4113
+ on(div, "compositionupdate", function(e) {
4114
+ input.composing.data = e.data;
4115
+ });
4116
+ on(div, "compositionend", function(e) {
4117
+ var ours = input.composing;
4118
+ if (!ours) return;
4119
+ if (e.data != ours.startData && !/\u200b/.test(e.data))
4120
+ ours.data = e.data;
4121
+ // Need a small delay to prevent other code (input event,
4122
+ // selection polling) from doing damage when fired right after
4123
+ // compositionend.
4124
+ setTimeout(function() {
4125
+ if (!ours.handled)
4126
+ input.applyComposition(ours);
4127
+ if (input.composing == ours)
4128
+ input.composing = null;
4129
+ }, 50);
4130
+ });
4131
+
4132
+ on(div, "touchstart", function() {
4133
+ input.forceCompositionEnd();
4134
+ });
4135
+
4136
+ on(div, "input", function() {
4137
+ if (input.composing) return;
4138
+ if (isReadOnly(cm) || !input.pollContent())
4139
+ runInOp(input.cm, function() {regChange(cm);});
4140
+ });
4141
+
4142
+ function onCopyCut(e) {
4143
+ if (cm.somethingSelected()) {
4144
+ lastCopied = cm.getSelections();
4145
+ if (e.type == "cut") cm.replaceSelection("", null, "cut");
4146
+ } else if (!cm.options.lineWiseCopyCut) {
4147
+ return;
4148
+ } else {
4149
+ var ranges = copyableRanges(cm);
4150
+ lastCopied = ranges.text;
4151
+ if (e.type == "cut") {
4152
+ cm.operation(function() {
4153
+ cm.setSelections(ranges.ranges, 0, sel_dontScroll);
4154
+ cm.replaceSelection("", null, "cut");
4155
+ });
4156
+ }
4157
+ }
4158
+ // iOS exposes the clipboard API, but seems to discard content inserted into it
4159
+ if (e.clipboardData && !ios) {
4160
+ e.preventDefault();
4161
+ e.clipboardData.clearData();
4162
+ e.clipboardData.setData("text/plain", lastCopied.join("\n"));
4163
+ } else {
4164
+ // Old-fashioned briefly-focus-a-textarea hack
4165
+ var kludge = hiddenTextarea(), te = kludge.firstChild;
4166
+ cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
4167
+ te.value = lastCopied.join("\n");
4168
+ var hadFocus = document.activeElement;
4169
+ selectInput(te);
4170
+ setTimeout(function() {
4171
+ cm.display.lineSpace.removeChild(kludge);
4172
+ hadFocus.focus();
4173
+ }, 50);
4174
+ }
4175
+ }
4176
+ on(div, "copy", onCopyCut);
4177
+ on(div, "cut", onCopyCut);
4178
+ },
4179
+
4180
+ prepareSelection: function() {
4181
+ var result = prepareSelection(this.cm, false);
4182
+ result.focus = this.cm.state.focused;
4183
+ return result;
4184
+ },
4185
+
4186
+ showSelection: function(info) {
4187
+ if (!info || !this.cm.display.view.length) return;
4188
+ if (info.focus) this.showPrimarySelection();
4189
+ this.showMultipleSelections(info);
4190
+ },
4191
+
4192
+ showPrimarySelection: function() {
4193
+ var sel = window.getSelection(), prim = this.cm.doc.sel.primary();
4194
+ var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset);
4195
+ var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset);
4196
+ if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
4197
+ cmp(minPos(curAnchor, curFocus), prim.from()) == 0 &&
4198
+ cmp(maxPos(curAnchor, curFocus), prim.to()) == 0)
4199
+ return;
4200
+
4201
+ var start = posToDOM(this.cm, prim.from());
4202
+ var end = posToDOM(this.cm, prim.to());
4203
+ if (!start && !end) return;
4204
+
4205
+ var view = this.cm.display.view;
4206
+ var old = sel.rangeCount && sel.getRangeAt(0);
4207
+ if (!start) {
4208
+ start = {node: view[0].measure.map[2], offset: 0};
4209
+ } else if (!end) { // FIXME dangerously hacky
4210
+ var measure = view[view.length - 1].measure;
4211
+ var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
4212
+ end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]};
4213
+ }
4214
+
4215
+ try { var rng = range(start.node, start.offset, end.offset, end.node); }
4216
+ catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
4217
+ if (rng) {
4218
+ sel.removeAllRanges();
4219
+ sel.addRange(rng);
4220
+ if (old && sel.anchorNode == null) sel.addRange(old);
4221
+ else if (gecko) this.startGracePeriod();
4222
+ }
4223
+ this.rememberSelection();
4224
+ },
4225
+
4226
+ startGracePeriod: function() {
4227
+ var input = this;
4228
+ clearTimeout(this.gracePeriod);
4229
+ this.gracePeriod = setTimeout(function() {
4230
+ input.gracePeriod = false;
4231
+ if (input.selectionChanged())
4232
+ input.cm.operation(function() { input.cm.curOp.selectionChanged = true; });
4233
+ }, 20);
4234
+ },
4235
+
4236
+ showMultipleSelections: function(info) {
4237
+ removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
4238
+ removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
4239
+ },
4240
+
4241
+ rememberSelection: function() {
4242
+ var sel = window.getSelection();
4243
+ this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;
4244
+ this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;
4245
+ },
4246
+
4247
+ selectionInEditor: function() {
4248
+ var sel = window.getSelection();
4249
+ if (!sel.rangeCount) return false;
4250
+ var node = sel.getRangeAt(0).commonAncestorContainer;
4251
+ return contains(this.div, node);
4252
+ },
4253
+
4254
+ focus: function() {
4255
+ if (this.cm.options.readOnly != "nocursor") this.div.focus();
4256
+ },
4257
+ blur: function() { this.div.blur(); },
4258
+ getField: function() { return this.div; },
4259
+
4260
+ supportsTouch: function() { return true; },
4261
+
4262
+ receivedFocus: function() {
4263
+ var input = this;
4264
+ if (this.selectionInEditor())
4265
+ this.pollSelection();
4266
+ else
4267
+ runInOp(this.cm, function() { input.cm.curOp.selectionChanged = true; });
4268
+
4269
+ function poll() {
4270
+ if (input.cm.state.focused) {
4271
+ input.pollSelection();
4272
+ input.polling.set(input.cm.options.pollInterval, poll);
4273
+ }
4274
+ }
4275
+ this.polling.set(this.cm.options.pollInterval, poll);
4276
+ },
4277
+
4278
+ selectionChanged: function() {
4279
+ var sel = window.getSelection();
4280
+ return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
4281
+ sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset;
4282
+ },
4283
+
4284
+ pollSelection: function() {
4285
+ if (!this.composing && !this.gracePeriod && this.selectionChanged()) {
4286
+ var sel = window.getSelection(), cm = this.cm;
4287
+ this.rememberSelection();
4288
+ var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
4289
+ var head = domToPos(cm, sel.focusNode, sel.focusOffset);
4290
+ if (anchor && head) runInOp(cm, function() {
4291
+ setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);
4292
+ if (anchor.bad || head.bad) cm.curOp.selectionChanged = true;
4293
+ });
4294
+ }
4295
+ },
4296
+
4297
+ pollContent: function() {
4298
+ var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();
4299
+ var from = sel.from(), to = sel.to();
4300
+ if (from.line < display.viewFrom || to.line > display.viewTo - 1) return false;
4301
+
4302
+ var fromIndex;
4303
+ if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
4304
+ var fromLine = lineNo(display.view[0].line);
4305
+ var fromNode = display.view[0].node;
4306
+ } else {
4307
+ var fromLine = lineNo(display.view[fromIndex].line);
4308
+ var fromNode = display.view[fromIndex - 1].node.nextSibling;
4309
+ }
4310
+ var toIndex = findViewIndex(cm, to.line);
4311
+ if (toIndex == display.view.length - 1) {
4312
+ var toLine = display.viewTo - 1;
4313
+ var toNode = display.lineDiv.lastChild;
4314
+ } else {
4315
+ var toLine = lineNo(display.view[toIndex + 1].line) - 1;
4316
+ var toNode = display.view[toIndex + 1].node.previousSibling;
4317
+ }
4318
+
4319
+ var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
4320
+ var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));
4321
+ while (newText.length > 1 && oldText.length > 1) {
4322
+ if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }
4323
+ else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }
4324
+ else break;
4325
+ }
4326
+
4327
+ var cutFront = 0, cutEnd = 0;
4328
+ var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);
4329
+ while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
4330
+ ++cutFront;
4331
+ var newBot = lst(newText), oldBot = lst(oldText);
4332
+ var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
4333
+ oldBot.length - (oldText.length == 1 ? cutFront : 0));
4334
+ while (cutEnd < maxCutEnd &&
4335
+ newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
4336
+ ++cutEnd;
4337
+
4338
+ newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd);
4339
+ newText[0] = newText[0].slice(cutFront);
4340
+
4341
+ var chFrom = Pos(fromLine, cutFront);
4342
+ var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);
4343
+ if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
4344
+ replaceRange(cm.doc, newText, chFrom, chTo, "+input");
4345
+ return true;
4346
+ }
4347
+ },
4348
+
4349
+ ensurePolled: function() {
4350
+ this.forceCompositionEnd();
4351
+ },
4352
+ reset: function() {
4353
+ this.forceCompositionEnd();
4354
+ },
4355
+ forceCompositionEnd: function() {
4356
+ if (!this.composing || this.composing.handled) return;
4357
+ this.applyComposition(this.composing);
4358
+ this.composing.handled = true;
4359
+ this.div.blur();
4360
+ this.div.focus();
4361
+ },
4362
+ applyComposition: function(composing) {
4363
+ if (isReadOnly(this.cm))
4364
+ operation(this.cm, regChange)(this.cm)
4365
+ else if (composing.data && composing.data != composing.startData)
4366
+ operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel);
4367
+ },
4368
+
4369
+ setUneditable: function(node) {
4370
+ node.contentEditable = "false"
4371
+ },
4372
+
4373
+ onKeyPress: function(e) {
4374
+ e.preventDefault();
4375
+ if (!isReadOnly(this.cm))
4376
+ operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0);
4377
+ },
4378
+
4379
+ readOnlyChanged: function(val) {
4380
+ this.div.contentEditable = String(val != "nocursor")
4381
+ },
4382
+
4383
+ onContextMenu: nothing,
4384
+ resetPosition: nothing,
4385
+
4386
+ needsContentAttribute: true
4387
+ }, ContentEditableInput.prototype);
4388
+
4389
+ function posToDOM(cm, pos) {
4390
+ var view = findViewForLine(cm, pos.line);
4391
+ if (!view || view.hidden) return null;
4392
+ var line = getLine(cm.doc, pos.line);
4393
+ var info = mapFromLineView(view, line, pos.line);
4394
+
4395
+ var order = getOrder(line), side = "left";
4396
+ if (order) {
4397
+ var partPos = getBidiPartAt(order, pos.ch);
4398
+ side = partPos % 2 ? "right" : "left";
4399
+ }
4400
+ var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);
4401
+ result.offset = result.collapse == "right" ? result.end : result.start;
4402
+ return result;
4403
+ }
4404
+
4405
+ function badPos(pos, bad) { if (bad) pos.bad = true; return pos; }
4406
+
4407
+ function domToPos(cm, node, offset) {
4408
+ var lineNode;
4409
+ if (node == cm.display.lineDiv) {
4410
+ lineNode = cm.display.lineDiv.childNodes[offset];
4411
+ if (!lineNode) return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true);
4412
+ node = null; offset = 0;
4413
+ } else {
4414
+ for (lineNode = node;; lineNode = lineNode.parentNode) {
4415
+ if (!lineNode || lineNode == cm.display.lineDiv) return null;
4416
+ if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) break;
4417
+ }
4418
+ }
4419
+ for (var i = 0; i < cm.display.view.length; i++) {
4420
+ var lineView = cm.display.view[i];
4421
+ if (lineView.node == lineNode)
4422
+ return locateNodeInLineView(lineView, node, offset);
4423
+ }
4424
+ }
4425
+
4426
+ function locateNodeInLineView(lineView, node, offset) {
4427
+ var wrapper = lineView.text.firstChild, bad = false;
4428
+ if (!node || !contains(wrapper, node)) return badPos(Pos(lineNo(lineView.line), 0), true);
4429
+ if (node == wrapper) {
4430
+ bad = true;
4431
+ node = wrapper.childNodes[offset];
4432
+ offset = 0;
4433
+ if (!node) {
4434
+ var line = lineView.rest ? lst(lineView.rest) : lineView.line;
4435
+ return badPos(Pos(lineNo(line), line.text.length), bad);
4436
+ }
4437
+ }
4438
+
4439
+ var textNode = node.nodeType == 3 ? node : null, topNode = node;
4440
+ if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
4441
+ textNode = node.firstChild;
4442
+ if (offset) offset = textNode.nodeValue.length;
4443
+ }
4444
+ while (topNode.parentNode != wrapper) topNode = topNode.parentNode;
4445
+ var measure = lineView.measure, maps = measure.maps;
4446
+
4447
+ function find(textNode, topNode, offset) {
4448
+ for (var i = -1; i < (maps ? maps.length : 0); i++) {
4449
+ var map = i < 0 ? measure.map : maps[i];
4450
+ for (var j = 0; j < map.length; j += 3) {
4451
+ var curNode = map[j + 2];
4452
+ if (curNode == textNode || curNode == topNode) {
4453
+ var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);
4454
+ var ch = map[j] + offset;
4455
+ if (offset < 0 || curNode != textNode) ch = map[j + (offset ? 1 : 0)];
4456
+ return Pos(line, ch);
4457
+ }
4458
+ }
4459
+ }
4460
+ }
4461
+ var found = find(textNode, topNode, offset);
4462
+ if (found) return badPos(found, bad);
4463
+
4464
+ // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
4465
+ for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
4466
+ found = find(after, after.firstChild, 0);
4467
+ if (found)
4468
+ return badPos(Pos(found.line, found.ch - dist), bad);
4469
+ else
4470
+ dist += after.textContent.length;
4471
+ }
4472
+ for (var before = topNode.previousSibling, dist = offset; before; before = before.previousSibling) {
4473
+ found = find(before, before.firstChild, -1);
4474
+ if (found)
4475
+ return badPos(Pos(found.line, found.ch + dist), bad);
4476
+ else
4477
+ dist += after.textContent.length;
4478
+ }
4479
+ }
4480
+
4481
+ function domTextBetween(cm, from, to, fromLine, toLine) {
4482
+ var text = "", closing = false, lineSep = cm.doc.lineSeparator();
4483
+ function recognizeMarker(id) { return function(marker) { return marker.id == id; }; }
4484
+ function walk(node) {
4485
+ if (node.nodeType == 1) {
4486
+ var cmText = node.getAttribute("cm-text");
4487
+ if (cmText != null) {
4488
+ if (cmText == "") cmText = node.textContent.replace(/\u200b/g, "");
4489
+ text += cmText;
4490
+ return;
4491
+ }
4492
+ var markerID = node.getAttribute("cm-marker"), range;
4493
+ if (markerID) {
4494
+ var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
4495
+ if (found.length && (range = found[0].find()))
4496
+ text += getBetween(cm.doc, range.from, range.to).join(lineSep);
4497
+ return;
4498
+ }
4499
+ if (node.getAttribute("contenteditable") == "false") return;
4500
+ for (var i = 0; i < node.childNodes.length; i++)
4501
+ walk(node.childNodes[i]);
4502
+ if (/^(pre|div|p)$/i.test(node.nodeName))
4503
+ closing = true;
4504
+ } else if (node.nodeType == 3) {
4505
+ var val = node.nodeValue;
4506
+ if (!val) return;
4507
+ if (closing) {
4508
+ text += lineSep;
4509
+ closing = false;
4510
+ }
4511
+ text += val;
4512
+ }
4513
+ }
4514
+ for (;;) {
4515
+ walk(from);
4516
+ if (from == to) break;
4517
+ from = from.nextSibling;
4518
+ }
4519
+ return text;
4520
+ }
4521
+
4522
+ CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput};
4523
+
4524
+ // SELECTION / CURSOR
4525
+
4526
+ // Selection objects are immutable. A new one is created every time
4527
+ // the selection changes. A selection is one or more non-overlapping
4528
+ // (and non-touching) ranges, sorted, and an integer that indicates
4529
+ // which one is the primary selection (the one that's scrolled into
4530
+ // view, that getCursor returns, etc).
4531
+ function Selection(ranges, primIndex) {
4532
+ this.ranges = ranges;
4533
+ this.primIndex = primIndex;
4534
+ }
4535
+
4536
+ Selection.prototype = {
4537
+ primary: function() { return this.ranges[this.primIndex]; },
4538
+ equals: function(other) {
4539
+ if (other == this) return true;
4540
+ if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false;
4541
+ for (var i = 0; i < this.ranges.length; i++) {
4542
+ var here = this.ranges[i], there = other.ranges[i];
4543
+ if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false;
4544
+ }
4545
+ return true;
4546
+ },
4547
+ deepCopy: function() {
4548
+ for (var out = [], i = 0; i < this.ranges.length; i++)
4549
+ out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head));
4550
+ return new Selection(out, this.primIndex);
4551
+ },
4552
+ somethingSelected: function() {
4553
+ for (var i = 0; i < this.ranges.length; i++)
4554
+ if (!this.ranges[i].empty()) return true;
4555
+ return false;
4556
+ },
4557
+ contains: function(pos, end) {
4558
+ if (!end) end = pos;
4559
+ for (var i = 0; i < this.ranges.length; i++) {
4560
+ var range = this.ranges[i];
4561
+ if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
4562
+ return i;
4563
+ }
4564
+ return -1;
4565
+ }
4566
+ };
4567
+
4568
+ function Range(anchor, head) {
4569
+ this.anchor = anchor; this.head = head;
4570
+ }
4571
+
4572
+ Range.prototype = {
4573
+ from: function() { return minPos(this.anchor, this.head); },
4574
+ to: function() { return maxPos(this.anchor, this.head); },
4575
+ empty: function() {
4576
+ return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch;
4577
+ }
4578
+ };
4579
+
4580
+ // Take an unsorted, potentially overlapping set of ranges, and
4581
+ // build a selection out of it. 'Consumes' ranges array (modifying
4582
+ // it).
4583
+ function normalizeSelection(ranges, primIndex) {
4584
+ var prim = ranges[primIndex];
4585
+ ranges.sort(function(a, b) { return cmp(a.from(), b.from()); });
4586
+ primIndex = indexOf(ranges, prim);
4587
+ for (var i = 1; i < ranges.length; i++) {
4588
+ var cur = ranges[i], prev = ranges[i - 1];
4589
+ if (cmp(prev.to(), cur.from()) >= 0) {
4590
+ var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());
4591
+ var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;
4592
+ if (i <= primIndex) --primIndex;
4593
+ ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));
4594
+ }
4595
+ }
4596
+ return new Selection(ranges, primIndex);
4597
+ }
4598
+
4599
+ function simpleSelection(anchor, head) {
4600
+ return new Selection([new Range(anchor, head || anchor)], 0);
4601
+ }
4602
+
4603
+ // Most of the external API clips given positions to make sure they
4604
+ // actually exist within the document.
4605
+ function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));}
4606
+ function clipPos(doc, pos) {
4607
+ if (pos.line < doc.first) return Pos(doc.first, 0);
4608
+ var last = doc.first + doc.size - 1;
4609
+ if (pos.line > last) return Pos(last, getLine(doc, last).text.length);
4610
+ return clipToLen(pos, getLine(doc, pos.line).text.length);
4611
+ }
4612
+ function clipToLen(pos, linelen) {
4613
+ var ch = pos.ch;
4614
+ if (ch == null || ch > linelen) return Pos(pos.line, linelen);
4615
+ else if (ch < 0) return Pos(pos.line, 0);
4616
+ else return pos;
4617
+ }
4618
+ function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;}
4619
+ function clipPosArray(doc, array) {
4620
+ for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]);
4621
+ return out;
4622
+ }
4623
+
4624
+ // SELECTION UPDATES
4625
+
4626
+ // The 'scroll' parameter given to many of these indicated whether
4627
+ // the new cursor position should be scrolled into view after
4628
+ // modifying the selection.
4629
+
4630
+ // If shift is held or the extend flag is set, extends a range to
4631
+ // include a given position (and optionally a second position).
4632
+ // Otherwise, simply returns the range between the given positions.
4633
+ // Used for cursor motion and such.
4634
+ function extendRange(doc, range, head, other) {
4635
+ if (doc.cm && doc.cm.display.shift || doc.extend) {
4636
+ var anchor = range.anchor;
4637
+ if (other) {
4638
+ var posBefore = cmp(head, anchor) < 0;
4639
+ if (posBefore != (cmp(other, anchor) < 0)) {
4640
+ anchor = head;
4641
+ head = other;
4642
+ } else if (posBefore != (cmp(head, other) < 0)) {
4643
+ head = other;
4644
+ }
4645
+ }
4646
+ return new Range(anchor, head);
4647
+ } else {
4648
+ return new Range(other || head, head);
4649
+ }
4650
+ }
4651
+
4652
+ // Extend the primary selection range, discard the rest.
4653
+ function extendSelection(doc, head, other, options) {
4654
+ setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options);
4655
+ }
4656
+
4657
+ // Extend all selections (pos is an array of selections with length
4658
+ // equal the number of selections)
4659
+ function extendSelections(doc, heads, options) {
4660
+ for (var out = [], i = 0; i < doc.sel.ranges.length; i++)
4661
+ out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null);
4662
+ var newSel = normalizeSelection(out, doc.sel.primIndex);
4663
+ setSelection(doc, newSel, options);
4664
+ }
4665
+
4666
+ // Updates a single range in the selection.
4667
+ function replaceOneSelection(doc, i, range, options) {
4668
+ var ranges = doc.sel.ranges.slice(0);
4669
+ ranges[i] = range;
4670
+ setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options);
4671
+ }
4672
+
4673
+ // Reset the selection to a single range.
4674
+ function setSimpleSelection(doc, anchor, head, options) {
4675
+ setSelection(doc, simpleSelection(anchor, head), options);
4676
+ }
4677
+
4678
+ // Give beforeSelectionChange handlers a change to influence a
4679
+ // selection update.
4680
+ function filterSelectionChange(doc, sel) {
4681
+ var obj = {
4682
+ ranges: sel.ranges,
4683
+ update: function(ranges) {
4684
+ this.ranges = [];
4685
+ for (var i = 0; i < ranges.length; i++)
4686
+ this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
4687
+ clipPos(doc, ranges[i].head));
4688
+ }
4689
+ };
4690
+ signal(doc, "beforeSelectionChange", doc, obj);
4691
+ if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
4692
+ if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1);
4693
+ else return sel;
4694
+ }
4695
+
4696
+ function setSelectionReplaceHistory(doc, sel, options) {
4697
+ var done = doc.history.done, last = lst(done);
4698
+ if (last && last.ranges) {
4699
+ done[done.length - 1] = sel;
4700
+ setSelectionNoUndo(doc, sel, options);
4701
+ } else {
4702
+ setSelection(doc, sel, options);
4703
+ }
4704
+ }
4705
+
4706
+ // Set a new selection.
4707
+ function setSelection(doc, sel, options) {
4708
+ setSelectionNoUndo(doc, sel, options);
4709
+ addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);
4710
+ }
4711
+
4712
+ function setSelectionNoUndo(doc, sel, options) {
4713
+ if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
4714
+ sel = filterSelectionChange(doc, sel);
4715
+
4716
+ var bias = options && options.bias ||
4717
+ (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
4718
+ setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
4719
+
4720
+ if (!(options && options.scroll === false) && doc.cm)
4721
+ ensureCursorVisible(doc.cm);
4722
+ }
4723
+
4724
+ function setSelectionInner(doc, sel) {
4725
+ if (sel.equals(doc.sel)) return;
4726
+
4727
+ doc.sel = sel;
4728
+
4729
+ if (doc.cm) {
4730
+ doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true;
4731
+ signalCursorActivity(doc.cm);
4732
+ }
4733
+ signalLater(doc, "cursorActivity", doc);
4734
+ }
4735
+
4736
+ // Verify that the selection does not partially select any atomic
4737
+ // marked ranges.
4738
+ function reCheckSelection(doc) {
4739
+ setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll);
4740
+ }
4741
+
4742
+ // Return a selection that does not partially select any atomic
4743
+ // ranges.
4744
+ function skipAtomicInSelection(doc, sel, bias, mayClear) {
4745
+ var out;
4746
+ for (var i = 0; i < sel.ranges.length; i++) {
4747
+ var range = sel.ranges[i];
4748
+ var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear);
4749
+ var newHead = skipAtomic(doc, range.head, bias, mayClear);
4750
+ if (out || newAnchor != range.anchor || newHead != range.head) {
4751
+ if (!out) out = sel.ranges.slice(0, i);
4752
+ out[i] = new Range(newAnchor, newHead);
4753
+ }
4754
+ }
4755
+ return out ? normalizeSelection(out, sel.primIndex) : sel;
4756
+ }
4757
+
4758
+ // Ensure a given position is not inside an atomic range.
4759
+ function skipAtomic(doc, pos, bias, mayClear) {
4760
+ var flipped = false, curPos = pos;
4761
+ var dir = bias || 1;
4762
+ doc.cantEdit = false;
4763
+ search: for (;;) {
4764
+ var line = getLine(doc, curPos.line);
4765
+ if (line.markedSpans) {
4766
+ for (var i = 0; i < line.markedSpans.length; ++i) {
4767
+ var sp = line.markedSpans[i], m = sp.marker;
4768
+ if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
4769
+ (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
4770
+ if (mayClear) {
4771
+ signal(m, "beforeCursorEnter");
4772
+ if (m.explicitlyCleared) {
4773
+ if (!line.markedSpans) break;
4774
+ else {--i; continue;}
4775
+ }
4776
+ }
4777
+ if (!m.atomic) continue;
4778
+ var newPos = m.find(dir < 0 ? -1 : 1);
4779
+ if (cmp(newPos, curPos) == 0) {
4780
+ newPos.ch += dir;
4781
+ if (newPos.ch < 0) {
4782
+ if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
4783
+ else newPos = null;
4784
+ } else if (newPos.ch > line.text.length) {
4785
+ if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
4786
+ else newPos = null;
4787
+ }
4788
+ if (!newPos) {
4789
+ if (flipped) {
4790
+ // Driven in a corner -- no valid cursor position found at all
4791
+ // -- try again *with* clearing, if we didn't already
4792
+ if (!mayClear) return skipAtomic(doc, pos, bias, true);
4793
+ // Otherwise, turn off editing until further notice, and return the start of the doc
4794
+ doc.cantEdit = true;
4795
+ return Pos(doc.first, 0);
4796
+ }
4797
+ flipped = true; newPos = pos; dir = -dir;
4798
+ }
4799
+ }
4800
+ curPos = newPos;
4801
+ continue search;
4802
+ }
4803
+ }
4804
+ }
4805
+ return curPos;
4806
+ }
4807
+ }
4808
+
4809
+ // SELECTION DRAWING
4810
+
4811
+ function updateSelection(cm) {
4812
+ cm.display.input.showSelection(cm.display.input.prepareSelection());
4813
+ }
4814
+
4815
+ function prepareSelection(cm, primary) {
4816
+ var doc = cm.doc, result = {};
4817
+ var curFragment = result.cursors = document.createDocumentFragment();
4818
+ var selFragment = result.selection = document.createDocumentFragment();
4819
+
4820
+ for (var i = 0; i < doc.sel.ranges.length; i++) {
4821
+ if (primary === false && i == doc.sel.primIndex) continue;
4822
+ var range = doc.sel.ranges[i];
4823
+ var collapsed = range.empty();
4824
+ if (collapsed || cm.options.showCursorWhenSelecting)
4825
+ drawSelectionCursor(cm, range.head, curFragment);
4826
+ if (!collapsed)
4827
+ drawSelectionRange(cm, range, selFragment);
4828
+ }
4829
+ return result;
4830
+ }
4831
+
4832
+ // Draws a cursor for the given range
4833
+ function drawSelectionCursor(cm, head, output) {
4834
+ var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine);
4835
+
4836
+ var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
4837
+ cursor.style.left = pos.left + "px";
4838
+ cursor.style.top = pos.top + "px";
4839
+ cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
4840
+
4841
+ if (pos.other) {
4842
+ // Secondary cursor, shown when on a 'jump' in bi-directional text
4843
+ var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
4844
+ otherCursor.style.display = "";
4845
+ otherCursor.style.left = pos.other.left + "px";
4846
+ otherCursor.style.top = pos.other.top + "px";
4847
+ otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
4848
+ }
4849
+ }
4850
+
4851
+ // Draws the given range as a highlighted selection
4852
+ function drawSelectionRange(cm, range, output) {
4853
+ var display = cm.display, doc = cm.doc;
4854
+ var fragment = document.createDocumentFragment();
4855
+ var padding = paddingH(cm.display), leftSide = padding.left;
4856
+ var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;
4857
+
4858
+ function add(left, top, width, bottom) {
4859
+ if (top < 0) top = 0;
4860
+ top = Math.round(top);
4861
+ bottom = Math.round(bottom);
4862
+ fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left +
4863
+ "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) +
4864
+ "px; height: " + (bottom - top) + "px"));
4865
+ }
4866
+
4867
+ function drawForLine(line, fromArg, toArg) {
4868
+ var lineObj = getLine(doc, line);
4869
+ var lineLen = lineObj.text.length;
4870
+ var start, end;
4871
+ function coords(ch, bias) {
4872
+ return charCoords(cm, Pos(line, ch), "div", lineObj, bias);
4873
+ }
4874
+
4875
+ iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) {
4876
+ var leftPos = coords(from, "left"), rightPos, left, right;
4877
+ if (from == to) {
4878
+ rightPos = leftPos;
4879
+ left = right = leftPos.left;
4880
+ } else {
4881
+ rightPos = coords(to - 1, "right");
4882
+ if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; }
4883
+ left = leftPos.left;
4884
+ right = rightPos.right;
4885
+ }
4886
+ if (fromArg == null && from == 0) left = leftSide;
4887
+ if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
4888
+ add(left, leftPos.top, null, leftPos.bottom);
4889
+ left = leftSide;
4890
+ if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top);
4891
+ }
4892
+ if (toArg == null && to == lineLen) right = rightSide;
4893
+ if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
4894
+ start = leftPos;
4895
+ if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
4896
+ end = rightPos;
4897
+ if (left < leftSide + 1) left = leftSide;
4898
+ add(left, rightPos.top, right - left, rightPos.bottom);
4899
+ });
4900
+ return {start: start, end: end};
4901
+ }
4902
+
4903
+ var sFrom = range.from(), sTo = range.to();
4904
+ if (sFrom.line == sTo.line) {
4905
+ drawForLine(sFrom.line, sFrom.ch, sTo.ch);
4906
+ } else {
4907
+ var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);
4908
+ var singleVLine = visualLine(fromLine) == visualLine(toLine);
4909
+ var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;
4910
+ var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;
4911
+ if (singleVLine) {
4912
+ if (leftEnd.top < rightStart.top - 2) {
4913
+ add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
4914
+ add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);
4915
+ } else {
4916
+ add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
4917
+ }
4918
+ }
4919
+ if (leftEnd.bottom < rightStart.top)
4920
+ add(leftSide, leftEnd.bottom, null, rightStart.top);
4921
+ }
4922
+
4923
+ output.appendChild(fragment);
4924
+ }
4925
+
4926
+ // Cursor-blinking
4927
+ function restartBlink(cm) {
4928
+ if (!cm.state.focused) return;
4929
+ var display = cm.display;
4930
+ clearInterval(display.blinker);
4931
+ var on = true;
4932
+ display.cursorDiv.style.visibility = "";
4933
+ if (cm.options.cursorBlinkRate > 0)
4934
+ display.blinker = setInterval(function() {
4935
+ display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";
4936
+ }, cm.options.cursorBlinkRate);
4937
+ else if (cm.options.cursorBlinkRate < 0)
4938
+ display.cursorDiv.style.visibility = "hidden";
4939
+ }
4940
+
4941
+ // HIGHLIGHT WORKER
4942
+
4943
+ function startWorker(cm, time) {
4944
+ if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
4945
+ cm.state.highlight.set(time, bind(highlightWorker, cm));
4946
+ }
4947
+
4948
+ function highlightWorker(cm) {
4949
+ var doc = cm.doc;
4950
+ if (doc.frontier < doc.first) doc.frontier = doc.first;
4951
+ if (doc.frontier >= cm.display.viewTo) return;
4952
+ var end = +new Date + cm.options.workTime;
4953
+ var state = copyState(doc.mode, getStateBefore(cm, doc.frontier));
4954
+ var changedLines = [];
4955
+
4956
+ doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {
4957
+ if (doc.frontier >= cm.display.viewFrom) { // Visible
4958
+ var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength;
4959
+ var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true);
4960
+ line.styles = highlighted.styles;
4961
+ var oldCls = line.styleClasses, newCls = highlighted.classes;
4962
+ if (newCls) line.styleClasses = newCls;
4963
+ else if (oldCls) line.styleClasses = null;
4964
+ var ischange = !oldStyles || oldStyles.length != line.styles.length ||
4965
+ oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
4966
+ for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
4967
+ if (ischange) changedLines.push(doc.frontier);
4968
+ line.stateAfter = tooLong ? state : copyState(doc.mode, state);
4969
+ } else {
4970
+ if (line.text.length <= cm.options.maxHighlightLength)
4971
+ processLine(cm, line.text, state);
4972
+ line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
4973
+ }
4974
+ ++doc.frontier;
4975
+ if (+new Date > end) {
4976
+ startWorker(cm, cm.options.workDelay);
4977
+ return true;
4978
+ }
4979
+ });
4980
+ if (changedLines.length) runInOp(cm, function() {
4981
+ for (var i = 0; i < changedLines.length; i++)
4982
+ regLineChange(cm, changedLines[i], "text");
4983
+ });
4984
+ }
4985
+
4986
+ // Finds the line to start with when starting a parse. Tries to
4987
+ // find a line with a stateAfter, so that it can start with a
4988
+ // valid state. If that fails, it returns the line with the
4989
+ // smallest indentation, which tends to need the least context to
4990
+ // parse correctly.
4991
+ function findStartLine(cm, n, precise) {
4992
+ var minindent, minline, doc = cm.doc;
4993
+ var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
4994
+ for (var search = n; search > lim; --search) {
4995
+ if (search <= doc.first) return doc.first;
4996
+ var line = getLine(doc, search - 1);
4997
+ if (line.stateAfter && (!precise || search <= doc.frontier)) return search;
4998
+ var indented = countColumn(line.text, null, cm.options.tabSize);
4999
+ if (minline == null || minindent > indented) {
5000
+ minline = search - 1;
5001
+ minindent = indented;
5002
+ }
5003
+ }
5004
+ return minline;
5005
+ }
5006
+
5007
+ function getStateBefore(cm, n, precise) {
5008
+ var doc = cm.doc, display = cm.display;
5009
+ if (!doc.mode.startState) return true;
5010
+ var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter;
5011
+ if (!state) state = startState(doc.mode);
5012
+ else state = copyState(doc.mode, state);
5013
+ doc.iter(pos, n, function(line) {
5014
+ processLine(cm, line.text, state);
5015
+ var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo;
5016
+ line.stateAfter = save ? copyState(doc.mode, state) : null;
5017
+ ++pos;
5018
+ });
5019
+ if (precise) doc.frontier = pos;
5020
+ return state;
5021
+ }
5022
+
5023
+ // POSITION MEASUREMENT
5024
+
5025
+ function paddingTop(display) {return display.lineSpace.offsetTop;}
5026
+ function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;}
5027
+ function paddingH(display) {
5028
+ if (display.cachedPaddingH) return display.cachedPaddingH;
5029
+ var e = removeChildrenAndAdd(display.measure, elt("pre", "x"));
5030
+ var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
5031
+ var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
5032
+ if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data;
5033
+ return data;
5034
+ }
5035
+
5036
+ function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; }
5037
+ function displayWidth(cm) {
5038
+ return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth;
5039
+ }
5040
+ function displayHeight(cm) {
5041
+ return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight;
5042
+ }
5043
+
5044
+ // Ensure the lineView.wrapping.heights array is populated. This is
5045
+ // an array of bottom offsets for the lines that make up a drawn
5046
+ // line. When lineWrapping is on, there might be more than one
5047
+ // height.
5048
+ function ensureLineHeights(cm, lineView, rect) {
5049
+ var wrapping = cm.options.lineWrapping;
5050
+ var curWidth = wrapping && displayWidth(cm);
5051
+ if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
5052
+ var heights = lineView.measure.heights = [];
5053
+ if (wrapping) {
5054
+ lineView.measure.width = curWidth;
5055
+ var rects = lineView.text.firstChild.getClientRects();
5056
+ for (var i = 0; i < rects.length - 1; i++) {
5057
+ var cur = rects[i], next = rects[i + 1];
5058
+ if (Math.abs(cur.bottom - next.bottom) > 2)
5059
+ heights.push((cur.bottom + next.top) / 2 - rect.top);
5060
+ }
5061
+ }
5062
+ heights.push(rect.bottom - rect.top);
5063
+ }
5064
+ }
5065
+
5066
+ // Find a line map (mapping character offsets to text nodes) and a
5067
+ // measurement cache for the given line number. (A line view might
5068
+ // contain multiple lines when collapsed ranges are present.)
5069
+ function mapFromLineView(lineView, line, lineN) {
5070
+ if (lineView.line == line)
5071
+ return {map: lineView.measure.map, cache: lineView.measure.cache};
5072
+ for (var i = 0; i < lineView.rest.length; i++)
5073
+ if (lineView.rest[i] == line)
5074
+ return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]};
5075
+ for (var i = 0; i < lineView.rest.length; i++)
5076
+ if (lineNo(lineView.rest[i]) > lineN)
5077
+ return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true};
5078
+ }
5079
+
5080
+ // Render a line into the hidden node display.externalMeasured. Used
5081
+ // when measurement is needed for a line that's not in the viewport.
5082
+ function updateExternalMeasurement(cm, line) {
5083
+ line = visualLine(line);
5084
+ var lineN = lineNo(line);
5085
+ var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);
5086
+ view.lineN = lineN;
5087
+ var built = view.built = buildLineContent(cm, view);
5088
+ view.text = built.pre;
5089
+ removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
5090
+ return view;
5091
+ }
5092
+
5093
+ // Get a {top, bottom, left, right} box (in line-local coordinates)
5094
+ // for a given character.
5095
+ function measureChar(cm, line, ch, bias) {
5096
+ return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias);
5097
+ }
5098
+
5099
+ // Find a line view that corresponds to the given line number.
5100
+ function findViewForLine(cm, lineN) {
5101
+ if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
5102
+ return cm.display.view[findViewIndex(cm, lineN)];
5103
+ var ext = cm.display.externalMeasured;
5104
+ if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
5105
+ return ext;
5106
+ }
5107
+
5108
+ // Measurement can be split in two steps, the set-up work that
5109
+ // applies to the whole line, and the measurement of the actual
5110
+ // character. Functions like coordsChar, that need to do a lot of
5111
+ // measurements in a row, can thus ensure that the set-up work is
5112
+ // only done once.
5113
+ function prepareMeasureForLine(cm, line) {
5114
+ var lineN = lineNo(line);
5115
+ var view = findViewForLine(cm, lineN);
5116
+ if (view && !view.text) {
5117
+ view = null;
5118
+ } else if (view && view.changes) {
5119
+ updateLineForChanges(cm, view, lineN, getDimensions(cm));
5120
+ cm.curOp.forceUpdate = true;
5121
+ }
5122
+ if (!view)
5123
+ view = updateExternalMeasurement(cm, line);
5124
+
5125
+ var info = mapFromLineView(view, line, lineN);
5126
+ return {
5127
+ line: line, view: view, rect: null,
5128
+ map: info.map, cache: info.cache, before: info.before,
5129
+ hasHeights: false
5130
+ };
5131
+ }
5132
+
5133
+ // Given a prepared measurement object, measures the position of an
5134
+ // actual character (or fetches it from the cache).
5135
+ function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
5136
+ if (prepared.before) ch = -1;
5137
+ var key = ch + (bias || ""), found;
5138
+ if (prepared.cache.hasOwnProperty(key)) {
5139
+ found = prepared.cache[key];
5140
+ } else {
5141
+ if (!prepared.rect)
5142
+ prepared.rect = prepared.view.text.getBoundingClientRect();
5143
+ if (!prepared.hasHeights) {
5144
+ ensureLineHeights(cm, prepared.view, prepared.rect);
5145
+ prepared.hasHeights = true;
5146
+ }
5147
+ found = measureCharInner(cm, prepared, ch, bias);
5148
+ if (!found.bogus) prepared.cache[key] = found;
5149
+ }
5150
+ return {left: found.left, right: found.right,
5151
+ top: varHeight ? found.rtop : found.top,
5152
+ bottom: varHeight ? found.rbottom : found.bottom};
5153
+ }
5154
+
5155
+ var nullRect = {left: 0, right: 0, top: 0, bottom: 0};
5156
+
5157
+ function nodeAndOffsetInLineMap(map, ch, bias) {
5158
+ var node, start, end, collapse;
5159
+ // First, search the line map for the text node corresponding to,
5160
+ // or closest to, the target character.
5161
+ for (var i = 0; i < map.length; i += 3) {
5162
+ var mStart = map[i], mEnd = map[i + 1];
5163
+ if (ch < mStart) {
5164
+ start = 0; end = 1;
5165
+ collapse = "left";
5166
+ } else if (ch < mEnd) {
5167
+ start = ch - mStart;
5168
+ end = start + 1;
5169
+ } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
5170
+ end = mEnd - mStart;
5171
+ start = end - 1;
5172
+ if (ch >= mEnd) collapse = "right";
5173
+ }
5174
+ if (start != null) {
5175
+ node = map[i + 2];
5176
+ if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
5177
+ collapse = bias;
5178
+ if (bias == "left" && start == 0)
5179
+ while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
5180
+ node = map[(i -= 3) + 2];
5181
+ collapse = "left";
5182
+ }
5183
+ if (bias == "right" && start == mEnd - mStart)
5184
+ while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
5185
+ node = map[(i += 3) + 2];
5186
+ collapse = "right";
5187
+ }
5188
+ break;
5189
+ }
5190
+ }
5191
+ return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd};
5192
+ }
5193
+
5194
+ function measureCharInner(cm, prepared, ch, bias) {
5195
+ var place = nodeAndOffsetInLineMap(prepared.map, ch, bias);
5196
+ var node = place.node, start = place.start, end = place.end, collapse = place.collapse;
5197
+
5198
+ var rect;
5199
+ if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
5200
+ for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned
5201
+ while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start;
5202
+ while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end;
5203
+ if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) {
5204
+ rect = node.parentNode.getBoundingClientRect();
5205
+ } else if (ie && cm.options.lineWrapping) {
5206
+ var rects = range(node, start, end).getClientRects();
5207
+ if (rects.length)
5208
+ rect = rects[bias == "right" ? rects.length - 1 : 0];
5209
+ else
5210
+ rect = nullRect;
5211
+ } else {
5212
+ rect = range(node, start, end).getBoundingClientRect() || nullRect;
5213
+ }
5214
+ if (rect.left || rect.right || start == 0) break;
5215
+ end = start;
5216
+ start = start - 1;
5217
+ collapse = "right";
5218
+ }
5219
+ if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect);
5220
+ } else { // If it is a widget, simply get the box for the whole widget.
5221
+ if (start > 0) collapse = bias = "right";
5222
+ var rects;
5223
+ if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
5224
+ rect = rects[bias == "right" ? rects.length - 1 : 0];
5225
+ else
5226
+ rect = node.getBoundingClientRect();
5227
+ }
5228
+ if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
5229
+ var rSpan = node.parentNode.getClientRects()[0];
5230
+ if (rSpan)
5231
+ rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom};
5232
+ else
5233
+ rect = nullRect;
5234
+ }
5235
+
5236
+ var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;
5237
+ var mid = (rtop + rbot) / 2;
5238
+ var heights = prepared.view.measure.heights;
5239
+ for (var i = 0; i < heights.length - 1; i++)
5240
+ if (mid < heights[i]) break;
5241
+ var top = i ? heights[i - 1] : 0, bot = heights[i];
5242
+ var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
5243
+ right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
5244
+ top: top, bottom: bot};
5245
+ if (!rect.left && !rect.right) result.bogus = true;
5246
+ if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }
5247
+
5248
+ return result;
5249
+ }
5250
+
5251
+ // Work around problem with bounding client rects on ranges being
5252
+ // returned incorrectly when zoomed on IE10 and below.
5253
+ function maybeUpdateRectForZooming(measure, rect) {
5254
+ if (!window.screen || screen.logicalXDPI == null ||
5255
+ screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
5256
+ return rect;
5257
+ var scaleX = screen.logicalXDPI / screen.deviceXDPI;
5258
+ var scaleY = screen.logicalYDPI / screen.deviceYDPI;
5259
+ return {left: rect.left * scaleX, right: rect.right * scaleX,
5260
+ top: rect.top * scaleY, bottom: rect.bottom * scaleY};
5261
+ }
5262
+
5263
+ function clearLineMeasurementCacheFor(lineView) {
5264
+ if (lineView.measure) {
5265
+ lineView.measure.cache = {};
5266
+ lineView.measure.heights = null;
5267
+ if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++)
5268
+ lineView.measure.caches[i] = {};
5269
+ }
5270
+ }
5271
+
5272
+ function clearLineMeasurementCache(cm) {
5273
+ cm.display.externalMeasure = null;
5274
+ removeChildren(cm.display.lineMeasure);
5275
+ for (var i = 0; i < cm.display.view.length; i++)
5276
+ clearLineMeasurementCacheFor(cm.display.view[i]);
5277
+ }
5278
+
5279
+ function clearCaches(cm) {
5280
+ clearLineMeasurementCache(cm);
5281
+ cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;
5282
+ if (!cm.options.lineWrapping) cm.display.maxLineChanged = true;
5283
+ cm.display.lineNumChars = null;
5284
+ }
5285
+
5286
+ function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; }
5287
+ function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; }
5288
+
5289
+ // Converts a {top, bottom, left, right} box from line-local
5290
+ // coordinates into another coordinate system. Context may be one of
5291
+ // "line", "div" (display.lineDiv), "local"/null (editor), "window",
5292
+ // or "page".
5293
+ function intoCoordSystem(cm, lineObj, rect, context) {
5294
+ if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) {
5295
+ var size = widgetHeight(lineObj.widgets[i]);
5296
+ rect.top += size; rect.bottom += size;
5297
+ }
5298
+ if (context == "line") return rect;
5299
+ if (!context) context = "local";
5300
+ var yOff = heightAtLine(lineObj);
5301
+ if (context == "local") yOff += paddingTop(cm.display);
5302
+ else yOff -= cm.display.viewOffset;
5303
+ if (context == "page" || context == "window") {
5304
+ var lOff = cm.display.lineSpace.getBoundingClientRect();
5305
+ yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
5306
+ var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
5307
+ rect.left += xOff; rect.right += xOff;
5308
+ }
5309
+ rect.top += yOff; rect.bottom += yOff;
5310
+ return rect;
5311
+ }
5312
+
5313
+ // Coverts a box from "div" coords to another coordinate system.
5314
+ // Context may be "window", "page", "div", or "local"/null.
5315
+ function fromCoordSystem(cm, coords, context) {
5316
+ if (context == "div") return coords;
5317
+ var left = coords.left, top = coords.top;
5318
+ // First move into "page" coordinate system
5319
+ if (context == "page") {
5320
+ left -= pageScrollX();
5321
+ top -= pageScrollY();
5322
+ } else if (context == "local" || !context) {
5323
+ var localBox = cm.display.sizer.getBoundingClientRect();
5324
+ left += localBox.left;
5325
+ top += localBox.top;
5326
+ }
5327
+
5328
+ var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();
5329
+ return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top};
5330
+ }
5331
+
5332
+ function charCoords(cm, pos, context, lineObj, bias) {
5333
+ if (!lineObj) lineObj = getLine(cm.doc, pos.line);
5334
+ return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context);
5335
+ }
5336
+
5337
+ // Returns a box for a given cursor position, which may have an
5338
+ // 'other' property containing the position of the secondary cursor
5339
+ // on a bidi boundary.
5340
+ function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
5341
+ lineObj = lineObj || getLine(cm.doc, pos.line);
5342
+ if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj);
5343
+ function get(ch, right) {
5344
+ var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight);
5345
+ if (right) m.left = m.right; else m.right = m.left;
5346
+ return intoCoordSystem(cm, lineObj, m, context);
5347
+ }
5348
+ function getBidi(ch, partPos) {
5349
+ var part = order[partPos], right = part.level % 2;
5350
+ if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
5351
+ part = order[--partPos];
5352
+ ch = bidiRight(part) - (part.level % 2 ? 0 : 1);
5353
+ right = true;
5354
+ } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
5355
+ part = order[++partPos];
5356
+ ch = bidiLeft(part) - part.level % 2;
5357
+ right = false;
5358
+ }
5359
+ if (right && ch == part.to && ch > part.from) return get(ch - 1);
5360
+ return get(ch, right);
5361
+ }
5362
+ var order = getOrder(lineObj), ch = pos.ch;
5363
+ if (!order) return get(ch);
5364
+ var partPos = getBidiPartAt(order, ch);
5365
+ var val = getBidi(ch, partPos);
5366
+ if (bidiOther != null) val.other = getBidi(ch, bidiOther);
5367
+ return val;
5368
+ }
5369
+
5370
+ // Used to cheaply estimate the coordinates for a position. Used for
5371
+ // intermediate scroll updates.
5372
+ function estimateCoords(cm, pos) {
5373
+ var left = 0, pos = clipPos(cm.doc, pos);
5374
+ if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch;
5375
+ var lineObj = getLine(cm.doc, pos.line);
5376
+ var top = heightAtLine(lineObj) + paddingTop(cm.display);
5377
+ return {left: left, right: left, top: top, bottom: top + lineObj.height};
5378
+ }
5379
+
5380
+ // Positions returned by coordsChar contain some extra information.
5381
+ // xRel is the relative x position of the input coordinates compared
5382
+ // to the found position (so xRel > 0 means the coordinates are to
5383
+ // the right of the character position, for example). When outside
5384
+ // is true, that means the coordinates lie outside the line's
5385
+ // vertical range.
5386
+ function PosWithInfo(line, ch, outside, xRel) {
5387
+ var pos = Pos(line, ch);
5388
+ pos.xRel = xRel;
5389
+ if (outside) pos.outside = true;
5390
+ return pos;
5391
+ }
5392
+
5393
+ // Compute the character position closest to the given coordinates.
5394
+ // Input must be lineSpace-local ("div" coordinate system).
5395
+ function coordsChar(cm, x, y) {
5396
+ var doc = cm.doc;
5397
+ y += cm.display.viewOffset;
5398
+ if (y < 0) return PosWithInfo(doc.first, 0, true, -1);
5399
+ var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
5400
+ if (lineN > last)
5401
+ return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1);
5402
+ if (x < 0) x = 0;
5403
+
5404
+ var lineObj = getLine(doc, lineN);
5405
+ for (;;) {
5406
+ var found = coordsCharInner(cm, lineObj, lineN, x, y);
5407
+ var merged = collapsedSpanAtEnd(lineObj);
5408
+ var mergedPos = merged && merged.find(0, true);
5409
+ if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
5410
+ lineN = lineNo(lineObj = mergedPos.to.line);
5411
+ else
5412
+ return found;
5413
+ }
5414
+ }
5415
+
5416
+ function coordsCharInner(cm, lineObj, lineNo, x, y) {
5417
+ var innerOff = y - heightAtLine(lineObj);
5418
+ var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth;
5419
+ var preparedMeasure = prepareMeasureForLine(cm, lineObj);
5420
+
5421
+ function getX(ch) {
5422
+ var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure);
5423
+ wrongLine = true;
5424
+ if (innerOff > sp.bottom) return sp.left - adjust;
5425
+ else if (innerOff < sp.top) return sp.left + adjust;
5426
+ else wrongLine = false;
5427
+ return sp.left;
5428
+ }
5429
+
5430
+ var bidi = getOrder(lineObj), dist = lineObj.text.length;
5431
+ var from = lineLeft(lineObj), to = lineRight(lineObj);
5432
+ var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine;
5433
+
5434
+ if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1);
5435
+ // Do a binary search between these bounds.
5436
+ for (;;) {
5437
+ if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
5438
+ var ch = x < fromX || x - fromX <= toX - x ? from : to;
5439
+ var xDiff = x - (ch == from ? fromX : toX);
5440
+ while (isExtendingChar(lineObj.text.charAt(ch))) ++ch;
5441
+ var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside,
5442
+ xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0);
5443
+ return pos;
5444
+ }
5445
+ var step = Math.ceil(dist / 2), middle = from + step;
5446
+ if (bidi) {
5447
+ middle = from;
5448
+ for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1);
5449
+ }
5450
+ var middleX = getX(middle);
5451
+ if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;}
5452
+ else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;}
5453
+ }
5454
+ }
5455
+
5456
+ var measureText;
5457
+ // Compute the default text height.
5458
+ function textHeight(display) {
5459
+ if (display.cachedTextHeight != null) return display.cachedTextHeight;
5460
+ if (measureText == null) {
5461
+ measureText = elt("pre");
5462
+ // Measure a bunch of lines, for browsers that compute
5463
+ // fractional heights.
5464
+ for (var i = 0; i < 49; ++i) {
5465
+ measureText.appendChild(document.createTextNode("x"));
5466
+ measureText.appendChild(elt("br"));
5467
+ }
5468
+ measureText.appendChild(document.createTextNode("x"));
5469
+ }
5470
+ removeChildrenAndAdd(display.measure, measureText);
5471
+ var height = measureText.offsetHeight / 50;
5472
+ if (height > 3) display.cachedTextHeight = height;
5473
+ removeChildren(display.measure);
5474
+ return height || 1;
5475
+ }
5476
+
5477
+ // Compute the default character width.
5478
+ function charWidth(display) {
5479
+ if (display.cachedCharWidth != null) return display.cachedCharWidth;
5480
+ var anchor = elt("span", "xxxxxxxxxx");
5481
+ var pre = elt("pre", [anchor]);
5482
+ removeChildrenAndAdd(display.measure, pre);
5483
+ var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;
5484
+ if (width > 2) display.cachedCharWidth = width;
5485
+ return width || 10;
5486
+ }
5487
+
5488
+ // OPERATIONS
5489
+
5490
+ // Operations are used to wrap a series of changes to the editor
5491
+ // state in such a way that each change won't have to update the
5492
+ // cursor and display (which would be awkward, slow, and
5493
+ // error-prone). Instead, display updates are batched and then all
5494
+ // combined and executed at once.
5495
+
5496
+ var operationGroup = null;
5497
+
5498
+ var nextOpId = 0;
5499
+ // Start a new operation.
5500
+ function startOperation(cm) {
5501
+ cm.curOp = {
5502
+ cm: cm,
5503
+ viewChanged: false, // Flag that indicates that lines might need to be redrawn
5504
+ startHeight: cm.doc.height, // Used to detect need to update scrollbar
5505
+ forceUpdate: false, // Used to force a redraw
5506
+ updateInput: null, // Whether to reset the input textarea
5507
+ typing: false, // Whether this reset should be careful to leave existing text (for compositing)
5508
+ changeObjs: null, // Accumulated changes, for firing change events
5509
+ cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
5510
+ cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
5511
+ selectionChanged: false, // Whether the selection needs to be redrawn
5512
+ updateMaxLine: false, // Set when the widest line needs to be determined anew
5513
+ scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
5514
+ scrollToPos: null, // Used to scroll to a specific position
5515
+ focus: false,
5516
+ id: ++nextOpId // Unique ID
5517
+ };
5518
+ if (operationGroup) {
5519
+ operationGroup.ops.push(cm.curOp);
5520
+ } else {
5521
+ cm.curOp.ownsGroup = operationGroup = {
5522
+ ops: [cm.curOp],
5523
+ delayedCallbacks: []
5524
+ };
5525
+ }
5526
+ }
5527
+
5528
+ function fireCallbacksForOps(group) {
5529
+ // Calls delayed callbacks and cursorActivity handlers until no
5530
+ // new ones appear
5531
+ var callbacks = group.delayedCallbacks, i = 0;
5532
+ do {
5533
+ for (; i < callbacks.length; i++)
5534
+ callbacks[i].call(null);
5535
+ for (var j = 0; j < group.ops.length; j++) {
5536
+ var op = group.ops[j];
5537
+ if (op.cursorActivityHandlers)
5538
+ while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
5539
+ op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm);
5540
+ }
5541
+ } while (i < callbacks.length);
5542
+ }
5543
+
5544
+ // Finish an operation, updating the display and signalling delayed events
5545
+ function endOperation(cm) {
5546
+ var op = cm.curOp, group = op.ownsGroup;
5547
+ if (!group) return;
5548
+
5549
+ try { fireCallbacksForOps(group); }
5550
+ finally {
5551
+ operationGroup = null;
5552
+ for (var i = 0; i < group.ops.length; i++)
5553
+ group.ops[i].cm.curOp = null;
5554
+ endOperations(group);
5555
+ }
5556
+ }
5557
+
5558
+ // The DOM updates done when an operation finishes are batched so
5559
+ // that the minimum number of relayouts are required.
5560
+ function endOperations(group) {
5561
+ var ops = group.ops;
5562
+ for (var i = 0; i < ops.length; i++) // Read DOM
5563
+ endOperation_R1(ops[i]);
5564
+ for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
5565
+ endOperation_W1(ops[i]);
5566
+ for (var i = 0; i < ops.length; i++) // Read DOM
5567
+ endOperation_R2(ops[i]);
5568
+ for (var i = 0; i < ops.length; i++) // Write DOM (maybe)
5569
+ endOperation_W2(ops[i]);
5570
+ for (var i = 0; i < ops.length; i++) // Read DOM
5571
+ endOperation_finish(ops[i]);
5572
+ }
5573
+
5574
+ function endOperation_R1(op) {
5575
+ var cm = op.cm, display = cm.display;
5576
+ maybeClipScrollbars(cm);
5577
+ if (op.updateMaxLine) findMaxLine(cm);
5578
+
5579
+ op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
5580
+ op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
5581
+ op.scrollToPos.to.line >= display.viewTo) ||
5582
+ display.maxLineChanged && cm.options.lineWrapping;
5583
+ op.update = op.mustUpdate &&
5584
+ new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
5585
+ }
5586
+
5587
+ function endOperation_W1(op) {
5588
+ op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);
5589
+ }
5590
+
5591
+ function endOperation_R2(op) {
5592
+ var cm = op.cm, display = cm.display;
5593
+ if (op.updatedDisplay) updateHeightsInViewport(cm);
5594
+
5595
+ op.barMeasure = measureForScrollbars(cm);
5596
+
5597
+ // If the max line changed since it was last measured, measure it,
5598
+ // and ensure the document's width matches it.
5599
+ // updateDisplay_W2 will use these properties to do the actual resizing
5600
+ if (display.maxLineChanged && !cm.options.lineWrapping) {
5601
+ op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;
5602
+ cm.display.sizerWidth = op.adjustWidthTo;
5603
+ op.barMeasure.scrollWidth =
5604
+ Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);
5605
+ op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));
5606
+ }
5607
+
5608
+ if (op.updatedDisplay || op.selectionChanged)
5609
+ op.preparedSelection = display.input.prepareSelection();
5610
+ }
5611
+
5612
+ function endOperation_W2(op) {
5613
+ var cm = op.cm;
5614
+
5615
+ if (op.adjustWidthTo != null) {
5616
+ cm.display.sizer.style.minWidth = op.adjustWidthTo + "px";
5617
+ if (op.maxScrollLeft < cm.doc.scrollLeft)
5618
+ setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true);
5619
+ cm.display.maxLineChanged = false;
5620
+ }
5621
+
5622
+ if (op.preparedSelection)
5623
+ cm.display.input.showSelection(op.preparedSelection);
5624
+ if (op.updatedDisplay)
5625
+ setDocumentHeight(cm, op.barMeasure);
5626
+ if (op.updatedDisplay || op.startHeight != cm.doc.height)
5627
+ updateScrollbars(cm, op.barMeasure);
5628
+
5629
+ if (op.selectionChanged) restartBlink(cm);
5630
+
5631
+ if (cm.state.focused && op.updateInput)
5632
+ cm.display.input.reset(op.typing);
5633
+ if (op.focus && op.focus == activeElt()) ensureFocus(op.cm);
5634
+ }
5635
+
5636
+ function endOperation_finish(op) {
5637
+ var cm = op.cm, display = cm.display, doc = cm.doc;
5638
+
5639
+ if (op.updatedDisplay) postUpdateDisplay(cm, op.update);
5640
+
5641
+ // Abort mouse wheel delta measurement, when scrolling explicitly
5642
+ if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
5643
+ display.wheelStartX = display.wheelStartY = null;
5644
+
5645
+ // Propagate the scroll position to the actual DOM scroller
5646
+ if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {
5647
+ doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop));
5648
+ display.scrollbars.setScrollTop(doc.scrollTop);
5649
+ display.scroller.scrollTop = doc.scrollTop;
5650
+ }
5651
+ if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {
5652
+ doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - displayWidth(cm), op.scrollLeft));
5653
+ display.scrollbars.setScrollLeft(doc.scrollLeft);
5654
+ display.scroller.scrollLeft = doc.scrollLeft;
5655
+ alignHorizontally(cm);
5656
+ }
5657
+ // If we need to scroll a specific position into view, do so.
5658
+ if (op.scrollToPos) {
5659
+ var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
5660
+ clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);
5661
+ if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords);
5662
+ }
5663
+
5664
+ // Fire events for markers that are hidden/unidden by editing or
5665
+ // undoing
5666
+ var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
5667
+ if (hidden) for (var i = 0; i < hidden.length; ++i)
5668
+ if (!hidden[i].lines.length) signal(hidden[i], "hide");
5669
+ if (unhidden) for (var i = 0; i < unhidden.length; ++i)
5670
+ if (unhidden[i].lines.length) signal(unhidden[i], "unhide");
5671
+
5672
+ if (display.wrapper.offsetHeight)
5673
+ doc.scrollTop = cm.display.scroller.scrollTop;
5674
+
5675
+ // Fire change events, and delayed event handlers
5676
+ if (op.changeObjs)
5677
+ signal(cm, "changes", cm, op.changeObjs);
5678
+ if (op.update)
5679
+ op.update.finish();
5680
+ }
5681
+
5682
+ // Run the given function in an operation
5683
+ function runInOp(cm, f) {
5684
+ if (cm.curOp) return f();
5685
+ startOperation(cm);
5686
+ try { return f(); }
5687
+ finally { endOperation(cm); }
5688
+ }
5689
+ // Wraps a function in an operation. Returns the wrapped function.
5690
+ function operation(cm, f) {
5691
+ return function() {
5692
+ if (cm.curOp) return f.apply(cm, arguments);
5693
+ startOperation(cm);
5694
+ try { return f.apply(cm, arguments); }
5695
+ finally { endOperation(cm); }
5696
+ };
5697
+ }
5698
+ // Used to add methods to editor and doc instances, wrapping them in
5699
+ // operations.
5700
+ function methodOp(f) {
5701
+ return function() {
5702
+ if (this.curOp) return f.apply(this, arguments);
5703
+ startOperation(this);
5704
+ try { return f.apply(this, arguments); }
5705
+ finally { endOperation(this); }
5706
+ };
5707
+ }
5708
+ function docMethodOp(f) {
5709
+ return function() {
5710
+ var cm = this.cm;
5711
+ if (!cm || cm.curOp) return f.apply(this, arguments);
5712
+ startOperation(cm);
5713
+ try { return f.apply(this, arguments); }
5714
+ finally { endOperation(cm); }
5715
+ };
5716
+ }
5717
+
5718
+ // VIEW TRACKING
5719
+
5720
+ // These objects are used to represent the visible (currently drawn)
5721
+ // part of the document. A LineView may correspond to multiple
5722
+ // logical lines, if those are connected by collapsed ranges.
5723
+ function LineView(doc, line, lineN) {
5724
+ // The starting line
5725
+ this.line = line;
5726
+ // Continuing lines, if any
5727
+ this.rest = visualLineContinued(line);
5728
+ // Number of logical lines in this visual line
5729
+ this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;
5730
+ this.node = this.text = null;
5731
+ this.hidden = lineIsHidden(doc, line);
5732
+ }
5733
+
5734
+ // Create a range of LineView objects for the given lines.
5735
+ function buildViewArray(cm, from, to) {
5736
+ var array = [], nextPos;
5737
+ for (var pos = from; pos < to; pos = nextPos) {
5738
+ var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);
5739
+ nextPos = pos + view.size;
5740
+ array.push(view);
5741
+ }
5742
+ return array;
5743
+ }
5744
+
5745
+ // Updates the display.view data structure for a given change to the
5746
+ // document. From and to are in pre-change coordinates. Lendiff is
5747
+ // the amount of lines added or subtracted by the change. This is
5748
+ // used for changes that span multiple lines, or change the way
5749
+ // lines are divided into visual lines. regLineChange (below)
5750
+ // registers single-line changes.
5751
+ function regChange(cm, from, to, lendiff) {
5752
+ if (from == null) from = cm.doc.first;
5753
+ if (to == null) to = cm.doc.first + cm.doc.size;
5754
+ if (!lendiff) lendiff = 0;
5755
+
5756
+ var display = cm.display;
5757
+ if (lendiff && to < display.viewTo &&
5758
+ (display.updateLineNumbers == null || display.updateLineNumbers > from))
5759
+ display.updateLineNumbers = from;
5760
+
5761
+ cm.curOp.viewChanged = true;
5762
+
5763
+ if (from >= display.viewTo) { // Change after
5764
+ if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
5765
+ resetView(cm);
5766
+ } else if (to <= display.viewFrom) { // Change before
5767
+ if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
5768
+ resetView(cm);
5769
+ } else {
5770
+ display.viewFrom += lendiff;
5771
+ display.viewTo += lendiff;
5772
+ }
5773
+ } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
5774
+ resetView(cm);
5775
+ } else if (from <= display.viewFrom) { // Top overlap
5776
+ var cut = viewCuttingPoint(cm, to, to + lendiff, 1);
5777
+ if (cut) {
5778
+ display.view = display.view.slice(cut.index);
5779
+ display.viewFrom = cut.lineN;
5780
+ display.viewTo += lendiff;
5781
+ } else {
5782
+ resetView(cm);
5783
+ }
5784
+ } else if (to >= display.viewTo) { // Bottom overlap
5785
+ var cut = viewCuttingPoint(cm, from, from, -1);
5786
+ if (cut) {
5787
+ display.view = display.view.slice(0, cut.index);
5788
+ display.viewTo = cut.lineN;
5789
+ } else {
5790
+ resetView(cm);
5791
+ }
5792
+ } else { // Gap in the middle
5793
+ var cutTop = viewCuttingPoint(cm, from, from, -1);
5794
+ var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1);
5795
+ if (cutTop && cutBot) {
5796
+ display.view = display.view.slice(0, cutTop.index)
5797
+ .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
5798
+ .concat(display.view.slice(cutBot.index));
5799
+ display.viewTo += lendiff;
5800
+ } else {
5801
+ resetView(cm);
5802
+ }
5803
+ }
5804
+
5805
+ var ext = display.externalMeasured;
5806
+ if (ext) {
5807
+ if (to < ext.lineN)
5808
+ ext.lineN += lendiff;
5809
+ else if (from < ext.lineN + ext.size)
5810
+ display.externalMeasured = null;
5811
+ }
5812
+ }
5813
+
5814
+ // Register a change to a single line. Type must be one of "text",
5815
+ // "gutter", "class", "widget"
5816
+ function regLineChange(cm, line, type) {
5817
+ cm.curOp.viewChanged = true;
5818
+ var display = cm.display, ext = cm.display.externalMeasured;
5819
+ if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
5820
+ display.externalMeasured = null;
5821
+
5822
+ if (line < display.viewFrom || line >= display.viewTo) return;
5823
+ var lineView = display.view[findViewIndex(cm, line)];
5824
+ if (lineView.node == null) return;
5825
+ var arr = lineView.changes || (lineView.changes = []);
5826
+ if (indexOf(arr, type) == -1) arr.push(type);
5827
+ }
5828
+
5829
+ // Clear the view.
5830
+ function resetView(cm) {
5831
+ cm.display.viewFrom = cm.display.viewTo = cm.doc.first;
5832
+ cm.display.view = [];
5833
+ cm.display.viewOffset = 0;
5834
+ }
5835
+
5836
+ // Find the view element corresponding to a given line. Return null
5837
+ // when the line isn't visible.
5838
+ function findViewIndex(cm, n) {
5839
+ if (n >= cm.display.viewTo) return null;
5840
+ n -= cm.display.viewFrom;
5841
+ if (n < 0) return null;
5842
+ var view = cm.display.view;
5843
+ for (var i = 0; i < view.length; i++) {
5844
+ n -= view[i].size;
5845
+ if (n < 0) return i;
5846
+ }
5847
+ }
5848
+
5849
+ function viewCuttingPoint(cm, oldN, newN, dir) {
5850
+ var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
5851
+ if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
5852
+ return {index: index, lineN: newN};
5853
+ for (var i = 0, n = cm.display.viewFrom; i < index; i++)
5854
+ n += view[i].size;
5855
+ if (n != oldN) {
5856
+ if (dir > 0) {
5857
+ if (index == view.length - 1) return null;
5858
+ diff = (n + view[index].size) - oldN;
5859
+ index++;
5860
+ } else {
5861
+ diff = n - oldN;
5862
+ }
5863
+ oldN += diff; newN += diff;
5864
+ }
5865
+ while (visualLineNo(cm.doc, newN) != newN) {
5866
+ if (index == (dir < 0 ? 0 : view.length - 1)) return null;
5867
+ newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
5868
+ index += dir;
5869
+ }
5870
+ return {index: index, lineN: newN};
5871
+ }
5872
+
5873
+ // Force the view to cover a given range, adding empty view element
5874
+ // or clipping off existing ones as needed.
5875
+ function adjustView(cm, from, to) {
5876
+ var display = cm.display, view = display.view;
5877
+ if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
5878
+ display.view = buildViewArray(cm, from, to);
5879
+ display.viewFrom = from;
5880
+ } else {
5881
+ if (display.viewFrom > from)
5882
+ display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view);
5883
+ else if (display.viewFrom < from)
5884
+ display.view = display.view.slice(findViewIndex(cm, from));
5885
+ display.viewFrom = from;
5886
+ if (display.viewTo < to)
5887
+ display.view = display.view.concat(buildViewArray(cm, display.viewTo, to));
5888
+ else if (display.viewTo > to)
5889
+ display.view = display.view.slice(0, findViewIndex(cm, to));
5890
+ }
5891
+ display.viewTo = to;
5892
+ }
5893
+
5894
+ // Count the number of lines in the view whose DOM representation is
5895
+ // out of date (or nonexistent).
5896
+ function countDirtyView(cm) {
5897
+ var view = cm.display.view, dirty = 0;
5898
+ for (var i = 0; i < view.length; i++) {
5899
+ var lineView = view[i];
5900
+ if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty;
5901
+ }
5902
+ return dirty;
5903
+ }
5904
+
5905
+ // EVENT HANDLERS
5906
+
5907
+ // Attach the necessary event handlers when initializing the editor
5908
+ function registerEventHandlers(cm) {
5909
+ var d = cm.display;
5910
+ on(d.scroller, "mousedown", operation(cm, onMouseDown));
5911
+ // Older IE's will not fire a second mousedown for a double click
5912
+ if (ie && ie_version < 11)
5913
+ on(d.scroller, "dblclick", operation(cm, function(e) {
5914
+ if (signalDOMEvent(cm, e)) return;
5915
+ var pos = posFromMouse(cm, e);
5916
+ if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return;
5917
+ e_preventDefault(e);
5918
+ var word = cm.findWordAt(pos);
5919
+ extendSelection(cm.doc, word.anchor, word.head);
5920
+ }));
5921
+ else
5922
+ on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); });
5923
+ // Some browsers fire contextmenu *after* opening the menu, at
5924
+ // which point we can't mess with it anymore. Context menu is
5925
+ // handled in onMouseDown for these browsers.
5926
+ if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);});
5927
+
5928
+ // Used to suppress mouse event handling when a touch happens
5929
+ var touchFinished, prevTouch = {end: 0};
5930
+ function finishTouch() {
5931
+ if (d.activeTouch) {
5932
+ touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000);
5933
+ prevTouch = d.activeTouch;
5934
+ prevTouch.end = +new Date;
5935
+ }
5936
+ };
5937
+ function isMouseLikeTouchEvent(e) {
5938
+ if (e.touches.length != 1) return false;
5939
+ var touch = e.touches[0];
5940
+ return touch.radiusX <= 1 && touch.radiusY <= 1;
5941
+ }
5942
+ function farAway(touch, other) {
5943
+ if (other.left == null) return true;
5944
+ var dx = other.left - touch.left, dy = other.top - touch.top;
5945
+ return dx * dx + dy * dy > 20 * 20;
5946
+ }
5947
+ on(d.scroller, "touchstart", function(e) {
5948
+ if (!isMouseLikeTouchEvent(e)) {
5949
+ clearTimeout(touchFinished);
5950
+ var now = +new Date;
5951
+ d.activeTouch = {start: now, moved: false,
5952
+ prev: now - prevTouch.end <= 300 ? prevTouch : null};
5953
+ if (e.touches.length == 1) {
5954
+ d.activeTouch.left = e.touches[0].pageX;
5955
+ d.activeTouch.top = e.touches[0].pageY;
5956
+ }
5957
+ }
5958
+ });
5959
+ on(d.scroller, "touchmove", function() {
5960
+ if (d.activeTouch) d.activeTouch.moved = true;
5961
+ });
5962
+ on(d.scroller, "touchend", function(e) {
5963
+ var touch = d.activeTouch;
5964
+ if (touch && !eventInWidget(d, e) && touch.left != null &&
5965
+ !touch.moved && new Date - touch.start < 300) {
5966
+ var pos = cm.coordsChar(d.activeTouch, "page"), range;
5967
+ if (!touch.prev || farAway(touch, touch.prev)) // Single tap
5968
+ range = new Range(pos, pos);
5969
+ else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
5970
+ range = cm.findWordAt(pos);
5971
+ else // Triple tap
5972
+ range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0)));
5973
+ cm.setSelection(range.anchor, range.head);
5974
+ cm.focus();
5975
+ e_preventDefault(e);
5976
+ }
5977
+ finishTouch();
5978
+ });
5979
+ on(d.scroller, "touchcancel", finishTouch);
5980
+
5981
+ // Sync scrolling between fake scrollbars and real scrollable
5982
+ // area, ensure viewport is updated when scrolling.
5983
+ on(d.scroller, "scroll", function() {
5984
+ if (d.scroller.clientHeight) {
5985
+ setScrollTop(cm, d.scroller.scrollTop);
5986
+ setScrollLeft(cm, d.scroller.scrollLeft, true);
5987
+ signal(cm, "scroll", cm);
5988
+ }
5989
+ });
5990
+
5991
+ // Listen to wheel events in order to try and update the viewport on time.
5992
+ on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);});
5993
+ on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);});
5994
+
5995
+ // Prevent wrapper from ever scrolling
5996
+ on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
5997
+
5998
+ d.dragFunctions = {
5999
+ enter: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);},
6000
+ over: function(e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }},
6001
+ start: function(e){onDragStart(cm, e);},
6002
+ drop: operation(cm, onDrop),
6003
+ leave: function() {clearDragCursor(cm);}
6004
+ };
6005
+
6006
+ var inp = d.input.getField();
6007
+ on(inp, "keyup", function(e) { onKeyUp.call(cm, e); });
6008
+ on(inp, "keydown", operation(cm, onKeyDown));
6009
+ on(inp, "keypress", operation(cm, onKeyPress));
6010
+ on(inp, "focus", bind(onFocus, cm));
6011
+ on(inp, "blur", bind(onBlur, cm));
6012
+ }
6013
+
6014
+ function dragDropChanged(cm, value, old) {
6015
+ var wasOn = old && old != CodeMirror.Init;
6016
+ if (!value != !wasOn) {
6017
+ var funcs = cm.display.dragFunctions;
6018
+ var toggle = value ? on : off;
6019
+ toggle(cm.display.scroller, "dragstart", funcs.start);
6020
+ toggle(cm.display.scroller, "dragenter", funcs.enter);
6021
+ toggle(cm.display.scroller, "dragover", funcs.over);
6022
+ toggle(cm.display.scroller, "dragleave", funcs.leave);
6023
+ toggle(cm.display.scroller, "drop", funcs.drop);
6024
+ }
6025
+ }
6026
+
6027
+ // Called when the window resizes
6028
+ function onResize(cm) {
6029
+ var d = cm.display;
6030
+ if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)
6031
+ return;
6032
+ // Might be a text scaling operation, clear size caches.
6033
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
6034
+ d.scrollbarsClipped = false;
6035
+ cm.setSize();
6036
+ }
6037
+
6038
+ // MOUSE EVENTS
6039
+
6040
+ // Return true when the given mouse event happened in a widget
6041
+ function eventInWidget(display, e) {
6042
+ for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
6043
+ if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
6044
+ (n.parentNode == display.sizer && n != display.mover))
6045
+ return true;
6046
+ }
6047
+ }
6048
+
6049
+ // Given a mouse event, find the corresponding position. If liberal
6050
+ // is false, it checks whether a gutter or scrollbar was clicked,
6051
+ // and returns null if it was. forRect is used by rectangular
6052
+ // selections, and tries to estimate a character position even for
6053
+ // coordinates beyond the right of the text.
6054
+ function posFromMouse(cm, e, liberal, forRect) {
6055
+ var display = cm.display;
6056
+ if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") return null;
6057
+
6058
+ var x, y, space = display.lineSpace.getBoundingClientRect();
6059
+ // Fails unpredictably on IE[67] when mouse is dragged around quickly.
6060
+ try { x = e.clientX - space.left; y = e.clientY - space.top; }
6061
+ catch (e) { return null; }
6062
+ var coords = coordsChar(cm, x, y), line;
6063
+ if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
6064
+ var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
6065
+ coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));
6066
+ }
6067
+ return coords;
6068
+ }
6069
+
6070
+ // A mouse down can be a single click, double click, triple click,
6071
+ // start of selection drag, start of text drag, new cursor
6072
+ // (ctrl-click), rectangle drag (alt-drag), or xwin
6073
+ // middle-click-paste. Or it might be a click on something we should
6074
+ // not interfere with, such as a scrollbar or widget.
6075
+ function onMouseDown(e) {
6076
+ var cm = this, display = cm.display;
6077
+ if (display.activeTouch && display.input.supportsTouch() || signalDOMEvent(cm, e)) return;
6078
+ display.shift = e.shiftKey;
6079
+
6080
+ if (eventInWidget(display, e)) {
6081
+ if (!webkit) {
6082
+ // Briefly turn off draggability, to allow widgets to do
6083
+ // normal dragging things.
6084
+ display.scroller.draggable = false;
6085
+ setTimeout(function(){display.scroller.draggable = true;}, 100);
6086
+ }
6087
+ return;
6088
+ }
6089
+ if (clickInGutter(cm, e)) return;
6090
+ var start = posFromMouse(cm, e);
6091
+ window.focus();
6092
+
6093
+ switch (e_button(e)) {
6094
+ case 1:
6095
+ // #3261: make sure, that we're not starting a second selection
6096
+ if (cm.state.selectingText)
6097
+ cm.state.selectingText(e);
6098
+ else if (start)
6099
+ leftButtonDown(cm, e, start);
6100
+ else if (e_target(e) == display.scroller)
6101
+ e_preventDefault(e);
6102
+ break;
6103
+ case 2:
6104
+ if (webkit) cm.state.lastMiddleDown = +new Date;
6105
+ if (start) extendSelection(cm.doc, start);
6106
+ setTimeout(function() {display.input.focus();}, 20);
6107
+ e_preventDefault(e);
6108
+ break;
6109
+ case 3:
6110
+ if (captureRightClick) onContextMenu(cm, e);
6111
+ else delayBlurEvent(cm);
6112
+ break;
6113
+ }
6114
+ }
6115
+
6116
+ var lastClick, lastDoubleClick;
6117
+ function leftButtonDown(cm, e, start) {
6118
+ if (ie) setTimeout(bind(ensureFocus, cm), 0);
6119
+ else cm.curOp.focus = activeElt();
6120
+
6121
+ var now = +new Date, type;
6122
+ if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
6123
+ type = "triple";
6124
+ } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {
6125
+ type = "double";
6126
+ lastDoubleClick = {time: now, pos: start};
6127
+ } else {
6128
+ type = "single";
6129
+ lastClick = {time: now, pos: start};
6130
+ }
6131
+
6132
+ var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;
6133
+ if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&
6134
+ type == "single" && (contained = sel.contains(start)) > -1 &&
6135
+ (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) &&
6136
+ (cmp(contained.to(), start) > 0 || start.xRel < 0))
6137
+ leftButtonStartDrag(cm, e, start, modifier);
6138
+ else
6139
+ leftButtonSelect(cm, e, start, type, modifier);
6140
+ }
6141
+
6142
+ // Start a text drag. When it ends, see if any dragging actually
6143
+ // happen, and treat as a click if it didn't.
6144
+ function leftButtonStartDrag(cm, e, start, modifier) {
6145
+ var display = cm.display, startTime = +new Date;
6146
+ var dragEnd = operation(cm, function(e2) {
6147
+ if (webkit) display.scroller.draggable = false;
6148
+ cm.state.draggingText = false;
6149
+ off(document, "mouseup", dragEnd);
6150
+ off(display.scroller, "drop", dragEnd);
6151
+ if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
6152
+ e_preventDefault(e2);
6153
+ if (!modifier && +new Date - 200 < startTime)
6154
+ extendSelection(cm.doc, start);
6155
+ // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
6156
+ if (webkit || ie && ie_version == 9)
6157
+ setTimeout(function() {document.body.focus(); display.input.focus();}, 20);
6158
+ else
6159
+ display.input.focus();
6160
+ }
6161
+ });
6162
+ // Let the drag handler handle this.
6163
+ if (webkit) display.scroller.draggable = true;
6164
+ cm.state.draggingText = dragEnd;
6165
+ // IE's approach to draggable
6166
+ if (display.scroller.dragDrop) display.scroller.dragDrop();
6167
+ on(document, "mouseup", dragEnd);
6168
+ on(display.scroller, "drop", dragEnd);
6169
+ }
6170
+
6171
+ // Normal selection, as opposed to text dragging.
6172
+ function leftButtonSelect(cm, e, start, type, addNew) {
6173
+ var display = cm.display, doc = cm.doc;
6174
+ e_preventDefault(e);
6175
+
6176
+ var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;
6177
+ if (addNew && !e.shiftKey) {
6178
+ ourIndex = doc.sel.contains(start);
6179
+ if (ourIndex > -1)
6180
+ ourRange = ranges[ourIndex];
6181
+ else
6182
+ ourRange = new Range(start, start);
6183
+ } else {
6184
+ ourRange = doc.sel.primary();
6185
+ ourIndex = doc.sel.primIndex;
6186
+ }
6187
+
6188
+ if (e.altKey) {
6189
+ type = "rect";
6190
+ if (!addNew) ourRange = new Range(start, start);
6191
+ start = posFromMouse(cm, e, true, true);
6192
+ ourIndex = -1;
6193
+ } else if (type == "double") {
6194
+ var word = cm.findWordAt(start);
6195
+ if (cm.display.shift || doc.extend)
6196
+ ourRange = extendRange(doc, ourRange, word.anchor, word.head);
6197
+ else
6198
+ ourRange = word;
6199
+ } else if (type == "triple") {
6200
+ var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)));
6201
+ if (cm.display.shift || doc.extend)
6202
+ ourRange = extendRange(doc, ourRange, line.anchor, line.head);
6203
+ else
6204
+ ourRange = line;
6205
+ } else {
6206
+ ourRange = extendRange(doc, ourRange, start);
6207
+ }
6208
+
6209
+ if (!addNew) {
6210
+ ourIndex = 0;
6211
+ setSelection(doc, new Selection([ourRange], 0), sel_mouse);
6212
+ startSel = doc.sel;
6213
+ } else if (ourIndex == -1) {
6214
+ ourIndex = ranges.length;
6215
+ setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
6216
+ {scroll: false, origin: "*mouse"});
6217
+ } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) {
6218
+ setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
6219
+ {scroll: false, origin: "*mouse"});
6220
+ startSel = doc.sel;
6221
+ } else {
6222
+ replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
6223
+ }
6224
+
6225
+ var lastPos = start;
6226
+ function extendTo(pos) {
6227
+ if (cmp(lastPos, pos) == 0) return;
6228
+ lastPos = pos;
6229
+
6230
+ if (type == "rect") {
6231
+ var ranges = [], tabSize = cm.options.tabSize;
6232
+ var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);
6233
+ var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);
6234
+ var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);
6235
+ for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
6236
+ line <= end; line++) {
6237
+ var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);
6238
+ if (left == right)
6239
+ ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos)));
6240
+ else if (text.length > leftPos)
6241
+ ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize))));
6242
+ }
6243
+ if (!ranges.length) ranges.push(new Range(start, start));
6244
+ setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
6245
+ {origin: "*mouse", scroll: false});
6246
+ cm.scrollIntoView(pos);
6247
+ } else {
6248
+ var oldRange = ourRange;
6249
+ var anchor = oldRange.anchor, head = pos;
6250
+ if (type != "single") {
6251
+ if (type == "double")
6252
+ var range = cm.findWordAt(pos);
6253
+ else
6254
+ var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0)));
6255
+ if (cmp(range.anchor, anchor) > 0) {
6256
+ head = range.head;
6257
+ anchor = minPos(oldRange.from(), range.anchor);
6258
+ } else {
6259
+ head = range.anchor;
6260
+ anchor = maxPos(oldRange.to(), range.head);
6261
+ }
6262
+ }
6263
+ var ranges = startSel.ranges.slice(0);
6264
+ ranges[ourIndex] = new Range(clipPos(doc, anchor), head);
6265
+ setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse);
6266
+ }
6267
+ }
6268
+
6269
+ var editorSize = display.wrapper.getBoundingClientRect();
6270
+ // Used to ensure timeout re-tries don't fire when another extend
6271
+ // happened in the meantime (clearTimeout isn't reliable -- at
6272
+ // least on Chrome, the timeouts still happen even when cleared,
6273
+ // if the clear happens after their scheduled firing time).
6274
+ var counter = 0;
6275
+
6276
+ function extend(e) {
6277
+ var curCount = ++counter;
6278
+ var cur = posFromMouse(cm, e, true, type == "rect");
6279
+ if (!cur) return;
6280
+ if (cmp(cur, lastPos) != 0) {
6281
+ cm.curOp.focus = activeElt();
6282
+ extendTo(cur);
6283
+ var visible = visibleLines(display, doc);
6284
+ if (cur.line >= visible.to || cur.line < visible.from)
6285
+ setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150);
6286
+ } else {
6287
+ var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
6288
+ if (outside) setTimeout(operation(cm, function() {
6289
+ if (counter != curCount) return;
6290
+ display.scroller.scrollTop += outside;
6291
+ extend(e);
6292
+ }), 50);
6293
+ }
6294
+ }
6295
+
6296
+ function done(e) {
6297
+ cm.state.selectingText = false;
6298
+ counter = Infinity;
6299
+ e_preventDefault(e);
6300
+ display.input.focus();
6301
+ off(document, "mousemove", move);
6302
+ off(document, "mouseup", up);
6303
+ doc.history.lastSelOrigin = null;
6304
+ }
6305
+
6306
+ var move = operation(cm, function(e) {
6307
+ if (!e_button(e)) done(e);
6308
+ else extend(e);
6309
+ });
6310
+ var up = operation(cm, done);
6311
+ cm.state.selectingText = up;
6312
+ on(document, "mousemove", move);
6313
+ on(document, "mouseup", up);
6314
+ }
6315
+
6316
+ // Determines whether an event happened in the gutter, and fires the
6317
+ // handlers for the corresponding event.
6318
+ function gutterEvent(cm, e, type, prevent, signalfn) {
6319
+ try { var mX = e.clientX, mY = e.clientY; }
6320
+ catch(e) { return false; }
6321
+ if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false;
6322
+ if (prevent) e_preventDefault(e);
6323
+
6324
+ var display = cm.display;
6325
+ var lineBox = display.lineDiv.getBoundingClientRect();
6326
+
6327
+ if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e);
6328
+ mY -= lineBox.top - display.viewOffset;
6329
+
6330
+ for (var i = 0; i < cm.options.gutters.length; ++i) {
6331
+ var g = display.gutters.childNodes[i];
6332
+ if (g && g.getBoundingClientRect().right >= mX) {
6333
+ var line = lineAtHeight(cm.doc, mY);
6334
+ var gutter = cm.options.gutters[i];
6335
+ signalfn(cm, type, cm, line, gutter, e);
6336
+ return e_defaultPrevented(e);
6337
+ }
6338
+ }
6339
+ }
6340
+
6341
+ function clickInGutter(cm, e) {
6342
+ return gutterEvent(cm, e, "gutterClick", true, signalLater);
6343
+ }
6344
+
6345
+ // Kludge to work around strange IE behavior where it'll sometimes
6346
+ // re-fire a series of drag-related events right after the drop (#1551)
6347
+ var lastDrop = 0;
6348
+
6349
+ function onDrop(e) {
6350
+ var cm = this;
6351
+ clearDragCursor(cm);
6352
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
6353
+ return;
6354
+ e_preventDefault(e);
6355
+ if (ie) lastDrop = +new Date;
6356
+ var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
6357
+ if (!pos || isReadOnly(cm)) return;
6358
+ // Might be a file drop, in which case we simply extract the text
6359
+ // and insert it.
6360
+ if (files && files.length && window.FileReader && window.File) {
6361
+ var n = files.length, text = Array(n), read = 0;
6362
+ var loadFile = function(file, i) {
6363
+ if (cm.options.allowDropFileTypes &&
6364
+ indexOf(cm.options.allowDropFileTypes, file.type) == -1)
6365
+ return;
6366
+
6367
+ var reader = new FileReader;
6368
+ reader.onload = operation(cm, function() {
6369
+ var content = reader.result;
6370
+ if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) content = "";
6371
+ text[i] = content;
6372
+ if (++read == n) {
6373
+ pos = clipPos(cm.doc, pos);
6374
+ var change = {from: pos, to: pos,
6375
+ text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())),
6376
+ origin: "paste"};
6377
+ makeChange(cm.doc, change);
6378
+ setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));
6379
+ }
6380
+ });
6381
+ reader.readAsText(file);
6382
+ };
6383
+ for (var i = 0; i < n; ++i) loadFile(files[i], i);
6384
+ } else { // Normal drop
6385
+ // Don't do a replace if the drop happened inside of the selected text.
6386
+ if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
6387
+ cm.state.draggingText(e);
6388
+ // Ensure the editor is re-focused
6389
+ setTimeout(function() {cm.display.input.focus();}, 20);
6390
+ return;
6391
+ }
6392
+ try {
6393
+ var text = e.dataTransfer.getData("Text");
6394
+ if (text) {
6395
+ if (cm.state.draggingText && !(mac ? e.altKey : e.ctrlKey))
6396
+ var selected = cm.listSelections();
6397
+ setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
6398
+ if (selected) for (var i = 0; i < selected.length; ++i)
6399
+ replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag");
6400
+ cm.replaceSelection(text, "around", "paste");
6401
+ cm.display.input.focus();
6402
+ }
6403
+ }
6404
+ catch(e){}
6405
+ }
6406
+ }
6407
+
6408
+ function onDragStart(cm, e) {
6409
+ if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; }
6410
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return;
6411
+
6412
+ e.dataTransfer.setData("Text", cm.getSelection());
6413
+
6414
+ // Use dummy image instead of default browsers image.
6415
+ // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
6416
+ if (e.dataTransfer.setDragImage && !safari) {
6417
+ var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
6418
+ img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
6419
+ if (presto) {
6420
+ img.width = img.height = 1;
6421
+ cm.display.wrapper.appendChild(img);
6422
+ // Force a relayout, or Opera won't use our image for some obscure reason
6423
+ img._top = img.offsetTop;
6424
+ }
6425
+ e.dataTransfer.setDragImage(img, 0, 0);
6426
+ if (presto) img.parentNode.removeChild(img);
6427
+ }
6428
+ }
6429
+
6430
+ function onDragOver(cm, e) {
6431
+ var pos = posFromMouse(cm, e);
6432
+ if (!pos) return;
6433
+ var frag = document.createDocumentFragment();
6434
+ drawSelectionCursor(cm, pos, frag);
6435
+ if (!cm.display.dragCursor) {
6436
+ cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors");
6437
+ cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv);
6438
+ }
6439
+ removeChildrenAndAdd(cm.display.dragCursor, frag);
6440
+ }
6441
+
6442
+ function clearDragCursor(cm) {
6443
+ if (cm.display.dragCursor) {
6444
+ cm.display.lineSpace.removeChild(cm.display.dragCursor);
6445
+ cm.display.dragCursor = null;
6446
+ }
6447
+ }
6448
+
6449
+ // SCROLL EVENTS
6450
+
6451
+ // Sync the scrollable area and scrollbars, ensure the viewport
6452
+ // covers the visible area.
6453
+ function setScrollTop(cm, val) {
6454
+ if (Math.abs(cm.doc.scrollTop - val) < 2) return;
6455
+ cm.doc.scrollTop = val;
6456
+ if (!gecko) updateDisplaySimple(cm, {top: val});
6457
+ if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val;
6458
+ cm.display.scrollbars.setScrollTop(val);
6459
+ if (gecko) updateDisplaySimple(cm);
6460
+ startWorker(cm, 100);
6461
+ }
6462
+ // Sync scroller and scrollbar, ensure the gutter elements are
6463
+ // aligned.
6464
+ function setScrollLeft(cm, val, isScroller) {
6465
+ if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return;
6466
+ val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth);
6467
+ cm.doc.scrollLeft = val;
6468
+ alignHorizontally(cm);
6469
+ if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val;
6470
+ cm.display.scrollbars.setScrollLeft(val);
6471
+ }
6472
+
6473
+ // Since the delta values reported on mouse wheel events are
6474
+ // unstandardized between browsers and even browser versions, and
6475
+ // generally horribly unpredictable, this code starts by measuring
6476
+ // the scroll effect that the first few mouse wheel events have,
6477
+ // and, from that, detects the way it can convert deltas to pixel
6478
+ // offsets afterwards.
6479
+ //
6480
+ // The reason we want to know the amount a wheel event will scroll
6481
+ // is that it gives us a chance to update the display before the
6482
+ // actual scrolling happens, reducing flickering.
6483
+
6484
+ var wheelSamples = 0, wheelPixelsPerUnit = null;
6485
+ // Fill in a browser-detected starting value on browsers where we
6486
+ // know one. These don't have to be accurate -- the result of them
6487
+ // being wrong would just be a slight flicker on the first wheel
6488
+ // scroll (if it is large enough).
6489
+ if (ie) wheelPixelsPerUnit = -.53;
6490
+ else if (gecko) wheelPixelsPerUnit = 15;
6491
+ else if (chrome) wheelPixelsPerUnit = -.7;
6492
+ else if (safari) wheelPixelsPerUnit = -1/3;
6493
+
6494
+ var wheelEventDelta = function(e) {
6495
+ var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
6496
+ if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
6497
+ if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail;
6498
+ else if (dy == null) dy = e.wheelDelta;
6499
+ return {x: dx, y: dy};
6500
+ };
6501
+ CodeMirror.wheelEventPixels = function(e) {
6502
+ var delta = wheelEventDelta(e);
6503
+ delta.x *= wheelPixelsPerUnit;
6504
+ delta.y *= wheelPixelsPerUnit;
6505
+ return delta;
6506
+ };
6507
+
6508
+ function onScrollWheel(cm, e) {
6509
+ var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
6510
+
6511
+ var display = cm.display, scroll = display.scroller;
6512
+ // Quit if there's nothing to scroll here
6513
+ var canScrollX = scroll.scrollWidth > scroll.clientWidth;
6514
+ var canScrollY = scroll.scrollHeight > scroll.clientHeight;
6515
+ if (!(dx && canScrollX || dy && canScrollY)) return;
6516
+
6517
+ // Webkit browsers on OS X abort momentum scrolls when the target
6518
+ // of the scroll event is removed from the scrollable element.
6519
+ // This hack (see related code in patchDisplay) makes sure the
6520
+ // element is kept around.
6521
+ if (dy && mac && webkit) {
6522
+ outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
6523
+ for (var i = 0; i < view.length; i++) {
6524
+ if (view[i].node == cur) {
6525
+ cm.display.currentWheelTarget = cur;
6526
+ break outer;
6527
+ }
6528
+ }
6529
+ }
6530
+ }
6531
+
6532
+ // On some browsers, horizontal scrolling will cause redraws to
6533
+ // happen before the gutter has been realigned, causing it to
6534
+ // wriggle around in a most unseemly way. When we have an
6535
+ // estimated pixels/delta value, we just handle horizontal
6536
+ // scrolling entirely here. It'll be slightly off from native, but
6537
+ // better than glitching out.
6538
+ if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
6539
+ if (dy && canScrollY)
6540
+ setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
6541
+ setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
6542
+ // Only prevent default scrolling if vertical scrolling is
6543
+ // actually possible. Otherwise, it causes vertical scroll
6544
+ // jitter on OSX trackpads when deltaX is small and deltaY
6545
+ // is large (issue #3579)
6546
+ if (!dy || (dy && canScrollY))
6547
+ e_preventDefault(e);
6548
+ display.wheelStartX = null; // Abort measurement, if in progress
6549
+ return;
6550
+ }
6551
+
6552
+ // 'Project' the visible viewport to cover the area that is being
6553
+ // scrolled into view (if we know enough to estimate it).
6554
+ if (dy && wheelPixelsPerUnit != null) {
6555
+ var pixels = dy * wheelPixelsPerUnit;
6556
+ var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
6557
+ if (pixels < 0) top = Math.max(0, top + pixels - 50);
6558
+ else bot = Math.min(cm.doc.height, bot + pixels + 50);
6559
+ updateDisplaySimple(cm, {top: top, bottom: bot});
6560
+ }
6561
+
6562
+ if (wheelSamples < 20) {
6563
+ if (display.wheelStartX == null) {
6564
+ display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
6565
+ display.wheelDX = dx; display.wheelDY = dy;
6566
+ setTimeout(function() {
6567
+ if (display.wheelStartX == null) return;
6568
+ var movedX = scroll.scrollLeft - display.wheelStartX;
6569
+ var movedY = scroll.scrollTop - display.wheelStartY;
6570
+ var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
6571
+ (movedX && display.wheelDX && movedX / display.wheelDX);
6572
+ display.wheelStartX = display.wheelStartY = null;
6573
+ if (!sample) return;
6574
+ wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
6575
+ ++wheelSamples;
6576
+ }, 200);
6577
+ } else {
6578
+ display.wheelDX += dx; display.wheelDY += dy;
6579
+ }
6580
+ }
6581
+ }
6582
+
6583
+ // KEY EVENTS
6584
+
6585
+ // Run a handler that was bound to a key.
6586
+ function doHandleBinding(cm, bound, dropShift) {
6587
+ if (typeof bound == "string") {
6588
+ bound = commands[bound];
6589
+ if (!bound) return false;
6590
+ }
6591
+ // Ensure previous input has been read, so that the handler sees a
6592
+ // consistent view of the document
6593
+ cm.display.input.ensurePolled();
6594
+ var prevShift = cm.display.shift, done = false;
6595
+ try {
6596
+ if (isReadOnly(cm)) cm.state.suppressEdits = true;
6597
+ if (dropShift) cm.display.shift = false;
6598
+ done = bound(cm) != Pass;
6599
+ } finally {
6600
+ cm.display.shift = prevShift;
6601
+ cm.state.suppressEdits = false;
6602
+ }
6603
+ return done;
6604
+ }
6605
+
6606
+ function lookupKeyForEditor(cm, name, handle) {
6607
+ for (var i = 0; i < cm.state.keyMaps.length; i++) {
6608
+ var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);
6609
+ if (result) return result;
6610
+ }
6611
+ return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
6612
+ || lookupKey(name, cm.options.keyMap, handle, cm);
6613
+ }
6614
+
6615
+ var stopSeq = new Delayed;
6616
+ function dispatchKey(cm, name, e, handle) {
6617
+ var seq = cm.state.keySeq;
6618
+ if (seq) {
6619
+ if (isModifierKey(name)) return "handled";
6620
+ stopSeq.set(50, function() {
6621
+ if (cm.state.keySeq == seq) {
6622
+ cm.state.keySeq = null;
6623
+ cm.display.input.reset();
6624
+ }
6625
+ });
6626
+ name = seq + " " + name;
6627
+ }
6628
+ var result = lookupKeyForEditor(cm, name, handle);
6629
+
6630
+ if (result == "multi")
6631
+ cm.state.keySeq = name;
6632
+ if (result == "handled")
6633
+ signalLater(cm, "keyHandled", cm, name, e);
6634
+
6635
+ if (result == "handled" || result == "multi") {
6636
+ e_preventDefault(e);
6637
+ restartBlink(cm);
6638
+ }
6639
+
6640
+ if (seq && !result && /\'$/.test(name)) {
6641
+ e_preventDefault(e);
6642
+ return true;
6643
+ }
6644
+ return !!result;
6645
+ }
6646
+
6647
+ // Handle a key from the keydown event.
6648
+ function handleKeyBinding(cm, e) {
6649
+ var name = keyName(e, true);
6650
+ if (!name) return false;
6651
+
6652
+ if (e.shiftKey && !cm.state.keySeq) {
6653
+ // First try to resolve full name (including 'Shift-'). Failing
6654
+ // that, see if there is a cursor-motion command (starting with
6655
+ // 'go') bound to the keyname without 'Shift-'.
6656
+ return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);})
6657
+ || dispatchKey(cm, name, e, function(b) {
6658
+ if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
6659
+ return doHandleBinding(cm, b);
6660
+ });
6661
+ } else {
6662
+ return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); });
6663
+ }
6664
+ }
6665
+
6666
+ // Handle a key from the keypress event
6667
+ function handleCharBinding(cm, e, ch) {
6668
+ return dispatchKey(cm, "'" + ch + "'", e,
6669
+ function(b) { return doHandleBinding(cm, b, true); });
6670
+ }
6671
+
6672
+ var lastStoppedKey = null;
6673
+ function onKeyDown(e) {
6674
+ var cm = this;
6675
+ cm.curOp.focus = activeElt();
6676
+ if (signalDOMEvent(cm, e)) return;
6677
+ // IE does strange things with escape.
6678
+ if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false;
6679
+ var code = e.keyCode;
6680
+ cm.display.shift = code == 16 || e.shiftKey;
6681
+ var handled = handleKeyBinding(cm, e);
6682
+ if (presto) {
6683
+ lastStoppedKey = handled ? code : null;
6684
+ // Opera has no cut event... we try to at least catch the key combo
6685
+ if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
6686
+ cm.replaceSelection("", null, "cut");
6687
+ }
6688
+
6689
+ // Turn mouse into crosshair when Alt is held on Mac.
6690
+ if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
6691
+ showCrossHair(cm);
6692
+ }
6693
+
6694
+ function showCrossHair(cm) {
6695
+ var lineDiv = cm.display.lineDiv;
6696
+ addClass(lineDiv, "CodeMirror-crosshair");
6697
+
6698
+ function up(e) {
6699
+ if (e.keyCode == 18 || !e.altKey) {
6700
+ rmClass(lineDiv, "CodeMirror-crosshair");
6701
+ off(document, "keyup", up);
6702
+ off(document, "mouseover", up);
6703
+ }
6704
+ }
6705
+ on(document, "keyup", up);
6706
+ on(document, "mouseover", up);
6707
+ }
6708
+
6709
+ function onKeyUp(e) {
6710
+ if (e.keyCode == 16) this.doc.sel.shift = false;
6711
+ signalDOMEvent(this, e);
6712
+ }
6713
+
6714
+ function onKeyPress(e) {
6715
+ var cm = this;
6716
+ if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return;
6717
+ var keyCode = e.keyCode, charCode = e.charCode;
6718
+ if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
6719
+ if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return;
6720
+ var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
6721
+ if (handleCharBinding(cm, e, ch)) return;
6722
+ cm.display.input.onKeyPress(e);
6723
+ }
6724
+
6725
+ // FOCUS/BLUR EVENTS
6726
+
6727
+ function delayBlurEvent(cm) {
6728
+ cm.state.delayingBlurEvent = true;
6729
+ setTimeout(function() {
6730
+ if (cm.state.delayingBlurEvent) {
6731
+ cm.state.delayingBlurEvent = false;
6732
+ onBlur(cm);
6733
+ }
6734
+ }, 100);
6735
+ }
6736
+
6737
+ function onFocus(cm) {
6738
+ if (cm.state.delayingBlurEvent) cm.state.delayingBlurEvent = false;
6739
+
6740
+ if (cm.options.readOnly == "nocursor") return;
6741
+ if (!cm.state.focused) {
6742
+ signal(cm, "focus", cm);
6743
+ cm.state.focused = true;
6744
+ addClass(cm.display.wrapper, "CodeMirror-focused");
6745
+ // This test prevents this from firing when a context
6746
+ // menu is closed (since the input reset would kill the
6747
+ // select-all detection hack)
6748
+ if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
6749
+ cm.display.input.reset();
6750
+ if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730
6751
+ }
6752
+ cm.display.input.receivedFocus();
6753
+ }
6754
+ restartBlink(cm);
6755
+ }
6756
+ function onBlur(cm) {
6757
+ if (cm.state.delayingBlurEvent) return;
6758
+
6759
+ if (cm.state.focused) {
6760
+ signal(cm, "blur", cm);
6761
+ cm.state.focused = false;
6762
+ rmClass(cm.display.wrapper, "CodeMirror-focused");
6763
+ }
6764
+ clearInterval(cm.display.blinker);
6765
+ setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150);
6766
+ }
6767
+
6768
+ // CONTEXT MENU HANDLING
6769
+
6770
+ // To make the context menu work, we need to briefly unhide the
6771
+ // textarea (making it as unobtrusive as possible) to let the
6772
+ // right-click take effect on it.
6773
+ function onContextMenu(cm, e) {
6774
+ if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return;
6775
+ if (signalDOMEvent(cm, e, "contextmenu")) return;
6776
+ cm.display.input.onContextMenu(e);
6777
+ }
6778
+
6779
+ function contextMenuInGutter(cm, e) {
6780
+ if (!hasHandler(cm, "gutterContextMenu")) return false;
6781
+ return gutterEvent(cm, e, "gutterContextMenu", false, signal);
6782
+ }
6783
+
6784
+ // UPDATING
6785
+
6786
+ // Compute the position of the end of a change (its 'to' property
6787
+ // refers to the pre-change end).
6788
+ var changeEnd = CodeMirror.changeEnd = function(change) {
6789
+ if (!change.text) return change.to;
6790
+ return Pos(change.from.line + change.text.length - 1,
6791
+ lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0));
6792
+ };
6793
+
6794
+ // Adjust a position to refer to the post-change position of the
6795
+ // same text, or the end of the change if the change covers it.
6796
+ function adjustForChange(pos, change) {
6797
+ if (cmp(pos, change.from) < 0) return pos;
6798
+ if (cmp(pos, change.to) <= 0) return changeEnd(change);
6799
+
6800
+ var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
6801
+ if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch;
6802
+ return Pos(line, ch);
6803
+ }
6804
+
6805
+ function computeSelAfterChange(doc, change) {
6806
+ var out = [];
6807
+ for (var i = 0; i < doc.sel.ranges.length; i++) {
6808
+ var range = doc.sel.ranges[i];
6809
+ out.push(new Range(adjustForChange(range.anchor, change),
6810
+ adjustForChange(range.head, change)));
6811
+ }
6812
+ return normalizeSelection(out, doc.sel.primIndex);
6813
+ }
6814
+
6815
+ function offsetPos(pos, old, nw) {
6816
+ if (pos.line == old.line)
6817
+ return Pos(nw.line, pos.ch - old.ch + nw.ch);
6818
+ else
6819
+ return Pos(nw.line + (pos.line - old.line), pos.ch);
6820
+ }
6821
+
6822
+ // Used by replaceSelections to allow moving the selection to the
6823
+ // start or around the replaced test. Hint may be "start" or "around".
6824
+ function computeReplacedSel(doc, changes, hint) {
6825
+ var out = [];
6826
+ var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;
6827
+ for (var i = 0; i < changes.length; i++) {
6828
+ var change = changes[i];
6829
+ var from = offsetPos(change.from, oldPrev, newPrev);
6830
+ var to = offsetPos(changeEnd(change), oldPrev, newPrev);
6831
+ oldPrev = change.to;
6832
+ newPrev = to;
6833
+ if (hint == "around") {
6834
+ var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;
6835
+ out[i] = new Range(inv ? to : from, inv ? from : to);
6836
+ } else {
6837
+ out[i] = new Range(from, from);
6838
+ }
6839
+ }
6840
+ return new Selection(out, doc.sel.primIndex);
6841
+ }
6842
+
6843
+ // Allow "beforeChange" event handlers to influence a change
6844
+ function filterChange(doc, change, update) {
6845
+ var obj = {
6846
+ canceled: false,
6847
+ from: change.from,
6848
+ to: change.to,
6849
+ text: change.text,
6850
+ origin: change.origin,
6851
+ cancel: function() { this.canceled = true; }
6852
+ };
6853
+ if (update) obj.update = function(from, to, text, origin) {
6854
+ if (from) this.from = clipPos(doc, from);
6855
+ if (to) this.to = clipPos(doc, to);
6856
+ if (text) this.text = text;
6857
+ if (origin !== undefined) this.origin = origin;
6858
+ };
6859
+ signal(doc, "beforeChange", doc, obj);
6860
+ if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj);
6861
+
6862
+ if (obj.canceled) return null;
6863
+ return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin};
6864
+ }
6865
+
6866
+ // Apply a change to a document, and add it to the document's
6867
+ // history, and propagating it to all linked documents.
6868
+ function makeChange(doc, change, ignoreReadOnly) {
6869
+ if (doc.cm) {
6870
+ if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly);
6871
+ if (doc.cm.state.suppressEdits) return;
6872
+ }
6873
+
6874
+ if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
6875
+ change = filterChange(doc, change, true);
6876
+ if (!change) return;
6877
+ }
6878
+
6879
+ // Possibly split or suppress the update based on the presence
6880
+ // of read-only spans in its range.
6881
+ var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
6882
+ if (split) {
6883
+ for (var i = split.length - 1; i >= 0; --i)
6884
+ makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text});
6885
+ } else {
6886
+ makeChangeInner(doc, change);
6887
+ }
6888
+ }
6889
+
6890
+ function makeChangeInner(doc, change) {
6891
+ if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return;
6892
+ var selAfter = computeSelAfterChange(doc, change);
6893
+ addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
6894
+
6895
+ makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
6896
+ var rebased = [];
6897
+
6898
+ linkedDocs(doc, function(doc, sharedHist) {
6899
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
6900
+ rebaseHist(doc.history, change);
6901
+ rebased.push(doc.history);
6902
+ }
6903
+ makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
6904
+ });
6905
+ }
6906
+
6907
+ // Revert a change stored in a document's history.
6908
+ function makeChangeFromHistory(doc, type, allowSelectionOnly) {
6909
+ if (doc.cm && doc.cm.state.suppressEdits) return;
6910
+
6911
+ var hist = doc.history, event, selAfter = doc.sel;
6912
+ var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;
6913
+
6914
+ // Verify that there is a useable event (so that ctrl-z won't
6915
+ // needlessly clear selection events)
6916
+ for (var i = 0; i < source.length; i++) {
6917
+ event = source[i];
6918
+ if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
6919
+ break;
6920
+ }
6921
+ if (i == source.length) return;
6922
+ hist.lastOrigin = hist.lastSelOrigin = null;
6923
+
6924
+ for (;;) {
6925
+ event = source.pop();
6926
+ if (event.ranges) {
6927
+ pushSelectionToHistory(event, dest);
6928
+ if (allowSelectionOnly && !event.equals(doc.sel)) {
6929
+ setSelection(doc, event, {clearRedo: false});
6930
+ return;
6931
+ }
6932
+ selAfter = event;
6933
+ }
6934
+ else break;
6935
+ }
6936
+
6937
+ // Build up a reverse change object to add to the opposite history
6938
+ // stack (redo when undoing, and vice versa).
6939
+ var antiChanges = [];
6940
+ pushSelectionToHistory(selAfter, dest);
6941
+ dest.push({changes: antiChanges, generation: hist.generation});
6942
+ hist.generation = event.generation || ++hist.maxGeneration;
6943
+
6944
+ var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
6945
+
6946
+ for (var i = event.changes.length - 1; i >= 0; --i) {
6947
+ var change = event.changes[i];
6948
+ change.origin = type;
6949
+ if (filter && !filterChange(doc, change, false)) {
6950
+ source.length = 0;
6951
+ return;
6952
+ }
6953
+
6954
+ antiChanges.push(historyChangeFromChange(doc, change));
6955
+
6956
+ var after = i ? computeSelAfterChange(doc, change) : lst(source);
6957
+ makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
6958
+ if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)});
6959
+ var rebased = [];
6960
+
6961
+ // Propagate to the linked documents
6962
+ linkedDocs(doc, function(doc, sharedHist) {
6963
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
6964
+ rebaseHist(doc.history, change);
6965
+ rebased.push(doc.history);
6966
+ }
6967
+ makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
6968
+ });
6969
+ }
6970
+ }
6971
+
6972
+ // Sub-views need their line numbers shifted when text is added
6973
+ // above or below them in the parent document.
6974
+ function shiftDoc(doc, distance) {
6975
+ if (distance == 0) return;
6976
+ doc.first += distance;
6977
+ doc.sel = new Selection(map(doc.sel.ranges, function(range) {
6978
+ return new Range(Pos(range.anchor.line + distance, range.anchor.ch),
6979
+ Pos(range.head.line + distance, range.head.ch));
6980
+ }), doc.sel.primIndex);
6981
+ if (doc.cm) {
6982
+ regChange(doc.cm, doc.first, doc.first - distance, distance);
6983
+ for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
6984
+ regLineChange(doc.cm, l, "gutter");
6985
+ }
6986
+ }
6987
+
6988
+ // More lower-level change function, handling only a single document
6989
+ // (not linked ones).
6990
+ function makeChangeSingleDoc(doc, change, selAfter, spans) {
6991
+ if (doc.cm && !doc.cm.curOp)
6992
+ return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans);
6993
+
6994
+ if (change.to.line < doc.first) {
6995
+ shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
6996
+ return;
6997
+ }
6998
+ if (change.from.line > doc.lastLine()) return;
6999
+
7000
+ // Clip the change to the size of this doc
7001
+ if (change.from.line < doc.first) {
7002
+ var shift = change.text.length - 1 - (doc.first - change.from.line);
7003
+ shiftDoc(doc, shift);
7004
+ change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
7005
+ text: [lst(change.text)], origin: change.origin};
7006
+ }
7007
+ var last = doc.lastLine();
7008
+ if (change.to.line > last) {
7009
+ change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
7010
+ text: [change.text[0]], origin: change.origin};
7011
+ }
7012
+
7013
+ change.removed = getBetween(doc, change.from, change.to);
7014
+
7015
+ if (!selAfter) selAfter = computeSelAfterChange(doc, change);
7016
+ if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans);
7017
+ else updateDoc(doc, change, spans);
7018
+ setSelectionNoUndo(doc, selAfter, sel_dontScroll);
7019
+ }
7020
+
7021
+ // Handle the interaction of a change to a document with the editor
7022
+ // that this document is part of.
7023
+ function makeChangeSingleDocInEditor(cm, change, spans) {
7024
+ var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
7025
+
7026
+ var recomputeMaxLength = false, checkWidthStart = from.line;
7027
+ if (!cm.options.lineWrapping) {
7028
+ checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));
7029
+ doc.iter(checkWidthStart, to.line + 1, function(line) {
7030
+ if (line == display.maxLine) {
7031
+ recomputeMaxLength = true;
7032
+ return true;
7033
+ }
7034
+ });
7035
+ }
7036
+
7037
+ if (doc.sel.contains(change.from, change.to) > -1)
7038
+ signalCursorActivity(cm);
7039
+
7040
+ updateDoc(doc, change, spans, estimateHeight(cm));
7041
+
7042
+ if (!cm.options.lineWrapping) {
7043
+ doc.iter(checkWidthStart, from.line + change.text.length, function(line) {
7044
+ var len = lineLength(line);
7045
+ if (len > display.maxLineLength) {
7046
+ display.maxLine = line;
7047
+ display.maxLineLength = len;
7048
+ display.maxLineChanged = true;
7049
+ recomputeMaxLength = false;
7050
+ }
7051
+ });
7052
+ if (recomputeMaxLength) cm.curOp.updateMaxLine = true;
7053
+ }
7054
+
7055
+ // Adjust frontier, schedule worker
7056
+ doc.frontier = Math.min(doc.frontier, from.line);
7057
+ startWorker(cm, 400);
7058
+
7059
+ var lendiff = change.text.length - (to.line - from.line) - 1;
7060
+ // Remember that these lines changed, for updating the display
7061
+ if (change.full)
7062
+ regChange(cm);
7063
+ else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
7064
+ regLineChange(cm, from.line, "text");
7065
+ else
7066
+ regChange(cm, from.line, to.line + 1, lendiff);
7067
+
7068
+ var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change");
7069
+ if (changeHandler || changesHandler) {
7070
+ var obj = {
7071
+ from: from, to: to,
7072
+ text: change.text,
7073
+ removed: change.removed,
7074
+ origin: change.origin
7075
+ };
7076
+ if (changeHandler) signalLater(cm, "change", cm, obj);
7077
+ if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj);
7078
+ }
7079
+ cm.display.selForContextMenu = null;
7080
+ }
7081
+
7082
+ function replaceRange(doc, code, from, to, origin) {
7083
+ if (!to) to = from;
7084
+ if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }
7085
+ if (typeof code == "string") code = doc.splitLines(code);
7086
+ makeChange(doc, {from: from, to: to, text: code, origin: origin});
7087
+ }
7088
+
7089
+ // SCROLLING THINGS INTO VIEW
7090
+
7091
+ // If an editor sits on the top or bottom of the window, partially
7092
+ // scrolled out of view, this ensures that the cursor is visible.
7093
+ function maybeScrollWindow(cm, coords) {
7094
+ if (signalDOMEvent(cm, "scrollCursorIntoView")) return;
7095
+
7096
+ var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
7097
+ if (coords.top + box.top < 0) doScroll = true;
7098
+ else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false;
7099
+ if (doScroll != null && !phantom) {
7100
+ var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " +
7101
+ (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " +
7102
+ (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " +
7103
+ coords.left + "px; width: 2px;");
7104
+ cm.display.lineSpace.appendChild(scrollNode);
7105
+ scrollNode.scrollIntoView(doScroll);
7106
+ cm.display.lineSpace.removeChild(scrollNode);
7107
+ }
7108
+ }
7109
+
7110
+ // Scroll a given position into view (immediately), verifying that
7111
+ // it actually became visible (as line heights are accurately
7112
+ // measured, the position of something may 'drift' during drawing).
7113
+ function scrollPosIntoView(cm, pos, end, margin) {
7114
+ if (margin == null) margin = 0;
7115
+ for (var limit = 0; limit < 5; limit++) {
7116
+ var changed = false, coords = cursorCoords(cm, pos);
7117
+ var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
7118
+ var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
7119
+ Math.min(coords.top, endCoords.top) - margin,
7120
+ Math.max(coords.left, endCoords.left),
7121
+ Math.max(coords.bottom, endCoords.bottom) + margin);
7122
+ var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
7123
+ if (scrollPos.scrollTop != null) {
7124
+ setScrollTop(cm, scrollPos.scrollTop);
7125
+ if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true;
7126
+ }
7127
+ if (scrollPos.scrollLeft != null) {
7128
+ setScrollLeft(cm, scrollPos.scrollLeft);
7129
+ if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true;
7130
+ }
7131
+ if (!changed) break;
7132
+ }
7133
+ return coords;
7134
+ }
7135
+
7136
+ // Scroll a given set of coordinates into view (immediately).
7137
+ function scrollIntoView(cm, x1, y1, x2, y2) {
7138
+ var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2);
7139
+ if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop);
7140
+ if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft);
7141
+ }
7142
+
7143
+ // Calculate a new scroll position needed to scroll the given
7144
+ // rectangle into view. Returns an object with scrollTop and
7145
+ // scrollLeft properties. When these are undefined, the
7146
+ // vertical/horizontal position does not need to be adjusted.
7147
+ function calculateScrollPos(cm, x1, y1, x2, y2) {
7148
+ var display = cm.display, snapMargin = textHeight(cm.display);
7149
+ if (y1 < 0) y1 = 0;
7150
+ var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
7151
+ var screen = displayHeight(cm), result = {};
7152
+ if (y2 - y1 > screen) y2 = y1 + screen;
7153
+ var docBottom = cm.doc.height + paddingVert(display);
7154
+ var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin;
7155
+ if (y1 < screentop) {
7156
+ result.scrollTop = atTop ? 0 : y1;
7157
+ } else if (y2 > screentop + screen) {
7158
+ var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen);
7159
+ if (newTop != screentop) result.scrollTop = newTop;
7160
+ }
7161
+
7162
+ var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
7163
+ var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
7164
+ var tooWide = x2 - x1 > screenw;
7165
+ if (tooWide) x2 = x1 + screenw;
7166
+ if (x1 < 10)
7167
+ result.scrollLeft = 0;
7168
+ else if (x1 < screenleft)
7169
+ result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10));
7170
+ else if (x2 > screenw + screenleft - 3)
7171
+ result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw;
7172
+ return result;
7173
+ }
7174
+
7175
+ // Store a relative adjustment to the scroll position in the current
7176
+ // operation (to be applied when the operation finishes).
7177
+ function addToScrollPos(cm, left, top) {
7178
+ if (left != null || top != null) resolveScrollToPos(cm);
7179
+ if (left != null)
7180
+ cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left;
7181
+ if (top != null)
7182
+ cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;
7183
+ }
7184
+
7185
+ // Make sure that at the end of the operation the current cursor is
7186
+ // shown.
7187
+ function ensureCursorVisible(cm) {
7188
+ resolveScrollToPos(cm);
7189
+ var cur = cm.getCursor(), from = cur, to = cur;
7190
+ if (!cm.options.lineWrapping) {
7191
+ from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur;
7192
+ to = Pos(cur.line, cur.ch + 1);
7193
+ }
7194
+ cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true};
7195
+ }
7196
+
7197
+ // When an operation has its scrollToPos property set, and another
7198
+ // scroll action is applied before the end of the operation, this
7199
+ // 'simulates' scrolling that position into view in a cheap way, so
7200
+ // that the effect of intermediate scroll commands is not ignored.
7201
+ function resolveScrollToPos(cm) {
7202
+ var range = cm.curOp.scrollToPos;
7203
+ if (range) {
7204
+ cm.curOp.scrollToPos = null;
7205
+ var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);
7206
+ var sPos = calculateScrollPos(cm, Math.min(from.left, to.left),
7207
+ Math.min(from.top, to.top) - range.margin,
7208
+ Math.max(from.right, to.right),
7209
+ Math.max(from.bottom, to.bottom) + range.margin);
7210
+ cm.scrollTo(sPos.scrollLeft, sPos.scrollTop);
7211
+ }
7212
+ }
7213
+
7214
+ // API UTILITIES
7215
+
7216
+ // Indent the given line. The how parameter can be "smart",
7217
+ // "add"/null, "subtract", or "prev". When aggressive is false
7218
+ // (typically set to true for forced single-line indents), empty
7219
+ // lines are not indented, and places where the mode returns Pass
7220
+ // are left alone.
7221
+ function indentLine(cm, n, how, aggressive) {
7222
+ var doc = cm.doc, state;
7223
+ if (how == null) how = "add";
7224
+ if (how == "smart") {
7225
+ // Fall back to "prev" when the mode doesn't have an indentation
7226
+ // method.
7227
+ if (!doc.mode.indent) how = "prev";
7228
+ else state = getStateBefore(cm, n);
7229
+ }
7230
+
7231
+ var tabSize = cm.options.tabSize;
7232
+ var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
7233
+ if (line.stateAfter) line.stateAfter = null;
7234
+ var curSpaceString = line.text.match(/^\s*/)[0], indentation;
7235
+ if (!aggressive && !/\S/.test(line.text)) {
7236
+ indentation = 0;
7237
+ how = "not";
7238
+ } else if (how == "smart") {
7239
+ indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
7240
+ if (indentation == Pass || indentation > 150) {
7241
+ if (!aggressive) return;
7242
+ how = "prev";
7243
+ }
7244
+ }
7245
+ if (how == "prev") {
7246
+ if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize);
7247
+ else indentation = 0;
7248
+ } else if (how == "add") {
7249
+ indentation = curSpace + cm.options.indentUnit;
7250
+ } else if (how == "subtract") {
7251
+ indentation = curSpace - cm.options.indentUnit;
7252
+ } else if (typeof how == "number") {
7253
+ indentation = curSpace + how;
7254
+ }
7255
+ indentation = Math.max(0, indentation);
7256
+
7257
+ var indentString = "", pos = 0;
7258
+ if (cm.options.indentWithTabs)
7259
+ for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";}
7260
+ if (pos < indentation) indentString += spaceStr(indentation - pos);
7261
+
7262
+ if (indentString != curSpaceString) {
7263
+ replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
7264
+ line.stateAfter = null;
7265
+ return true;
7266
+ } else {
7267
+ // Ensure that, if the cursor was in the whitespace at the start
7268
+ // of the line, it is moved to the end of that space.
7269
+ for (var i = 0; i < doc.sel.ranges.length; i++) {
7270
+ var range = doc.sel.ranges[i];
7271
+ if (range.head.line == n && range.head.ch < curSpaceString.length) {
7272
+ var pos = Pos(n, curSpaceString.length);
7273
+ replaceOneSelection(doc, i, new Range(pos, pos));
7274
+ break;
7275
+ }
7276
+ }
7277
+ }
7278
+ }
7279
+
7280
+ // Utility for applying a change to a line by handle or number,
7281
+ // returning the number and optionally registering the line as
7282
+ // changed.
7283
+ function changeLine(doc, handle, changeType, op) {
7284
+ var no = handle, line = handle;
7285
+ if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle));
7286
+ else no = lineNo(handle);
7287
+ if (no == null) return null;
7288
+ if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType);
7289
+ return line;
7290
+ }
7291
+
7292
+ // Helper for deleting text near the selection(s), used to implement
7293
+ // backspace, delete, and similar functionality.
7294
+ function deleteNearSelection(cm, compute) {
7295
+ var ranges = cm.doc.sel.ranges, kill = [];
7296
+ // Build up a set of ranges to kill first, merging overlapping
7297
+ // ranges.
7298
+ for (var i = 0; i < ranges.length; i++) {
7299
+ var toKill = compute(ranges[i]);
7300
+ while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
7301
+ var replaced = kill.pop();
7302
+ if (cmp(replaced.from, toKill.from) < 0) {
7303
+ toKill.from = replaced.from;
7304
+ break;
7305
+ }
7306
+ }
7307
+ kill.push(toKill);
7308
+ }
7309
+ // Next, remove those actual ranges.
7310
+ runInOp(cm, function() {
7311
+ for (var i = kill.length - 1; i >= 0; i--)
7312
+ replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete");
7313
+ ensureCursorVisible(cm);
7314
+ });
7315
+ }
7316
+
7317
+ // Used for horizontal relative motion. Dir is -1 or 1 (left or
7318
+ // right), unit can be "char", "column" (like char, but doesn't
7319
+ // cross line boundaries), "word" (across next word), or "group" (to
7320
+ // the start of next group of word or non-word-non-whitespace
7321
+ // chars). The visually param controls whether, in right-to-left
7322
+ // text, direction 1 means to move towards the next index in the
7323
+ // string, or towards the character to the right of the current
7324
+ // position. The resulting position will have a hitSide=true
7325
+ // property if it reached the end of the document.
7326
+ function findPosH(doc, pos, dir, unit, visually) {
7327
+ var line = pos.line, ch = pos.ch, origDir = dir;
7328
+ var lineObj = getLine(doc, line);
7329
+ var possible = true;
7330
+ function findNextLine() {
7331
+ var l = line + dir;
7332
+ if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
7333
+ line = l;
7334
+ return lineObj = getLine(doc, l);
7335
+ }
7336
+ function moveOnce(boundToLine) {
7337
+ var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true);
7338
+ if (next == null) {
7339
+ if (!boundToLine && findNextLine()) {
7340
+ if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
7341
+ else ch = dir < 0 ? lineObj.text.length : 0;
7342
+ } else return (possible = false);
7343
+ } else ch = next;
7344
+ return true;
7345
+ }
7346
+
7347
+ if (unit == "char") moveOnce();
7348
+ else if (unit == "column") moveOnce(true);
7349
+ else if (unit == "word" || unit == "group") {
7350
+ var sawType = null, group = unit == "group";
7351
+ var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
7352
+ for (var first = true;; first = false) {
7353
+ if (dir < 0 && !moveOnce(!first)) break;
7354
+ var cur = lineObj.text.charAt(ch) || "\n";
7355
+ var type = isWordChar(cur, helper) ? "w"
7356
+ : group && cur == "\n" ? "n"
7357
+ : !group || /\s/.test(cur) ? null
7358
+ : "p";
7359
+ if (group && !first && !type) type = "s";
7360
+ if (sawType && sawType != type) {
7361
+ if (dir < 0) {dir = 1; moveOnce();}
7362
+ break;
7363
+ }
7364
+
7365
+ if (type) sawType = type;
7366
+ if (dir > 0 && !moveOnce(!first)) break;
7367
+ }
7368
+ }
7369
+ var result = skipAtomic(doc, Pos(line, ch), origDir, true);
7370
+ if (!possible) result.hitSide = true;
7371
+ return result;
7372
+ }
7373
+
7374
+ // For relative vertical movement. Dir may be -1 or 1. Unit can be
7375
+ // "page" or "line". The resulting position will have a hitSide=true
7376
+ // property if it reached the end of the document.
7377
+ function findPosV(cm, pos, dir, unit) {
7378
+ var doc = cm.doc, x = pos.left, y;
7379
+ if (unit == "page") {
7380
+ var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
7381
+ y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display));
7382
+ } else if (unit == "line") {
7383
+ y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
7384
+ }
7385
+ for (;;) {
7386
+ var target = coordsChar(cm, x, y);
7387
+ if (!target.outside) break;
7388
+ if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; }
7389
+ y += dir * 5;
7390
+ }
7391
+ return target;
7392
+ }
7393
+
7394
+ // EDITOR METHODS
7395
+
7396
+ // The publicly visible API. Note that methodOp(f) means
7397
+ // 'wrap f in an operation, performed on its `this` parameter'.
7398
+
7399
+ // This is not the complete set of editor methods. Most of the
7400
+ // methods defined on the Doc type are also injected into
7401
+ // CodeMirror.prototype, for backwards compatibility and
7402
+ // convenience.
7403
+
7404
+ CodeMirror.prototype = {
7405
+ constructor: CodeMirror,
7406
+ focus: function(){window.focus(); this.display.input.focus();},
7407
+
7408
+ setOption: function(option, value) {
7409
+ var options = this.options, old = options[option];
7410
+ if (options[option] == value && option != "mode") return;
7411
+ options[option] = value;
7412
+ if (optionHandlers.hasOwnProperty(option))
7413
+ operation(this, optionHandlers[option])(this, value, old);
7414
+ },
7415
+
7416
+ getOption: function(option) {return this.options[option];},
7417
+ getDoc: function() {return this.doc;},
7418
+
7419
+ addKeyMap: function(map, bottom) {
7420
+ this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));
7421
+ },
7422
+ removeKeyMap: function(map) {
7423
+ var maps = this.state.keyMaps;
7424
+ for (var i = 0; i < maps.length; ++i)
7425
+ if (maps[i] == map || maps[i].name == map) {
7426
+ maps.splice(i, 1);
7427
+ return true;
7428
+ }
7429
+ },
7430
+
7431
+ addOverlay: methodOp(function(spec, options) {
7432
+ var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
7433
+ if (mode.startState) throw new Error("Overlays may not be stateful.");
7434
+ this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque});
7435
+ this.state.modeGen++;
7436
+ regChange(this);
7437
+ }),
7438
+ removeOverlay: methodOp(function(spec) {
7439
+ var overlays = this.state.overlays;
7440
+ for (var i = 0; i < overlays.length; ++i) {
7441
+ var cur = overlays[i].modeSpec;
7442
+ if (cur == spec || typeof spec == "string" && cur.name == spec) {
7443
+ overlays.splice(i, 1);
7444
+ this.state.modeGen++;
7445
+ regChange(this);
7446
+ return;
7447
+ }
7448
+ }
7449
+ }),
7450
+
7451
+ indentLine: methodOp(function(n, dir, aggressive) {
7452
+ if (typeof dir != "string" && typeof dir != "number") {
7453
+ if (dir == null) dir = this.options.smartIndent ? "smart" : "prev";
7454
+ else dir = dir ? "add" : "subtract";
7455
+ }
7456
+ if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive);
7457
+ }),
7458
+ indentSelection: methodOp(function(how) {
7459
+ var ranges = this.doc.sel.ranges, end = -1;
7460
+ for (var i = 0; i < ranges.length; i++) {
7461
+ var range = ranges[i];
7462
+ if (!range.empty()) {
7463
+ var from = range.from(), to = range.to();
7464
+ var start = Math.max(end, from.line);
7465
+ end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
7466
+ for (var j = start; j < end; ++j)
7467
+ indentLine(this, j, how);
7468
+ var newRanges = this.doc.sel.ranges;
7469
+ if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
7470
+ replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll);
7471
+ } else if (range.head.line > end) {
7472
+ indentLine(this, range.head.line, how, true);
7473
+ end = range.head.line;
7474
+ if (i == this.doc.sel.primIndex) ensureCursorVisible(this);
7475
+ }
7476
+ }
7477
+ }),
7478
+
7479
+ // Fetch the parser token for a given character. Useful for hacks
7480
+ // that want to inspect the mode state (say, for completion).
7481
+ getTokenAt: function(pos, precise) {
7482
+ return takeToken(this, pos, precise);
7483
+ },
7484
+
7485
+ getLineTokens: function(line, precise) {
7486
+ return takeToken(this, Pos(line), precise, true);
7487
+ },
7488
+
7489
+ getTokenTypeAt: function(pos) {
7490
+ pos = clipPos(this.doc, pos);
7491
+ var styles = getLineStyles(this, getLine(this.doc, pos.line));
7492
+ var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
7493
+ var type;
7494
+ if (ch == 0) type = styles[2];
7495
+ else for (;;) {
7496
+ var mid = (before + after) >> 1;
7497
+ if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid;
7498
+ else if (styles[mid * 2 + 1] < ch) before = mid + 1;
7499
+ else { type = styles[mid * 2 + 2]; break; }
7500
+ }
7501
+ var cut = type ? type.indexOf("cm-overlay ") : -1;
7502
+ return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1);
7503
+ },
7504
+
7505
+ getModeAt: function(pos) {
7506
+ var mode = this.doc.mode;
7507
+ if (!mode.innerMode) return mode;
7508
+ return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode;
7509
+ },
7510
+
7511
+ getHelper: function(pos, type) {
7512
+ return this.getHelpers(pos, type)[0];
7513
+ },
7514
+
7515
+ getHelpers: function(pos, type) {
7516
+ var found = [];
7517
+ if (!helpers.hasOwnProperty(type)) return found;
7518
+ var help = helpers[type], mode = this.getModeAt(pos);
7519
+ if (typeof mode[type] == "string") {
7520
+ if (help[mode[type]]) found.push(help[mode[type]]);
7521
+ } else if (mode[type]) {
7522
+ for (var i = 0; i < mode[type].length; i++) {
7523
+ var val = help[mode[type][i]];
7524
+ if (val) found.push(val);
7525
+ }
7526
+ } else if (mode.helperType && help[mode.helperType]) {
7527
+ found.push(help[mode.helperType]);
7528
+ } else if (help[mode.name]) {
7529
+ found.push(help[mode.name]);
7530
+ }
7531
+ for (var i = 0; i < help._global.length; i++) {
7532
+ var cur = help._global[i];
7533
+ if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
7534
+ found.push(cur.val);
7535
+ }
7536
+ return found;
7537
+ },
7538
+
7539
+ getStateAfter: function(line, precise) {
7540
+ var doc = this.doc;
7541
+ line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
7542
+ return getStateBefore(this, line + 1, precise);
7543
+ },
7544
+
7545
+ cursorCoords: function(start, mode) {
7546
+ var pos, range = this.doc.sel.primary();
7547
+ if (start == null) pos = range.head;
7548
+ else if (typeof start == "object") pos = clipPos(this.doc, start);
7549
+ else pos = start ? range.from() : range.to();
7550
+ return cursorCoords(this, pos, mode || "page");
7551
+ },
7552
+
7553
+ charCoords: function(pos, mode) {
7554
+ return charCoords(this, clipPos(this.doc, pos), mode || "page");
7555
+ },
7556
+
7557
+ coordsChar: function(coords, mode) {
7558
+ coords = fromCoordSystem(this, coords, mode || "page");
7559
+ return coordsChar(this, coords.left, coords.top);
7560
+ },
7561
+
7562
+ lineAtHeight: function(height, mode) {
7563
+ height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
7564
+ return lineAtHeight(this.doc, height + this.display.viewOffset);
7565
+ },
7566
+ heightAtLine: function(line, mode) {
7567
+ var end = false, lineObj;
7568
+ if (typeof line == "number") {
7569
+ var last = this.doc.first + this.doc.size - 1;
7570
+ if (line < this.doc.first) line = this.doc.first;
7571
+ else if (line > last) { line = last; end = true; }
7572
+ lineObj = getLine(this.doc, line);
7573
+ } else {
7574
+ lineObj = line;
7575
+ }
7576
+ return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top +
7577
+ (end ? this.doc.height - heightAtLine(lineObj) : 0);
7578
+ },
7579
+
7580
+ defaultTextHeight: function() { return textHeight(this.display); },
7581
+ defaultCharWidth: function() { return charWidth(this.display); },
7582
+
7583
+ setGutterMarker: methodOp(function(line, gutterID, value) {
7584
+ return changeLine(this.doc, line, "gutter", function(line) {
7585
+ var markers = line.gutterMarkers || (line.gutterMarkers = {});
7586
+ markers[gutterID] = value;
7587
+ if (!value && isEmpty(markers)) line.gutterMarkers = null;
7588
+ return true;
7589
+ });
7590
+ }),
7591
+
7592
+ clearGutter: methodOp(function(gutterID) {
7593
+ var cm = this, doc = cm.doc, i = doc.first;
7594
+ doc.iter(function(line) {
7595
+ if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
7596
+ line.gutterMarkers[gutterID] = null;
7597
+ regLineChange(cm, i, "gutter");
7598
+ if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null;
7599
+ }
7600
+ ++i;
7601
+ });
7602
+ }),
7603
+
7604
+ lineInfo: function(line) {
7605
+ if (typeof line == "number") {
7606
+ if (!isLine(this.doc, line)) return null;
7607
+ var n = line;
7608
+ line = getLine(this.doc, line);
7609
+ if (!line) return null;
7610
+ } else {
7611
+ var n = lineNo(line);
7612
+ if (n == null) return null;
7613
+ }
7614
+ return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
7615
+ textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
7616
+ widgets: line.widgets};
7617
+ },
7618
+
7619
+ getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};},
7620
+
7621
+ addWidget: function(pos, node, scroll, vert, horiz) {
7622
+ var display = this.display;
7623
+ pos = cursorCoords(this, clipPos(this.doc, pos));
7624
+ var top = pos.bottom, left = pos.left;
7625
+ node.style.position = "absolute";
7626
+ node.setAttribute("cm-ignore-events", "true");
7627
+ this.display.input.setUneditable(node);
7628
+ display.sizer.appendChild(node);
7629
+ if (vert == "over") {
7630
+ top = pos.top;
7631
+ } else if (vert == "above" || vert == "near") {
7632
+ var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
7633
+ hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
7634
+ // Default to positioning above (if specified and possible); otherwise default to positioning below
7635
+ if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
7636
+ top = pos.top - node.offsetHeight;
7637
+ else if (pos.bottom + node.offsetHeight <= vspace)
7638
+ top = pos.bottom;
7639
+ if (left + node.offsetWidth > hspace)
7640
+ left = hspace - node.offsetWidth;
7641
+ }
7642
+ node.style.top = top + "px";
7643
+ node.style.left = node.style.right = "";
7644
+ if (horiz == "right") {
7645
+ left = display.sizer.clientWidth - node.offsetWidth;
7646
+ node.style.right = "0px";
7647
+ } else {
7648
+ if (horiz == "left") left = 0;
7649
+ else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2;
7650
+ node.style.left = left + "px";
7651
+ }
7652
+ if (scroll)
7653
+ scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight);
7654
+ },
7655
+
7656
+ triggerOnKeyDown: methodOp(onKeyDown),
7657
+ triggerOnKeyPress: methodOp(onKeyPress),
7658
+ triggerOnKeyUp: onKeyUp,
7659
+
7660
+ execCommand: function(cmd) {
7661
+ if (commands.hasOwnProperty(cmd))
7662
+ return commands[cmd].call(null, this);
7663
+ },
7664
+
7665
+ triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),
7666
+
7667
+ findPosH: function(from, amount, unit, visually) {
7668
+ var dir = 1;
7669
+ if (amount < 0) { dir = -1; amount = -amount; }
7670
+ for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
7671
+ cur = findPosH(this.doc, cur, dir, unit, visually);
7672
+ if (cur.hitSide) break;
7673
+ }
7674
+ return cur;
7675
+ },
7676
+
7677
+ moveH: methodOp(function(dir, unit) {
7678
+ var cm = this;
7679
+ cm.extendSelectionsBy(function(range) {
7680
+ if (cm.display.shift || cm.doc.extend || range.empty())
7681
+ return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually);
7682
+ else
7683
+ return dir < 0 ? range.from() : range.to();
7684
+ }, sel_move);
7685
+ }),
7686
+
7687
+ deleteH: methodOp(function(dir, unit) {
7688
+ var sel = this.doc.sel, doc = this.doc;
7689
+ if (sel.somethingSelected())
7690
+ doc.replaceSelection("", null, "+delete");
7691
+ else
7692
+ deleteNearSelection(this, function(range) {
7693
+ var other = findPosH(doc, range.head, dir, unit, false);
7694
+ return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other};
7695
+ });
7696
+ }),
7697
+
7698
+ findPosV: function(from, amount, unit, goalColumn) {
7699
+ var dir = 1, x = goalColumn;
7700
+ if (amount < 0) { dir = -1; amount = -amount; }
7701
+ for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) {
7702
+ var coords = cursorCoords(this, cur, "div");
7703
+ if (x == null) x = coords.left;
7704
+ else coords.left = x;
7705
+ cur = findPosV(this, coords, dir, unit);
7706
+ if (cur.hitSide) break;
7707
+ }
7708
+ return cur;
7709
+ },
7710
+
7711
+ moveV: methodOp(function(dir, unit) {
7712
+ var cm = this, doc = this.doc, goals = [];
7713
+ var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected();
7714
+ doc.extendSelectionsBy(function(range) {
7715
+ if (collapse)
7716
+ return dir < 0 ? range.from() : range.to();
7717
+ var headPos = cursorCoords(cm, range.head, "div");
7718
+ if (range.goalColumn != null) headPos.left = range.goalColumn;
7719
+ goals.push(headPos.left);
7720
+ var pos = findPosV(cm, headPos, dir, unit);
7721
+ if (unit == "page" && range == doc.sel.primary())
7722
+ addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top);
7723
+ return pos;
7724
+ }, sel_move);
7725
+ if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++)
7726
+ doc.sel.ranges[i].goalColumn = goals[i];
7727
+ }),
7728
+
7729
+ // Find the word at the given position (as returned by coordsChar).
7730
+ findWordAt: function(pos) {
7731
+ var doc = this.doc, line = getLine(doc, pos.line).text;
7732
+ var start = pos.ch, end = pos.ch;
7733
+ if (line) {
7734
+ var helper = this.getHelper(pos, "wordChars");
7735
+ if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end;
7736
+ var startChar = line.charAt(start);
7737
+ var check = isWordChar(startChar, helper)
7738
+ ? function(ch) { return isWordChar(ch, helper); }
7739
+ : /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);}
7740
+ : function(ch) {return !/\s/.test(ch) && !isWordChar(ch);};
7741
+ while (start > 0 && check(line.charAt(start - 1))) --start;
7742
+ while (end < line.length && check(line.charAt(end))) ++end;
7743
+ }
7744
+ return new Range(Pos(pos.line, start), Pos(pos.line, end));
7745
+ },
7746
+
7747
+ toggleOverwrite: function(value) {
7748
+ if (value != null && value == this.state.overwrite) return;
7749
+ if (this.state.overwrite = !this.state.overwrite)
7750
+ addClass(this.display.cursorDiv, "CodeMirror-overwrite");
7751
+ else
7752
+ rmClass(this.display.cursorDiv, "CodeMirror-overwrite");
7753
+
7754
+ signal(this, "overwriteToggle", this, this.state.overwrite);
7755
+ },
7756
+ hasFocus: function() { return this.display.input.getField() == activeElt(); },
7757
+
7758
+ scrollTo: methodOp(function(x, y) {
7759
+ if (x != null || y != null) resolveScrollToPos(this);
7760
+ if (x != null) this.curOp.scrollLeft = x;
7761
+ if (y != null) this.curOp.scrollTop = y;
7762
+ }),
7763
+ getScrollInfo: function() {
7764
+ var scroller = this.display.scroller;
7765
+ return {left: scroller.scrollLeft, top: scroller.scrollTop,
7766
+ height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
7767
+ width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
7768
+ clientHeight: displayHeight(this), clientWidth: displayWidth(this)};
7769
+ },
7770
+
7771
+ scrollIntoView: methodOp(function(range, margin) {
7772
+ if (range == null) {
7773
+ range = {from: this.doc.sel.primary().head, to: null};
7774
+ if (margin == null) margin = this.options.cursorScrollMargin;
7775
+ } else if (typeof range == "number") {
7776
+ range = {from: Pos(range, 0), to: null};
7777
+ } else if (range.from == null) {
7778
+ range = {from: range, to: null};
7779
+ }
7780
+ if (!range.to) range.to = range.from;
7781
+ range.margin = margin || 0;
7782
+
7783
+ if (range.from.line != null) {
7784
+ resolveScrollToPos(this);
7785
+ this.curOp.scrollToPos = range;
7786
+ } else {
7787
+ var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left),
7788
+ Math.min(range.from.top, range.to.top) - range.margin,
7789
+ Math.max(range.from.right, range.to.right),
7790
+ Math.max(range.from.bottom, range.to.bottom) + range.margin);
7791
+ this.scrollTo(sPos.scrollLeft, sPos.scrollTop);
7792
+ }
7793
+ }),
7794
+
7795
+ setSize: methodOp(function(width, height) {
7796
+ var cm = this;
7797
+ function interpret(val) {
7798
+ return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val;
7799
+ }
7800
+ if (width != null) cm.display.wrapper.style.width = interpret(width);
7801
+ if (height != null) cm.display.wrapper.style.height = interpret(height);
7802
+ if (cm.options.lineWrapping) clearLineMeasurementCache(this);
7803
+ var lineNo = cm.display.viewFrom;
7804
+ cm.doc.iter(lineNo, cm.display.viewTo, function(line) {
7805
+ if (line.widgets) for (var i = 0; i < line.widgets.length; i++)
7806
+ if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, "widget"); break; }
7807
+ ++lineNo;
7808
+ });
7809
+ cm.curOp.forceUpdate = true;
7810
+ signal(cm, "refresh", this);
7811
+ }),
7812
+
7813
+ operation: function(f){return runInOp(this, f);},
7814
+
7815
+ refresh: methodOp(function() {
7816
+ var oldHeight = this.display.cachedTextHeight;
7817
+ regChange(this);
7818
+ this.curOp.forceUpdate = true;
7819
+ clearCaches(this);
7820
+ this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop);
7821
+ updateGutterSpace(this);
7822
+ if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
7823
+ estimateLineHeights(this);
7824
+ signal(this, "refresh", this);
7825
+ }),
7826
+
7827
+ swapDoc: methodOp(function(doc) {
7828
+ var old = this.doc;
7829
+ old.cm = null;
7830
+ attachDoc(this, doc);
7831
+ clearCaches(this);
7832
+ this.display.input.reset();
7833
+ this.scrollTo(doc.scrollLeft, doc.scrollTop);
7834
+ this.curOp.forceScroll = true;
7835
+ signalLater(this, "swapDoc", this, old);
7836
+ return old;
7837
+ }),
7838
+
7839
+ getInputField: function(){return this.display.input.getField();},
7840
+ getWrapperElement: function(){return this.display.wrapper;},
7841
+ getScrollerElement: function(){return this.display.scroller;},
7842
+ getGutterElement: function(){return this.display.gutters;}
7843
+ };
7844
+ eventMixin(CodeMirror);
7845
+
7846
+ // OPTION DEFAULTS
7847
+
7848
+ // The default configuration options.
7849
+ var defaults = CodeMirror.defaults = {};
7850
+ // Functions to run when options are changed.
7851
+ var optionHandlers = CodeMirror.optionHandlers = {};
7852
+
7853
+ function option(name, deflt, handle, notOnInit) {
7854
+ CodeMirror.defaults[name] = deflt;
7855
+ if (handle) optionHandlers[name] =
7856
+ notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle;
7857
+ }
7858
+
7859
+ // Passed to option handlers when there is no old value.
7860
+ var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}};
7861
+
7862
+ // These two are, on init, called from the constructor because they
7863
+ // have to be initialized before the editor can start at all.
7864
+ option("value", "", function(cm, val) {
7865
+ cm.setValue(val);
7866
+ }, true);
7867
+ option("mode", null, function(cm, val) {
7868
+ cm.doc.modeOption = val;
7869
+ loadMode(cm);
7870
+ }, true);
7871
+
7872
+ option("indentUnit", 2, loadMode, true);
7873
+ option("indentWithTabs", false);
7874
+ option("smartIndent", true);
7875
+ option("tabSize", 4, function(cm) {
7876
+ resetModeState(cm);
7877
+ clearCaches(cm);
7878
+ regChange(cm);
7879
+ }, true);
7880
+ option("lineSeparator", null, function(cm, val) {
7881
+ cm.doc.lineSep = val;
7882
+ if (!val) return;
7883
+ var newBreaks = [], lineNo = cm.doc.first;
7884
+ cm.doc.iter(function(line) {
7885
+ for (var pos = 0;;) {
7886
+ var found = line.text.indexOf(val, pos);
7887
+ if (found == -1) break;
7888
+ pos = found + val.length;
7889
+ newBreaks.push(Pos(lineNo, found));
7890
+ }
7891
+ lineNo++;
7892
+ });
7893
+ for (var i = newBreaks.length - 1; i >= 0; i--)
7894
+ replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length))
7895
+ });
7896
+ option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) {
7897
+ cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
7898
+ if (old != CodeMirror.Init) cm.refresh();
7899
+ });
7900
+ option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true);
7901
+ option("electricChars", true);
7902
+ option("inputStyle", mobile ? "contenteditable" : "textarea", function() {
7903
+ throw new Error("inputStyle can not (yet) be changed in a running editor"); // FIXME
7904
+ }, true);
7905
+ option("rtlMoveVisually", !windows);
7906
+ option("wholeLineUpdateBefore", true);
7907
+
7908
+ option("theme", "default", function(cm) {
7909
+ themeChanged(cm);
7910
+ guttersChanged(cm);
7911
+ }, true);
7912
+ option("keyMap", "default", function(cm, val, old) {
7913
+ var next = getKeyMap(val);
7914
+ var prev = old != CodeMirror.Init && getKeyMap(old);
7915
+ if (prev && prev.detach) prev.detach(cm, next);
7916
+ if (next.attach) next.attach(cm, prev || null);
7917
+ });
7918
+ option("extraKeys", null);
7919
+
7920
+ option("lineWrapping", false, wrappingChanged, true);
7921
+ option("gutters", [], function(cm) {
7922
+ setGuttersForLineNumbers(cm.options);
7923
+ guttersChanged(cm);
7924
+ }, true);
7925
+ option("fixedGutter", true, function(cm, val) {
7926
+ cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
7927
+ cm.refresh();
7928
+ }, true);
7929
+ option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true);
7930
+ option("scrollbarStyle", "native", function(cm) {
7931
+ initScrollbars(cm);
7932
+ updateScrollbars(cm);
7933
+ cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);
7934
+ cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);
7935
+ }, true);
7936
+ option("lineNumbers", false, function(cm) {
7937
+ setGuttersForLineNumbers(cm.options);
7938
+ guttersChanged(cm);
7939
+ }, true);
7940
+ option("firstLineNumber", 1, guttersChanged, true);
7941
+ option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true);
7942
+ option("showCursorWhenSelecting", false, updateSelection, true);
7943
+
7944
+ option("resetSelectionOnContextMenu", true);
7945
+ option("lineWiseCopyCut", true);
7946
+
7947
+ option("readOnly", false, function(cm, val) {
7948
+ if (val == "nocursor") {
7949
+ onBlur(cm);
7950
+ cm.display.input.blur();
7951
+ cm.display.disabled = true;
7952
+ } else {
7953
+ cm.display.disabled = false;
7954
+ }
7955
+ cm.display.input.readOnlyChanged(val)
7956
+ });
7957
+ option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);
7958
+ option("dragDrop", true, dragDropChanged);
7959
+ option("allowDropFileTypes", null);
7960
+
7961
+ option("cursorBlinkRate", 530);
7962
+ option("cursorScrollMargin", 0);
7963
+ option("cursorHeight", 1, updateSelection, true);
7964
+ option("singleCursorHeightPerLine", true, updateSelection, true);
7965
+ option("workTime", 100);
7966
+ option("workDelay", 100);
7967
+ option("flattenSpans", true, resetModeState, true);
7968
+ option("addModeClass", false, resetModeState, true);
7969
+ option("pollInterval", 100);
7970
+ option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;});
7971
+ option("historyEventDelay", 1250);
7972
+ option("viewportMargin", 10, function(cm){cm.refresh();}, true);
7973
+ option("maxHighlightLength", 10000, resetModeState, true);
7974
+ option("moveInputWithCursor", true, function(cm, val) {
7975
+ if (!val) cm.display.input.resetPosition();
7976
+ });
7977
+
7978
+ option("tabindex", null, function(cm, val) {
7979
+ cm.display.input.getField().tabIndex = val || "";
7980
+ });
7981
+ option("autofocus", null);
7982
+
7983
+ // MODE DEFINITION AND QUERYING
7984
+
7985
+ // Known modes, by name and by MIME
7986
+ var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
7987
+
7988
+ // Extra arguments are stored as the mode's dependencies, which is
7989
+ // used by (legacy) mechanisms like loadmode.js to automatically
7990
+ // load a mode. (Preferred mechanism is the require/define calls.)
7991
+ CodeMirror.defineMode = function(name, mode) {
7992
+ if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
7993
+ if (arguments.length > 2)
7994
+ mode.dependencies = Array.prototype.slice.call(arguments, 2);
7995
+ modes[name] = mode;
7996
+ };
7997
+
7998
+ CodeMirror.defineMIME = function(mime, spec) {
7999
+ mimeModes[mime] = spec;
8000
+ };
8001
+
8002
+ // Given a MIME type, a {name, ...options} config object, or a name
8003
+ // string, return a mode config object.
8004
+ CodeMirror.resolveMode = function(spec) {
8005
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
8006
+ spec = mimeModes[spec];
8007
+ } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
8008
+ var found = mimeModes[spec.name];
8009
+ if (typeof found == "string") found = {name: found};
8010
+ spec = createObj(found, spec);
8011
+ spec.name = found.name;
8012
+ } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
8013
+ return CodeMirror.resolveMode("application/xml");
8014
+ }
8015
+ if (typeof spec == "string") return {name: spec};
8016
+ else return spec || {name: "null"};
8017
+ };
8018
+
8019
+ // Given a mode spec (anything that resolveMode accepts), find and
8020
+ // initialize an actual mode object.
8021
+ CodeMirror.getMode = function(options, spec) {
8022
+ var spec = CodeMirror.resolveMode(spec);
8023
+ var mfactory = modes[spec.name];
8024
+ if (!mfactory) return CodeMirror.getMode(options, "text/plain");
8025
+ var modeObj = mfactory(options, spec);
8026
+ if (modeExtensions.hasOwnProperty(spec.name)) {
8027
+ var exts = modeExtensions[spec.name];
8028
+ for (var prop in exts) {
8029
+ if (!exts.hasOwnProperty(prop)) continue;
8030
+ if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
8031
+ modeObj[prop] = exts[prop];
8032
+ }
8033
+ }
8034
+ modeObj.name = spec.name;
8035
+ if (spec.helperType) modeObj.helperType = spec.helperType;
8036
+ if (spec.modeProps) for (var prop in spec.modeProps)
8037
+ modeObj[prop] = spec.modeProps[prop];
8038
+
8039
+ return modeObj;
8040
+ };
8041
+
8042
+ // Minimal default mode.
8043
+ CodeMirror.defineMode("null", function() {
8044
+ return {token: function(stream) {stream.skipToEnd();}};
8045
+ });
8046
+ CodeMirror.defineMIME("text/plain", "null");
8047
+
8048
+ // This can be used to attach properties to mode objects from
8049
+ // outside the actual mode definition.
8050
+ var modeExtensions = CodeMirror.modeExtensions = {};
8051
+ CodeMirror.extendMode = function(mode, properties) {
8052
+ var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
8053
+ copyObj(properties, exts);
8054
+ };
8055
+
8056
+ // EXTENSIONS
8057
+
8058
+ CodeMirror.defineExtension = function(name, func) {
8059
+ CodeMirror.prototype[name] = func;
8060
+ };
8061
+ CodeMirror.defineDocExtension = function(name, func) {
8062
+ Doc.prototype[name] = func;
8063
+ };
8064
+ CodeMirror.defineOption = option;
8065
+
8066
+ var initHooks = [];
8067
+ CodeMirror.defineInitHook = function(f) {initHooks.push(f);};
8068
+
8069
+ var helpers = CodeMirror.helpers = {};
8070
+ CodeMirror.registerHelper = function(type, name, value) {
8071
+ if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []};
8072
+ helpers[type][name] = value;
8073
+ };
8074
+ CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
8075
+ CodeMirror.registerHelper(type, name, value);
8076
+ helpers[type]._global.push({pred: predicate, val: value});
8077
+ };
8078
+
8079
+ // MODE STATE HANDLING
8080
+
8081
+ // Utility functions for working with state. Exported because nested
8082
+ // modes need to do this for their inner modes.
8083
+
8084
+ var copyState = CodeMirror.copyState = function(mode, state) {
8085
+ if (state === true) return state;
8086
+ if (mode.copyState) return mode.copyState(state);
8087
+ var nstate = {};
8088
+ for (var n in state) {
8089
+ var val = state[n];
8090
+ if (val instanceof Array) val = val.concat([]);
8091
+ nstate[n] = val;
8092
+ }
8093
+ return nstate;
8094
+ };
8095
+
8096
+ var startState = CodeMirror.startState = function(mode, a1, a2) {
8097
+ return mode.startState ? mode.startState(a1, a2) : true;
8098
+ };
8099
+
8100
+ // Given a mode and a state (for that mode), find the inner mode and
8101
+ // state at the position that the state refers to.
8102
+ CodeMirror.innerMode = function(mode, state) {
8103
+ while (mode.innerMode) {
8104
+ var info = mode.innerMode(state);
8105
+ if (!info || info.mode == mode) break;
8106
+ state = info.state;
8107
+ mode = info.mode;
8108
+ }
8109
+ return info || {mode: mode, state: state};
8110
+ };
8111
+
8112
+ // STANDARD COMMANDS
8113
+
8114
+ // Commands are parameter-less actions that can be performed on an
8115
+ // editor, mostly used for keybindings.
8116
+ var commands = CodeMirror.commands = {
8117
+ selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);},
8118
+ singleSelection: function(cm) {
8119
+ cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll);
8120
+ },
8121
+ killLine: function(cm) {
8122
+ deleteNearSelection(cm, function(range) {
8123
+ if (range.empty()) {
8124
+ var len = getLine(cm.doc, range.head.line).text.length;
8125
+ if (range.head.ch == len && range.head.line < cm.lastLine())
8126
+ return {from: range.head, to: Pos(range.head.line + 1, 0)};
8127
+ else
8128
+ return {from: range.head, to: Pos(range.head.line, len)};
8129
+ } else {
8130
+ return {from: range.from(), to: range.to()};
8131
+ }
8132
+ });
8133
+ },
8134
+ deleteLine: function(cm) {
8135
+ deleteNearSelection(cm, function(range) {
8136
+ return {from: Pos(range.from().line, 0),
8137
+ to: clipPos(cm.doc, Pos(range.to().line + 1, 0))};
8138
+ });
8139
+ },
8140
+ delLineLeft: function(cm) {
8141
+ deleteNearSelection(cm, function(range) {
8142
+ return {from: Pos(range.from().line, 0), to: range.from()};
8143
+ });
8144
+ },
8145
+ delWrappedLineLeft: function(cm) {
8146
+ deleteNearSelection(cm, function(range) {
8147
+ var top = cm.charCoords(range.head, "div").top + 5;
8148
+ var leftPos = cm.coordsChar({left: 0, top: top}, "div");
8149
+ return {from: leftPos, to: range.from()};
8150
+ });
8151
+ },
8152
+ delWrappedLineRight: function(cm) {
8153
+ deleteNearSelection(cm, function(range) {
8154
+ var top = cm.charCoords(range.head, "div").top + 5;
8155
+ var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
8156
+ return {from: range.from(), to: rightPos };
8157
+ });
8158
+ },
8159
+ undo: function(cm) {cm.undo();},
8160
+ redo: function(cm) {cm.redo();},
8161
+ undoSelection: function(cm) {cm.undoSelection();},
8162
+ redoSelection: function(cm) {cm.redoSelection();},
8163
+ goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));},
8164
+ goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));},
8165
+ goLineStart: function(cm) {
8166
+ cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); },
8167
+ {origin: "+move", bias: 1});
8168
+ },
8169
+ goLineStartSmart: function(cm) {
8170
+ cm.extendSelectionsBy(function(range) {
8171
+ return lineStartSmart(cm, range.head);
8172
+ }, {origin: "+move", bias: 1});
8173
+ },
8174
+ goLineEnd: function(cm) {
8175
+ cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); },
8176
+ {origin: "+move", bias: -1});
8177
+ },
8178
+ goLineRight: function(cm) {
8179
+ cm.extendSelectionsBy(function(range) {
8180
+ var top = cm.charCoords(range.head, "div").top + 5;
8181
+ return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
8182
+ }, sel_move);
8183
+ },
8184
+ goLineLeft: function(cm) {
8185
+ cm.extendSelectionsBy(function(range) {
8186
+ var top = cm.charCoords(range.head, "div").top + 5;
8187
+ return cm.coordsChar({left: 0, top: top}, "div");
8188
+ }, sel_move);
8189
+ },
8190
+ goLineLeftSmart: function(cm) {
8191
+ cm.extendSelectionsBy(function(range) {
8192
+ var top = cm.charCoords(range.head, "div").top + 5;
8193
+ var pos = cm.coordsChar({left: 0, top: top}, "div");
8194
+ if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head);
8195
+ return pos;
8196
+ }, sel_move);
8197
+ },
8198
+ goLineUp: function(cm) {cm.moveV(-1, "line");},
8199
+ goLineDown: function(cm) {cm.moveV(1, "line");},
8200
+ goPageUp: function(cm) {cm.moveV(-1, "page");},
8201
+ goPageDown: function(cm) {cm.moveV(1, "page");},
8202
+ goCharLeft: function(cm) {cm.moveH(-1, "char");},
8203
+ goCharRight: function(cm) {cm.moveH(1, "char");},
8204
+ goColumnLeft: function(cm) {cm.moveH(-1, "column");},
8205
+ goColumnRight: function(cm) {cm.moveH(1, "column");},
8206
+ goWordLeft: function(cm) {cm.moveH(-1, "word");},
8207
+ goGroupRight: function(cm) {cm.moveH(1, "group");},
8208
+ goGroupLeft: function(cm) {cm.moveH(-1, "group");},
8209
+ goWordRight: function(cm) {cm.moveH(1, "word");},
8210
+ delCharBefore: function(cm) {cm.deleteH(-1, "char");},
8211
+ delCharAfter: function(cm) {cm.deleteH(1, "char");},
8212
+ delWordBefore: function(cm) {cm.deleteH(-1, "word");},
8213
+ delWordAfter: function(cm) {cm.deleteH(1, "word");},
8214
+ delGroupBefore: function(cm) {cm.deleteH(-1, "group");},
8215
+ delGroupAfter: function(cm) {cm.deleteH(1, "group");},
8216
+ indentAuto: function(cm) {cm.indentSelection("smart");},
8217
+ indentMore: function(cm) {cm.indentSelection("add");},
8218
+ indentLess: function(cm) {cm.indentSelection("subtract");},
8219
+ insertTab: function(cm) {cm.replaceSelection("\t");},
8220
+ insertSoftTab: function(cm) {
8221
+ var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;
8222
+ for (var i = 0; i < ranges.length; i++) {
8223
+ var pos = ranges[i].from();
8224
+ var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);
8225
+ spaces.push(new Array(tabSize - col % tabSize + 1).join(" "));
8226
+ }
8227
+ cm.replaceSelections(spaces);
8228
+ },
8229
+ defaultTab: function(cm) {
8230
+ if (cm.somethingSelected()) cm.indentSelection("add");
8231
+ else cm.execCommand("insertTab");
8232
+ },
8233
+ transposeChars: function(cm) {
8234
+ runInOp(cm, function() {
8235
+ var ranges = cm.listSelections(), newSel = [];
8236
+ for (var i = 0; i < ranges.length; i++) {
8237
+ var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
8238
+ if (line) {
8239
+ if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1);
8240
+ if (cur.ch > 0) {
8241
+ cur = new Pos(cur.line, cur.ch + 1);
8242
+ cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
8243
+ Pos(cur.line, cur.ch - 2), cur, "+transpose");
8244
+ } else if (cur.line > cm.doc.first) {
8245
+ var prev = getLine(cm.doc, cur.line - 1).text;
8246
+ if (prev)
8247
+ cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
8248
+ prev.charAt(prev.length - 1),
8249
+ Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose");
8250
+ }
8251
+ }
8252
+ newSel.push(new Range(cur, cur));
8253
+ }
8254
+ cm.setSelections(newSel);
8255
+ });
8256
+ },
8257
+ newlineAndIndent: function(cm) {
8258
+ runInOp(cm, function() {
8259
+ var len = cm.listSelections().length;
8260
+ for (var i = 0; i < len; i++) {
8261
+ var range = cm.listSelections()[i];
8262
+ cm.replaceRange(cm.doc.lineSeparator(), range.anchor, range.head, "+input");
8263
+ cm.indentLine(range.from().line + 1, null, true);
8264
+ }
8265
+ ensureCursorVisible(cm);
8266
+ });
8267
+ },
8268
+ toggleOverwrite: function(cm) {cm.toggleOverwrite();}
8269
+ };
8270
+
8271
+
8272
+ // STANDARD KEYMAPS
8273
+
8274
+ var keyMap = CodeMirror.keyMap = {};
8275
+
8276
+ keyMap.basic = {
8277
+ "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
8278
+ "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
8279
+ "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
8280
+ "Tab": "defaultTab", "Shift-Tab": "indentAuto",
8281
+ "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
8282
+ "Esc": "singleSelection"
8283
+ };
8284
+ // Note that the save and find-related commands aren't defined by
8285
+ // default. User code or addons can define them. Unknown commands
8286
+ // are simply ignored.
8287
+ keyMap.pcDefault = {
8288
+ "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
8289
+ "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
8290
+ "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
8291
+ "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
8292
+ "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
8293
+ "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
8294
+ "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
8295
+ fallthrough: "basic"
8296
+ };
8297
+ // Very basic readline/emacs-style bindings, which are standard on Mac.
8298
+ keyMap.emacsy = {
8299
+ "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
8300
+ "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
8301
+ "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
8302
+ "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars"
8303
+ };
8304
+ keyMap.macDefault = {
8305
+ "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
8306
+ "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
8307
+ "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
8308
+ "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
8309
+ "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
8310
+ "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
8311
+ "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
8312
+ fallthrough: ["basic", "emacsy"]
8313
+ };
8314
+ keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
8315
+
8316
+ // KEYMAP DISPATCH
8317
+
8318
+ function normalizeKeyName(name) {
8319
+ var parts = name.split(/-(?!$)/), name = parts[parts.length - 1];
8320
+ var alt, ctrl, shift, cmd;
8321
+ for (var i = 0; i < parts.length - 1; i++) {
8322
+ var mod = parts[i];
8323
+ if (/^(cmd|meta|m)$/i.test(mod)) cmd = true;
8324
+ else if (/^a(lt)?$/i.test(mod)) alt = true;
8325
+ else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true;
8326
+ else if (/^s(hift)$/i.test(mod)) shift = true;
8327
+ else throw new Error("Unrecognized modifier name: " + mod);
8328
+ }
8329
+ if (alt) name = "Alt-" + name;
8330
+ if (ctrl) name = "Ctrl-" + name;
8331
+ if (cmd) name = "Cmd-" + name;
8332
+ if (shift) name = "Shift-" + name;
8333
+ return name;
8334
+ }
8335
+
8336
+ // This is a kludge to keep keymaps mostly working as raw objects
8337
+ // (backwards compatibility) while at the same time support features
8338
+ // like normalization and multi-stroke key bindings. It compiles a
8339
+ // new normalized keymap, and then updates the old object to reflect
8340
+ // this.
8341
+ CodeMirror.normalizeKeyMap = function(keymap) {
8342
+ var copy = {};
8343
+ for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) {
8344
+ var value = keymap[keyname];
8345
+ if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue;
8346
+ if (value == "...") { delete keymap[keyname]; continue; }
8347
+
8348
+ var keys = map(keyname.split(" "), normalizeKeyName);
8349
+ for (var i = 0; i < keys.length; i++) {
8350
+ var val, name;
8351
+ if (i == keys.length - 1) {
8352
+ name = keys.join(" ");
8353
+ val = value;
8354
+ } else {
8355
+ name = keys.slice(0, i + 1).join(" ");
8356
+ val = "...";
8357
+ }
8358
+ var prev = copy[name];
8359
+ if (!prev) copy[name] = val;
8360
+ else if (prev != val) throw new Error("Inconsistent bindings for " + name);
8361
+ }
8362
+ delete keymap[keyname];
8363
+ }
8364
+ for (var prop in copy) keymap[prop] = copy[prop];
8365
+ return keymap;
8366
+ };
8367
+
8368
+ var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) {
8369
+ map = getKeyMap(map);
8370
+ var found = map.call ? map.call(key, context) : map[key];
8371
+ if (found === false) return "nothing";
8372
+ if (found === "...") return "multi";
8373
+ if (found != null && handle(found)) return "handled";
8374
+
8375
+ if (map.fallthrough) {
8376
+ if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
8377
+ return lookupKey(key, map.fallthrough, handle, context);
8378
+ for (var i = 0; i < map.fallthrough.length; i++) {
8379
+ var result = lookupKey(key, map.fallthrough[i], handle, context);
8380
+ if (result) return result;
8381
+ }
8382
+ }
8383
+ };
8384
+
8385
+ // Modifier key presses don't count as 'real' key presses for the
8386
+ // purpose of keymap fallthrough.
8387
+ var isModifierKey = CodeMirror.isModifierKey = function(value) {
8388
+ var name = typeof value == "string" ? value : keyNames[value.keyCode];
8389
+ return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod";
8390
+ };
8391
+
8392
+ // Look up the name of a key as indicated by an event object.
8393
+ var keyName = CodeMirror.keyName = function(event, noShift) {
8394
+ if (presto && event.keyCode == 34 && event["char"]) return false;
8395
+ var base = keyNames[event.keyCode], name = base;
8396
+ if (name == null || event.altGraphKey) return false;
8397
+ if (event.altKey && base != "Alt") name = "Alt-" + name;
8398
+ if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name;
8399
+ if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name;
8400
+ if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name;
8401
+ return name;
8402
+ };
8403
+
8404
+ function getKeyMap(val) {
8405
+ return typeof val == "string" ? keyMap[val] : val;
8406
+ }
8407
+
8408
+ // FROMTEXTAREA
8409
+
8410
+ CodeMirror.fromTextArea = function(textarea, options) {
8411
+ options = options ? copyObj(options) : {};
8412
+ options.value = textarea.value;
8413
+ if (!options.tabindex && textarea.tabIndex)
8414
+ options.tabindex = textarea.tabIndex;
8415
+ if (!options.placeholder && textarea.placeholder)
8416
+ options.placeholder = textarea.placeholder;
8417
+ // Set autofocus to true if this textarea is focused, or if it has
8418
+ // autofocus and no other element is focused.
8419
+ if (options.autofocus == null) {
8420
+ var hasFocus = activeElt();
8421
+ options.autofocus = hasFocus == textarea ||
8422
+ textarea.getAttribute("autofocus") != null && hasFocus == document.body;
8423
+ }
8424
+
8425
+ function save() {textarea.value = cm.getValue();}
8426
+ if (textarea.form) {
8427
+ on(textarea.form, "submit", save);
8428
+ // Deplorable hack to make the submit method do the right thing.
8429
+ if (!options.leaveSubmitMethodAlone) {
8430
+ var form = textarea.form, realSubmit = form.submit;
8431
+ try {
8432
+ var wrappedSubmit = form.submit = function() {
8433
+ save();
8434
+ form.submit = realSubmit;
8435
+ form.submit();
8436
+ form.submit = wrappedSubmit;
8437
+ };
8438
+ } catch(e) {}
8439
+ }
8440
+ }
8441
+
8442
+ options.finishInit = function(cm) {
8443
+ cm.save = save;
8444
+ cm.getTextArea = function() { return textarea; };
8445
+ cm.toTextArea = function() {
8446
+ cm.toTextArea = isNaN; // Prevent this from being ran twice
8447
+ save();
8448
+ textarea.parentNode.removeChild(cm.getWrapperElement());
8449
+ textarea.style.display = "";
8450
+ if (textarea.form) {
8451
+ off(textarea.form, "submit", save);
8452
+ if (typeof textarea.form.submit == "function")
8453
+ textarea.form.submit = realSubmit;
8454
+ }
8455
+ };
8456
+ };
8457
+
8458
+ textarea.style.display = "none";
8459
+ var cm = CodeMirror(function(node) {
8460
+ textarea.parentNode.insertBefore(node, textarea.nextSibling);
8461
+ }, options);
8462
+ return cm;
8463
+ };
8464
+
8465
+ // STRING STREAM
8466
+
8467
+ // Fed to the mode parsers, provides helper functions to make
8468
+ // parsers more succinct.
8469
+
8470
+ var StringStream = CodeMirror.StringStream = function(string, tabSize) {
8471
+ this.pos = this.start = 0;
8472
+ this.string = string;
8473
+ this.tabSize = tabSize || 8;
8474
+ this.lastColumnPos = this.lastColumnValue = 0;
8475
+ this.lineStart = 0;
8476
+ };
8477
+
8478
+ StringStream.prototype = {
8479
+ eol: function() {return this.pos >= this.string.length;},
8480
+ sol: function() {return this.pos == this.lineStart;},
8481
+ peek: function() {return this.string.charAt(this.pos) || undefined;},
8482
+ next: function() {
8483
+ if (this.pos < this.string.length)
8484
+ return this.string.charAt(this.pos++);
8485
+ },
8486
+ eat: function(match) {
8487
+ var ch = this.string.charAt(this.pos);
8488
+ if (typeof match == "string") var ok = ch == match;
8489
+ else var ok = ch && (match.test ? match.test(ch) : match(ch));
8490
+ if (ok) {++this.pos; return ch;}
8491
+ },
8492
+ eatWhile: function(match) {
8493
+ var start = this.pos;
8494
+ while (this.eat(match)){}
8495
+ return this.pos > start;
8496
+ },
8497
+ eatSpace: function() {
8498
+ var start = this.pos;
8499
+ while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
8500
+ return this.pos > start;
8501
+ },
8502
+ skipToEnd: function() {this.pos = this.string.length;},
8503
+ skipTo: function(ch) {
8504
+ var found = this.string.indexOf(ch, this.pos);
8505
+ if (found > -1) {this.pos = found; return true;}
8506
+ },
8507
+ backUp: function(n) {this.pos -= n;},
8508
+ column: function() {
8509
+ if (this.lastColumnPos < this.start) {
8510
+ this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
8511
+ this.lastColumnPos = this.start;
8512
+ }
8513
+ return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
8514
+ },
8515
+ indentation: function() {
8516
+ return countColumn(this.string, null, this.tabSize) -
8517
+ (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
8518
+ },
8519
+ match: function(pattern, consume, caseInsensitive) {
8520
+ if (typeof pattern == "string") {
8521
+ var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
8522
+ var substr = this.string.substr(this.pos, pattern.length);
8523
+ if (cased(substr) == cased(pattern)) {
8524
+ if (consume !== false) this.pos += pattern.length;
8525
+ return true;
8526
+ }
8527
+ } else {
8528
+ var match = this.string.slice(this.pos).match(pattern);
8529
+ if (match && match.index > 0) return null;
8530
+ if (match && consume !== false) this.pos += match[0].length;
8531
+ return match;
8532
+ }
8533
+ },
8534
+ current: function(){return this.string.slice(this.start, this.pos);},
8535
+ hideFirstChars: function(n, inner) {
8536
+ this.lineStart += n;
8537
+ try { return inner(); }
8538
+ finally { this.lineStart -= n; }
8539
+ }
8540
+ };
8541
+
8542
+ // TEXTMARKERS
8543
+
8544
+ // Created with markText and setBookmark methods. A TextMarker is a
8545
+ // handle that can be used to clear or find a marked position in the
8546
+ // document. Line objects hold arrays (markedSpans) containing
8547
+ // {from, to, marker} object pointing to such marker objects, and
8548
+ // indicating that such a marker is present on that line. Multiple
8549
+ // lines may point to the same marker when it spans across lines.
8550
+ // The spans will have null for their from/to properties when the
8551
+ // marker continues beyond the start/end of the line. Markers have
8552
+ // links back to the lines they currently touch.
8553
+
8554
+ var nextMarkerId = 0;
8555
+
8556
+ var TextMarker = CodeMirror.TextMarker = function(doc, type) {
8557
+ this.lines = [];
8558
+ this.type = type;
8559
+ this.doc = doc;
8560
+ this.id = ++nextMarkerId;
8561
+ };
8562
+ eventMixin(TextMarker);
8563
+
8564
+ // Clear the marker.
8565
+ TextMarker.prototype.clear = function() {
8566
+ if (this.explicitlyCleared) return;
8567
+ var cm = this.doc.cm, withOp = cm && !cm.curOp;
8568
+ if (withOp) startOperation(cm);
8569
+ if (hasHandler(this, "clear")) {
8570
+ var found = this.find();
8571
+ if (found) signalLater(this, "clear", found.from, found.to);
8572
+ }
8573
+ var min = null, max = null;
8574
+ for (var i = 0; i < this.lines.length; ++i) {
8575
+ var line = this.lines[i];
8576
+ var span = getMarkedSpanFor(line.markedSpans, this);
8577
+ if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text");
8578
+ else if (cm) {
8579
+ if (span.to != null) max = lineNo(line);
8580
+ if (span.from != null) min = lineNo(line);
8581
+ }
8582
+ line.markedSpans = removeMarkedSpan(line.markedSpans, span);
8583
+ if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)
8584
+ updateLineHeight(line, textHeight(cm.display));
8585
+ }
8586
+ if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) {
8587
+ var visual = visualLine(this.lines[i]), len = lineLength(visual);
8588
+ if (len > cm.display.maxLineLength) {
8589
+ cm.display.maxLine = visual;
8590
+ cm.display.maxLineLength = len;
8591
+ cm.display.maxLineChanged = true;
8592
+ }
8593
+ }
8594
+
8595
+ if (min != null && cm && this.collapsed) regChange(cm, min, max + 1);
8596
+ this.lines.length = 0;
8597
+ this.explicitlyCleared = true;
8598
+ if (this.atomic && this.doc.cantEdit) {
8599
+ this.doc.cantEdit = false;
8600
+ if (cm) reCheckSelection(cm.doc);
8601
+ }
8602
+ if (cm) signalLater(cm, "markerCleared", cm, this);
8603
+ if (withOp) endOperation(cm);
8604
+ if (this.parent) this.parent.clear();
8605
+ };
8606
+
8607
+ // Find the position of the marker in the document. Returns a {from,
8608
+ // to} object by default. Side can be passed to get a specific side
8609
+ // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
8610
+ // Pos objects returned contain a line object, rather than a line
8611
+ // number (used to prevent looking up the same line twice).
8612
+ TextMarker.prototype.find = function(side, lineObj) {
8613
+ if (side == null && this.type == "bookmark") side = 1;
8614
+ var from, to;
8615
+ for (var i = 0; i < this.lines.length; ++i) {
8616
+ var line = this.lines[i];
8617
+ var span = getMarkedSpanFor(line.markedSpans, this);
8618
+ if (span.from != null) {
8619
+ from = Pos(lineObj ? line : lineNo(line), span.from);
8620
+ if (side == -1) return from;
8621
+ }
8622
+ if (span.to != null) {
8623
+ to = Pos(lineObj ? line : lineNo(line), span.to);
8624
+ if (side == 1) return to;
8625
+ }
8626
+ }
8627
+ return from && {from: from, to: to};
8628
+ };
8629
+
8630
+ // Signals that the marker's widget changed, and surrounding layout
8631
+ // should be recomputed.
8632
+ TextMarker.prototype.changed = function() {
8633
+ var pos = this.find(-1, true), widget = this, cm = this.doc.cm;
8634
+ if (!pos || !cm) return;
8635
+ runInOp(cm, function() {
8636
+ var line = pos.line, lineN = lineNo(pos.line);
8637
+ var view = findViewForLine(cm, lineN);
8638
+ if (view) {
8639
+ clearLineMeasurementCacheFor(view);
8640
+ cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;
8641
+ }
8642
+ cm.curOp.updateMaxLine = true;
8643
+ if (!lineIsHidden(widget.doc, line) && widget.height != null) {
8644
+ var oldHeight = widget.height;
8645
+ widget.height = null;
8646
+ var dHeight = widgetHeight(widget) - oldHeight;
8647
+ if (dHeight)
8648
+ updateLineHeight(line, line.height + dHeight);
8649
+ }
8650
+ });
8651
+ };
8652
+
8653
+ TextMarker.prototype.attachLine = function(line) {
8654
+ if (!this.lines.length && this.doc.cm) {
8655
+ var op = this.doc.cm.curOp;
8656
+ if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
8657
+ (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this);
8658
+ }
8659
+ this.lines.push(line);
8660
+ };
8661
+ TextMarker.prototype.detachLine = function(line) {
8662
+ this.lines.splice(indexOf(this.lines, line), 1);
8663
+ if (!this.lines.length && this.doc.cm) {
8664
+ var op = this.doc.cm.curOp;
8665
+ (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
8666
+ }
8667
+ };
8668
+
8669
+ // Collapsed markers have unique ids, in order to be able to order
8670
+ // them, which is needed for uniquely determining an outer marker
8671
+ // when they overlap (they may nest, but not partially overlap).
8672
+ var nextMarkerId = 0;
8673
+
8674
+ // Create a marker, wire it up to the right lines, and
8675
+ function markText(doc, from, to, options, type) {
8676
+ // Shared markers (across linked documents) are handled separately
8677
+ // (markTextShared will call out to this again, once per
8678
+ // document).
8679
+ if (options && options.shared) return markTextShared(doc, from, to, options, type);
8680
+ // Ensure we are in an operation.
8681
+ if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type);
8682
+
8683
+ var marker = new TextMarker(doc, type), diff = cmp(from, to);
8684
+ if (options) copyObj(options, marker, false);
8685
+ // Don't connect empty markers unless clearWhenEmpty is false
8686
+ if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
8687
+ return marker;
8688
+ if (marker.replacedWith) {
8689
+ // Showing up as a widget implies collapsed (widget replaces text)
8690
+ marker.collapsed = true;
8691
+ marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget");
8692
+ if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true");
8693
+ if (options.insertLeft) marker.widgetNode.insertLeft = true;
8694
+ }
8695
+ if (marker.collapsed) {
8696
+ if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
8697
+ from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
8698
+ throw new Error("Inserting collapsed marker partially overlapping an existing one");
8699
+ sawCollapsedSpans = true;
8700
+ }
8701
+
8702
+ if (marker.addToHistory)
8703
+ addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN);
8704
+
8705
+ var curLine = from.line, cm = doc.cm, updateMaxLine;
8706
+ doc.iter(curLine, to.line + 1, function(line) {
8707
+ if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
8708
+ updateMaxLine = true;
8709
+ if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0);
8710
+ addMarkedSpan(line, new MarkedSpan(marker,
8711
+ curLine == from.line ? from.ch : null,
8712
+ curLine == to.line ? to.ch : null));
8713
+ ++curLine;
8714
+ });
8715
+ // lineIsHidden depends on the presence of the spans, so needs a second pass
8716
+ if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) {
8717
+ if (lineIsHidden(doc, line)) updateLineHeight(line, 0);
8718
+ });
8719
+
8720
+ if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); });
8721
+
8722
+ if (marker.readOnly) {
8723
+ sawReadOnlySpans = true;
8724
+ if (doc.history.done.length || doc.history.undone.length)
8725
+ doc.clearHistory();
8726
+ }
8727
+ if (marker.collapsed) {
8728
+ marker.id = ++nextMarkerId;
8729
+ marker.atomic = true;
8730
+ }
8731
+ if (cm) {
8732
+ // Sync editor state
8733
+ if (updateMaxLine) cm.curOp.updateMaxLine = true;
8734
+ if (marker.collapsed)
8735
+ regChange(cm, from.line, to.line + 1);
8736
+ else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)
8737
+ for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text");
8738
+ if (marker.atomic) reCheckSelection(cm.doc);
8739
+ signalLater(cm, "markerAdded", cm, marker);
8740
+ }
8741
+ return marker;
8742
+ }
8743
+
8744
+ // SHARED TEXTMARKERS
8745
+
8746
+ // A shared marker spans multiple linked documents. It is
8747
+ // implemented as a meta-marker-object controlling multiple normal
8748
+ // markers.
8749
+ var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) {
8750
+ this.markers = markers;
8751
+ this.primary = primary;
8752
+ for (var i = 0; i < markers.length; ++i)
8753
+ markers[i].parent = this;
8754
+ };
8755
+ eventMixin(SharedTextMarker);
8756
+
8757
+ SharedTextMarker.prototype.clear = function() {
8758
+ if (this.explicitlyCleared) return;
8759
+ this.explicitlyCleared = true;
8760
+ for (var i = 0; i < this.markers.length; ++i)
8761
+ this.markers[i].clear();
8762
+ signalLater(this, "clear");
8763
+ };
8764
+ SharedTextMarker.prototype.find = function(side, lineObj) {
8765
+ return this.primary.find(side, lineObj);
8766
+ };
8767
+
8768
+ function markTextShared(doc, from, to, options, type) {
8769
+ options = copyObj(options);
8770
+ options.shared = false;
8771
+ var markers = [markText(doc, from, to, options, type)], primary = markers[0];
8772
+ var widget = options.widgetNode;
8773
+ linkedDocs(doc, function(doc) {
8774
+ if (widget) options.widgetNode = widget.cloneNode(true);
8775
+ markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
8776
+ for (var i = 0; i < doc.linked.length; ++i)
8777
+ if (doc.linked[i].isParent) return;
8778
+ primary = lst(markers);
8779
+ });
8780
+ return new SharedTextMarker(markers, primary);
8781
+ }
8782
+
8783
+ function findSharedMarkers(doc) {
8784
+ return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())),
8785
+ function(m) { return m.parent; });
8786
+ }
8787
+
8788
+ function copySharedMarkers(doc, markers) {
8789
+ for (var i = 0; i < markers.length; i++) {
8790
+ var marker = markers[i], pos = marker.find();
8791
+ var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);
8792
+ if (cmp(mFrom, mTo)) {
8793
+ var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);
8794
+ marker.markers.push(subMark);
8795
+ subMark.parent = marker;
8796
+ }
8797
+ }
8798
+ }
8799
+
8800
+ function detachSharedMarkers(markers) {
8801
+ for (var i = 0; i < markers.length; i++) {
8802
+ var marker = markers[i], linked = [marker.primary.doc];;
8803
+ linkedDocs(marker.primary.doc, function(d) { linked.push(d); });
8804
+ for (var j = 0; j < marker.markers.length; j++) {
8805
+ var subMarker = marker.markers[j];
8806
+ if (indexOf(linked, subMarker.doc) == -1) {
8807
+ subMarker.parent = null;
8808
+ marker.markers.splice(j--, 1);
8809
+ }
8810
+ }
8811
+ }
8812
+ }
8813
+
8814
+ // TEXTMARKER SPANS
8815
+
8816
+ function MarkedSpan(marker, from, to) {
8817
+ this.marker = marker;
8818
+ this.from = from; this.to = to;
8819
+ }
8820
+
8821
+ // Search an array of spans for a span matching the given marker.
8822
+ function getMarkedSpanFor(spans, marker) {
8823
+ if (spans) for (var i = 0; i < spans.length; ++i) {
8824
+ var span = spans[i];
8825
+ if (span.marker == marker) return span;
8826
+ }
8827
+ }
8828
+ // Remove a span from an array, returning undefined if no spans are
8829
+ // left (we don't store arrays for lines without spans).
8830
+ function removeMarkedSpan(spans, span) {
8831
+ for (var r, i = 0; i < spans.length; ++i)
8832
+ if (spans[i] != span) (r || (r = [])).push(spans[i]);
8833
+ return r;
8834
+ }
8835
+ // Add a span to a line.
8836
+ function addMarkedSpan(line, span) {
8837
+ line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
8838
+ span.marker.attachLine(line);
8839
+ }
8840
+
8841
+ // Used for the algorithm that adjusts markers for a change in the
8842
+ // document. These functions cut an array of spans at a given
8843
+ // character position, returning an array of remaining chunks (or
8844
+ // undefined if nothing remains).
8845
+ function markedSpansBefore(old, startCh, isInsert) {
8846
+ if (old) for (var i = 0, nw; i < old.length; ++i) {
8847
+ var span = old[i], marker = span.marker;
8848
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
8849
+ if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
8850
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
8851
+ (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));
8852
+ }
8853
+ }
8854
+ return nw;
8855
+ }
8856
+ function markedSpansAfter(old, endCh, isInsert) {
8857
+ if (old) for (var i = 0, nw; i < old.length; ++i) {
8858
+ var span = old[i], marker = span.marker;
8859
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
8860
+ if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
8861
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
8862
+ (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
8863
+ span.to == null ? null : span.to - endCh));
8864
+ }
8865
+ }
8866
+ return nw;
8867
+ }
8868
+
8869
+ // Given a change object, compute the new set of marker spans that
8870
+ // cover the line in which the change took place. Removes spans
8871
+ // entirely within the change, reconnects spans belonging to the
8872
+ // same marker that appear on both sides of the change, and cuts off
8873
+ // spans partially within the change. Returns an array of span
8874
+ // arrays with one element for each line in (after) the change.
8875
+ function stretchSpansOverChange(doc, change) {
8876
+ if (change.full) return null;
8877
+ var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
8878
+ var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
8879
+ if (!oldFirst && !oldLast) return null;
8880
+
8881
+ var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;
8882
+ // Get the spans that 'stick out' on both sides
8883
+ var first = markedSpansBefore(oldFirst, startCh, isInsert);
8884
+ var last = markedSpansAfter(oldLast, endCh, isInsert);
8885
+
8886
+ // Next, merge those two ends
8887
+ var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
8888
+ if (first) {
8889
+ // Fix up .to properties of first
8890
+ for (var i = 0; i < first.length; ++i) {
8891
+ var span = first[i];
8892
+ if (span.to == null) {
8893
+ var found = getMarkedSpanFor(last, span.marker);
8894
+ if (!found) span.to = startCh;
8895
+ else if (sameLine) span.to = found.to == null ? null : found.to + offset;
8896
+ }
8897
+ }
8898
+ }
8899
+ if (last) {
8900
+ // Fix up .from in last (or move them into first in case of sameLine)
8901
+ for (var i = 0; i < last.length; ++i) {
8902
+ var span = last[i];
8903
+ if (span.to != null) span.to += offset;
8904
+ if (span.from == null) {
8905
+ var found = getMarkedSpanFor(first, span.marker);
8906
+ if (!found) {
8907
+ span.from = offset;
8908
+ if (sameLine) (first || (first = [])).push(span);
8909
+ }
8910
+ } else {
8911
+ span.from += offset;
8912
+ if (sameLine) (first || (first = [])).push(span);
8913
+ }
8914
+ }
8915
+ }
8916
+ // Make sure we didn't create any zero-length spans
8917
+ if (first) first = clearEmptySpans(first);
8918
+ if (last && last != first) last = clearEmptySpans(last);
8919
+
8920
+ var newMarkers = [first];
8921
+ if (!sameLine) {
8922
+ // Fill gap with whole-line-spans
8923
+ var gap = change.text.length - 2, gapMarkers;
8924
+ if (gap > 0 && first)
8925
+ for (var i = 0; i < first.length; ++i)
8926
+ if (first[i].to == null)
8927
+ (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null));
8928
+ for (var i = 0; i < gap; ++i)
8929
+ newMarkers.push(gapMarkers);
8930
+ newMarkers.push(last);
8931
+ }
8932
+ return newMarkers;
8933
+ }
8934
+
8935
+ // Remove spans that are empty and don't have a clearWhenEmpty
8936
+ // option of false.
8937
+ function clearEmptySpans(spans) {
8938
+ for (var i = 0; i < spans.length; ++i) {
8939
+ var span = spans[i];
8940
+ if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
8941
+ spans.splice(i--, 1);
8942
+ }
8943
+ if (!spans.length) return null;
8944
+ return spans;
8945
+ }
8946
+
8947
+ // Used for un/re-doing changes from the history. Combines the
8948
+ // result of computing the existing spans with the set of spans that
8949
+ // existed in the history (so that deleting around a span and then
8950
+ // undoing brings back the span).
8951
+ function mergeOldSpans(doc, change) {
8952
+ var old = getOldSpans(doc, change);
8953
+ var stretched = stretchSpansOverChange(doc, change);
8954
+ if (!old) return stretched;
8955
+ if (!stretched) return old;
8956
+
8957
+ for (var i = 0; i < old.length; ++i) {
8958
+ var oldCur = old[i], stretchCur = stretched[i];
8959
+ if (oldCur && stretchCur) {
8960
+ spans: for (var j = 0; j < stretchCur.length; ++j) {
8961
+ var span = stretchCur[j];
8962
+ for (var k = 0; k < oldCur.length; ++k)
8963
+ if (oldCur[k].marker == span.marker) continue spans;
8964
+ oldCur.push(span);
8965
+ }
8966
+ } else if (stretchCur) {
8967
+ old[i] = stretchCur;
8968
+ }
8969
+ }
8970
+ return old;
8971
+ }
8972
+
8973
+ // Used to 'clip' out readOnly ranges when making a change.
8974
+ function removeReadOnlyRanges(doc, from, to) {
8975
+ var markers = null;
8976
+ doc.iter(from.line, to.line + 1, function(line) {
8977
+ if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
8978
+ var mark = line.markedSpans[i].marker;
8979
+ if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
8980
+ (markers || (markers = [])).push(mark);
8981
+ }
8982
+ });
8983
+ if (!markers) return null;
8984
+ var parts = [{from: from, to: to}];
8985
+ for (var i = 0; i < markers.length; ++i) {
8986
+ var mk = markers[i], m = mk.find(0);
8987
+ for (var j = 0; j < parts.length; ++j) {
8988
+ var p = parts[j];
8989
+ if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue;
8990
+ var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);
8991
+ if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
8992
+ newParts.push({from: p.from, to: m.from});
8993
+ if (dto > 0 || !mk.inclusiveRight && !dto)
8994
+ newParts.push({from: m.to, to: p.to});
8995
+ parts.splice.apply(parts, newParts);
8996
+ j += newParts.length - 1;
8997
+ }
8998
+ }
8999
+ return parts;
9000
+ }
9001
+
9002
+ // Connect or disconnect spans from a line.
9003
+ function detachMarkedSpans(line) {
9004
+ var spans = line.markedSpans;
9005
+ if (!spans) return;
9006
+ for (var i = 0; i < spans.length; ++i)
9007
+ spans[i].marker.detachLine(line);
9008
+ line.markedSpans = null;
9009
+ }
9010
+ function attachMarkedSpans(line, spans) {
9011
+ if (!spans) return;
9012
+ for (var i = 0; i < spans.length; ++i)
9013
+ spans[i].marker.attachLine(line);
9014
+ line.markedSpans = spans;
9015
+ }
9016
+
9017
+ // Helpers used when computing which overlapping collapsed span
9018
+ // counts as the larger one.
9019
+ function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; }
9020
+ function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; }
9021
+
9022
+ // Returns a number indicating which of two overlapping collapsed
9023
+ // spans is larger (and thus includes the other). Falls back to
9024
+ // comparing ids when the spans cover exactly the same range.
9025
+ function compareCollapsedMarkers(a, b) {
9026
+ var lenDiff = a.lines.length - b.lines.length;
9027
+ if (lenDiff != 0) return lenDiff;
9028
+ var aPos = a.find(), bPos = b.find();
9029
+ var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);
9030
+ if (fromCmp) return -fromCmp;
9031
+ var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);
9032
+ if (toCmp) return toCmp;
9033
+ return b.id - a.id;
9034
+ }
9035
+
9036
+ // Find out whether a line ends or starts in a collapsed span. If
9037
+ // so, return the marker for that span.
9038
+ function collapsedSpanAtSide(line, start) {
9039
+ var sps = sawCollapsedSpans && line.markedSpans, found;
9040
+ if (sps) for (var sp, i = 0; i < sps.length; ++i) {
9041
+ sp = sps[i];
9042
+ if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
9043
+ (!found || compareCollapsedMarkers(found, sp.marker) < 0))
9044
+ found = sp.marker;
9045
+ }
9046
+ return found;
9047
+ }
9048
+ function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); }
9049
+ function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); }
9050
+
9051
+ // Test whether there exists a collapsed span that partially
9052
+ // overlaps (covers the start or end, but not both) of a new span.
9053
+ // Such overlap is not allowed.
9054
+ function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
9055
+ var line = getLine(doc, lineNo);
9056
+ var sps = sawCollapsedSpans && line.markedSpans;
9057
+ if (sps) for (var i = 0; i < sps.length; ++i) {
9058
+ var sp = sps[i];
9059
+ if (!sp.marker.collapsed) continue;
9060
+ var found = sp.marker.find(0);
9061
+ var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
9062
+ var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
9063
+ if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue;
9064
+ if (fromCmp <= 0 && (cmp(found.to, from) > 0 || (sp.marker.inclusiveRight && marker.inclusiveLeft)) ||
9065
+ fromCmp >= 0 && (cmp(found.from, to) < 0 || (sp.marker.inclusiveLeft && marker.inclusiveRight)))
9066
+ return true;
9067
+ }
9068
+ }
9069
+
9070
+ // A visual line is a line as drawn on the screen. Folding, for
9071
+ // example, can cause multiple logical lines to appear on the same
9072
+ // visual line. This finds the start of the visual line that the
9073
+ // given line is part of (usually that is the line itself).
9074
+ function visualLine(line) {
9075
+ var merged;
9076
+ while (merged = collapsedSpanAtStart(line))
9077
+ line = merged.find(-1, true).line;
9078
+ return line;
9079
+ }
9080
+
9081
+ // Returns an array of logical lines that continue the visual line
9082
+ // started by the argument, or undefined if there are no such lines.
9083
+ function visualLineContinued(line) {
9084
+ var merged, lines;
9085
+ while (merged = collapsedSpanAtEnd(line)) {
9086
+ line = merged.find(1, true).line;
9087
+ (lines || (lines = [])).push(line);
9088
+ }
9089
+ return lines;
9090
+ }
9091
+
9092
+ // Get the line number of the start of the visual line that the
9093
+ // given line number is part of.
9094
+ function visualLineNo(doc, lineN) {
9095
+ var line = getLine(doc, lineN), vis = visualLine(line);
9096
+ if (line == vis) return lineN;
9097
+ return lineNo(vis);
9098
+ }
9099
+ // Get the line number of the start of the next visual line after
9100
+ // the given line.
9101
+ function visualLineEndNo(doc, lineN) {
9102
+ if (lineN > doc.lastLine()) return lineN;
9103
+ var line = getLine(doc, lineN), merged;
9104
+ if (!lineIsHidden(doc, line)) return lineN;
9105
+ while (merged = collapsedSpanAtEnd(line))
9106
+ line = merged.find(1, true).line;
9107
+ return lineNo(line) + 1;
9108
+ }
9109
+
9110
+ // Compute whether a line is hidden. Lines count as hidden when they
9111
+ // are part of a visual line that starts with another line, or when
9112
+ // they are entirely covered by collapsed, non-widget span.
9113
+ function lineIsHidden(doc, line) {
9114
+ var sps = sawCollapsedSpans && line.markedSpans;
9115
+ if (sps) for (var sp, i = 0; i < sps.length; ++i) {
9116
+ sp = sps[i];
9117
+ if (!sp.marker.collapsed) continue;
9118
+ if (sp.from == null) return true;
9119
+ if (sp.marker.widgetNode) continue;
9120
+ if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
9121
+ return true;
9122
+ }
9123
+ }
9124
+ function lineIsHiddenInner(doc, line, span) {
9125
+ if (span.to == null) {
9126
+ var end = span.marker.find(1, true);
9127
+ return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker));
9128
+ }
9129
+ if (span.marker.inclusiveRight && span.to == line.text.length)
9130
+ return true;
9131
+ for (var sp, i = 0; i < line.markedSpans.length; ++i) {
9132
+ sp = line.markedSpans[i];
9133
+ if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
9134
+ (sp.to == null || sp.to != span.from) &&
9135
+ (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
9136
+ lineIsHiddenInner(doc, line, sp)) return true;
9137
+ }
9138
+ }
9139
+
9140
+ // LINE WIDGETS
9141
+
9142
+ // Line widgets are block elements displayed above or below a line.
9143
+
9144
+ var LineWidget = CodeMirror.LineWidget = function(doc, node, options) {
9145
+ if (options) for (var opt in options) if (options.hasOwnProperty(opt))
9146
+ this[opt] = options[opt];
9147
+ this.doc = doc;
9148
+ this.node = node;
9149
+ };
9150
+ eventMixin(LineWidget);
9151
+
9152
+ function adjustScrollWhenAboveVisible(cm, line, diff) {
9153
+ if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
9154
+ addToScrollPos(cm, null, diff);
9155
+ }
9156
+
9157
+ LineWidget.prototype.clear = function() {
9158
+ var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
9159
+ if (no == null || !ws) return;
9160
+ for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1);
9161
+ if (!ws.length) line.widgets = null;
9162
+ var height = widgetHeight(this);
9163
+ updateLineHeight(line, Math.max(0, line.height - height));
9164
+ if (cm) runInOp(cm, function() {
9165
+ adjustScrollWhenAboveVisible(cm, line, -height);
9166
+ regLineChange(cm, no, "widget");
9167
+ });
9168
+ };
9169
+ LineWidget.prototype.changed = function() {
9170
+ var oldH = this.height, cm = this.doc.cm, line = this.line;
9171
+ this.height = null;
9172
+ var diff = widgetHeight(this) - oldH;
9173
+ if (!diff) return;
9174
+ updateLineHeight(line, line.height + diff);
9175
+ if (cm) runInOp(cm, function() {
9176
+ cm.curOp.forceUpdate = true;
9177
+ adjustScrollWhenAboveVisible(cm, line, diff);
9178
+ });
9179
+ };
9180
+
9181
+ function widgetHeight(widget) {
9182
+ if (widget.height != null) return widget.height;
9183
+ var cm = widget.doc.cm;
9184
+ if (!cm) return 0;
9185
+ if (!contains(document.body, widget.node)) {
9186
+ var parentStyle = "position: relative;";
9187
+ if (widget.coverGutter)
9188
+ parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;";
9189
+ if (widget.noHScroll)
9190
+ parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;";
9191
+ removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle));
9192
+ }
9193
+ return widget.height = widget.node.offsetHeight;
9194
+ }
9195
+
9196
+ function addLineWidget(doc, handle, node, options) {
9197
+ var widget = new LineWidget(doc, node, options);
9198
+ var cm = doc.cm;
9199
+ if (cm && widget.noHScroll) cm.display.alignWidgets = true;
9200
+ changeLine(doc, handle, "widget", function(line) {
9201
+ var widgets = line.widgets || (line.widgets = []);
9202
+ if (widget.insertAt == null) widgets.push(widget);
9203
+ else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget);
9204
+ widget.line = line;
9205
+ if (cm && !lineIsHidden(doc, line)) {
9206
+ var aboveVisible = heightAtLine(line) < doc.scrollTop;
9207
+ updateLineHeight(line, line.height + widgetHeight(widget));
9208
+ if (aboveVisible) addToScrollPos(cm, null, widget.height);
9209
+ cm.curOp.forceUpdate = true;
9210
+ }
9211
+ return true;
9212
+ });
9213
+ return widget;
9214
+ }
9215
+
9216
+ // LINE DATA STRUCTURE
9217
+
9218
+ // Line objects. These hold state related to a line, including
9219
+ // highlighting info (the styles array).
9220
+ var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) {
9221
+ this.text = text;
9222
+ attachMarkedSpans(this, markedSpans);
9223
+ this.height = estimateHeight ? estimateHeight(this) : 1;
9224
+ };
9225
+ eventMixin(Line);
9226
+ Line.prototype.lineNo = function() { return lineNo(this); };
9227
+
9228
+ // Change the content (text, markers) of a line. Automatically
9229
+ // invalidates cached information and tries to re-estimate the
9230
+ // line's height.
9231
+ function updateLine(line, text, markedSpans, estimateHeight) {
9232
+ line.text = text;
9233
+ if (line.stateAfter) line.stateAfter = null;
9234
+ if (line.styles) line.styles = null;
9235
+ if (line.order != null) line.order = null;
9236
+ detachMarkedSpans(line);
9237
+ attachMarkedSpans(line, markedSpans);
9238
+ var estHeight = estimateHeight ? estimateHeight(line) : 1;
9239
+ if (estHeight != line.height) updateLineHeight(line, estHeight);
9240
+ }
9241
+
9242
+ // Detach a line from the document tree and its markers.
9243
+ function cleanUpLine(line) {
9244
+ line.parent = null;
9245
+ detachMarkedSpans(line);
9246
+ }
9247
+
9248
+ function extractLineClasses(type, output) {
9249
+ if (type) for (;;) {
9250
+ var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/);
9251
+ if (!lineClass) break;
9252
+ type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);
9253
+ var prop = lineClass[1] ? "bgClass" : "textClass";
9254
+ if (output[prop] == null)
9255
+ output[prop] = lineClass[2];
9256
+ else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop]))
9257
+ output[prop] += " " + lineClass[2];
9258
+ }
9259
+ return type;
9260
+ }
9261
+
9262
+ function callBlankLine(mode, state) {
9263
+ if (mode.blankLine) return mode.blankLine(state);
9264
+ if (!mode.innerMode) return;
9265
+ var inner = CodeMirror.innerMode(mode, state);
9266
+ if (inner.mode.blankLine) return inner.mode.blankLine(inner.state);
9267
+ }
9268
+
9269
+ function readToken(mode, stream, state, inner) {
9270
+ for (var i = 0; i < 10; i++) {
9271
+ if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode;
9272
+ var style = mode.token(stream, state);
9273
+ if (stream.pos > stream.start) return style;
9274
+ }
9275
+ throw new Error("Mode " + mode.name + " failed to advance stream.");
9276
+ }
9277
+
9278
+ // Utility for getTokenAt and getLineTokens
9279
+ function takeToken(cm, pos, precise, asArray) {
9280
+ function getObj(copy) {
9281
+ return {start: stream.start, end: stream.pos,
9282
+ string: stream.current(),
9283
+ type: style || null,
9284
+ state: copy ? copyState(doc.mode, state) : state};
9285
+ }
9286
+
9287
+ var doc = cm.doc, mode = doc.mode, style;
9288
+ pos = clipPos(doc, pos);
9289
+ var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise);
9290
+ var stream = new StringStream(line.text, cm.options.tabSize), tokens;
9291
+ if (asArray) tokens = [];
9292
+ while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
9293
+ stream.start = stream.pos;
9294
+ style = readToken(mode, stream, state);
9295
+ if (asArray) tokens.push(getObj(true));
9296
+ }
9297
+ return asArray ? tokens : getObj();
9298
+ }
9299
+
9300
+ // Run the given mode's parser over a line, calling f for each token.
9301
+ function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {
9302
+ var flattenSpans = mode.flattenSpans;
9303
+ if (flattenSpans == null) flattenSpans = cm.options.flattenSpans;
9304
+ var curStart = 0, curStyle = null;
9305
+ var stream = new StringStream(text, cm.options.tabSize), style;
9306
+ var inner = cm.options.addModeClass && [null];
9307
+ if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses);
9308
+ while (!stream.eol()) {
9309
+ if (stream.pos > cm.options.maxHighlightLength) {
9310
+ flattenSpans = false;
9311
+ if (forceToEnd) processLine(cm, text, state, stream.pos);
9312
+ stream.pos = text.length;
9313
+ style = null;
9314
+ } else {
9315
+ style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses);
9316
+ }
9317
+ if (inner) {
9318
+ var mName = inner[0].name;
9319
+ if (mName) style = "m-" + (style ? mName + " " + style : mName);
9320
+ }
9321
+ if (!flattenSpans || curStyle != style) {
9322
+ while (curStart < stream.start) {
9323
+ curStart = Math.min(stream.start, curStart + 50000);
9324
+ f(curStart, curStyle);
9325
+ }
9326
+ curStyle = style;
9327
+ }
9328
+ stream.start = stream.pos;
9329
+ }
9330
+ while (curStart < stream.pos) {
9331
+ // Webkit seems to refuse to render text nodes longer than 57444 characters
9332
+ var pos = Math.min(stream.pos, curStart + 50000);
9333
+ f(pos, curStyle);
9334
+ curStart = pos;
9335
+ }
9336
+ }
9337
+
9338
+ // Compute a style array (an array starting with a mode generation
9339
+ // -- for invalidation -- followed by pairs of end positions and
9340
+ // style strings), which is used to highlight the tokens on the
9341
+ // line.
9342
+ function highlightLine(cm, line, state, forceToEnd) {
9343
+ // A styles array always starts with a number identifying the
9344
+ // mode/overlays that it is based on (for easy invalidation).
9345
+ var st = [cm.state.modeGen], lineClasses = {};
9346
+ // Compute the base array of styles
9347
+ runMode(cm, line.text, cm.doc.mode, state, function(end, style) {
9348
+ st.push(end, style);
9349
+ }, lineClasses, forceToEnd);
9350
+
9351
+ // Run overlays, adjust style array.
9352
+ for (var o = 0; o < cm.state.overlays.length; ++o) {
9353
+ var overlay = cm.state.overlays[o], i = 1, at = 0;
9354
+ runMode(cm, line.text, overlay.mode, true, function(end, style) {
9355
+ var start = i;
9356
+ // Ensure there's a token end at the current position, and that i points at it
9357
+ while (at < end) {
9358
+ var i_end = st[i];
9359
+ if (i_end > end)
9360
+ st.splice(i, 1, end, st[i+1], i_end);
9361
+ i += 2;
9362
+ at = Math.min(end, i_end);
9363
+ }
9364
+ if (!style) return;
9365
+ if (overlay.opaque) {
9366
+ st.splice(start, i - start, end, "cm-overlay " + style);
9367
+ i = start + 2;
9368
+ } else {
9369
+ for (; start < i; start += 2) {
9370
+ var cur = st[start+1];
9371
+ st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style;
9372
+ }
9373
+ }
9374
+ }, lineClasses);
9375
+ }
9376
+
9377
+ return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null};
9378
+ }
9379
+
9380
+ function getLineStyles(cm, line, updateFrontier) {
9381
+ if (!line.styles || line.styles[0] != cm.state.modeGen) {
9382
+ var state = getStateBefore(cm, lineNo(line));
9383
+ var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state);
9384
+ line.stateAfter = state;
9385
+ line.styles = result.styles;
9386
+ if (result.classes) line.styleClasses = result.classes;
9387
+ else if (line.styleClasses) line.styleClasses = null;
9388
+ if (updateFrontier === cm.doc.frontier) cm.doc.frontier++;
9389
+ }
9390
+ return line.styles;
9391
+ }
9392
+
9393
+ // Lightweight form of highlight -- proceed over this line and
9394
+ // update state, but don't save a style array. Used for lines that
9395
+ // aren't currently visible.
9396
+ function processLine(cm, text, state, startAt) {
9397
+ var mode = cm.doc.mode;
9398
+ var stream = new StringStream(text, cm.options.tabSize);
9399
+ stream.start = stream.pos = startAt || 0;
9400
+ if (text == "") callBlankLine(mode, state);
9401
+ while (!stream.eol()) {
9402
+ readToken(mode, stream, state);
9403
+ stream.start = stream.pos;
9404
+ }
9405
+ }
9406
+
9407
+ // Convert a style as returned by a mode (either null, or a string
9408
+ // containing one or more styles) to a CSS style. This is cached,
9409
+ // and also looks for line-wide styles.
9410
+ var styleToClassCache = {}, styleToClassCacheWithMode = {};
9411
+ function interpretTokenStyle(style, options) {
9412
+ if (!style || /^\s*$/.test(style)) return null;
9413
+ var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
9414
+ return cache[style] ||
9415
+ (cache[style] = style.replace(/\S+/g, "cm-$&"));
9416
+ }
9417
+
9418
+ // Render the DOM representation of the text of a line. Also builds
9419
+ // up a 'line map', which points at the DOM nodes that represent
9420
+ // specific stretches of text, and is used by the measuring code.
9421
+ // The returned object contains the DOM node, this map, and
9422
+ // information about line-wide styles that were set by the mode.
9423
+ function buildLineContent(cm, lineView) {
9424
+ // The padding-right forces the element to have a 'border', which
9425
+ // is needed on Webkit to be able to get line-level bounding
9426
+ // rectangles for it (in measureChar).
9427
+ var content = elt("span", null, null, webkit ? "padding-right: .1px" : null);
9428
+ var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content,
9429
+ col: 0, pos: 0, cm: cm,
9430
+ splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")};
9431
+ lineView.measure = {};
9432
+
9433
+ // Iterate over the logical lines that make up this visual line.
9434
+ for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
9435
+ var line = i ? lineView.rest[i - 1] : lineView.line, order;
9436
+ builder.pos = 0;
9437
+ builder.addToken = buildToken;
9438
+ // Optionally wire in some hacks into the token-rendering
9439
+ // algorithm, to deal with browser quirks.
9440
+ if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
9441
+ builder.addToken = buildTokenBadBidi(builder.addToken, order);
9442
+ builder.map = [];
9443
+ var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);
9444
+ insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));
9445
+ if (line.styleClasses) {
9446
+ if (line.styleClasses.bgClass)
9447
+ builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "");
9448
+ if (line.styleClasses.textClass)
9449
+ builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "");
9450
+ }
9451
+
9452
+ // Ensure at least a single node is present, for measuring.
9453
+ if (builder.map.length == 0)
9454
+ builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure)));
9455
+
9456
+ // Store the map and a cache object for the current logical line
9457
+ if (i == 0) {
9458
+ lineView.measure.map = builder.map;
9459
+ lineView.measure.cache = {};
9460
+ } else {
9461
+ (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map);
9462
+ (lineView.measure.caches || (lineView.measure.caches = [])).push({});
9463
+ }
9464
+ }
9465
+
9466
+ // See issue #2901
9467
+ if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className))
9468
+ builder.content.className = "cm-tab-wrap-hack";
9469
+
9470
+ signal(cm, "renderLine", cm, lineView.line, builder.pre);
9471
+ if (builder.pre.className)
9472
+ builder.textClass = joinClasses(builder.pre.className, builder.textClass || "");
9473
+
9474
+ return builder;
9475
+ }
9476
+
9477
+ function defaultSpecialCharPlaceholder(ch) {
9478
+ var token = elt("span", "\u2022", "cm-invalidchar");
9479
+ token.title = "\\u" + ch.charCodeAt(0).toString(16);
9480
+ token.setAttribute("aria-label", token.title);
9481
+ return token;
9482
+ }
9483
+
9484
+ // Build up the DOM representation for a single token, and add it to
9485
+ // the line map. Takes care to render special characters separately.
9486
+ function buildToken(builder, text, style, startStyle, endStyle, title, css) {
9487
+ if (!text) return;
9488
+ var displayText = builder.splitSpaces ? text.replace(/ {3,}/g, splitSpaces) : text;
9489
+ var special = builder.cm.state.specialChars, mustWrap = false;
9490
+ if (!special.test(text)) {
9491
+ builder.col += text.length;
9492
+ var content = document.createTextNode(displayText);
9493
+ builder.map.push(builder.pos, builder.pos + text.length, content);
9494
+ if (ie && ie_version < 9) mustWrap = true;
9495
+ builder.pos += text.length;
9496
+ } else {
9497
+ var content = document.createDocumentFragment(), pos = 0;
9498
+ while (true) {
9499
+ special.lastIndex = pos;
9500
+ var m = special.exec(text);
9501
+ var skipped = m ? m.index - pos : text.length - pos;
9502
+ if (skipped) {
9503
+ var txt = document.createTextNode(displayText.slice(pos, pos + skipped));
9504
+ if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
9505
+ else content.appendChild(txt);
9506
+ builder.map.push(builder.pos, builder.pos + skipped, txt);
9507
+ builder.col += skipped;
9508
+ builder.pos += skipped;
9509
+ }
9510
+ if (!m) break;
9511
+ pos += skipped + 1;
9512
+ if (m[0] == "\t") {
9513
+ var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
9514
+ var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
9515
+ txt.setAttribute("role", "presentation");
9516
+ txt.setAttribute("cm-text", "\t");
9517
+ builder.col += tabWidth;
9518
+ } else if (m[0] == "\r" || m[0] == "\n") {
9519
+ var txt = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar"));
9520
+ txt.setAttribute("cm-text", m[0]);
9521
+ builder.col += 1;
9522
+ } else {
9523
+ var txt = builder.cm.options.specialCharPlaceholder(m[0]);
9524
+ txt.setAttribute("cm-text", m[0]);
9525
+ if (ie && ie_version < 9) content.appendChild(elt("span", [txt]));
9526
+ else content.appendChild(txt);
9527
+ builder.col += 1;
9528
+ }
9529
+ builder.map.push(builder.pos, builder.pos + 1, txt);
9530
+ builder.pos++;
9531
+ }
9532
+ }
9533
+ if (style || startStyle || endStyle || mustWrap || css) {
9534
+ var fullStyle = style || "";
9535
+ if (startStyle) fullStyle += startStyle;
9536
+ if (endStyle) fullStyle += endStyle;
9537
+ var token = elt("span", [content], fullStyle, css);
9538
+ if (title) token.title = title;
9539
+ return builder.content.appendChild(token);
9540
+ }
9541
+ builder.content.appendChild(content);
9542
+ }
9543
+
9544
+ function splitSpaces(old) {
9545
+ var out = " ";
9546
+ for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0";
9547
+ out += " ";
9548
+ return out;
9549
+ }
9550
+
9551
+ // Work around nonsense dimensions being reported for stretches of
9552
+ // right-to-left text.
9553
+ function buildTokenBadBidi(inner, order) {
9554
+ return function(builder, text, style, startStyle, endStyle, title, css) {
9555
+ style = style ? style + " cm-force-border" : "cm-force-border";
9556
+ var start = builder.pos, end = start + text.length;
9557
+ for (;;) {
9558
+ // Find the part that overlaps with the start of this text
9559
+ for (var i = 0; i < order.length; i++) {
9560
+ var part = order[i];
9561
+ if (part.to > start && part.from <= start) break;
9562
+ }
9563
+ if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css);
9564
+ inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css);
9565
+ startStyle = null;
9566
+ text = text.slice(part.to - start);
9567
+ start = part.to;
9568
+ }
9569
+ };
9570
+ }
9571
+
9572
+ function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
9573
+ var widget = !ignoreWidget && marker.widgetNode;
9574
+ if (widget) builder.map.push(builder.pos, builder.pos + size, widget);
9575
+ if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
9576
+ if (!widget)
9577
+ widget = builder.content.appendChild(document.createElement("span"));
9578
+ widget.setAttribute("cm-marker", marker.id);
9579
+ }
9580
+ if (widget) {
9581
+ builder.cm.display.input.setUneditable(widget);
9582
+ builder.content.appendChild(widget);
9583
+ }
9584
+ builder.pos += size;
9585
+ }
9586
+
9587
+ // Outputs a number of spans to make up a line, taking highlighting
9588
+ // and marked text into account.
9589
+ function insertLineContent(line, builder, styles) {
9590
+ var spans = line.markedSpans, allText = line.text, at = 0;
9591
+ if (!spans) {
9592
+ for (var i = 1; i < styles.length; i+=2)
9593
+ builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options));
9594
+ return;
9595
+ }
9596
+
9597
+ var len = allText.length, pos = 0, i = 1, text = "", style, css;
9598
+ var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed;
9599
+ for (;;) {
9600
+ if (nextChange == pos) { // Update current marker set
9601
+ spanStyle = spanEndStyle = spanStartStyle = title = css = "";
9602
+ collapsed = null; nextChange = Infinity;
9603
+ var foundBookmarks = [];
9604
+ for (var j = 0; j < spans.length; ++j) {
9605
+ var sp = spans[j], m = sp.marker;
9606
+ if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
9607
+ foundBookmarks.push(m);
9608
+ } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
9609
+ if (sp.to != null && sp.to != pos && nextChange > sp.to) {
9610
+ nextChange = sp.to;
9611
+ spanEndStyle = "";
9612
+ }
9613
+ if (m.className) spanStyle += " " + m.className;
9614
+ if (m.css) css = m.css;
9615
+ if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
9616
+ if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
9617
+ if (m.title && !title) title = m.title;
9618
+ if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
9619
+ collapsed = sp;
9620
+ } else if (sp.from > pos && nextChange > sp.from) {
9621
+ nextChange = sp.from;
9622
+ }
9623
+ }
9624
+ if (collapsed && (collapsed.from || 0) == pos) {
9625
+ buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
9626
+ collapsed.marker, collapsed.from == null);
9627
+ if (collapsed.to == null) return;
9628
+ if (collapsed.to == pos) collapsed = false;
9629
+ }
9630
+ if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
9631
+ buildCollapsedSpan(builder, 0, foundBookmarks[j]);
9632
+ }
9633
+ if (pos >= len) break;
9634
+
9635
+ var upto = Math.min(len, nextChange);
9636
+ while (true) {
9637
+ if (text) {
9638
+ var end = pos + text.length;
9639
+ if (!collapsed) {
9640
+ var tokenText = end > upto ? text.slice(0, upto - pos) : text;
9641
+ builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
9642
+ spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css);
9643
+ }
9644
+ if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;}
9645
+ pos = end;
9646
+ spanStartStyle = "";
9647
+ }
9648
+ text = allText.slice(at, at = styles[i++]);
9649
+ style = interpretTokenStyle(styles[i++], builder.cm.options);
9650
+ }
9651
+ }
9652
+ }
9653
+
9654
+ // DOCUMENT DATA STRUCTURE
9655
+
9656
+ // By default, updates that start and end at the beginning of a line
9657
+ // are treated specially, in order to make the association of line
9658
+ // widgets and marker elements with the text behave more intuitive.
9659
+ function isWholeLineUpdate(doc, change) {
9660
+ return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
9661
+ (!doc.cm || doc.cm.options.wholeLineUpdateBefore);
9662
+ }
9663
+
9664
+ // Perform a change on the document data structure.
9665
+ function updateDoc(doc, change, markedSpans, estimateHeight) {
9666
+ function spansFor(n) {return markedSpans ? markedSpans[n] : null;}
9667
+ function update(line, text, spans) {
9668
+ updateLine(line, text, spans, estimateHeight);
9669
+ signalLater(line, "change", line, change);
9670
+ }
9671
+ function linesFor(start, end) {
9672
+ for (var i = start, result = []; i < end; ++i)
9673
+ result.push(new Line(text[i], spansFor(i), estimateHeight));
9674
+ return result;
9675
+ }
9676
+
9677
+ var from = change.from, to = change.to, text = change.text;
9678
+ var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
9679
+ var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
9680
+
9681
+ // Adjust the line structure
9682
+ if (change.full) {
9683
+ doc.insert(0, linesFor(0, text.length));
9684
+ doc.remove(text.length, doc.size - text.length);
9685
+ } else if (isWholeLineUpdate(doc, change)) {
9686
+ // This is a whole-line replace. Treated specially to make
9687
+ // sure line objects move the way they are supposed to.
9688
+ var added = linesFor(0, text.length - 1);
9689
+ update(lastLine, lastLine.text, lastSpans);
9690
+ if (nlines) doc.remove(from.line, nlines);
9691
+ if (added.length) doc.insert(from.line, added);
9692
+ } else if (firstLine == lastLine) {
9693
+ if (text.length == 1) {
9694
+ update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
9695
+ } else {
9696
+ var added = linesFor(1, text.length - 1);
9697
+ added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
9698
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
9699
+ doc.insert(from.line + 1, added);
9700
+ }
9701
+ } else if (text.length == 1) {
9702
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
9703
+ doc.remove(from.line + 1, nlines);
9704
+ } else {
9705
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
9706
+ update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
9707
+ var added = linesFor(1, text.length - 1);
9708
+ if (nlines > 1) doc.remove(from.line + 1, nlines - 1);
9709
+ doc.insert(from.line + 1, added);
9710
+ }
9711
+
9712
+ signalLater(doc, "change", doc, change);
9713
+ }
9714
+
9715
+ // The document is represented as a BTree consisting of leaves, with
9716
+ // chunk of lines in them, and branches, with up to ten leaves or
9717
+ // other branch nodes below them. The top node is always a branch
9718
+ // node, and is the document object itself (meaning it has
9719
+ // additional methods and properties).
9720
+ //
9721
+ // All nodes have parent links. The tree is used both to go from
9722
+ // line numbers to line objects, and to go from objects to numbers.
9723
+ // It also indexes by height, and is used to convert between height
9724
+ // and line object, and to find the total height of the document.
9725
+ //
9726
+ // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
9727
+
9728
+ function LeafChunk(lines) {
9729
+ this.lines = lines;
9730
+ this.parent = null;
9731
+ for (var i = 0, height = 0; i < lines.length; ++i) {
9732
+ lines[i].parent = this;
9733
+ height += lines[i].height;
9734
+ }
9735
+ this.height = height;
9736
+ }
9737
+
9738
+ LeafChunk.prototype = {
9739
+ chunkSize: function() { return this.lines.length; },
9740
+ // Remove the n lines at offset 'at'.
9741
+ removeInner: function(at, n) {
9742
+ for (var i = at, e = at + n; i < e; ++i) {
9743
+ var line = this.lines[i];
9744
+ this.height -= line.height;
9745
+ cleanUpLine(line);
9746
+ signalLater(line, "delete");
9747
+ }
9748
+ this.lines.splice(at, n);
9749
+ },
9750
+ // Helper used to collapse a small branch into a single leaf.
9751
+ collapse: function(lines) {
9752
+ lines.push.apply(lines, this.lines);
9753
+ },
9754
+ // Insert the given array of lines at offset 'at', count them as
9755
+ // having the given height.
9756
+ insertInner: function(at, lines, height) {
9757
+ this.height += height;
9758
+ this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
9759
+ for (var i = 0; i < lines.length; ++i) lines[i].parent = this;
9760
+ },
9761
+ // Used to iterate over a part of the tree.
9762
+ iterN: function(at, n, op) {
9763
+ for (var e = at + n; at < e; ++at)
9764
+ if (op(this.lines[at])) return true;
9765
+ }
9766
+ };
9767
+
9768
+ function BranchChunk(children) {
9769
+ this.children = children;
9770
+ var size = 0, height = 0;
9771
+ for (var i = 0; i < children.length; ++i) {
9772
+ var ch = children[i];
9773
+ size += ch.chunkSize(); height += ch.height;
9774
+ ch.parent = this;
9775
+ }
9776
+ this.size = size;
9777
+ this.height = height;
9778
+ this.parent = null;
9779
+ }
9780
+
9781
+ BranchChunk.prototype = {
9782
+ chunkSize: function() { return this.size; },
9783
+ removeInner: function(at, n) {
9784
+ this.size -= n;
9785
+ for (var i = 0; i < this.children.length; ++i) {
9786
+ var child = this.children[i], sz = child.chunkSize();
9787
+ if (at < sz) {
9788
+ var rm = Math.min(n, sz - at), oldHeight = child.height;
9789
+ child.removeInner(at, rm);
9790
+ this.height -= oldHeight - child.height;
9791
+ if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
9792
+ if ((n -= rm) == 0) break;
9793
+ at = 0;
9794
+ } else at -= sz;
9795
+ }
9796
+ // If the result is smaller than 25 lines, ensure that it is a
9797
+ // single leaf node.
9798
+ if (this.size - n < 25 &&
9799
+ (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
9800
+ var lines = [];
9801
+ this.collapse(lines);
9802
+ this.children = [new LeafChunk(lines)];
9803
+ this.children[0].parent = this;
9804
+ }
9805
+ },
9806
+ collapse: function(lines) {
9807
+ for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines);
9808
+ },
9809
+ insertInner: function(at, lines, height) {
9810
+ this.size += lines.length;
9811
+ this.height += height;
9812
+ for (var i = 0; i < this.children.length; ++i) {
9813
+ var child = this.children[i], sz = child.chunkSize();
9814
+ if (at <= sz) {
9815
+ child.insertInner(at, lines, height);
9816
+ if (child.lines && child.lines.length > 50) {
9817
+ while (child.lines.length > 50) {
9818
+ var spilled = child.lines.splice(child.lines.length - 25, 25);
9819
+ var newleaf = new LeafChunk(spilled);
9820
+ child.height -= newleaf.height;
9821
+ this.children.splice(i + 1, 0, newleaf);
9822
+ newleaf.parent = this;
9823
+ }
9824
+ this.maybeSpill();
9825
+ }
9826
+ break;
9827
+ }
9828
+ at -= sz;
9829
+ }
9830
+ },
9831
+ // When a node has grown, check whether it should be split.
9832
+ maybeSpill: function() {
9833
+ if (this.children.length <= 10) return;
9834
+ var me = this;
9835
+ do {
9836
+ var spilled = me.children.splice(me.children.length - 5, 5);
9837
+ var sibling = new BranchChunk(spilled);
9838
+ if (!me.parent) { // Become the parent node
9839
+ var copy = new BranchChunk(me.children);
9840
+ copy.parent = me;
9841
+ me.children = [copy, sibling];
9842
+ me = copy;
9843
+ } else {
9844
+ me.size -= sibling.size;
9845
+ me.height -= sibling.height;
9846
+ var myIndex = indexOf(me.parent.children, me);
9847
+ me.parent.children.splice(myIndex + 1, 0, sibling);
9848
+ }
9849
+ sibling.parent = me.parent;
9850
+ } while (me.children.length > 10);
9851
+ me.parent.maybeSpill();
9852
+ },
9853
+ iterN: function(at, n, op) {
9854
+ for (var i = 0; i < this.children.length; ++i) {
9855
+ var child = this.children[i], sz = child.chunkSize();
9856
+ if (at < sz) {
9857
+ var used = Math.min(n, sz - at);
9858
+ if (child.iterN(at, used, op)) return true;
9859
+ if ((n -= used) == 0) break;
9860
+ at = 0;
9861
+ } else at -= sz;
9862
+ }
9863
+ }
9864
+ };
9865
+
9866
+ var nextDocId = 0;
9867
+ var Doc = CodeMirror.Doc = function(text, mode, firstLine, lineSep) {
9868
+ if (!(this instanceof Doc)) return new Doc(text, mode, firstLine, lineSep);
9869
+ if (firstLine == null) firstLine = 0;
9870
+
9871
+ BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
9872
+ this.first = firstLine;
9873
+ this.scrollTop = this.scrollLeft = 0;
9874
+ this.cantEdit = false;
9875
+ this.cleanGeneration = 1;
9876
+ this.frontier = firstLine;
9877
+ var start = Pos(firstLine, 0);
9878
+ this.sel = simpleSelection(start);
9879
+ this.history = new History(null);
9880
+ this.id = ++nextDocId;
9881
+ this.modeOption = mode;
9882
+ this.lineSep = lineSep;
9883
+
9884
+ if (typeof text == "string") text = this.splitLines(text);
9885
+ updateDoc(this, {from: start, to: start, text: text});
9886
+ setSelection(this, simpleSelection(start), sel_dontScroll);
9887
+ };
9888
+
9889
+ Doc.prototype = createObj(BranchChunk.prototype, {
9890
+ constructor: Doc,
9891
+ // Iterate over the document. Supports two forms -- with only one
9892
+ // argument, it calls that for each line in the document. With
9893
+ // three, it iterates over the range given by the first two (with
9894
+ // the second being non-inclusive).
9895
+ iter: function(from, to, op) {
9896
+ if (op) this.iterN(from - this.first, to - from, op);
9897
+ else this.iterN(this.first, this.first + this.size, from);
9898
+ },
9899
+
9900
+ // Non-public interface for adding and removing lines.
9901
+ insert: function(at, lines) {
9902
+ var height = 0;
9903
+ for (var i = 0; i < lines.length; ++i) height += lines[i].height;
9904
+ this.insertInner(at - this.first, lines, height);
9905
+ },
9906
+ remove: function(at, n) { this.removeInner(at - this.first, n); },
9907
+
9908
+ // From here, the methods are part of the public interface. Most
9909
+ // are also available from CodeMirror (editor) instances.
9910
+
9911
+ getValue: function(lineSep) {
9912
+ var lines = getLines(this, this.first, this.first + this.size);
9913
+ if (lineSep === false) return lines;
9914
+ return lines.join(lineSep || this.lineSeparator());
9915
+ },
9916
+ setValue: docMethodOp(function(code) {
9917
+ var top = Pos(this.first, 0), last = this.first + this.size - 1;
9918
+ makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
9919
+ text: this.splitLines(code), origin: "setValue", full: true}, true);
9920
+ setSelection(this, simpleSelection(top));
9921
+ }),
9922
+ replaceRange: function(code, from, to, origin) {
9923
+ from = clipPos(this, from);
9924
+ to = to ? clipPos(this, to) : from;
9925
+ replaceRange(this, code, from, to, origin);
9926
+ },
9927
+ getRange: function(from, to, lineSep) {
9928
+ var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
9929
+ if (lineSep === false) return lines;
9930
+ return lines.join(lineSep || this.lineSeparator());
9931
+ },
9932
+
9933
+ getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
9934
+
9935
+ getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);},
9936
+ getLineNumber: function(line) {return lineNo(line);},
9937
+
9938
+ getLineHandleVisualStart: function(line) {
9939
+ if (typeof line == "number") line = getLine(this, line);
9940
+ return visualLine(line);
9941
+ },
9942
+
9943
+ lineCount: function() {return this.size;},
9944
+ firstLine: function() {return this.first;},
9945
+ lastLine: function() {return this.first + this.size - 1;},
9946
+
9947
+ clipPos: function(pos) {return clipPos(this, pos);},
9948
+
9949
+ getCursor: function(start) {
9950
+ var range = this.sel.primary(), pos;
9951
+ if (start == null || start == "head") pos = range.head;
9952
+ else if (start == "anchor") pos = range.anchor;
9953
+ else if (start == "end" || start == "to" || start === false) pos = range.to();
9954
+ else pos = range.from();
9955
+ return pos;
9956
+ },
9957
+ listSelections: function() { return this.sel.ranges; },
9958
+ somethingSelected: function() {return this.sel.somethingSelected();},
9959
+
9960
+ setCursor: docMethodOp(function(line, ch, options) {
9961
+ setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options);
9962
+ }),
9963
+ setSelection: docMethodOp(function(anchor, head, options) {
9964
+ setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);
9965
+ }),
9966
+ extendSelection: docMethodOp(function(head, other, options) {
9967
+ extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
9968
+ }),
9969
+ extendSelections: docMethodOp(function(heads, options) {
9970
+ extendSelections(this, clipPosArray(this, heads, options));
9971
+ }),
9972
+ extendSelectionsBy: docMethodOp(function(f, options) {
9973
+ extendSelections(this, map(this.sel.ranges, f), options);
9974
+ }),
9975
+ setSelections: docMethodOp(function(ranges, primary, options) {
9976
+ if (!ranges.length) return;
9977
+ for (var i = 0, out = []; i < ranges.length; i++)
9978
+ out[i] = new Range(clipPos(this, ranges[i].anchor),
9979
+ clipPos(this, ranges[i].head));
9980
+ if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex);
9981
+ setSelection(this, normalizeSelection(out, primary), options);
9982
+ }),
9983
+ addSelection: docMethodOp(function(anchor, head, options) {
9984
+ var ranges = this.sel.ranges.slice(0);
9985
+ ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));
9986
+ setSelection(this, normalizeSelection(ranges, ranges.length - 1), options);
9987
+ }),
9988
+
9989
+ getSelection: function(lineSep) {
9990
+ var ranges = this.sel.ranges, lines;
9991
+ for (var i = 0; i < ranges.length; i++) {
9992
+ var sel = getBetween(this, ranges[i].from(), ranges[i].to());
9993
+ lines = lines ? lines.concat(sel) : sel;
9994
+ }
9995
+ if (lineSep === false) return lines;
9996
+ else return lines.join(lineSep || this.lineSeparator());
9997
+ },
9998
+ getSelections: function(lineSep) {
9999
+ var parts = [], ranges = this.sel.ranges;
10000
+ for (var i = 0; i < ranges.length; i++) {
10001
+ var sel = getBetween(this, ranges[i].from(), ranges[i].to());
10002
+ if (lineSep !== false) sel = sel.join(lineSep || this.lineSeparator());
10003
+ parts[i] = sel;
10004
+ }
10005
+ return parts;
10006
+ },
10007
+ replaceSelection: function(code, collapse, origin) {
10008
+ var dup = [];
10009
+ for (var i = 0; i < this.sel.ranges.length; i++)
10010
+ dup[i] = code;
10011
+ this.replaceSelections(dup, collapse, origin || "+input");
10012
+ },
10013
+ replaceSelections: docMethodOp(function(code, collapse, origin) {
10014
+ var changes = [], sel = this.sel;
10015
+ for (var i = 0; i < sel.ranges.length; i++) {
10016
+ var range = sel.ranges[i];
10017
+ changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin};
10018
+ }
10019
+ var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
10020
+ for (var i = changes.length - 1; i >= 0; i--)
10021
+ makeChange(this, changes[i]);
10022
+ if (newSel) setSelectionReplaceHistory(this, newSel);
10023
+ else if (this.cm) ensureCursorVisible(this.cm);
10024
+ }),
10025
+ undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),
10026
+ redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),
10027
+ undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),
10028
+ redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}),
10029
+
10030
+ setExtending: function(val) {this.extend = val;},
10031
+ getExtending: function() {return this.extend;},
10032
+
10033
+ historySize: function() {
10034
+ var hist = this.history, done = 0, undone = 0;
10035
+ for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done;
10036
+ for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone;
10037
+ return {undo: done, redo: undone};
10038
+ },
10039
+ clearHistory: function() {this.history = new History(this.history.maxGeneration);},
10040
+
10041
+ markClean: function() {
10042
+ this.cleanGeneration = this.changeGeneration(true);
10043
+ },
10044
+ changeGeneration: function(forceSplit) {
10045
+ if (forceSplit)
10046
+ this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null;
10047
+ return this.history.generation;
10048
+ },
10049
+ isClean: function (gen) {
10050
+ return this.history.generation == (gen || this.cleanGeneration);
10051
+ },
10052
+
10053
+ getHistory: function() {
10054
+ return {done: copyHistoryArray(this.history.done),
10055
+ undone: copyHistoryArray(this.history.undone)};
10056
+ },
10057
+ setHistory: function(histData) {
10058
+ var hist = this.history = new History(this.history.maxGeneration);
10059
+ hist.done = copyHistoryArray(histData.done.slice(0), null, true);
10060
+ hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
10061
+ },
10062
+
10063
+ addLineClass: docMethodOp(function(handle, where, cls) {
10064
+ return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
10065
+ var prop = where == "text" ? "textClass"
10066
+ : where == "background" ? "bgClass"
10067
+ : where == "gutter" ? "gutterClass" : "wrapClass";
10068
+ if (!line[prop]) line[prop] = cls;
10069
+ else if (classTest(cls).test(line[prop])) return false;
10070
+ else line[prop] += " " + cls;
10071
+ return true;
10072
+ });
10073
+ }),
10074
+ removeLineClass: docMethodOp(function(handle, where, cls) {
10075
+ return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) {
10076
+ var prop = where == "text" ? "textClass"
10077
+ : where == "background" ? "bgClass"
10078
+ : where == "gutter" ? "gutterClass" : "wrapClass";
10079
+ var cur = line[prop];
10080
+ if (!cur) return false;
10081
+ else if (cls == null) line[prop] = null;
10082
+ else {
10083
+ var found = cur.match(classTest(cls));
10084
+ if (!found) return false;
10085
+ var end = found.index + found[0].length;
10086
+ line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
10087
+ }
10088
+ return true;
10089
+ });
10090
+ }),
10091
+
10092
+ addLineWidget: docMethodOp(function(handle, node, options) {
10093
+ return addLineWidget(this, handle, node, options);
10094
+ }),
10095
+ removeLineWidget: function(widget) { widget.clear(); },
10096
+
10097
+ markText: function(from, to, options) {
10098
+ return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range");
10099
+ },
10100
+ setBookmark: function(pos, options) {
10101
+ var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
10102
+ insertLeft: options && options.insertLeft,
10103
+ clearWhenEmpty: false, shared: options && options.shared,
10104
+ handleMouseEvents: options && options.handleMouseEvents};
10105
+ pos = clipPos(this, pos);
10106
+ return markText(this, pos, pos, realOpts, "bookmark");
10107
+ },
10108
+ findMarksAt: function(pos) {
10109
+ pos = clipPos(this, pos);
10110
+ var markers = [], spans = getLine(this, pos.line).markedSpans;
10111
+ if (spans) for (var i = 0; i < spans.length; ++i) {
10112
+ var span = spans[i];
10113
+ if ((span.from == null || span.from <= pos.ch) &&
10114
+ (span.to == null || span.to >= pos.ch))
10115
+ markers.push(span.marker.parent || span.marker);
10116
+ }
10117
+ return markers;
10118
+ },
10119
+ findMarks: function(from, to, filter) {
10120
+ from = clipPos(this, from); to = clipPos(this, to);
10121
+ var found = [], lineNo = from.line;
10122
+ this.iter(from.line, to.line + 1, function(line) {
10123
+ var spans = line.markedSpans;
10124
+ if (spans) for (var i = 0; i < spans.length; i++) {
10125
+ var span = spans[i];
10126
+ if (!(lineNo == from.line && from.ch > span.to ||
10127
+ span.from == null && lineNo != from.line||
10128
+ lineNo == to.line && span.from > to.ch) &&
10129
+ (!filter || filter(span.marker)))
10130
+ found.push(span.marker.parent || span.marker);
10131
+ }
10132
+ ++lineNo;
10133
+ });
10134
+ return found;
10135
+ },
10136
+ getAllMarks: function() {
10137
+ var markers = [];
10138
+ this.iter(function(line) {
10139
+ var sps = line.markedSpans;
10140
+ if (sps) for (var i = 0; i < sps.length; ++i)
10141
+ if (sps[i].from != null) markers.push(sps[i].marker);
10142
+ });
10143
+ return markers;
10144
+ },
10145
+
10146
+ posFromIndex: function(off) {
10147
+ var ch, lineNo = this.first;
10148
+ this.iter(function(line) {
10149
+ var sz = line.text.length + 1;
10150
+ if (sz > off) { ch = off; return true; }
10151
+ off -= sz;
10152
+ ++lineNo;
10153
+ });
10154
+ return clipPos(this, Pos(lineNo, ch));
10155
+ },
10156
+ indexFromPos: function (coords) {
10157
+ coords = clipPos(this, coords);
10158
+ var index = coords.ch;
10159
+ if (coords.line < this.first || coords.ch < 0) return 0;
10160
+ this.iter(this.first, coords.line, function (line) {
10161
+ index += line.text.length + 1;
10162
+ });
10163
+ return index;
10164
+ },
10165
+
10166
+ copy: function(copyHistory) {
10167
+ var doc = new Doc(getLines(this, this.first, this.first + this.size),
10168
+ this.modeOption, this.first, this.lineSep);
10169
+ doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
10170
+ doc.sel = this.sel;
10171
+ doc.extend = false;
10172
+ if (copyHistory) {
10173
+ doc.history.undoDepth = this.history.undoDepth;
10174
+ doc.setHistory(this.getHistory());
10175
+ }
10176
+ return doc;
10177
+ },
10178
+
10179
+ linkedDoc: function(options) {
10180
+ if (!options) options = {};
10181
+ var from = this.first, to = this.first + this.size;
10182
+ if (options.from != null && options.from > from) from = options.from;
10183
+ if (options.to != null && options.to < to) to = options.to;
10184
+ var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep);
10185
+ if (options.sharedHist) copy.history = this.history;
10186
+ (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
10187
+ copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
10188
+ copySharedMarkers(copy, findSharedMarkers(this));
10189
+ return copy;
10190
+ },
10191
+ unlinkDoc: function(other) {
10192
+ if (other instanceof CodeMirror) other = other.doc;
10193
+ if (this.linked) for (var i = 0; i < this.linked.length; ++i) {
10194
+ var link = this.linked[i];
10195
+ if (link.doc != other) continue;
10196
+ this.linked.splice(i, 1);
10197
+ other.unlinkDoc(this);
10198
+ detachSharedMarkers(findSharedMarkers(this));
10199
+ break;
10200
+ }
10201
+ // If the histories were shared, split them again
10202
+ if (other.history == this.history) {
10203
+ var splitIds = [other.id];
10204
+ linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true);
10205
+ other.history = new History(null);
10206
+ other.history.done = copyHistoryArray(this.history.done, splitIds);
10207
+ other.history.undone = copyHistoryArray(this.history.undone, splitIds);
10208
+ }
10209
+ },
10210
+ iterLinkedDocs: function(f) {linkedDocs(this, f);},
10211
+
10212
+ getMode: function() {return this.mode;},
10213
+ getEditor: function() {return this.cm;},
10214
+
10215
+ splitLines: function(str) {
10216
+ if (this.lineSep) return str.split(this.lineSep);
10217
+ return splitLinesAuto(str);
10218
+ },
10219
+ lineSeparator: function() { return this.lineSep || "\n"; }
10220
+ });
10221
+
10222
+ // Public alias.
10223
+ Doc.prototype.eachLine = Doc.prototype.iter;
10224
+
10225
+ // Set up methods on CodeMirror's prototype to redirect to the editor's document.
10226
+ var dontDelegate = "iter insert remove copy getEditor constructor".split(" ");
10227
+ for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
10228
+ CodeMirror.prototype[prop] = (function(method) {
10229
+ return function() {return method.apply(this.doc, arguments);};
10230
+ })(Doc.prototype[prop]);
10231
+
10232
+ eventMixin(Doc);
10233
+
10234
+ // Call f for all linked documents.
10235
+ function linkedDocs(doc, f, sharedHistOnly) {
10236
+ function propagate(doc, skip, sharedHist) {
10237
+ if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) {
10238
+ var rel = doc.linked[i];
10239
+ if (rel.doc == skip) continue;
10240
+ var shared = sharedHist && rel.sharedHist;
10241
+ if (sharedHistOnly && !shared) continue;
10242
+ f(rel.doc, shared);
10243
+ propagate(rel.doc, doc, shared);
10244
+ }
10245
+ }
10246
+ propagate(doc, null, true);
10247
+ }
10248
+
10249
+ // Attach a document to an editor.
10250
+ function attachDoc(cm, doc) {
10251
+ if (doc.cm) throw new Error("This document is already in use.");
10252
+ cm.doc = doc;
10253
+ doc.cm = cm;
10254
+ estimateLineHeights(cm);
10255
+ loadMode(cm);
10256
+ if (!cm.options.lineWrapping) findMaxLine(cm);
10257
+ cm.options.mode = doc.modeOption;
10258
+ regChange(cm);
10259
+ }
10260
+
10261
+ // LINE UTILITIES
10262
+
10263
+ // Find the line object corresponding to the given line number.
10264
+ function getLine(doc, n) {
10265
+ n -= doc.first;
10266
+ if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document.");
10267
+ for (var chunk = doc; !chunk.lines;) {
10268
+ for (var i = 0;; ++i) {
10269
+ var child = chunk.children[i], sz = child.chunkSize();
10270
+ if (n < sz) { chunk = child; break; }
10271
+ n -= sz;
10272
+ }
10273
+ }
10274
+ return chunk.lines[n];
10275
+ }
10276
+
10277
+ // Get the part of a document between two positions, as an array of
10278
+ // strings.
10279
+ function getBetween(doc, start, end) {
10280
+ var out = [], n = start.line;
10281
+ doc.iter(start.line, end.line + 1, function(line) {
10282
+ var text = line.text;
10283
+ if (n == end.line) text = text.slice(0, end.ch);
10284
+ if (n == start.line) text = text.slice(start.ch);
10285
+ out.push(text);
10286
+ ++n;
10287
+ });
10288
+ return out;
10289
+ }
10290
+ // Get the lines between from and to, as array of strings.
10291
+ function getLines(doc, from, to) {
10292
+ var out = [];
10293
+ doc.iter(from, to, function(line) { out.push(line.text); });
10294
+ return out;
10295
+ }
10296
+
10297
+ // Update the height of a line, propagating the height change
10298
+ // upwards to parent nodes.
10299
+ function updateLineHeight(line, height) {
10300
+ var diff = height - line.height;
10301
+ if (diff) for (var n = line; n; n = n.parent) n.height += diff;
10302
+ }
10303
+
10304
+ // Given a line object, find its line number by walking up through
10305
+ // its parent links.
10306
+ function lineNo(line) {
10307
+ if (line.parent == null) return null;
10308
+ var cur = line.parent, no = indexOf(cur.lines, line);
10309
+ for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
10310
+ for (var i = 0;; ++i) {
10311
+ if (chunk.children[i] == cur) break;
10312
+ no += chunk.children[i].chunkSize();
10313
+ }
10314
+ }
10315
+ return no + cur.first;
10316
+ }
10317
+
10318
+ // Find the line at the given vertical position, using the height
10319
+ // information in the document tree.
10320
+ function lineAtHeight(chunk, h) {
10321
+ var n = chunk.first;
10322
+ outer: do {
10323
+ for (var i = 0; i < chunk.children.length; ++i) {
10324
+ var child = chunk.children[i], ch = child.height;
10325
+ if (h < ch) { chunk = child; continue outer; }
10326
+ h -= ch;
10327
+ n += child.chunkSize();
10328
+ }
10329
+ return n;
10330
+ } while (!chunk.lines);
10331
+ for (var i = 0; i < chunk.lines.length; ++i) {
10332
+ var line = chunk.lines[i], lh = line.height;
10333
+ if (h < lh) break;
10334
+ h -= lh;
10335
+ }
10336
+ return n + i;
10337
+ }
10338
+
10339
+
10340
+ // Find the height above the given line.
10341
+ function heightAtLine(lineObj) {
10342
+ lineObj = visualLine(lineObj);
10343
+
10344
+ var h = 0, chunk = lineObj.parent;
10345
+ for (var i = 0; i < chunk.lines.length; ++i) {
10346
+ var line = chunk.lines[i];
10347
+ if (line == lineObj) break;
10348
+ else h += line.height;
10349
+ }
10350
+ for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
10351
+ for (var i = 0; i < p.children.length; ++i) {
10352
+ var cur = p.children[i];
10353
+ if (cur == chunk) break;
10354
+ else h += cur.height;
10355
+ }
10356
+ }
10357
+ return h;
10358
+ }
10359
+
10360
+ // Get the bidi ordering for the given line (and cache it). Returns
10361
+ // false for lines that are fully left-to-right, and an array of
10362
+ // BidiSpan objects otherwise.
10363
+ function getOrder(line) {
10364
+ var order = line.order;
10365
+ if (order == null) order = line.order = bidiOrdering(line.text);
10366
+ return order;
10367
+ }
10368
+
10369
+ // HISTORY
10370
+
10371
+ function History(startGen) {
10372
+ // Arrays of change events and selections. Doing something adds an
10373
+ // event to done and clears undo. Undoing moves events from done
10374
+ // to undone, redoing moves them in the other direction.
10375
+ this.done = []; this.undone = [];
10376
+ this.undoDepth = Infinity;
10377
+ // Used to track when changes can be merged into a single undo
10378
+ // event
10379
+ this.lastModTime = this.lastSelTime = 0;
10380
+ this.lastOp = this.lastSelOp = null;
10381
+ this.lastOrigin = this.lastSelOrigin = null;
10382
+ // Used by the isClean() method
10383
+ this.generation = this.maxGeneration = startGen || 1;
10384
+ }
10385
+
10386
+ // Create a history change event from an updateDoc-style change
10387
+ // object.
10388
+ function historyChangeFromChange(doc, change) {
10389
+ var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
10390
+ attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
10391
+ linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true);
10392
+ return histChange;
10393
+ }
10394
+
10395
+ // Pop all selection events off the end of a history array. Stop at
10396
+ // a change event.
10397
+ function clearSelectionEvents(array) {
10398
+ while (array.length) {
10399
+ var last = lst(array);
10400
+ if (last.ranges) array.pop();
10401
+ else break;
10402
+ }
10403
+ }
10404
+
10405
+ // Find the top change event in the history. Pop off selection
10406
+ // events that are in the way.
10407
+ function lastChangeEvent(hist, force) {
10408
+ if (force) {
10409
+ clearSelectionEvents(hist.done);
10410
+ return lst(hist.done);
10411
+ } else if (hist.done.length && !lst(hist.done).ranges) {
10412
+ return lst(hist.done);
10413
+ } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
10414
+ hist.done.pop();
10415
+ return lst(hist.done);
10416
+ }
10417
+ }
10418
+
10419
+ // Register a change in the history. Merges changes that are within
10420
+ // a single operation, ore are close together with an origin that
10421
+ // allows merging (starting with "+") into a single event.
10422
+ function addChangeToHistory(doc, change, selAfter, opId) {
10423
+ var hist = doc.history;
10424
+ hist.undone.length = 0;
10425
+ var time = +new Date, cur;
10426
+
10427
+ if ((hist.lastOp == opId ||
10428
+ hist.lastOrigin == change.origin && change.origin &&
10429
+ ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
10430
+ change.origin.charAt(0) == "*")) &&
10431
+ (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
10432
+ // Merge this change into the last event
10433
+ var last = lst(cur.changes);
10434
+ if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
10435
+ // Optimized case for simple insertion -- don't want to add
10436
+ // new changesets for every character typed
10437
+ last.to = changeEnd(change);
10438
+ } else {
10439
+ // Add new sub-event
10440
+ cur.changes.push(historyChangeFromChange(doc, change));
10441
+ }
10442
+ } else {
10443
+ // Can not be merged, start a new event.
10444
+ var before = lst(hist.done);
10445
+ if (!before || !before.ranges)
10446
+ pushSelectionToHistory(doc.sel, hist.done);
10447
+ cur = {changes: [historyChangeFromChange(doc, change)],
10448
+ generation: hist.generation};
10449
+ hist.done.push(cur);
10450
+ while (hist.done.length > hist.undoDepth) {
10451
+ hist.done.shift();
10452
+ if (!hist.done[0].ranges) hist.done.shift();
10453
+ }
10454
+ }
10455
+ hist.done.push(selAfter);
10456
+ hist.generation = ++hist.maxGeneration;
10457
+ hist.lastModTime = hist.lastSelTime = time;
10458
+ hist.lastOp = hist.lastSelOp = opId;
10459
+ hist.lastOrigin = hist.lastSelOrigin = change.origin;
10460
+
10461
+ if (!last) signal(doc, "historyAdded");
10462
+ }
10463
+
10464
+ function selectionEventCanBeMerged(doc, origin, prev, sel) {
10465
+ var ch = origin.charAt(0);
10466
+ return ch == "*" ||
10467
+ ch == "+" &&
10468
+ prev.ranges.length == sel.ranges.length &&
10469
+ prev.somethingSelected() == sel.somethingSelected() &&
10470
+ new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500);
10471
+ }
10472
+
10473
+ // Called whenever the selection changes, sets the new selection as
10474
+ // the pending selection in the history, and pushes the old pending
10475
+ // selection into the 'done' array when it was significantly
10476
+ // different (in number of selected ranges, emptiness, or time).
10477
+ function addSelectionToHistory(doc, sel, opId, options) {
10478
+ var hist = doc.history, origin = options && options.origin;
10479
+
10480
+ // A new event is started when the previous origin does not match
10481
+ // the current, or the origins don't allow matching. Origins
10482
+ // starting with * are always merged, those starting with + are
10483
+ // merged when similar and close together in time.
10484
+ if (opId == hist.lastSelOp ||
10485
+ (origin && hist.lastSelOrigin == origin &&
10486
+ (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
10487
+ selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
10488
+ hist.done[hist.done.length - 1] = sel;
10489
+ else
10490
+ pushSelectionToHistory(sel, hist.done);
10491
+
10492
+ hist.lastSelTime = +new Date;
10493
+ hist.lastSelOrigin = origin;
10494
+ hist.lastSelOp = opId;
10495
+ if (options && options.clearRedo !== false)
10496
+ clearSelectionEvents(hist.undone);
10497
+ }
10498
+
10499
+ function pushSelectionToHistory(sel, dest) {
10500
+ var top = lst(dest);
10501
+ if (!(top && top.ranges && top.equals(sel)))
10502
+ dest.push(sel);
10503
+ }
10504
+
10505
+ // Used to store marked span information in the history.
10506
+ function attachLocalSpans(doc, change, from, to) {
10507
+ var existing = change["spans_" + doc.id], n = 0;
10508
+ doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) {
10509
+ if (line.markedSpans)
10510
+ (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans;
10511
+ ++n;
10512
+ });
10513
+ }
10514
+
10515
+ // When un/re-doing restores text containing marked spans, those
10516
+ // that have been explicitly cleared should not be restored.
10517
+ function removeClearedSpans(spans) {
10518
+ if (!spans) return null;
10519
+ for (var i = 0, out; i < spans.length; ++i) {
10520
+ if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); }
10521
+ else if (out) out.push(spans[i]);
10522
+ }
10523
+ return !out ? spans : out.length ? out : null;
10524
+ }
10525
+
10526
+ // Retrieve and filter the old marked spans stored in a change event.
10527
+ function getOldSpans(doc, change) {
10528
+ var found = change["spans_" + doc.id];
10529
+ if (!found) return null;
10530
+ for (var i = 0, nw = []; i < change.text.length; ++i)
10531
+ nw.push(removeClearedSpans(found[i]));
10532
+ return nw;
10533
+ }
10534
+
10535
+ // Used both to provide a JSON-safe object in .getHistory, and, when
10536
+ // detaching a document, to split the history in two
10537
+ function copyHistoryArray(events, newGroup, instantiateSel) {
10538
+ for (var i = 0, copy = []; i < events.length; ++i) {
10539
+ var event = events[i];
10540
+ if (event.ranges) {
10541
+ copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);
10542
+ continue;
10543
+ }
10544
+ var changes = event.changes, newChanges = [];
10545
+ copy.push({changes: newChanges});
10546
+ for (var j = 0; j < changes.length; ++j) {
10547
+ var change = changes[j], m;
10548
+ newChanges.push({from: change.from, to: change.to, text: change.text});
10549
+ if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) {
10550
+ if (indexOf(newGroup, Number(m[1])) > -1) {
10551
+ lst(newChanges)[prop] = change[prop];
10552
+ delete change[prop];
10553
+ }
10554
+ }
10555
+ }
10556
+ }
10557
+ return copy;
10558
+ }
10559
+
10560
+ // Rebasing/resetting history to deal with externally-sourced changes
10561
+
10562
+ function rebaseHistSelSingle(pos, from, to, diff) {
10563
+ if (to < pos.line) {
10564
+ pos.line += diff;
10565
+ } else if (from < pos.line) {
10566
+ pos.line = from;
10567
+ pos.ch = 0;
10568
+ }
10569
+ }
10570
+
10571
+ // Tries to rebase an array of history events given a change in the
10572
+ // document. If the change touches the same lines as the event, the
10573
+ // event, and everything 'behind' it, is discarded. If the change is
10574
+ // before the event, the event's positions are updated. Uses a
10575
+ // copy-on-write scheme for the positions, to avoid having to
10576
+ // reallocate them all on every rebase, but also avoid problems with
10577
+ // shared position objects being unsafely updated.
10578
+ function rebaseHistArray(array, from, to, diff) {
10579
+ for (var i = 0; i < array.length; ++i) {
10580
+ var sub = array[i], ok = true;
10581
+ if (sub.ranges) {
10582
+ if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }
10583
+ for (var j = 0; j < sub.ranges.length; j++) {
10584
+ rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);
10585
+ rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);
10586
+ }
10587
+ continue;
10588
+ }
10589
+ for (var j = 0; j < sub.changes.length; ++j) {
10590
+ var cur = sub.changes[j];
10591
+ if (to < cur.from.line) {
10592
+ cur.from = Pos(cur.from.line + diff, cur.from.ch);
10593
+ cur.to = Pos(cur.to.line + diff, cur.to.ch);
10594
+ } else if (from <= cur.to.line) {
10595
+ ok = false;
10596
+ break;
10597
+ }
10598
+ }
10599
+ if (!ok) {
10600
+ array.splice(0, i + 1);
10601
+ i = 0;
10602
+ }
10603
+ }
10604
+ }
10605
+
10606
+ function rebaseHist(hist, change) {
10607
+ var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
10608
+ rebaseHistArray(hist.done, from, to, diff);
10609
+ rebaseHistArray(hist.undone, from, to, diff);
10610
+ }
10611
+
10612
+ // EVENT UTILITIES
10613
+
10614
+ // Due to the fact that we still support jurassic IE versions, some
10615
+ // compatibility wrappers are needed.
10616
+
10617
+ var e_preventDefault = CodeMirror.e_preventDefault = function(e) {
10618
+ if (e.preventDefault) e.preventDefault();
10619
+ else e.returnValue = false;
10620
+ };
10621
+ var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) {
10622
+ if (e.stopPropagation) e.stopPropagation();
10623
+ else e.cancelBubble = true;
10624
+ };
10625
+ function e_defaultPrevented(e) {
10626
+ return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false;
10627
+ }
10628
+ var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);};
10629
+
10630
+ function e_target(e) {return e.target || e.srcElement;}
10631
+ function e_button(e) {
10632
+ var b = e.which;
10633
+ if (b == null) {
10634
+ if (e.button & 1) b = 1;
10635
+ else if (e.button & 2) b = 3;
10636
+ else if (e.button & 4) b = 2;
10637
+ }
10638
+ if (mac && e.ctrlKey && b == 1) b = 3;
10639
+ return b;
10640
+ }
10641
+
10642
+ // EVENT HANDLING
10643
+
10644
+ // Lightweight event framework. on/off also work on DOM nodes,
10645
+ // registering native DOM handlers.
10646
+
10647
+ var on = CodeMirror.on = function(emitter, type, f) {
10648
+ if (emitter.addEventListener)
10649
+ emitter.addEventListener(type, f, false);
10650
+ else if (emitter.attachEvent)
10651
+ emitter.attachEvent("on" + type, f);
10652
+ else {
10653
+ var map = emitter._handlers || (emitter._handlers = {});
10654
+ var arr = map[type] || (map[type] = []);
10655
+ arr.push(f);
10656
+ }
10657
+ };
10658
+
10659
+ var noHandlers = []
10660
+ function getHandlers(emitter, type, copy) {
10661
+ var arr = emitter._handlers && emitter._handlers[type]
10662
+ if (copy) return arr && arr.length > 0 ? arr.slice() : noHandlers
10663
+ else return arr || noHandlers
10664
+ }
10665
+
10666
+ var off = CodeMirror.off = function(emitter, type, f) {
10667
+ if (emitter.removeEventListener)
10668
+ emitter.removeEventListener(type, f, false);
10669
+ else if (emitter.detachEvent)
10670
+ emitter.detachEvent("on" + type, f);
10671
+ else {
10672
+ var handlers = getHandlers(emitter, type, false)
10673
+ for (var i = 0; i < handlers.length; ++i)
10674
+ if (handlers[i] == f) { handlers.splice(i, 1); break; }
10675
+ }
10676
+ };
10677
+
10678
+ var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {
10679
+ var handlers = getHandlers(emitter, type, true)
10680
+ if (!handlers.length) return;
10681
+ var args = Array.prototype.slice.call(arguments, 2);
10682
+ for (var i = 0; i < handlers.length; ++i) handlers[i].apply(null, args);
10683
+ };
10684
+
10685
+ var orphanDelayedCallbacks = null;
10686
+
10687
+ // Often, we want to signal events at a point where we are in the
10688
+ // middle of some work, but don't want the handler to start calling
10689
+ // other methods on the editor, which might be in an inconsistent
10690
+ // state or simply not expect any other events to happen.
10691
+ // signalLater looks whether there are any handlers, and schedules
10692
+ // them to be executed when the last operation ends, or, if no
10693
+ // operation is active, when a timeout fires.
10694
+ function signalLater(emitter, type /*, values...*/) {
10695
+ var arr = getHandlers(emitter, type, false)
10696
+ if (!arr.length) return;
10697
+ var args = Array.prototype.slice.call(arguments, 2), list;
10698
+ if (operationGroup) {
10699
+ list = operationGroup.delayedCallbacks;
10700
+ } else if (orphanDelayedCallbacks) {
10701
+ list = orphanDelayedCallbacks;
10702
+ } else {
10703
+ list = orphanDelayedCallbacks = [];
10704
+ setTimeout(fireOrphanDelayed, 0);
10705
+ }
10706
+ function bnd(f) {return function(){f.apply(null, args);};};
10707
+ for (var i = 0; i < arr.length; ++i)
10708
+ list.push(bnd(arr[i]));
10709
+ }
10710
+
10711
+ function fireOrphanDelayed() {
10712
+ var delayed = orphanDelayedCallbacks;
10713
+ orphanDelayedCallbacks = null;
10714
+ for (var i = 0; i < delayed.length; ++i) delayed[i]();
10715
+ }
10716
+
10717
+ // The DOM events that CodeMirror handles can be overridden by
10718
+ // registering a (non-DOM) handler on the editor for the event name,
10719
+ // and preventDefault-ing the event in that handler.
10720
+ function signalDOMEvent(cm, e, override) {
10721
+ if (typeof e == "string")
10722
+ e = {type: e, preventDefault: function() { this.defaultPrevented = true; }};
10723
+ signal(cm, override || e.type, cm, e);
10724
+ return e_defaultPrevented(e) || e.codemirrorIgnore;
10725
+ }
10726
+
10727
+ function signalCursorActivity(cm) {
10728
+ var arr = cm._handlers && cm._handlers.cursorActivity;
10729
+ if (!arr) return;
10730
+ var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);
10731
+ for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1)
10732
+ set.push(arr[i]);
10733
+ }
10734
+
10735
+ function hasHandler(emitter, type) {
10736
+ return getHandlers(emitter, type).length > 0
10737
+ }
10738
+
10739
+ // Add on and off methods to a constructor's prototype, to make
10740
+ // registering events on such objects more convenient.
10741
+ function eventMixin(ctor) {
10742
+ ctor.prototype.on = function(type, f) {on(this, type, f);};
10743
+ ctor.prototype.off = function(type, f) {off(this, type, f);};
10744
+ }
10745
+
10746
+ // MISC UTILITIES
10747
+
10748
+ // Number of pixels added to scroller and sizer to hide scrollbar
10749
+ var scrollerGap = 30;
10750
+
10751
+ // Returned or thrown by various protocols to signal 'I'm not
10752
+ // handling this'.
10753
+ var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}};
10754
+
10755
+ // Reused option objects for setSelection & friends
10756
+ var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};
10757
+
10758
+ function Delayed() {this.id = null;}
10759
+ Delayed.prototype.set = function(ms, f) {
10760
+ clearTimeout(this.id);
10761
+ this.id = setTimeout(f, ms);
10762
+ };
10763
+
10764
+ // Counts the column offset in a string, taking tabs into account.
10765
+ // Used mostly to find indentation.
10766
+ var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) {
10767
+ if (end == null) {
10768
+ end = string.search(/[^\s\u00a0]/);
10769
+ if (end == -1) end = string.length;
10770
+ }
10771
+ for (var i = startIndex || 0, n = startValue || 0;;) {
10772
+ var nextTab = string.indexOf("\t", i);
10773
+ if (nextTab < 0 || nextTab >= end)
10774
+ return n + (end - i);
10775
+ n += nextTab - i;
10776
+ n += tabSize - (n % tabSize);
10777
+ i = nextTab + 1;
10778
+ }
10779
+ };
10780
+
10781
+ // The inverse of countColumn -- find the offset that corresponds to
10782
+ // a particular column.
10783
+ var findColumn = CodeMirror.findColumn = function(string, goal, tabSize) {
10784
+ for (var pos = 0, col = 0;;) {
10785
+ var nextTab = string.indexOf("\t", pos);
10786
+ if (nextTab == -1) nextTab = string.length;
10787
+ var skipped = nextTab - pos;
10788
+ if (nextTab == string.length || col + skipped >= goal)
10789
+ return pos + Math.min(skipped, goal - col);
10790
+ col += nextTab - pos;
10791
+ col += tabSize - (col % tabSize);
10792
+ pos = nextTab + 1;
10793
+ if (col >= goal) return pos;
10794
+ }
10795
+ }
10796
+
10797
+ var spaceStrs = [""];
10798
+ function spaceStr(n) {
10799
+ while (spaceStrs.length <= n)
10800
+ spaceStrs.push(lst(spaceStrs) + " ");
10801
+ return spaceStrs[n];
10802
+ }
10803
+
10804
+ function lst(arr) { return arr[arr.length-1]; }
10805
+
10806
+ var selectInput = function(node) { node.select(); };
10807
+ if (ios) // Mobile Safari apparently has a bug where select() is broken.
10808
+ selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; };
10809
+ else if (ie) // Suppress mysterious IE10 errors
10810
+ selectInput = function(node) { try { node.select(); } catch(_e) {} };
10811
+
10812
+ function indexOf(array, elt) {
10813
+ for (var i = 0; i < array.length; ++i)
10814
+ if (array[i] == elt) return i;
10815
+ return -1;
10816
+ }
10817
+ function map(array, f) {
10818
+ var out = [];
10819
+ for (var i = 0; i < array.length; i++) out[i] = f(array[i], i);
10820
+ return out;
10821
+ }
10822
+
10823
+ function nothing() {}
10824
+
10825
+ function createObj(base, props) {
10826
+ var inst;
10827
+ if (Object.create) {
10828
+ inst = Object.create(base);
10829
+ } else {
10830
+ nothing.prototype = base;
10831
+ inst = new nothing();
10832
+ }
10833
+ if (props) copyObj(props, inst);
10834
+ return inst;
10835
+ };
10836
+
10837
+ function copyObj(obj, target, overwrite) {
10838
+ if (!target) target = {};
10839
+ for (var prop in obj)
10840
+ if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
10841
+ target[prop] = obj[prop];
10842
+ return target;
10843
+ }
10844
+
10845
+ function bind(f) {
10846
+ var args = Array.prototype.slice.call(arguments, 1);
10847
+ return function(){return f.apply(null, args);};
10848
+ }
10849
+
10850
+ var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
10851
+ var isWordCharBasic = CodeMirror.isWordChar = function(ch) {
10852
+ return /\w/.test(ch) || ch > "\x80" &&
10853
+ (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch));
10854
+ };
10855
+ function isWordChar(ch, helper) {
10856
+ if (!helper) return isWordCharBasic(ch);
10857
+ if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true;
10858
+ return helper.test(ch);
10859
+ }
10860
+
10861
+ function isEmpty(obj) {
10862
+ for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false;
10863
+ return true;
10864
+ }
10865
+
10866
+ // Extending unicode characters. A series of a non-extending char +
10867
+ // any number of extending chars is treated as a single unit as far
10868
+ // as editing and measuring is concerned. This is not fully correct,
10869
+ // since some scripts/fonts/browsers also treat other configurations
10870
+ // of code points as a group.
10871
+ var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
10872
+ function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); }
10873
+
10874
+ // DOM UTILITIES
10875
+
10876
+ function elt(tag, content, className, style) {
10877
+ var e = document.createElement(tag);
10878
+ if (className) e.className = className;
10879
+ if (style) e.style.cssText = style;
10880
+ if (typeof content == "string") e.appendChild(document.createTextNode(content));
10881
+ else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
10882
+ return e;
10883
+ }
10884
+
10885
+ var range;
10886
+ if (document.createRange) range = function(node, start, end, endNode) {
10887
+ var r = document.createRange();
10888
+ r.setEnd(endNode || node, end);
10889
+ r.setStart(node, start);
10890
+ return r;
10891
+ };
10892
+ else range = function(node, start, end) {
10893
+ var r = document.body.createTextRange();
10894
+ try { r.moveToElementText(node.parentNode); }
10895
+ catch(e) { return r; }
10896
+ r.collapse(true);
10897
+ r.moveEnd("character", end);
10898
+ r.moveStart("character", start);
10899
+ return r;
10900
+ };
10901
+
10902
+ function removeChildren(e) {
10903
+ for (var count = e.childNodes.length; count > 0; --count)
10904
+ e.removeChild(e.firstChild);
10905
+ return e;
10906
+ }
10907
+
10908
+ function removeChildrenAndAdd(parent, e) {
10909
+ return removeChildren(parent).appendChild(e);
10910
+ }
10911
+
10912
+ var contains = CodeMirror.contains = function(parent, child) {
10913
+ if (child.nodeType == 3) // Android browser always returns false when child is a textnode
10914
+ child = child.parentNode;
10915
+ if (parent.contains)
10916
+ return parent.contains(child);
10917
+ do {
10918
+ if (child.nodeType == 11) child = child.host;
10919
+ if (child == parent) return true;
10920
+ } while (child = child.parentNode);
10921
+ };
10922
+
10923
+ function activeElt() {
10924
+ var activeElement = document.activeElement;
10925
+ while (activeElement && activeElement.root && activeElement.root.activeElement)
10926
+ activeElement = activeElement.root.activeElement;
10927
+ return activeElement;
10928
+ }
10929
+ // Older versions of IE throws unspecified error when touching
10930
+ // document.activeElement in some cases (during loading, in iframe)
10931
+ if (ie && ie_version < 11) activeElt = function() {
10932
+ try { return document.activeElement; }
10933
+ catch(e) { return document.body; }
10934
+ };
10935
+
10936
+ function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); }
10937
+ var rmClass = CodeMirror.rmClass = function(node, cls) {
10938
+ var current = node.className;
10939
+ var match = classTest(cls).exec(current);
10940
+ if (match) {
10941
+ var after = current.slice(match.index + match[0].length);
10942
+ node.className = current.slice(0, match.index) + (after ? match[1] + after : "");
10943
+ }
10944
+ };
10945
+ var addClass = CodeMirror.addClass = function(node, cls) {
10946
+ var current = node.className;
10947
+ if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls;
10948
+ };
10949
+ function joinClasses(a, b) {
10950
+ var as = a.split(" ");
10951
+ for (var i = 0; i < as.length; i++)
10952
+ if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i];
10953
+ return b;
10954
+ }
10955
+
10956
+ // WINDOW-WIDE EVENTS
10957
+
10958
+ // These must be handled carefully, because naively registering a
10959
+ // handler for each editor will cause the editors to never be
10960
+ // garbage collected.
10961
+
10962
+ function forEachCodeMirror(f) {
10963
+ if (!document.body.getElementsByClassName) return;
10964
+ var byClass = document.body.getElementsByClassName("CodeMirror");
10965
+ for (var i = 0; i < byClass.length; i++) {
10966
+ var cm = byClass[i].CodeMirror;
10967
+ if (cm) f(cm);
10968
+ }
10969
+ }
10970
+
10971
+ var globalsRegistered = false;
10972
+ function ensureGlobalHandlers() {
10973
+ if (globalsRegistered) return;
10974
+ registerGlobalHandlers();
10975
+ globalsRegistered = true;
10976
+ }
10977
+ function registerGlobalHandlers() {
10978
+ // When the window resizes, we need to refresh active editors.
10979
+ var resizeTimer;
10980
+ on(window, "resize", function() {
10981
+ if (resizeTimer == null) resizeTimer = setTimeout(function() {
10982
+ resizeTimer = null;
10983
+ forEachCodeMirror(onResize);
10984
+ }, 100);
10985
+ });
10986
+ // When the window loses focus, we want to show the editor as blurred
10987
+ on(window, "blur", function() {
10988
+ forEachCodeMirror(onBlur);
10989
+ });
10990
+ }
10991
+
10992
+ // FEATURE DETECTION
10993
+
10994
+ // Detect drag-and-drop
10995
+ var dragAndDrop = function() {
10996
+ // There is *some* kind of drag-and-drop support in IE6-8, but I
10997
+ // couldn't get it to work yet.
10998
+ if (ie && ie_version < 9) return false;
10999
+ var div = elt('div');
11000
+ return "draggable" in div || "dragDrop" in div;
11001
+ }();
11002
+
11003
+ var zwspSupported;
11004
+ function zeroWidthElement(measure) {
11005
+ if (zwspSupported == null) {
11006
+ var test = elt("span", "\u200b");
11007
+ removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
11008
+ if (measure.firstChild.offsetHeight != 0)
11009
+ zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8);
11010
+ }
11011
+ var node = zwspSupported ? elt("span", "\u200b") :
11012
+ elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
11013
+ node.setAttribute("cm-text", "");
11014
+ return node;
11015
+ }
11016
+
11017
+ // Feature-detect IE's crummy client rect reporting for bidi text
11018
+ var badBidiRects;
11019
+ function hasBadBidiRects(measure) {
11020
+ if (badBidiRects != null) return badBidiRects;
11021
+ var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
11022
+ var r0 = range(txt, 0, 1).getBoundingClientRect();
11023
+ if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780)
11024
+ var r1 = range(txt, 1, 2).getBoundingClientRect();
11025
+ return badBidiRects = (r1.right - r0.right < 3);
11026
+ }
11027
+
11028
+ // See if "".split is the broken IE version, if so, provide an
11029
+ // alternative way to split lines.
11030
+ var splitLinesAuto = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
11031
+ var pos = 0, result = [], l = string.length;
11032
+ while (pos <= l) {
11033
+ var nl = string.indexOf("\n", pos);
11034
+ if (nl == -1) nl = string.length;
11035
+ var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
11036
+ var rt = line.indexOf("\r");
11037
+ if (rt != -1) {
11038
+ result.push(line.slice(0, rt));
11039
+ pos += rt + 1;
11040
+ } else {
11041
+ result.push(line);
11042
+ pos = nl + 1;
11043
+ }
11044
+ }
11045
+ return result;
11046
+ } : function(string){return string.split(/\r\n?|\n/);};
11047
+
11048
+ var hasSelection = window.getSelection ? function(te) {
11049
+ try { return te.selectionStart != te.selectionEnd; }
11050
+ catch(e) { return false; }
11051
+ } : function(te) {
11052
+ try {var range = te.ownerDocument.selection.createRange();}
11053
+ catch(e) {}
11054
+ if (!range || range.parentElement() != te) return false;
11055
+ return range.compareEndPoints("StartToEnd", range) != 0;
11056
+ };
11057
+
11058
+ var hasCopyEvent = (function() {
11059
+ var e = elt("div");
11060
+ if ("oncopy" in e) return true;
11061
+ e.setAttribute("oncopy", "return;");
11062
+ return typeof e.oncopy == "function";
11063
+ })();
11064
+
11065
+ var badZoomedRects = null;
11066
+ function hasBadZoomedRects(measure) {
11067
+ if (badZoomedRects != null) return badZoomedRects;
11068
+ var node = removeChildrenAndAdd(measure, elt("span", "x"));
11069
+ var normal = node.getBoundingClientRect();
11070
+ var fromRange = range(node, 0, 1).getBoundingClientRect();
11071
+ return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1;
11072
+ }
11073
+
11074
+ // KEY NAMES
11075
+
11076
+ var keyNames = CodeMirror.keyNames = {
11077
+ 3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
11078
+ 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
11079
+ 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
11080
+ 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
11081
+ 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete",
11082
+ 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
11083
+ 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
11084
+ 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
11085
+ };
11086
+ (function() {
11087
+ // Number keys
11088
+ for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i);
11089
+ // Alphabetic keys
11090
+ for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i);
11091
+ // Function keys
11092
+ for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i;
11093
+ })();
11094
+
11095
+ // BIDI HELPERS
11096
+
11097
+ function iterateBidiSections(order, from, to, f) {
11098
+ if (!order) return f(from, to, "ltr");
11099
+ var found = false;
11100
+ for (var i = 0; i < order.length; ++i) {
11101
+ var part = order[i];
11102
+ if (part.from < to && part.to > from || from == to && part.to == from) {
11103
+ f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr");
11104
+ found = true;
11105
+ }
11106
+ }
11107
+ if (!found) f(from, to, "ltr");
11108
+ }
11109
+
11110
+ function bidiLeft(part) { return part.level % 2 ? part.to : part.from; }
11111
+ function bidiRight(part) { return part.level % 2 ? part.from : part.to; }
11112
+
11113
+ function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; }
11114
+ function lineRight(line) {
11115
+ var order = getOrder(line);
11116
+ if (!order) return line.text.length;
11117
+ return bidiRight(lst(order));
11118
+ }
11119
+
11120
+ function lineStart(cm, lineN) {
11121
+ var line = getLine(cm.doc, lineN);
11122
+ var visual = visualLine(line);
11123
+ if (visual != line) lineN = lineNo(visual);
11124
+ var order = getOrder(visual);
11125
+ var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual);
11126
+ return Pos(lineN, ch);
11127
+ }
11128
+ function lineEnd(cm, lineN) {
11129
+ var merged, line = getLine(cm.doc, lineN);
11130
+ while (merged = collapsedSpanAtEnd(line)) {
11131
+ line = merged.find(1, true).line;
11132
+ lineN = null;
11133
+ }
11134
+ var order = getOrder(line);
11135
+ var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line);
11136
+ return Pos(lineN == null ? lineNo(line) : lineN, ch);
11137
+ }
11138
+ function lineStartSmart(cm, pos) {
11139
+ var start = lineStart(cm, pos.line);
11140
+ var line = getLine(cm.doc, start.line);
11141
+ var order = getOrder(line);
11142
+ if (!order || order[0].level == 0) {
11143
+ var firstNonWS = Math.max(0, line.text.search(/\S/));
11144
+ var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;
11145
+ return Pos(start.line, inWS ? 0 : firstNonWS);
11146
+ }
11147
+ return start;
11148
+ }
11149
+
11150
+ function compareBidiLevel(order, a, b) {
11151
+ var linedir = order[0].level;
11152
+ if (a == linedir) return true;
11153
+ if (b == linedir) return false;
11154
+ return a < b;
11155
+ }
11156
+ var bidiOther;
11157
+ function getBidiPartAt(order, pos) {
11158
+ bidiOther = null;
11159
+ for (var i = 0, found; i < order.length; ++i) {
11160
+ var cur = order[i];
11161
+ if (cur.from < pos && cur.to > pos) return i;
11162
+ if ((cur.from == pos || cur.to == pos)) {
11163
+ if (found == null) {
11164
+ found = i;
11165
+ } else if (compareBidiLevel(order, cur.level, order[found].level)) {
11166
+ if (cur.from != cur.to) bidiOther = found;
11167
+ return i;
11168
+ } else {
11169
+ if (cur.from != cur.to) bidiOther = i;
11170
+ return found;
11171
+ }
11172
+ }
11173
+ }
11174
+ return found;
11175
+ }
11176
+
11177
+ function moveInLine(line, pos, dir, byUnit) {
11178
+ if (!byUnit) return pos + dir;
11179
+ do pos += dir;
11180
+ while (pos > 0 && isExtendingChar(line.text.charAt(pos)));
11181
+ return pos;
11182
+ }
11183
+
11184
+ // This is needed in order to move 'visually' through bi-directional
11185
+ // text -- i.e., pressing left should make the cursor go left, even
11186
+ // when in RTL text. The tricky part is the 'jumps', where RTL and
11187
+ // LTR text touch each other. This often requires the cursor offset
11188
+ // to move more than one unit, in order to visually move one unit.
11189
+ function moveVisually(line, start, dir, byUnit) {
11190
+ var bidi = getOrder(line);
11191
+ if (!bidi) return moveLogically(line, start, dir, byUnit);
11192
+ var pos = getBidiPartAt(bidi, start), part = bidi[pos];
11193
+ var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit);
11194
+
11195
+ for (;;) {
11196
+ if (target > part.from && target < part.to) return target;
11197
+ if (target == part.from || target == part.to) {
11198
+ if (getBidiPartAt(bidi, target) == pos) return target;
11199
+ part = bidi[pos += dir];
11200
+ return (dir > 0) == part.level % 2 ? part.to : part.from;
11201
+ } else {
11202
+ part = bidi[pos += dir];
11203
+ if (!part) return null;
11204
+ if ((dir > 0) == part.level % 2)
11205
+ target = moveInLine(line, part.to, -1, byUnit);
11206
+ else
11207
+ target = moveInLine(line, part.from, 1, byUnit);
11208
+ }
11209
+ }
11210
+ }
11211
+
11212
+ function moveLogically(line, start, dir, byUnit) {
11213
+ var target = start + dir;
11214
+ if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir;
11215
+ return target < 0 || target > line.text.length ? null : target;
11216
+ }
11217
+
11218
+ // Bidirectional ordering algorithm
11219
+ // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
11220
+ // that this (partially) implements.
11221
+
11222
+ // One-char codes used for character types:
11223
+ // L (L): Left-to-Right
11224
+ // R (R): Right-to-Left
11225
+ // r (AL): Right-to-Left Arabic
11226
+ // 1 (EN): European Number
11227
+ // + (ES): European Number Separator
11228
+ // % (ET): European Number Terminator
11229
+ // n (AN): Arabic Number
11230
+ // , (CS): Common Number Separator
11231
+ // m (NSM): Non-Spacing Mark
11232
+ // b (BN): Boundary Neutral
11233
+ // s (B): Paragraph Separator
11234
+ // t (S): Segment Separator
11235
+ // w (WS): Whitespace
11236
+ // N (ON): Other Neutrals
11237
+
11238
+ // Returns null if characters are ordered as they appear
11239
+ // (left-to-right), or an array of sections ({from, to, level}
11240
+ // objects) in the order in which they occur visually.
11241
+ var bidiOrdering = (function() {
11242
+ // Character types for codepoints 0 to 0xff
11243
+ var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";
11244
+ // Character types for codepoints 0x600 to 0x6ff
11245
+ var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm";
11246
+ function charType(code) {
11247
+ if (code <= 0xf7) return lowTypes.charAt(code);
11248
+ else if (0x590 <= code && code <= 0x5f4) return "R";
11249
+ else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600);
11250
+ else if (0x6ee <= code && code <= 0x8ac) return "r";
11251
+ else if (0x2000 <= code && code <= 0x200b) return "w";
11252
+ else if (code == 0x200c) return "b";
11253
+ else return "L";
11254
+ }
11255
+
11256
+ var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
11257
+ var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
11258
+ // Browsers seem to always treat the boundaries of block elements as being L.
11259
+ var outerType = "L";
11260
+
11261
+ function BidiSpan(level, from, to) {
11262
+ this.level = level;
11263
+ this.from = from; this.to = to;
11264
+ }
11265
+
11266
+ return function(str) {
11267
+ if (!bidiRE.test(str)) return false;
11268
+ var len = str.length, types = [];
11269
+ for (var i = 0, type; i < len; ++i)
11270
+ types.push(type = charType(str.charCodeAt(i)));
11271
+
11272
+ // W1. Examine each non-spacing mark (NSM) in the level run, and
11273
+ // change the type of the NSM to the type of the previous
11274
+ // character. If the NSM is at the start of the level run, it will
11275
+ // get the type of sor.
11276
+ for (var i = 0, prev = outerType; i < len; ++i) {
11277
+ var type = types[i];
11278
+ if (type == "m") types[i] = prev;
11279
+ else prev = type;
11280
+ }
11281
+
11282
+ // W2. Search backwards from each instance of a European number
11283
+ // until the first strong type (R, L, AL, or sor) is found. If an
11284
+ // AL is found, change the type of the European number to Arabic
11285
+ // number.
11286
+ // W3. Change all ALs to R.
11287
+ for (var i = 0, cur = outerType; i < len; ++i) {
11288
+ var type = types[i];
11289
+ if (type == "1" && cur == "r") types[i] = "n";
11290
+ else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; }
11291
+ }
11292
+
11293
+ // W4. A single European separator between two European numbers
11294
+ // changes to a European number. A single common separator between
11295
+ // two numbers of the same type changes to that type.
11296
+ for (var i = 1, prev = types[0]; i < len - 1; ++i) {
11297
+ var type = types[i];
11298
+ if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1";
11299
+ else if (type == "," && prev == types[i+1] &&
11300
+ (prev == "1" || prev == "n")) types[i] = prev;
11301
+ prev = type;
11302
+ }
11303
+
11304
+ // W5. A sequence of European terminators adjacent to European
11305
+ // numbers changes to all European numbers.
11306
+ // W6. Otherwise, separators and terminators change to Other
11307
+ // Neutral.
11308
+ for (var i = 0; i < len; ++i) {
11309
+ var type = types[i];
11310
+ if (type == ",") types[i] = "N";
11311
+ else if (type == "%") {
11312
+ for (var end = i + 1; end < len && types[end] == "%"; ++end) {}
11313
+ var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N";
11314
+ for (var j = i; j < end; ++j) types[j] = replace;
11315
+ i = end - 1;
11316
+ }
11317
+ }
11318
+
11319
+ // W7. Search backwards from each instance of a European number
11320
+ // until the first strong type (R, L, or sor) is found. If an L is
11321
+ // found, then change the type of the European number to L.
11322
+ for (var i = 0, cur = outerType; i < len; ++i) {
11323
+ var type = types[i];
11324
+ if (cur == "L" && type == "1") types[i] = "L";
11325
+ else if (isStrong.test(type)) cur = type;
11326
+ }
11327
+
11328
+ // N1. A sequence of neutrals takes the direction of the
11329
+ // surrounding strong text if the text on both sides has the same
11330
+ // direction. European and Arabic numbers act as if they were R in
11331
+ // terms of their influence on neutrals. Start-of-level-run (sor)
11332
+ // and end-of-level-run (eor) are used at level run boundaries.
11333
+ // N2. Any remaining neutrals take the embedding direction.
11334
+ for (var i = 0; i < len; ++i) {
11335
+ if (isNeutral.test(types[i])) {
11336
+ for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {}
11337
+ var before = (i ? types[i-1] : outerType) == "L";
11338
+ var after = (end < len ? types[end] : outerType) == "L";
11339
+ var replace = before || after ? "L" : "R";
11340
+ for (var j = i; j < end; ++j) types[j] = replace;
11341
+ i = end - 1;
11342
+ }
11343
+ }
11344
+
11345
+ // Here we depart from the documented algorithm, in order to avoid
11346
+ // building up an actual levels array. Since there are only three
11347
+ // levels (0, 1, 2) in an implementation that doesn't take
11348
+ // explicit embedding into account, we can build up the order on
11349
+ // the fly, without following the level-based algorithm.
11350
+ var order = [], m;
11351
+ for (var i = 0; i < len;) {
11352
+ if (countsAsLeft.test(types[i])) {
11353
+ var start = i;
11354
+ for (++i; i < len && countsAsLeft.test(types[i]); ++i) {}
11355
+ order.push(new BidiSpan(0, start, i));
11356
+ } else {
11357
+ var pos = i, at = order.length;
11358
+ for (++i; i < len && types[i] != "L"; ++i) {}
11359
+ for (var j = pos; j < i;) {
11360
+ if (countsAsNum.test(types[j])) {
11361
+ if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j));
11362
+ var nstart = j;
11363
+ for (++j; j < i && countsAsNum.test(types[j]); ++j) {}
11364
+ order.splice(at, 0, new BidiSpan(2, nstart, j));
11365
+ pos = j;
11366
+ } else ++j;
11367
+ }
11368
+ if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i));
11369
+ }
11370
+ }
11371
+ if (order[0].level == 1 && (m = str.match(/^\s+/))) {
11372
+ order[0].from = m[0].length;
11373
+ order.unshift(new BidiSpan(0, 0, m[0].length));
11374
+ }
11375
+ if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
11376
+ lst(order).to -= m[0].length;
11377
+ order.push(new BidiSpan(0, len - m[0].length, len));
11378
+ }
11379
+ if (order[0].level == 2)
11380
+ order.unshift(new BidiSpan(1, order[0].to, order[0].to));
11381
+ if (order[0].level != lst(order).level)
11382
+ order.push(new BidiSpan(order[0].level, len, len));
11383
+
11384
+ return order;
11385
+ };
11386
+ })();
11387
+
11388
+ // THE END
11389
+
11390
+ CodeMirror.version = "5.8.0";
11391
+
11392
+ return CodeMirror;
11393
+ });
11394
+
11395
+ },{}],17:[function(require,module,exports){
11396
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
11397
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
11398
+
11399
+ (function(mod) {
11400
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
11401
+ mod(require("../../lib/codemirror"));
11402
+ else if (typeof define == "function" && define.amd) // AMD
11403
+ define(["../../lib/codemirror"], mod);
11404
+ else // Plain browser env
11405
+ mod(CodeMirror);
11406
+ })(function(CodeMirror) {
11407
+ "use strict";
11408
+
11409
+ CodeMirror.defineMode("css", function(config, parserConfig) {
11410
+ var provided = parserConfig;
11411
+ if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
11412
+ parserConfig.inline = provided.inline;
11413
+
11414
+ var indentUnit = config.indentUnit,
11415
+ tokenHooks = parserConfig.tokenHooks,
11416
+ documentTypes = parserConfig.documentTypes || {},
11417
+ mediaTypes = parserConfig.mediaTypes || {},
11418
+ mediaFeatures = parserConfig.mediaFeatures || {},
11419
+ mediaValueKeywords = parserConfig.mediaValueKeywords || {},
11420
+ propertyKeywords = parserConfig.propertyKeywords || {},
11421
+ nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
11422
+ fontProperties = parserConfig.fontProperties || {},
11423
+ counterDescriptors = parserConfig.counterDescriptors || {},
11424
+ colorKeywords = parserConfig.colorKeywords || {},
11425
+ valueKeywords = parserConfig.valueKeywords || {},
11426
+ allowNested = parserConfig.allowNested,
11427
+ supportsAtComponent = parserConfig.supportsAtComponent === true;
11428
+
11429
+ var type, override;
11430
+ function ret(style, tp) { type = tp; return style; }
11431
+
11432
+ // Tokenizers
11433
+
11434
+ function tokenBase(stream, state) {
11435
+ var ch = stream.next();
11436
+ if (tokenHooks[ch]) {
11437
+ var result = tokenHooks[ch](stream, state);
11438
+ if (result !== false) return result;
11439
+ }
11440
+ if (ch == "@") {
11441
+ stream.eatWhile(/[\w\\\-]/);
11442
+ return ret("def", stream.current());
11443
+ } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
11444
+ return ret(null, "compare");
11445
+ } else if (ch == "\"" || ch == "'") {
11446
+ state.tokenize = tokenString(ch);
11447
+ return state.tokenize(stream, state);
11448
+ } else if (ch == "#") {
11449
+ stream.eatWhile(/[\w\\\-]/);
11450
+ return ret("atom", "hash");
11451
+ } else if (ch == "!") {
11452
+ stream.match(/^\s*\w*/);
11453
+ return ret("keyword", "important");
11454
+ } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
11455
+ stream.eatWhile(/[\w.%]/);
11456
+ return ret("number", "unit");
11457
+ } else if (ch === "-") {
11458
+ if (/[\d.]/.test(stream.peek())) {
11459
+ stream.eatWhile(/[\w.%]/);
11460
+ return ret("number", "unit");
11461
+ } else if (stream.match(/^-[\w\\\-]+/)) {
11462
+ stream.eatWhile(/[\w\\\-]/);
11463
+ if (stream.match(/^\s*:/, false))
11464
+ return ret("variable-2", "variable-definition");
11465
+ return ret("variable-2", "variable");
11466
+ } else if (stream.match(/^\w+-/)) {
11467
+ return ret("meta", "meta");
11468
+ }
11469
+ } else if (/[,+>*\/]/.test(ch)) {
11470
+ return ret(null, "select-op");
11471
+ } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
11472
+ return ret("qualifier", "qualifier");
11473
+ } else if (/[:;{}\[\]\(\)]/.test(ch)) {
11474
+ return ret(null, ch);
11475
+ } else if ((ch == "u" && stream.match(/rl(-prefix)?\(/)) ||
11476
+ (ch == "d" && stream.match("omain(")) ||
11477
+ (ch == "r" && stream.match("egexp("))) {
11478
+ stream.backUp(1);
11479
+ state.tokenize = tokenParenthesized;
11480
+ return ret("property", "word");
11481
+ } else if (/[\w\\\-]/.test(ch)) {
11482
+ stream.eatWhile(/[\w\\\-]/);
11483
+ return ret("property", "word");
11484
+ } else {
11485
+ return ret(null, null);
11486
+ }
11487
+ }
11488
+
11489
+ function tokenString(quote) {
11490
+ return function(stream, state) {
11491
+ var escaped = false, ch;
11492
+ while ((ch = stream.next()) != null) {
11493
+ if (ch == quote && !escaped) {
11494
+ if (quote == ")") stream.backUp(1);
11495
+ break;
11496
+ }
11497
+ escaped = !escaped && ch == "\\";
11498
+ }
11499
+ if (ch == quote || !escaped && quote != ")") state.tokenize = null;
11500
+ return ret("string", "string");
11501
+ };
11502
+ }
11503
+
11504
+ function tokenParenthesized(stream, state) {
11505
+ stream.next(); // Must be '('
11506
+ if (!stream.match(/\s*[\"\')]/, false))
11507
+ state.tokenize = tokenString(")");
11508
+ else
11509
+ state.tokenize = null;
11510
+ return ret(null, "(");
11511
+ }
11512
+
11513
+ // Context management
11514
+
11515
+ function Context(type, indent, prev) {
11516
+ this.type = type;
11517
+ this.indent = indent;
11518
+ this.prev = prev;
11519
+ }
11520
+
11521
+ function pushContext(state, stream, type, indent) {
11522
+ state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context);
11523
+ return type;
11524
+ }
11525
+
11526
+ function popContext(state) {
11527
+ if (state.context.prev)
11528
+ state.context = state.context.prev;
11529
+ return state.context.type;
11530
+ }
11531
+
11532
+ function pass(type, stream, state) {
11533
+ return states[state.context.type](type, stream, state);
11534
+ }
11535
+ function popAndPass(type, stream, state, n) {
11536
+ for (var i = n || 1; i > 0; i--)
11537
+ state.context = state.context.prev;
11538
+ return pass(type, stream, state);
11539
+ }
11540
+
11541
+ // Parser
11542
+
11543
+ function wordAsValue(stream) {
11544
+ var word = stream.current().toLowerCase();
11545
+ if (valueKeywords.hasOwnProperty(word))
11546
+ override = "atom";
11547
+ else if (colorKeywords.hasOwnProperty(word))
11548
+ override = "keyword";
11549
+ else
11550
+ override = "variable";
11551
+ }
11552
+
11553
+ var states = {};
11554
+
11555
+ states.top = function(type, stream, state) {
11556
+ if (type == "{") {
11557
+ return pushContext(state, stream, "block");
11558
+ } else if (type == "}" && state.context.prev) {
11559
+ return popContext(state);
11560
+ } else if (supportsAtComponent && /@component/.test(type)) {
11561
+ return pushContext(state, stream, "atComponentBlock");
11562
+ } else if (/^@(-moz-)?document$/.test(type)) {
11563
+ return pushContext(state, stream, "documentTypes");
11564
+ } else if (/^@(media|supports|(-moz-)?document|import)$/.test(type)) {
11565
+ return pushContext(state, stream, "atBlock");
11566
+ } else if (/^@(font-face|counter-style)/.test(type)) {
11567
+ state.stateArg = type;
11568
+ return "restricted_atBlock_before";
11569
+ } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
11570
+ return "keyframes";
11571
+ } else if (type && type.charAt(0) == "@") {
11572
+ return pushContext(state, stream, "at");
11573
+ } else if (type == "hash") {
11574
+ override = "builtin";
11575
+ } else if (type == "word") {
11576
+ override = "tag";
11577
+ } else if (type == "variable-definition") {
11578
+ return "maybeprop";
11579
+ } else if (type == "interpolation") {
11580
+ return pushContext(state, stream, "interpolation");
11581
+ } else if (type == ":") {
11582
+ return "pseudo";
11583
+ } else if (allowNested && type == "(") {
11584
+ return pushContext(state, stream, "parens");
11585
+ }
11586
+ return state.context.type;
11587
+ };
11588
+
11589
+ states.block = function(type, stream, state) {
11590
+ if (type == "word") {
11591
+ var word = stream.current().toLowerCase();
11592
+ if (propertyKeywords.hasOwnProperty(word)) {
11593
+ override = "property";
11594
+ return "maybeprop";
11595
+ } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
11596
+ override = "string-2";
11597
+ return "maybeprop";
11598
+ } else if (allowNested) {
11599
+ override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
11600
+ return "block";
11601
+ } else {
11602
+ override += " error";
11603
+ return "maybeprop";
11604
+ }
11605
+ } else if (type == "meta") {
11606
+ return "block";
11607
+ } else if (!allowNested && (type == "hash" || type == "qualifier")) {
11608
+ override = "error";
11609
+ return "block";
11610
+ } else {
11611
+ return states.top(type, stream, state);
11612
+ }
11613
+ };
11614
+
11615
+ states.maybeprop = function(type, stream, state) {
11616
+ if (type == ":") return pushContext(state, stream, "prop");
11617
+ return pass(type, stream, state);
11618
+ };
11619
+
11620
+ states.prop = function(type, stream, state) {
11621
+ if (type == ";") return popContext(state);
11622
+ if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
11623
+ if (type == "}" || type == "{") return popAndPass(type, stream, state);
11624
+ if (type == "(") return pushContext(state, stream, "parens");
11625
+
11626
+ if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {
11627
+ override += " error";
11628
+ } else if (type == "word") {
11629
+ wordAsValue(stream);
11630
+ } else if (type == "interpolation") {
11631
+ return pushContext(state, stream, "interpolation");
11632
+ }
11633
+ return "prop";
11634
+ };
11635
+
11636
+ states.propBlock = function(type, _stream, state) {
11637
+ if (type == "}") return popContext(state);
11638
+ if (type == "word") { override = "property"; return "maybeprop"; }
11639
+ return state.context.type;
11640
+ };
11641
+
11642
+ states.parens = function(type, stream, state) {
11643
+ if (type == "{" || type == "}") return popAndPass(type, stream, state);
11644
+ if (type == ")") return popContext(state);
11645
+ if (type == "(") return pushContext(state, stream, "parens");
11646
+ if (type == "interpolation") return pushContext(state, stream, "interpolation");
11647
+ if (type == "word") wordAsValue(stream);
11648
+ return "parens";
11649
+ };
11650
+
11651
+ states.pseudo = function(type, stream, state) {
11652
+ if (type == "word") {
11653
+ override = "variable-3";
11654
+ return state.context.type;
11655
+ }
11656
+ return pass(type, stream, state);
11657
+ };
11658
+
11659
+ states.documentTypes = function(type, stream, state) {
11660
+ if (type == "word" && documentTypes.hasOwnProperty(stream.current())) {
11661
+ override = "tag";
11662
+ return state.context.type;
11663
+ } else {
11664
+ return states.atBlock(type, stream, state);
11665
+ }
11666
+ };
11667
+
11668
+ states.atBlock = function(type, stream, state) {
11669
+ if (type == "(") return pushContext(state, stream, "atBlock_parens");
11670
+ if (type == "}" || type == ";") return popAndPass(type, stream, state);
11671
+ if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
11672
+
11673
+ if (type == "interpolation") return pushContext(state, stream, "interpolation");
11674
+
11675
+ if (type == "word") {
11676
+ var word = stream.current().toLowerCase();
11677
+ if (word == "only" || word == "not" || word == "and" || word == "or")
11678
+ override = "keyword";
11679
+ else if (mediaTypes.hasOwnProperty(word))
11680
+ override = "attribute";
11681
+ else if (mediaFeatures.hasOwnProperty(word))
11682
+ override = "property";
11683
+ else if (mediaValueKeywords.hasOwnProperty(word))
11684
+ override = "keyword";
11685
+ else if (propertyKeywords.hasOwnProperty(word))
11686
+ override = "property";
11687
+ else if (nonStandardPropertyKeywords.hasOwnProperty(word))
11688
+ override = "string-2";
11689
+ else if (valueKeywords.hasOwnProperty(word))
11690
+ override = "atom";
11691
+ else if (colorKeywords.hasOwnProperty(word))
11692
+ override = "keyword";
11693
+ else
11694
+ override = "error";
11695
+ }
11696
+ return state.context.type;
11697
+ };
11698
+
11699
+ states.atComponentBlock = function(type, stream, state) {
11700
+ if (type == "}")
11701
+ return popAndPass(type, stream, state);
11702
+ if (type == "{")
11703
+ return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false);
11704
+ if (type == "word")
11705
+ override = "error";
11706
+ return state.context.type;
11707
+ };
11708
+
11709
+ states.atBlock_parens = function(type, stream, state) {
11710
+ if (type == ")") return popContext(state);
11711
+ if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
11712
+ return states.atBlock(type, stream, state);
11713
+ };
11714
+
11715
+ states.restricted_atBlock_before = function(type, stream, state) {
11716
+ if (type == "{")
11717
+ return pushContext(state, stream, "restricted_atBlock");
11718
+ if (type == "word" && state.stateArg == "@counter-style") {
11719
+ override = "variable";
11720
+ return "restricted_atBlock_before";
11721
+ }
11722
+ return pass(type, stream, state);
11723
+ };
11724
+
11725
+ states.restricted_atBlock = function(type, stream, state) {
11726
+ if (type == "}") {
11727
+ state.stateArg = null;
11728
+ return popContext(state);
11729
+ }
11730
+ if (type == "word") {
11731
+ if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
11732
+ (state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
11733
+ override = "error";
11734
+ else
11735
+ override = "property";
11736
+ return "maybeprop";
11737
+ }
11738
+ return "restricted_atBlock";
11739
+ };
11740
+
11741
+ states.keyframes = function(type, stream, state) {
11742
+ if (type == "word") { override = "variable"; return "keyframes"; }
11743
+ if (type == "{") return pushContext(state, stream, "top");
11744
+ return pass(type, stream, state);
11745
+ };
11746
+
11747
+ states.at = function(type, stream, state) {
11748
+ if (type == ";") return popContext(state);
11749
+ if (type == "{" || type == "}") return popAndPass(type, stream, state);
11750
+ if (type == "word") override = "tag";
11751
+ else if (type == "hash") override = "builtin";
11752
+ return "at";
11753
+ };
11754
+
11755
+ states.interpolation = function(type, stream, state) {
11756
+ if (type == "}") return popContext(state);
11757
+ if (type == "{" || type == ";") return popAndPass(type, stream, state);
11758
+ if (type == "word") override = "variable";
11759
+ else if (type != "variable" && type != "(" && type != ")") override = "error";
11760
+ return "interpolation";
11761
+ };
11762
+
11763
+ return {
11764
+ startState: function(base) {
11765
+ return {tokenize: null,
11766
+ state: parserConfig.inline ? "block" : "top",
11767
+ stateArg: null,
11768
+ context: new Context(parserConfig.inline ? "block" : "top", base || 0, null)};
11769
+ },
11770
+
11771
+ token: function(stream, state) {
11772
+ if (!state.tokenize && stream.eatSpace()) return null;
11773
+ var style = (state.tokenize || tokenBase)(stream, state);
11774
+ if (style && typeof style == "object") {
11775
+ type = style[1];
11776
+ style = style[0];
11777
+ }
11778
+ override = style;
11779
+ state.state = states[state.state](type, stream, state);
11780
+ return override;
11781
+ },
11782
+
11783
+ indent: function(state, textAfter) {
11784
+ var cx = state.context, ch = textAfter && textAfter.charAt(0);
11785
+ var indent = cx.indent;
11786
+ if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
11787
+ if (cx.prev) {
11788
+ if (ch == "}" && (cx.type == "block" || cx.type == "top" ||
11789
+ cx.type == "interpolation" || cx.type == "restricted_atBlock")) {
11790
+ // Resume indentation from parent context.
11791
+ cx = cx.prev;
11792
+ indent = cx.indent;
11793
+ } else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
11794
+ ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
11795
+ // Dedent relative to current context.
11796
+ indent = Math.max(0, cx.indent - indentUnit);
11797
+ cx = cx.prev;
11798
+ }
11799
+ }
11800
+ return indent;
11801
+ },
11802
+
11803
+ electricChars: "}",
11804
+ blockCommentStart: "/*",
11805
+ blockCommentEnd: "*/",
11806
+ fold: "brace"
11807
+ };
11808
+ });
11809
+
11810
+ function keySet(array) {
11811
+ var keys = {};
11812
+ for (var i = 0; i < array.length; ++i) {
11813
+ keys[array[i]] = true;
11814
+ }
11815
+ return keys;
11816
+ }
11817
+
11818
+ var documentTypes_ = [
11819
+ "domain", "regexp", "url", "url-prefix"
11820
+ ], documentTypes = keySet(documentTypes_);
11821
+
11822
+ var mediaTypes_ = [
11823
+ "all", "aural", "braille", "handheld", "print", "projection", "screen",
11824
+ "tty", "tv", "embossed"
11825
+ ], mediaTypes = keySet(mediaTypes_);
11826
+
11827
+ var mediaFeatures_ = [
11828
+ "width", "min-width", "max-width", "height", "min-height", "max-height",
11829
+ "device-width", "min-device-width", "max-device-width", "device-height",
11830
+ "min-device-height", "max-device-height", "aspect-ratio",
11831
+ "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
11832
+ "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
11833
+ "max-color", "color-index", "min-color-index", "max-color-index",
11834
+ "monochrome", "min-monochrome", "max-monochrome", "resolution",
11835
+ "min-resolution", "max-resolution", "scan", "grid", "orientation",
11836
+ "device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
11837
+ "pointer", "any-pointer", "hover", "any-hover"
11838
+ ], mediaFeatures = keySet(mediaFeatures_);
11839
+
11840
+ var mediaValueKeywords_ = [
11841
+ "landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
11842
+ "interlace", "progressive"
11843
+ ], mediaValueKeywords = keySet(mediaValueKeywords_);
11844
+
11845
+ var propertyKeywords_ = [
11846
+ "align-content", "align-items", "align-self", "alignment-adjust",
11847
+ "alignment-baseline", "anchor-point", "animation", "animation-delay",
11848
+ "animation-direction", "animation-duration", "animation-fill-mode",
11849
+ "animation-iteration-count", "animation-name", "animation-play-state",
11850
+ "animation-timing-function", "appearance", "azimuth", "backface-visibility",
11851
+ "background", "background-attachment", "background-clip", "background-color",
11852
+ "background-image", "background-origin", "background-position",
11853
+ "background-repeat", "background-size", "baseline-shift", "binding",
11854
+ "bleed", "bookmark-label", "bookmark-level", "bookmark-state",
11855
+ "bookmark-target", "border", "border-bottom", "border-bottom-color",
11856
+ "border-bottom-left-radius", "border-bottom-right-radius",
11857
+ "border-bottom-style", "border-bottom-width", "border-collapse",
11858
+ "border-color", "border-image", "border-image-outset",
11859
+ "border-image-repeat", "border-image-slice", "border-image-source",
11860
+ "border-image-width", "border-left", "border-left-color",
11861
+ "border-left-style", "border-left-width", "border-radius", "border-right",
11862
+ "border-right-color", "border-right-style", "border-right-width",
11863
+ "border-spacing", "border-style", "border-top", "border-top-color",
11864
+ "border-top-left-radius", "border-top-right-radius", "border-top-style",
11865
+ "border-top-width", "border-width", "bottom", "box-decoration-break",
11866
+ "box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
11867
+ "caption-side", "clear", "clip", "color", "color-profile", "column-count",
11868
+ "column-fill", "column-gap", "column-rule", "column-rule-color",
11869
+ "column-rule-style", "column-rule-width", "column-span", "column-width",
11870
+ "columns", "content", "counter-increment", "counter-reset", "crop", "cue",
11871
+ "cue-after", "cue-before", "cursor", "direction", "display",
11872
+ "dominant-baseline", "drop-initial-after-adjust",
11873
+ "drop-initial-after-align", "drop-initial-before-adjust",
11874
+ "drop-initial-before-align", "drop-initial-size", "drop-initial-value",
11875
+ "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
11876
+ "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
11877
+ "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
11878
+ "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
11879
+ "font-stretch", "font-style", "font-synthesis", "font-variant",
11880
+ "font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
11881
+ "font-variant-ligatures", "font-variant-numeric", "font-variant-position",
11882
+ "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
11883
+ "grid-auto-position", "grid-auto-rows", "grid-column", "grid-column-end",
11884
+ "grid-column-start", "grid-row", "grid-row-end", "grid-row-start",
11885
+ "grid-template", "grid-template-areas", "grid-template-columns",
11886
+ "grid-template-rows", "hanging-punctuation", "height", "hyphens",
11887
+ "icon", "image-orientation", "image-rendering", "image-resolution",
11888
+ "inline-box-align", "justify-content", "left", "letter-spacing",
11889
+ "line-break", "line-height", "line-stacking", "line-stacking-ruby",
11890
+ "line-stacking-shift", "line-stacking-strategy", "list-style",
11891
+ "list-style-image", "list-style-position", "list-style-type", "margin",
11892
+ "margin-bottom", "margin-left", "margin-right", "margin-top",
11893
+ "marker-offset", "marks", "marquee-direction", "marquee-loop",
11894
+ "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
11895
+ "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
11896
+ "nav-left", "nav-right", "nav-up", "object-fit", "object-position",
11897
+ "opacity", "order", "orphans", "outline",
11898
+ "outline-color", "outline-offset", "outline-style", "outline-width",
11899
+ "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
11900
+ "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
11901
+ "page", "page-break-after", "page-break-before", "page-break-inside",
11902
+ "page-policy", "pause", "pause-after", "pause-before", "perspective",
11903
+ "perspective-origin", "pitch", "pitch-range", "play-during", "position",
11904
+ "presentation-level", "punctuation-trim", "quotes", "region-break-after",
11905
+ "region-break-before", "region-break-inside", "region-fragment",
11906
+ "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
11907
+ "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
11908
+ "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
11909
+ "shape-outside", "size", "speak", "speak-as", "speak-header",
11910
+ "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
11911
+ "tab-size", "table-layout", "target", "target-name", "target-new",
11912
+ "target-position", "text-align", "text-align-last", "text-decoration",
11913
+ "text-decoration-color", "text-decoration-line", "text-decoration-skip",
11914
+ "text-decoration-style", "text-emphasis", "text-emphasis-color",
11915
+ "text-emphasis-position", "text-emphasis-style", "text-height",
11916
+ "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
11917
+ "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
11918
+ "text-wrap", "top", "transform", "transform-origin", "transform-style",
11919
+ "transition", "transition-delay", "transition-duration",
11920
+ "transition-property", "transition-timing-function", "unicode-bidi",
11921
+ "vertical-align", "visibility", "voice-balance", "voice-duration",
11922
+ "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
11923
+ "voice-volume", "volume", "white-space", "widows", "width", "word-break",
11924
+ "word-spacing", "word-wrap", "z-index",
11925
+ // SVG-specific
11926
+ "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
11927
+ "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
11928
+ "color-interpolation", "color-interpolation-filters",
11929
+ "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
11930
+ "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
11931
+ "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
11932
+ "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
11933
+ "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
11934
+ "glyph-orientation-vertical", "text-anchor", "writing-mode"
11935
+ ], propertyKeywords = keySet(propertyKeywords_);
11936
+
11937
+ var nonStandardPropertyKeywords_ = [
11938
+ "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
11939
+ "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
11940
+ "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
11941
+ "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
11942
+ "searchfield-results-decoration", "zoom"
11943
+ ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
11944
+
11945
+ var fontProperties_ = [
11946
+ "font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
11947
+ "font-stretch", "font-weight", "font-style"
11948
+ ], fontProperties = keySet(fontProperties_);
11949
+
11950
+ var counterDescriptors_ = [
11951
+ "additive-symbols", "fallback", "negative", "pad", "prefix", "range",
11952
+ "speak-as", "suffix", "symbols", "system"
11953
+ ], counterDescriptors = keySet(counterDescriptors_);
11954
+
11955
+ var colorKeywords_ = [
11956
+ "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
11957
+ "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
11958
+ "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
11959
+ "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
11960
+ "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
11961
+ "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
11962
+ "darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
11963
+ "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
11964
+ "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
11965
+ "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
11966
+ "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
11967
+ "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
11968
+ "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
11969
+ "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
11970
+ "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
11971
+ "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
11972
+ "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
11973
+ "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
11974
+ "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
11975
+ "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
11976
+ "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
11977
+ "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
11978
+ "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
11979
+ "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
11980
+ "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
11981
+ "whitesmoke", "yellow", "yellowgreen"
11982
+ ], colorKeywords = keySet(colorKeywords_);
11983
+
11984
+ var valueKeywords_ = [
11985
+ "above", "absolute", "activeborder", "additive", "activecaption", "afar",
11986
+ "after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
11987
+ "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
11988
+ "arabic-indic", "armenian", "asterisks", "attr", "auto", "avoid", "avoid-column", "avoid-page",
11989
+ "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
11990
+ "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
11991
+ "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
11992
+ "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
11993
+ "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
11994
+ "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
11995
+ "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
11996
+ "col-resize", "collapse", "column", "column-reverse", "compact", "condensed", "contain", "content",
11997
+ "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
11998
+ "cross", "crosshair", "currentcolor", "cursive", "cyclic", "dashed", "decimal",
11999
+ "decimal-leading-zero", "default", "default-button", "destination-atop",
12000
+ "destination-in", "destination-out", "destination-over", "devanagari",
12001
+ "disc", "discard", "disclosure-closed", "disclosure-open", "document",
12002
+ "dot-dash", "dot-dot-dash",
12003
+ "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
12004
+ "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
12005
+ "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
12006
+ "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
12007
+ "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
12008
+ "ethiopic-halehame-gez", "ethiopic-halehame-om-et",
12009
+ "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
12010
+ "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
12011
+ "ethiopic-numeric", "ew-resize", "expanded", "extends", "extra-condensed",
12012
+ "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
12013
+ "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
12014
+ "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
12015
+ "help", "hidden", "hide", "higher", "highlight", "highlighttext",
12016
+ "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
12017
+ "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
12018
+ "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
12019
+ "inline-block", "inline-flex", "inline-table", "inset", "inside", "intrinsic", "invert",
12020
+ "italic", "japanese-formal", "japanese-informal", "justify", "kannada",
12021
+ "katakana", "katakana-iroha", "keep-all", "khmer",
12022
+ "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
12023
+ "landscape", "lao", "large", "larger", "left", "level", "lighter",
12024
+ "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
12025
+ "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
12026
+ "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
12027
+ "lower-roman", "lowercase", "ltr", "malayalam", "match", "matrix", "matrix3d",
12028
+ "media-controls-background", "media-current-time-display",
12029
+ "media-fullscreen-button", "media-mute-button", "media-play-button",
12030
+ "media-return-to-realtime-button", "media-rewind-button",
12031
+ "media-seek-back-button", "media-seek-forward-button", "media-slider",
12032
+ "media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
12033
+ "media-volume-slider-container", "media-volume-sliderthumb", "medium",
12034
+ "menu", "menulist", "menulist-button", "menulist-text",
12035
+ "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
12036
+ "mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
12037
+ "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
12038
+ "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
12039
+ "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
12040
+ "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
12041
+ "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
12042
+ "painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter",
12043
+ "pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
12044
+ "progress", "push-button", "radial-gradient", "radio", "read-only",
12045
+ "read-write", "read-write-plaintext-only", "rectangle", "region",
12046
+ "relative", "repeat", "repeating-linear-gradient",
12047
+ "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
12048
+ "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
12049
+ "rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running",
12050
+ "s-resize", "sans-serif", "scale", "scale3d", "scaleX", "scaleY", "scaleZ",
12051
+ "scroll", "scrollbar", "se-resize", "searchfield",
12052
+ "searchfield-cancel-button", "searchfield-decoration",
12053
+ "searchfield-results-button", "searchfield-results-decoration",
12054
+ "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
12055
+ "simp-chinese-formal", "simp-chinese-informal", "single",
12056
+ "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
12057
+ "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
12058
+ "small", "small-caps", "small-caption", "smaller", "solid", "somali",
12059
+ "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square",
12060
+ "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
12061
+ "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table",
12062
+ "table-caption", "table-cell", "table-column", "table-column-group",
12063
+ "table-footer-group", "table-header-group", "table-row", "table-row-group",
12064
+ "tamil",
12065
+ "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
12066
+ "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
12067
+ "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
12068
+ "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
12069
+ "trad-chinese-formal", "trad-chinese-informal",
12070
+ "translate", "translate3d", "translateX", "translateY", "translateZ",
12071
+ "transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
12072
+ "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
12073
+ "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
12074
+ "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
12075
+ "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
12076
+ "window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
12077
+ "xx-large", "xx-small"
12078
+ ], valueKeywords = keySet(valueKeywords_);
12079
+
12080
+ var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_)
12081
+ .concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_)
12082
+ .concat(valueKeywords_);
12083
+ CodeMirror.registerHelper("hintWords", "css", allWords);
12084
+
12085
+ function tokenCComment(stream, state) {
12086
+ var maybeEnd = false, ch;
12087
+ while ((ch = stream.next()) != null) {
12088
+ if (maybeEnd && ch == "/") {
12089
+ state.tokenize = null;
12090
+ break;
12091
+ }
12092
+ maybeEnd = (ch == "*");
12093
+ }
12094
+ return ["comment", "comment"];
12095
+ }
12096
+
12097
+ CodeMirror.defineMIME("text/css", {
12098
+ documentTypes: documentTypes,
12099
+ mediaTypes: mediaTypes,
12100
+ mediaFeatures: mediaFeatures,
12101
+ mediaValueKeywords: mediaValueKeywords,
12102
+ propertyKeywords: propertyKeywords,
12103
+ nonStandardPropertyKeywords: nonStandardPropertyKeywords,
12104
+ fontProperties: fontProperties,
12105
+ counterDescriptors: counterDescriptors,
12106
+ colorKeywords: colorKeywords,
12107
+ valueKeywords: valueKeywords,
12108
+ tokenHooks: {
12109
+ "/": function(stream, state) {
12110
+ if (!stream.eat("*")) return false;
12111
+ state.tokenize = tokenCComment;
12112
+ return tokenCComment(stream, state);
12113
+ }
12114
+ },
12115
+ name: "css"
12116
+ });
12117
+
12118
+ CodeMirror.defineMIME("text/x-scss", {
12119
+ mediaTypes: mediaTypes,
12120
+ mediaFeatures: mediaFeatures,
12121
+ mediaValueKeywords: mediaValueKeywords,
12122
+ propertyKeywords: propertyKeywords,
12123
+ nonStandardPropertyKeywords: nonStandardPropertyKeywords,
12124
+ colorKeywords: colorKeywords,
12125
+ valueKeywords: valueKeywords,
12126
+ fontProperties: fontProperties,
12127
+ allowNested: true,
12128
+ tokenHooks: {
12129
+ "/": function(stream, state) {
12130
+ if (stream.eat("/")) {
12131
+ stream.skipToEnd();
12132
+ return ["comment", "comment"];
12133
+ } else if (stream.eat("*")) {
12134
+ state.tokenize = tokenCComment;
12135
+ return tokenCComment(stream, state);
12136
+ } else {
12137
+ return ["operator", "operator"];
12138
+ }
12139
+ },
12140
+ ":": function(stream) {
12141
+ if (stream.match(/\s*\{/))
12142
+ return [null, "{"];
12143
+ return false;
12144
+ },
12145
+ "$": function(stream) {
12146
+ stream.match(/^[\w-]+/);
12147
+ if (stream.match(/^\s*:/, false))
12148
+ return ["variable-2", "variable-definition"];
12149
+ return ["variable-2", "variable"];
12150
+ },
12151
+ "#": function(stream) {
12152
+ if (!stream.eat("{")) return false;
12153
+ return [null, "interpolation"];
12154
+ }
12155
+ },
12156
+ name: "css",
12157
+ helperType: "scss"
12158
+ });
12159
+
12160
+ CodeMirror.defineMIME("text/x-less", {
12161
+ mediaTypes: mediaTypes,
12162
+ mediaFeatures: mediaFeatures,
12163
+ mediaValueKeywords: mediaValueKeywords,
12164
+ propertyKeywords: propertyKeywords,
12165
+ nonStandardPropertyKeywords: nonStandardPropertyKeywords,
12166
+ colorKeywords: colorKeywords,
12167
+ valueKeywords: valueKeywords,
12168
+ fontProperties: fontProperties,
12169
+ allowNested: true,
12170
+ tokenHooks: {
12171
+ "/": function(stream, state) {
12172
+ if (stream.eat("/")) {
12173
+ stream.skipToEnd();
12174
+ return ["comment", "comment"];
12175
+ } else if (stream.eat("*")) {
12176
+ state.tokenize = tokenCComment;
12177
+ return tokenCComment(stream, state);
12178
+ } else {
12179
+ return ["operator", "operator"];
12180
+ }
12181
+ },
12182
+ "@": function(stream) {
12183
+ if (stream.eat("{")) return [null, "interpolation"];
12184
+ if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
12185
+ stream.eatWhile(/[\w\\\-]/);
12186
+ if (stream.match(/^\s*:/, false))
12187
+ return ["variable-2", "variable-definition"];
12188
+ return ["variable-2", "variable"];
12189
+ },
12190
+ "&": function() {
12191
+ return ["atom", "atom"];
12192
+ }
12193
+ },
12194
+ name: "css",
12195
+ helperType: "less"
12196
+ });
12197
+
12198
+ CodeMirror.defineMIME("text/x-gss", {
12199
+ documentTypes: documentTypes,
12200
+ mediaTypes: mediaTypes,
12201
+ mediaFeatures: mediaFeatures,
12202
+ propertyKeywords: propertyKeywords,
12203
+ nonStandardPropertyKeywords: nonStandardPropertyKeywords,
12204
+ fontProperties: fontProperties,
12205
+ counterDescriptors: counterDescriptors,
12206
+ colorKeywords: colorKeywords,
12207
+ valueKeywords: valueKeywords,
12208
+ supportsAtComponent: true,
12209
+ tokenHooks: {
12210
+ "/": function(stream, state) {
12211
+ if (!stream.eat("*")) return false;
12212
+ state.tokenize = tokenCComment;
12213
+ return tokenCComment(stream, state);
12214
+ }
12215
+ },
12216
+ name: "css",
12217
+ helperType: "gss"
12218
+ });
12219
+
12220
+ });
12221
+
12222
+ },{"../../lib/codemirror":16}],18:[function(require,module,exports){
12223
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
12224
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
12225
+
12226
+ (function(mod) {
12227
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
12228
+ mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
12229
+ else if (typeof define == "function" && define.amd) // AMD
12230
+ define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
12231
+ else // Plain browser env
12232
+ mod(CodeMirror);
12233
+ })(function(CodeMirror) {
12234
+ "use strict";
12235
+
12236
+ var defaultTags = {
12237
+ script: [
12238
+ ["lang", /(javascript|babel)/i, "javascript"],
12239
+ ["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, "javascript"],
12240
+ ["type", /./, "text/plain"],
12241
+ [null, null, "javascript"]
12242
+ ],
12243
+ style: [
12244
+ ["lang", /^css$/i, "css"],
12245
+ ["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"],
12246
+ ["type", /./, "text/plain"],
12247
+ [null, null, "css"]
12248
+ ]
12249
+ };
12250
+
12251
+ function maybeBackup(stream, pat, style) {
12252
+ var cur = stream.current(), close = cur.search(pat);
12253
+ if (close > -1) {
12254
+ stream.backUp(cur.length - close);
12255
+ } else if (cur.match(/<\/?$/)) {
12256
+ stream.backUp(cur.length);
12257
+ if (!stream.match(pat, false)) stream.match(cur);
12258
+ }
12259
+ return style;
12260
+ }
12261
+
12262
+ var attrRegexpCache = {};
12263
+ function getAttrRegexp(attr) {
12264
+ var regexp = attrRegexpCache[attr];
12265
+ if (regexp) return regexp;
12266
+ return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*");
12267
+ }
12268
+
12269
+ function getAttrValue(stream, attr) {
12270
+ var pos = stream.pos, match;
12271
+ while (pos >= 0 && stream.string.charAt(pos) !== "<") pos--;
12272
+ if (pos < 0) return pos;
12273
+ if (match = stream.string.slice(pos, stream.pos).match(getAttrRegexp(attr)))
12274
+ return match[2];
12275
+ return "";
12276
+ }
12277
+
12278
+ function getTagRegexp(tagName, anchored) {
12279
+ return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i");
12280
+ }
12281
+
12282
+ function addTags(from, to) {
12283
+ for (var tag in from) {
12284
+ var dest = to[tag] || (to[tag] = []);
12285
+ var source = from[tag];
12286
+ for (var i = source.length - 1; i >= 0; i--)
12287
+ dest.unshift(source[i])
12288
+ }
12289
+ }
12290
+
12291
+ function findMatchingMode(tagInfo, stream) {
12292
+ for (var i = 0; i < tagInfo.length; i++) {
12293
+ var spec = tagInfo[i];
12294
+ if (!spec[0] || spec[1].test(getAttrValue(stream, spec[0]))) return spec[2];
12295
+ }
12296
+ }
12297
+
12298
+ CodeMirror.defineMode("htmlmixed", function (config, parserConfig) {
12299
+ var htmlMode = CodeMirror.getMode(config, {
12300
+ name: "xml",
12301
+ htmlMode: true,
12302
+ multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
12303
+ multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag
12304
+ });
12305
+
12306
+ var tags = {};
12307
+ var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes;
12308
+ addTags(defaultTags, tags);
12309
+ if (configTags) addTags(configTags, tags);
12310
+ if (configScript) for (var i = configScript.length - 1; i >= 0; i--)
12311
+ tags.script.unshift(["type", configScript[i].matches, configScript[i].mode])
12312
+
12313
+ function html(stream, state) {
12314
+ var tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase();
12315
+ var tagInfo = tagName && tags.hasOwnProperty(tagName) && tags[tagName];
12316
+
12317
+ var style = htmlMode.token(stream, state.htmlState), modeSpec;
12318
+
12319
+ if (tagInfo && /\btag\b/.test(style) && stream.current() === ">" &&
12320
+ (modeSpec = findMatchingMode(tagInfo, stream))) {
12321
+ var mode = CodeMirror.getMode(config, modeSpec);
12322
+ var endTagA = getTagRegexp(tagName, true), endTag = getTagRegexp(tagName, false);
12323
+ state.token = function (stream, state) {
12324
+ if (stream.match(endTagA, false)) {
12325
+ state.token = html;
12326
+ state.localState = state.localMode = null;
12327
+ return null;
12328
+ }
12329
+ return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState));
12330
+ };
12331
+ state.localMode = mode;
12332
+ state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, ""));
12333
+ }
12334
+ return style;
12335
+ };
12336
+
12337
+ return {
12338
+ startState: function () {
12339
+ var state = htmlMode.startState();
12340
+ return {token: html, localMode: null, localState: null, htmlState: state};
12341
+ },
12342
+
12343
+ copyState: function (state) {
12344
+ var local;
12345
+ if (state.localState) {
12346
+ local = CodeMirror.copyState(state.localMode, state.localState);
12347
+ }
12348
+ return {token: state.token, localMode: state.localMode, localState: local,
12349
+ htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
12350
+ },
12351
+
12352
+ token: function (stream, state) {
12353
+ return state.token(stream, state);
12354
+ },
12355
+
12356
+ indent: function (state, textAfter) {
12357
+ if (!state.localMode || /^\s*<\//.test(textAfter))
12358
+ return htmlMode.indent(state.htmlState, textAfter);
12359
+ else if (state.localMode.indent)
12360
+ return state.localMode.indent(state.localState, textAfter);
12361
+ else
12362
+ return CodeMirror.Pass;
12363
+ },
12364
+
12365
+ innerMode: function (state) {
12366
+ return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
12367
+ }
12368
+ };
12369
+ }, "xml", "javascript", "css");
12370
+
12371
+ CodeMirror.defineMIME("text/html", "htmlmixed");
12372
+ });
12373
+
12374
+ },{"../../lib/codemirror":16,"../css/css":17,"../javascript/javascript":19,"../xml/xml":20}],19:[function(require,module,exports){
12375
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
12376
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
12377
+
12378
+ // TODO actually recognize syntax of TypeScript constructs
12379
+
12380
+ (function(mod) {
12381
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
12382
+ mod(require("../../lib/codemirror"));
12383
+ else if (typeof define == "function" && define.amd) // AMD
12384
+ define(["../../lib/codemirror"], mod);
12385
+ else // Plain browser env
12386
+ mod(CodeMirror);
12387
+ })(function(CodeMirror) {
12388
+ "use strict";
12389
+
12390
+ CodeMirror.defineMode("javascript", function(config, parserConfig) {
12391
+ var indentUnit = config.indentUnit;
12392
+ var statementIndent = parserConfig.statementIndent;
12393
+ var jsonldMode = parserConfig.jsonld;
12394
+ var jsonMode = parserConfig.json || jsonldMode;
12395
+ var isTS = parserConfig.typescript;
12396
+ var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
12397
+
12398
+ // Tokenizer
12399
+
12400
+ var keywords = function(){
12401
+ function kw(type) {return {type: type, style: "keyword"};}
12402
+ var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
12403
+ var operator = kw("operator"), atom = {type: "atom", style: "atom"};
12404
+
12405
+ var jsKeywords = {
12406
+ "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
12407
+ "return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C,
12408
+ "var": kw("var"), "const": kw("var"), "let": kw("var"),
12409
+ "async": kw("async"), "function": kw("function"), "catch": kw("catch"),
12410
+ "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
12411
+ "in": operator, "typeof": operator, "instanceof": operator,
12412
+ "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
12413
+ "this": kw("this"), "class": kw("class"), "super": kw("atom"),
12414
+ "await": C, "yield": C, "export": kw("export"), "import": kw("import"), "extends": C
12415
+ };
12416
+
12417
+ // Extend the 'normal' keywords with the TypeScript language extensions
12418
+ if (isTS) {
12419
+ var type = {type: "variable", style: "variable-3"};
12420
+ var tsKeywords = {
12421
+ // object-like things
12422
+ "interface": kw("interface"),
12423
+ "extends": kw("extends"),
12424
+ "constructor": kw("constructor"),
12425
+
12426
+ // scope modifiers
12427
+ "public": kw("public"),
12428
+ "private": kw("private"),
12429
+ "protected": kw("protected"),
12430
+ "static": kw("static"),
12431
+
12432
+ // types
12433
+ "string": type, "number": type, "boolean": type, "any": type
12434
+ };
12435
+
12436
+ for (var attr in tsKeywords) {
12437
+ jsKeywords[attr] = tsKeywords[attr];
12438
+ }
12439
+ }
12440
+
12441
+ return jsKeywords;
12442
+ }();
12443
+
12444
+ var isOperatorChar = /[+\-*&%=<>!?|~^]/;
12445
+ var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
12446
+
12447
+ function readRegexp(stream) {
12448
+ var escaped = false, next, inSet = false;
12449
+ while ((next = stream.next()) != null) {
12450
+ if (!escaped) {
12451
+ if (next == "/" && !inSet) return;
12452
+ if (next == "[") inSet = true;
12453
+ else if (inSet && next == "]") inSet = false;
12454
+ }
12455
+ escaped = !escaped && next == "\\";
12456
+ }
12457
+ }
12458
+
12459
+ // Used as scratch variables to communicate multiple values without
12460
+ // consing up tons of objects.
12461
+ var type, content;
12462
+ function ret(tp, style, cont) {
12463
+ type = tp; content = cont;
12464
+ return style;
12465
+ }
12466
+ function tokenBase(stream, state) {
12467
+ var ch = stream.next();
12468
+ if (ch == '"' || ch == "'") {
12469
+ state.tokenize = tokenString(ch);
12470
+ return state.tokenize(stream, state);
12471
+ } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
12472
+ return ret("number", "number");
12473
+ } else if (ch == "." && stream.match("..")) {
12474
+ return ret("spread", "meta");
12475
+ } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
12476
+ return ret(ch);
12477
+ } else if (ch == "=" && stream.eat(">")) {
12478
+ return ret("=>", "operator");
12479
+ } else if (ch == "0" && stream.eat(/x/i)) {
12480
+ stream.eatWhile(/[\da-f]/i);
12481
+ return ret("number", "number");
12482
+ } else if (ch == "0" && stream.eat(/o/i)) {
12483
+ stream.eatWhile(/[0-7]/i);
12484
+ return ret("number", "number");
12485
+ } else if (ch == "0" && stream.eat(/b/i)) {
12486
+ stream.eatWhile(/[01]/i);
12487
+ return ret("number", "number");
12488
+ } else if (/\d/.test(ch)) {
12489
+ stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
12490
+ return ret("number", "number");
12491
+ } else if (ch == "/") {
12492
+ if (stream.eat("*")) {
12493
+ state.tokenize = tokenComment;
12494
+ return tokenComment(stream, state);
12495
+ } else if (stream.eat("/")) {
12496
+ stream.skipToEnd();
12497
+ return ret("comment", "comment");
12498
+ } else if (state.lastType == "operator" || state.lastType == "keyword c" ||
12499
+ state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
12500
+ readRegexp(stream);
12501
+ stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
12502
+ return ret("regexp", "string-2");
12503
+ } else {
12504
+ stream.eatWhile(isOperatorChar);
12505
+ return ret("operator", "operator", stream.current());
12506
+ }
12507
+ } else if (ch == "`") {
12508
+ state.tokenize = tokenQuasi;
12509
+ return tokenQuasi(stream, state);
12510
+ } else if (ch == "#") {
12511
+ stream.skipToEnd();
12512
+ return ret("error", "error");
12513
+ } else if (isOperatorChar.test(ch)) {
12514
+ stream.eatWhile(isOperatorChar);
12515
+ return ret("operator", "operator", stream.current());
12516
+ } else if (wordRE.test(ch)) {
12517
+ stream.eatWhile(wordRE);
12518
+ var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
12519
+ return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
12520
+ ret("variable", "variable", word);
12521
+ }
12522
+ }
12523
+
12524
+ function tokenString(quote) {
12525
+ return function(stream, state) {
12526
+ var escaped = false, next;
12527
+ if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
12528
+ state.tokenize = tokenBase;
12529
+ return ret("jsonld-keyword", "meta");
12530
+ }
12531
+ while ((next = stream.next()) != null) {
12532
+ if (next == quote && !escaped) break;
12533
+ escaped = !escaped && next == "\\";
12534
+ }
12535
+ if (!escaped) state.tokenize = tokenBase;
12536
+ return ret("string", "string");
12537
+ };
12538
+ }
12539
+
12540
+ function tokenComment(stream, state) {
12541
+ var maybeEnd = false, ch;
12542
+ while (ch = stream.next()) {
12543
+ if (ch == "/" && maybeEnd) {
12544
+ state.tokenize = tokenBase;
12545
+ break;
12546
+ }
12547
+ maybeEnd = (ch == "*");
12548
+ }
12549
+ return ret("comment", "comment");
12550
+ }
12551
+
12552
+ function tokenQuasi(stream, state) {
12553
+ var escaped = false, next;
12554
+ while ((next = stream.next()) != null) {
12555
+ if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
12556
+ state.tokenize = tokenBase;
12557
+ break;
12558
+ }
12559
+ escaped = !escaped && next == "\\";
12560
+ }
12561
+ return ret("quasi", "string-2", stream.current());
12562
+ }
12563
+
12564
+ var brackets = "([{}])";
12565
+ // This is a crude lookahead trick to try and notice that we're
12566
+ // parsing the argument patterns for a fat-arrow function before we
12567
+ // actually hit the arrow token. It only works if the arrow is on
12568
+ // the same line as the arguments and there's no strange noise
12569
+ // (comments) in between. Fallback is to only notice when we hit the
12570
+ // arrow, and not declare the arguments as locals for the arrow
12571
+ // body.
12572
+ function findFatArrow(stream, state) {
12573
+ if (state.fatArrowAt) state.fatArrowAt = null;
12574
+ var arrow = stream.string.indexOf("=>", stream.start);
12575
+ if (arrow < 0) return;
12576
+
12577
+ var depth = 0, sawSomething = false;
12578
+ for (var pos = arrow - 1; pos >= 0; --pos) {
12579
+ var ch = stream.string.charAt(pos);
12580
+ var bracket = brackets.indexOf(ch);
12581
+ if (bracket >= 0 && bracket < 3) {
12582
+ if (!depth) { ++pos; break; }
12583
+ if (--depth == 0) break;
12584
+ } else if (bracket >= 3 && bracket < 6) {
12585
+ ++depth;
12586
+ } else if (wordRE.test(ch)) {
12587
+ sawSomething = true;
12588
+ } else if (/["'\/]/.test(ch)) {
12589
+ return;
12590
+ } else if (sawSomething && !depth) {
12591
+ ++pos;
12592
+ break;
12593
+ }
12594
+ }
12595
+ if (sawSomething && !depth) state.fatArrowAt = pos;
12596
+ }
12597
+
12598
+ // Parser
12599
+
12600
+ var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
12601
+
12602
+ function JSLexical(indented, column, type, align, prev, info) {
12603
+ this.indented = indented;
12604
+ this.column = column;
12605
+ this.type = type;
12606
+ this.prev = prev;
12607
+ this.info = info;
12608
+ if (align != null) this.align = align;
12609
+ }
12610
+
12611
+ function inScope(state, varname) {
12612
+ for (var v = state.localVars; v; v = v.next)
12613
+ if (v.name == varname) return true;
12614
+ for (var cx = state.context; cx; cx = cx.prev) {
12615
+ for (var v = cx.vars; v; v = v.next)
12616
+ if (v.name == varname) return true;
12617
+ }
12618
+ }
12619
+
12620
+ function parseJS(state, style, type, content, stream) {
12621
+ var cc = state.cc;
12622
+ // Communicate our context to the combinators.
12623
+ // (Less wasteful than consing up a hundred closures on every call.)
12624
+ cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
12625
+
12626
+ if (!state.lexical.hasOwnProperty("align"))
12627
+ state.lexical.align = true;
12628
+
12629
+ while(true) {
12630
+ var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
12631
+ if (combinator(type, content)) {
12632
+ while(cc.length && cc[cc.length - 1].lex)
12633
+ cc.pop()();
12634
+ if (cx.marked) return cx.marked;
12635
+ if (type == "variable" && inScope(state, content)) return "variable-2";
12636
+ return style;
12637
+ }
12638
+ }
12639
+ }
12640
+
12641
+ // Combinator utils
12642
+
12643
+ var cx = {state: null, column: null, marked: null, cc: null};
12644
+ function pass() {
12645
+ for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
12646
+ }
12647
+ function cont() {
12648
+ pass.apply(null, arguments);
12649
+ return true;
12650
+ }
12651
+ function register(varname) {
12652
+ function inList(list) {
12653
+ for (var v = list; v; v = v.next)
12654
+ if (v.name == varname) return true;
12655
+ return false;
12656
+ }
12657
+ var state = cx.state;
12658
+ cx.marked = "def";
12659
+ if (state.context) {
12660
+ if (inList(state.localVars)) return;
12661
+ state.localVars = {name: varname, next: state.localVars};
12662
+ } else {
12663
+ if (inList(state.globalVars)) return;
12664
+ if (parserConfig.globalVars)
12665
+ state.globalVars = {name: varname, next: state.globalVars};
12666
+ }
12667
+ }
12668
+
12669
+ // Combinators
12670
+
12671
+ var defaultVars = {name: "this", next: {name: "arguments"}};
12672
+ function pushcontext() {
12673
+ cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
12674
+ cx.state.localVars = defaultVars;
12675
+ }
12676
+ function popcontext() {
12677
+ cx.state.localVars = cx.state.context.vars;
12678
+ cx.state.context = cx.state.context.prev;
12679
+ }
12680
+ function pushlex(type, info) {
12681
+ var result = function() {
12682
+ var state = cx.state, indent = state.indented;
12683
+ if (state.lexical.type == "stat") indent = state.lexical.indented;
12684
+ else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
12685
+ indent = outer.indented;
12686
+ state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
12687
+ };
12688
+ result.lex = true;
12689
+ return result;
12690
+ }
12691
+ function poplex() {
12692
+ var state = cx.state;
12693
+ if (state.lexical.prev) {
12694
+ if (state.lexical.type == ")")
12695
+ state.indented = state.lexical.indented;
12696
+ state.lexical = state.lexical.prev;
12697
+ }
12698
+ }
12699
+ poplex.lex = true;
12700
+
12701
+ function expect(wanted) {
12702
+ function exp(type) {
12703
+ if (type == wanted) return cont();
12704
+ else if (wanted == ";") return pass();
12705
+ else return cont(exp);
12706
+ };
12707
+ return exp;
12708
+ }
12709
+
12710
+ function statement(type, value) {
12711
+ if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
12712
+ if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
12713
+ if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
12714
+ if (type == "{") return cont(pushlex("}"), block, poplex);
12715
+ if (type == ";") return cont();
12716
+ if (type == "if") {
12717
+ if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
12718
+ cx.state.cc.pop()();
12719
+ return cont(pushlex("form"), expression, statement, poplex, maybeelse);
12720
+ }
12721
+ if (type == "function") return cont(functiondef);
12722
+ if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
12723
+ if (type == "variable") return cont(pushlex("stat"), maybelabel);
12724
+ if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
12725
+ block, poplex, poplex);
12726
+ if (type == "case") return cont(expression, expect(":"));
12727
+ if (type == "default") return cont(expect(":"));
12728
+ if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
12729
+ statement, poplex, popcontext);
12730
+ if (type == "class") return cont(pushlex("form"), className, poplex);
12731
+ if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
12732
+ if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
12733
+ return pass(pushlex("stat"), expression, expect(";"), poplex);
12734
+ }
12735
+ function expression(type) {
12736
+ return expressionInner(type, false);
12737
+ }
12738
+ function expressionNoComma(type) {
12739
+ return expressionInner(type, true);
12740
+ }
12741
+ function expressionInner(type, noComma) {
12742
+ if (cx.state.fatArrowAt == cx.stream.start) {
12743
+ var body = noComma ? arrowBodyNoComma : arrowBody;
12744
+ if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
12745
+ else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
12746
+ }
12747
+
12748
+ var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
12749
+ if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
12750
+ if (type == "async") return cont(expression);
12751
+ if (type == "function") return cont(functiondef, maybeop);
12752
+ if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
12753
+ if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
12754
+ if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
12755
+ if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
12756
+ if (type == "{") return contCommasep(objprop, "}", null, maybeop);
12757
+ if (type == "quasi") return pass(quasi, maybeop);
12758
+ if (type == "new") return cont(maybeTarget(noComma));
12759
+ return cont();
12760
+ }
12761
+ function maybeexpression(type) {
12762
+ if (type.match(/[;\}\)\],]/)) return pass();
12763
+ return pass(expression);
12764
+ }
12765
+ function maybeexpressionNoComma(type) {
12766
+ if (type.match(/[;\}\)\],]/)) return pass();
12767
+ return pass(expressionNoComma);
12768
+ }
12769
+
12770
+ function maybeoperatorComma(type, value) {
12771
+ if (type == ",") return cont(expression);
12772
+ return maybeoperatorNoComma(type, value, false);
12773
+ }
12774
+ function maybeoperatorNoComma(type, value, noComma) {
12775
+ var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
12776
+ var expr = noComma == false ? expression : expressionNoComma;
12777
+ if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
12778
+ if (type == "operator") {
12779
+ if (/\+\+|--/.test(value)) return cont(me);
12780
+ if (value == "?") return cont(expression, expect(":"), expr);
12781
+ return cont(expr);
12782
+ }
12783
+ if (type == "quasi") { return pass(quasi, me); }
12784
+ if (type == ";") return;
12785
+ if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
12786
+ if (type == ".") return cont(property, me);
12787
+ if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
12788
+ }
12789
+ function quasi(type, value) {
12790
+ if (type != "quasi") return pass();
12791
+ if (value.slice(value.length - 2) != "${") return cont(quasi);
12792
+ return cont(expression, continueQuasi);
12793
+ }
12794
+ function continueQuasi(type) {
12795
+ if (type == "}") {
12796
+ cx.marked = "string-2";
12797
+ cx.state.tokenize = tokenQuasi;
12798
+ return cont(quasi);
12799
+ }
12800
+ }
12801
+ function arrowBody(type) {
12802
+ findFatArrow(cx.stream, cx.state);
12803
+ return pass(type == "{" ? statement : expression);
12804
+ }
12805
+ function arrowBodyNoComma(type) {
12806
+ findFatArrow(cx.stream, cx.state);
12807
+ return pass(type == "{" ? statement : expressionNoComma);
12808
+ }
12809
+ function maybeTarget(noComma) {
12810
+ return function(type) {
12811
+ if (type == ".") return cont(noComma ? targetNoComma : target);
12812
+ else return pass(noComma ? expressionNoComma : expression);
12813
+ };
12814
+ }
12815
+ function target(_, value) {
12816
+ if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
12817
+ }
12818
+ function targetNoComma(_, value) {
12819
+ if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
12820
+ }
12821
+ function maybelabel(type) {
12822
+ if (type == ":") return cont(poplex, statement);
12823
+ return pass(maybeoperatorComma, expect(";"), poplex);
12824
+ }
12825
+ function property(type) {
12826
+ if (type == "variable") {cx.marked = "property"; return cont();}
12827
+ }
12828
+ function objprop(type, value) {
12829
+ if (type == "async") {
12830
+ return cont(objprop);
12831
+ } else if (type == "variable" || cx.style == "keyword") {
12832
+ cx.marked = "property";
12833
+ if (value == "get" || value == "set") return cont(getterSetter);
12834
+ return cont(afterprop);
12835
+ } else if (type == "number" || type == "string") {
12836
+ cx.marked = jsonldMode ? "property" : (cx.style + " property");
12837
+ return cont(afterprop);
12838
+ } else if (type == "jsonld-keyword") {
12839
+ return cont(afterprop);
12840
+ } else if (type == "[") {
12841
+ return cont(expression, expect("]"), afterprop);
12842
+ }
12843
+ }
12844
+ function getterSetter(type) {
12845
+ if (type != "variable") return pass(afterprop);
12846
+ cx.marked = "property";
12847
+ return cont(functiondef);
12848
+ }
12849
+ function afterprop(type) {
12850
+ if (type == ":") return cont(expressionNoComma);
12851
+ if (type == "(") return pass(functiondef);
12852
+ }
12853
+ function commasep(what, end) {
12854
+ function proceed(type) {
12855
+ if (type == ",") {
12856
+ var lex = cx.state.lexical;
12857
+ if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
12858
+ return cont(what, proceed);
12859
+ }
12860
+ if (type == end) return cont();
12861
+ return cont(expect(end));
12862
+ }
12863
+ return function(type) {
12864
+ if (type == end) return cont();
12865
+ return pass(what, proceed);
12866
+ };
12867
+ }
12868
+ function contCommasep(what, end, info) {
12869
+ for (var i = 3; i < arguments.length; i++)
12870
+ cx.cc.push(arguments[i]);
12871
+ return cont(pushlex(end, info), commasep(what, end), poplex);
12872
+ }
12873
+ function block(type) {
12874
+ if (type == "}") return cont();
12875
+ return pass(statement, block);
12876
+ }
12877
+ function maybetype(type) {
12878
+ if (isTS && type == ":") return cont(typedef);
12879
+ }
12880
+ function maybedefault(_, value) {
12881
+ if (value == "=") return cont(expressionNoComma);
12882
+ }
12883
+ function typedef(type) {
12884
+ if (type == "variable") {cx.marked = "variable-3"; return cont();}
12885
+ }
12886
+ function vardef() {
12887
+ return pass(pattern, maybetype, maybeAssign, vardefCont);
12888
+ }
12889
+ function pattern(type, value) {
12890
+ if (type == "variable") { register(value); return cont(); }
12891
+ if (type == "spread") return cont(pattern);
12892
+ if (type == "[") return contCommasep(pattern, "]");
12893
+ if (type == "{") return contCommasep(proppattern, "}");
12894
+ }
12895
+ function proppattern(type, value) {
12896
+ if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
12897
+ register(value);
12898
+ return cont(maybeAssign);
12899
+ }
12900
+ if (type == "variable") cx.marked = "property";
12901
+ if (type == "spread") return cont(pattern);
12902
+ return cont(expect(":"), pattern, maybeAssign);
12903
+ }
12904
+ function maybeAssign(_type, value) {
12905
+ if (value == "=") return cont(expressionNoComma);
12906
+ }
12907
+ function vardefCont(type) {
12908
+ if (type == ",") return cont(vardef);
12909
+ }
12910
+ function maybeelse(type, value) {
12911
+ if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
12912
+ }
12913
+ function forspec(type) {
12914
+ if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
12915
+ }
12916
+ function forspec1(type) {
12917
+ if (type == "var") return cont(vardef, expect(";"), forspec2);
12918
+ if (type == ";") return cont(forspec2);
12919
+ if (type == "variable") return cont(formaybeinof);
12920
+ return pass(expression, expect(";"), forspec2);
12921
+ }
12922
+ function formaybeinof(_type, value) {
12923
+ if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
12924
+ return cont(maybeoperatorComma, forspec2);
12925
+ }
12926
+ function forspec2(type, value) {
12927
+ if (type == ";") return cont(forspec3);
12928
+ if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
12929
+ return pass(expression, expect(";"), forspec3);
12930
+ }
12931
+ function forspec3(type) {
12932
+ if (type != ")") cont(expression);
12933
+ }
12934
+ function functiondef(type, value) {
12935
+ if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
12936
+ if (type == "variable") {register(value); return cont(functiondef);}
12937
+ if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
12938
+ }
12939
+ function funarg(type) {
12940
+ if (type == "spread") return cont(funarg);
12941
+ return pass(pattern, maybetype, maybedefault);
12942
+ }
12943
+ function className(type, value) {
12944
+ if (type == "variable") {register(value); return cont(classNameAfter);}
12945
+ }
12946
+ function classNameAfter(type, value) {
12947
+ if (value == "extends") return cont(expression, classNameAfter);
12948
+ if (type == "{") return cont(pushlex("}"), classBody, poplex);
12949
+ }
12950
+ function classBody(type, value) {
12951
+ if (type == "variable" || cx.style == "keyword") {
12952
+ if (value == "static") {
12953
+ cx.marked = "keyword";
12954
+ return cont(classBody);
12955
+ }
12956
+ cx.marked = "property";
12957
+ if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);
12958
+ return cont(functiondef, classBody);
12959
+ }
12960
+ if (value == "*") {
12961
+ cx.marked = "keyword";
12962
+ return cont(classBody);
12963
+ }
12964
+ if (type == ";") return cont(classBody);
12965
+ if (type == "}") return cont();
12966
+ }
12967
+ function classGetterSetter(type) {
12968
+ if (type != "variable") return pass();
12969
+ cx.marked = "property";
12970
+ return cont();
12971
+ }
12972
+ function afterExport(_type, value) {
12973
+ if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
12974
+ if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
12975
+ return pass(statement);
12976
+ }
12977
+ function afterImport(type) {
12978
+ if (type == "string") return cont();
12979
+ return pass(importSpec, maybeFrom);
12980
+ }
12981
+ function importSpec(type, value) {
12982
+ if (type == "{") return contCommasep(importSpec, "}");
12983
+ if (type == "variable") register(value);
12984
+ if (value == "*") cx.marked = "keyword";
12985
+ return cont(maybeAs);
12986
+ }
12987
+ function maybeAs(_type, value) {
12988
+ if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
12989
+ }
12990
+ function maybeFrom(_type, value) {
12991
+ if (value == "from") { cx.marked = "keyword"; return cont(expression); }
12992
+ }
12993
+ function arrayLiteral(type) {
12994
+ if (type == "]") return cont();
12995
+ return pass(expressionNoComma, maybeArrayComprehension);
12996
+ }
12997
+ function maybeArrayComprehension(type) {
12998
+ if (type == "for") return pass(comprehension, expect("]"));
12999
+ if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
13000
+ return pass(commasep(expressionNoComma, "]"));
13001
+ }
13002
+ function comprehension(type) {
13003
+ if (type == "for") return cont(forspec, comprehension);
13004
+ if (type == "if") return cont(expression, comprehension);
13005
+ }
13006
+
13007
+ function isContinuedStatement(state, textAfter) {
13008
+ return state.lastType == "operator" || state.lastType == "," ||
13009
+ isOperatorChar.test(textAfter.charAt(0)) ||
13010
+ /[,.]/.test(textAfter.charAt(0));
13011
+ }
13012
+
13013
+ // Interface
13014
+
13015
+ return {
13016
+ startState: function(basecolumn) {
13017
+ var state = {
13018
+ tokenize: tokenBase,
13019
+ lastType: "sof",
13020
+ cc: [],
13021
+ lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
13022
+ localVars: parserConfig.localVars,
13023
+ context: parserConfig.localVars && {vars: parserConfig.localVars},
13024
+ indented: 0
13025
+ };
13026
+ if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
13027
+ state.globalVars = parserConfig.globalVars;
13028
+ return state;
13029
+ },
13030
+
13031
+ token: function(stream, state) {
13032
+ if (stream.sol()) {
13033
+ if (!state.lexical.hasOwnProperty("align"))
13034
+ state.lexical.align = false;
13035
+ state.indented = stream.indentation();
13036
+ findFatArrow(stream, state);
13037
+ }
13038
+ if (state.tokenize != tokenComment && stream.eatSpace()) return null;
13039
+ var style = state.tokenize(stream, state);
13040
+ if (type == "comment") return style;
13041
+ state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
13042
+ return parseJS(state, style, type, content, stream);
13043
+ },
13044
+
13045
+ indent: function(state, textAfter) {
13046
+ if (state.tokenize == tokenComment) return CodeMirror.Pass;
13047
+ if (state.tokenize != tokenBase) return 0;
13048
+ var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
13049
+ // Kludge to prevent 'maybelse' from blocking lexical scope pops
13050
+ if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
13051
+ var c = state.cc[i];
13052
+ if (c == poplex) lexical = lexical.prev;
13053
+ else if (c != maybeelse) break;
13054
+ }
13055
+ if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
13056
+ if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
13057
+ lexical = lexical.prev;
13058
+ var type = lexical.type, closing = firstChar == type;
13059
+
13060
+ if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
13061
+ else if (type == "form" && firstChar == "{") return lexical.indented;
13062
+ else if (type == "form") return lexical.indented + indentUnit;
13063
+ else if (type == "stat")
13064
+ return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
13065
+ else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
13066
+ return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
13067
+ else if (lexical.align) return lexical.column + (closing ? 0 : 1);
13068
+ else return lexical.indented + (closing ? 0 : indentUnit);
13069
+ },
13070
+
13071
+ electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
13072
+ blockCommentStart: jsonMode ? null : "/*",
13073
+ blockCommentEnd: jsonMode ? null : "*/",
13074
+ lineComment: jsonMode ? null : "//",
13075
+ fold: "brace",
13076
+ closeBrackets: "()[]{}''\"\"``",
13077
+
13078
+ helperType: jsonMode ? "json" : "javascript",
13079
+ jsonldMode: jsonldMode,
13080
+ jsonMode: jsonMode
13081
+ };
13082
+ });
13083
+
13084
+ CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
13085
+
13086
+ CodeMirror.defineMIME("text/javascript", "javascript");
13087
+ CodeMirror.defineMIME("text/ecmascript", "javascript");
13088
+ CodeMirror.defineMIME("application/javascript", "javascript");
13089
+ CodeMirror.defineMIME("application/x-javascript", "javascript");
13090
+ CodeMirror.defineMIME("application/ecmascript", "javascript");
13091
+ CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
13092
+ CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
13093
+ CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
13094
+ CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
13095
+ CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
13096
+
13097
+ });
13098
+
13099
+ },{"../../lib/codemirror":16}],20:[function(require,module,exports){
13100
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
13101
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
13102
+
13103
+ (function(mod) {
13104
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
13105
+ mod(require("../../lib/codemirror"));
13106
+ else if (typeof define == "function" && define.amd) // AMD
13107
+ define(["../../lib/codemirror"], mod);
13108
+ else // Plain browser env
13109
+ mod(CodeMirror);
13110
+ })(function(CodeMirror) {
13111
+ "use strict";
13112
+
13113
+ CodeMirror.defineMode("xml", function(config, parserConfig) {
13114
+ var indentUnit = config.indentUnit;
13115
+ var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
13116
+ var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;
13117
+ if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
13118
+
13119
+ var Kludges = parserConfig.htmlMode ? {
13120
+ autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
13121
+ 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
13122
+ 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
13123
+ 'track': true, 'wbr': true, 'menuitem': true},
13124
+ implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
13125
+ 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
13126
+ 'th': true, 'tr': true},
13127
+ contextGrabbers: {
13128
+ 'dd': {'dd': true, 'dt': true},
13129
+ 'dt': {'dd': true, 'dt': true},
13130
+ 'li': {'li': true},
13131
+ 'option': {'option': true, 'optgroup': true},
13132
+ 'optgroup': {'optgroup': true},
13133
+ 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
13134
+ 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
13135
+ 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
13136
+ 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
13137
+ 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
13138
+ 'rp': {'rp': true, 'rt': true},
13139
+ 'rt': {'rp': true, 'rt': true},
13140
+ 'tbody': {'tbody': true, 'tfoot': true},
13141
+ 'td': {'td': true, 'th': true},
13142
+ 'tfoot': {'tbody': true},
13143
+ 'th': {'td': true, 'th': true},
13144
+ 'thead': {'tbody': true, 'tfoot': true},
13145
+ 'tr': {'tr': true}
13146
+ },
13147
+ doNotIndent: {"pre": true},
13148
+ allowUnquoted: true,
13149
+ allowMissing: true,
13150
+ caseFold: true
13151
+ } : {
13152
+ autoSelfClosers: {},
13153
+ implicitlyClosed: {},
13154
+ contextGrabbers: {},
13155
+ doNotIndent: {},
13156
+ allowUnquoted: false,
13157
+ allowMissing: false,
13158
+ caseFold: false
13159
+ };
13160
+ var alignCDATA = parserConfig.alignCDATA;
13161
+
13162
+ // Return variables for tokenizers
13163
+ var type, setStyle;
13164
+
13165
+ function inText(stream, state) {
13166
+ function chain(parser) {
13167
+ state.tokenize = parser;
13168
+ return parser(stream, state);
13169
+ }
13170
+
13171
+ var ch = stream.next();
13172
+ if (ch == "<") {
13173
+ if (stream.eat("!")) {
13174
+ if (stream.eat("[")) {
13175
+ if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
13176
+ else return null;
13177
+ } else if (stream.match("--")) {
13178
+ return chain(inBlock("comment", "-->"));
13179
+ } else if (stream.match("DOCTYPE", true, true)) {
13180
+ stream.eatWhile(/[\w\._\-]/);
13181
+ return chain(doctype(1));
13182
+ } else {
13183
+ return null;
13184
+ }
13185
+ } else if (stream.eat("?")) {
13186
+ stream.eatWhile(/[\w\._\-]/);
13187
+ state.tokenize = inBlock("meta", "?>");
13188
+ return "meta";
13189
+ } else {
13190
+ type = stream.eat("/") ? "closeTag" : "openTag";
13191
+ state.tokenize = inTag;
13192
+ return "tag bracket";
13193
+ }
13194
+ } else if (ch == "&") {
13195
+ var ok;
13196
+ if (stream.eat("#")) {
13197
+ if (stream.eat("x")) {
13198
+ ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
13199
+ } else {
13200
+ ok = stream.eatWhile(/[\d]/) && stream.eat(";");
13201
+ }
13202
+ } else {
13203
+ ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
13204
+ }
13205
+ return ok ? "atom" : "error";
13206
+ } else {
13207
+ stream.eatWhile(/[^&<]/);
13208
+ return null;
13209
+ }
13210
+ }
13211
+ inText.isInText = true;
13212
+
13213
+ function inTag(stream, state) {
13214
+ var ch = stream.next();
13215
+ if (ch == ">" || (ch == "/" && stream.eat(">"))) {
13216
+ state.tokenize = inText;
13217
+ type = ch == ">" ? "endTag" : "selfcloseTag";
13218
+ return "tag bracket";
13219
+ } else if (ch == "=") {
13220
+ type = "equals";
13221
+ return null;
13222
+ } else if (ch == "<") {
13223
+ state.tokenize = inText;
13224
+ state.state = baseState;
13225
+ state.tagName = state.tagStart = null;
13226
+ var next = state.tokenize(stream, state);
13227
+ return next ? next + " tag error" : "tag error";
13228
+ } else if (/[\'\"]/.test(ch)) {
13229
+ state.tokenize = inAttribute(ch);
13230
+ state.stringStartCol = stream.column();
13231
+ return state.tokenize(stream, state);
13232
+ } else {
13233
+ stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
13234
+ return "word";
13235
+ }
13236
+ }
13237
+
13238
+ function inAttribute(quote) {
13239
+ var closure = function(stream, state) {
13240
+ while (!stream.eol()) {
13241
+ if (stream.next() == quote) {
13242
+ state.tokenize = inTag;
13243
+ break;
13244
+ }
13245
+ }
13246
+ return "string";
13247
+ };
13248
+ closure.isInAttribute = true;
13249
+ return closure;
13250
+ }
13251
+
13252
+ function inBlock(style, terminator) {
13253
+ return function(stream, state) {
13254
+ while (!stream.eol()) {
13255
+ if (stream.match(terminator)) {
13256
+ state.tokenize = inText;
13257
+ break;
13258
+ }
13259
+ stream.next();
13260
+ }
13261
+ return style;
13262
+ };
13263
+ }
13264
+ function doctype(depth) {
13265
+ return function(stream, state) {
13266
+ var ch;
13267
+ while ((ch = stream.next()) != null) {
13268
+ if (ch == "<") {
13269
+ state.tokenize = doctype(depth + 1);
13270
+ return state.tokenize(stream, state);
13271
+ } else if (ch == ">") {
13272
+ if (depth == 1) {
13273
+ state.tokenize = inText;
13274
+ break;
13275
+ } else {
13276
+ state.tokenize = doctype(depth - 1);
13277
+ return state.tokenize(stream, state);
13278
+ }
13279
+ }
13280
+ }
13281
+ return "meta";
13282
+ };
13283
+ }
13284
+
13285
+ function Context(state, tagName, startOfLine) {
13286
+ this.prev = state.context;
13287
+ this.tagName = tagName;
13288
+ this.indent = state.indented;
13289
+ this.startOfLine = startOfLine;
13290
+ if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
13291
+ this.noIndent = true;
13292
+ }
13293
+ function popContext(state) {
13294
+ if (state.context) state.context = state.context.prev;
13295
+ }
13296
+ function maybePopContext(state, nextTagName) {
13297
+ var parentTagName;
13298
+ while (true) {
13299
+ if (!state.context) {
13300
+ return;
13301
+ }
13302
+ parentTagName = state.context.tagName;
13303
+ if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
13304
+ !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
13305
+ return;
13306
+ }
13307
+ popContext(state);
13308
+ }
13309
+ }
13310
+
13311
+ function baseState(type, stream, state) {
13312
+ if (type == "openTag") {
13313
+ state.tagStart = stream.column();
13314
+ return tagNameState;
13315
+ } else if (type == "closeTag") {
13316
+ return closeTagNameState;
13317
+ } else {
13318
+ return baseState;
13319
+ }
13320
+ }
13321
+ function tagNameState(type, stream, state) {
13322
+ if (type == "word") {
13323
+ state.tagName = stream.current();
13324
+ setStyle = "tag";
13325
+ return attrState;
13326
+ } else {
13327
+ setStyle = "error";
13328
+ return tagNameState;
13329
+ }
13330
+ }
13331
+ function closeTagNameState(type, stream, state) {
13332
+ if (type == "word") {
13333
+ var tagName = stream.current();
13334
+ if (state.context && state.context.tagName != tagName &&
13335
+ Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
13336
+ popContext(state);
13337
+ if (state.context && state.context.tagName == tagName) {
13338
+ setStyle = "tag";
13339
+ return closeState;
13340
+ } else {
13341
+ setStyle = "tag error";
13342
+ return closeStateErr;
13343
+ }
13344
+ } else {
13345
+ setStyle = "error";
13346
+ return closeStateErr;
13347
+ }
13348
+ }
13349
+
13350
+ function closeState(type, _stream, state) {
13351
+ if (type != "endTag") {
13352
+ setStyle = "error";
13353
+ return closeState;
13354
+ }
13355
+ popContext(state);
13356
+ return baseState;
13357
+ }
13358
+ function closeStateErr(type, stream, state) {
13359
+ setStyle = "error";
13360
+ return closeState(type, stream, state);
13361
+ }
13362
+
13363
+ function attrState(type, _stream, state) {
13364
+ if (type == "word") {
13365
+ setStyle = "attribute";
13366
+ return attrEqState;
13367
+ } else if (type == "endTag" || type == "selfcloseTag") {
13368
+ var tagName = state.tagName, tagStart = state.tagStart;
13369
+ state.tagName = state.tagStart = null;
13370
+ if (type == "selfcloseTag" ||
13371
+ Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
13372
+ maybePopContext(state, tagName);
13373
+ } else {
13374
+ maybePopContext(state, tagName);
13375
+ state.context = new Context(state, tagName, tagStart == state.indented);
13376
+ }
13377
+ return baseState;
13378
+ }
13379
+ setStyle = "error";
13380
+ return attrState;
13381
+ }
13382
+ function attrEqState(type, stream, state) {
13383
+ if (type == "equals") return attrValueState;
13384
+ if (!Kludges.allowMissing) setStyle = "error";
13385
+ return attrState(type, stream, state);
13386
+ }
13387
+ function attrValueState(type, stream, state) {
13388
+ if (type == "string") return attrContinuedState;
13389
+ if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
13390
+ setStyle = "error";
13391
+ return attrState(type, stream, state);
13392
+ }
13393
+ function attrContinuedState(type, stream, state) {
13394
+ if (type == "string") return attrContinuedState;
13395
+ return attrState(type, stream, state);
13396
+ }
13397
+
13398
+ return {
13399
+ startState: function() {
13400
+ return {tokenize: inText,
13401
+ state: baseState,
13402
+ indented: 0,
13403
+ tagName: null, tagStart: null,
13404
+ context: null};
13405
+ },
13406
+
13407
+ token: function(stream, state) {
13408
+ if (!state.tagName && stream.sol())
13409
+ state.indented = stream.indentation();
13410
+
13411
+ if (stream.eatSpace()) return null;
13412
+ type = null;
13413
+ var style = state.tokenize(stream, state);
13414
+ if ((style || type) && style != "comment") {
13415
+ setStyle = null;
13416
+ state.state = state.state(type || style, stream, state);
13417
+ if (setStyle)
13418
+ style = setStyle == "error" ? style + " error" : setStyle;
13419
+ }
13420
+ return style;
13421
+ },
13422
+
13423
+ indent: function(state, textAfter, fullLine) {
13424
+ var context = state.context;
13425
+ // Indent multi-line strings (e.g. css).
13426
+ if (state.tokenize.isInAttribute) {
13427
+ if (state.tagStart == state.indented)
13428
+ return state.stringStartCol + 1;
13429
+ else
13430
+ return state.indented + indentUnit;
13431
+ }
13432
+ if (context && context.noIndent) return CodeMirror.Pass;
13433
+ if (state.tokenize != inTag && state.tokenize != inText)
13434
+ return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
13435
+ // Indent the starts of attribute names.
13436
+ if (state.tagName) {
13437
+ if (multilineTagIndentPastTag)
13438
+ return state.tagStart + state.tagName.length + 2;
13439
+ else
13440
+ return state.tagStart + indentUnit * multilineTagIndentFactor;
13441
+ }
13442
+ if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
13443
+ var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
13444
+ if (tagAfter && tagAfter[1]) { // Closing tag spotted
13445
+ while (context) {
13446
+ if (context.tagName == tagAfter[2]) {
13447
+ context = context.prev;
13448
+ break;
13449
+ } else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
13450
+ context = context.prev;
13451
+ } else {
13452
+ break;
13453
+ }
13454
+ }
13455
+ } else if (tagAfter) { // Opening tag spotted
13456
+ while (context) {
13457
+ var grabbers = Kludges.contextGrabbers[context.tagName];
13458
+ if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
13459
+ context = context.prev;
13460
+ else
13461
+ break;
13462
+ }
13463
+ }
13464
+ while (context && !context.startOfLine)
13465
+ context = context.prev;
13466
+ if (context) return context.indent + indentUnit;
13467
+ else return 0;
13468
+ },
13469
+
13470
+ electricInput: /<\/[\s\w:]+>$/,
13471
+ blockCommentStart: "<!--",
13472
+ blockCommentEnd: "-->",
13473
+
13474
+ configuration: parserConfig.htmlMode ? "html" : "xml",
13475
+ helperType: parserConfig.htmlMode ? "html" : "xml"
13476
+ };
13477
+ });
13478
+
13479
+ CodeMirror.defineMIME("text/xml", "xml");
13480
+ CodeMirror.defineMIME("application/xml", "xml");
13481
+ if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
13482
+ CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
13483
+
13484
+ });
13485
+
13486
+ },{"../../lib/codemirror":16}]},{},[10])
13487
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJhc3NldHMvYnJvd3NlcmlmeS9hZG1pbi9maWVsZC1mb3Jtcy1yb3dzLmpzIiwiYXNzZXRzL2Jyb3dzZXJpZnkvYWRtaW4vZmllbGQtZm9ybXMuanMiLCJhc3NldHMvYnJvd3NlcmlmeS9hZG1pbi9maWVsZC1nZW5lcmF0b3IuanMiLCJhc3NldHMvYnJvd3NlcmlmeS9hZG1pbi9maWVsZC1oZWxwZXIuanMiLCJhc3NldHMvYnJvd3NlcmlmeS9hZG1pbi9maWVsZHMtZmFjdG9yeS5qcyIsImFzc2V0cy9icm93c2VyaWZ5L2FkbWluL2ZpZWxkcy5qcyIsImFzc2V0cy9icm93c2VyaWZ5L2FkbWluL2Zvcm0tZWRpdG9yLmpzIiwiYXNzZXRzL2Jyb3dzZXJpZnkvYWRtaW4vZm9ybS13YXRjaGVyLmpzIiwiYXNzZXRzL2Jyb3dzZXJpZnkvYWRtaW4vb3ZlcmxheS5qcyIsImFzc2V0cy9icm93c2VyaWZ5L2Zvcm1zLWFkbWluLmpzIiwiYXNzZXRzL2Jyb3dzZXJpZnkvdGhpcmQtcGFydHkvYmVhdXRpZnktaHRtbC5qcyIsImFzc2V0cy9icm93c2VyaWZ5L3RoaXJkLXBhcnR5L3JlbmRlci5qcyIsIm5vZGVfbW9kdWxlcy9jb2RlbWlycm9yL2FkZG9uL2VkaXQvY2xvc2V0YWcuanMiLCJub2RlX21vZHVsZXMvY29kZW1pcnJvci9hZGRvbi9lZGl0L21hdGNodGFncy5qcyIsIm5vZGVfbW9kdWxlcy9jb2RlbWlycm9yL2FkZG9uL2ZvbGQveG1sLWZvbGQuanMiLCJub2RlX21vZHVsZXMvY29kZW1pcnJvci9saWIvY29kZW1pcnJvci5qcyIsIm5vZGVfbW9kdWxlcy9jb2RlbWlycm9yL21vZGUvY3NzL2Nzcy5qcyIsIm5vZGVfbW9kdWxlcy9jb2RlbWlycm9yL21vZGUvaHRtbG1peGVkL2h0bWxtaXhlZC5qcyIsIm5vZGVfbW9kdWxlcy9jb2RlbWlycm9yL21vZGUvamF2YXNjcmlwdC9qYXZhc2NyaXB0LmpzIiwibm9kZV9tb2R1bGVzL2NvZGVtaXJyb3IvbW9kZS94bWwveG1sLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkxBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9GQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL3lCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeHBSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6ekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNudEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwidmFyIHJvd3MgPSBmdW5jdGlvbihtKSB7XG5cdCd1c2Ugc3RyaWN0JztcblxuXHR2YXIgciA9IHt9O1xuXG5cdHIubGFiZWwgPSBmdW5jdGlvbiAoY29uZmlnKSB7XG5cdFx0Ly8gbGFiZWwgcm93XG5cdFx0cmV0dXJuIG0oXCJkaXZcIiwgW1xuXHRcdFx0bShcImxhYmVsXCIsIFwiRmllbGQgTGFiZWxcIiksXG5cdFx0XHRtKFwiaW5wdXQud2lkZWZhdFwiLCB7XG5cdFx0XHRcdHR5cGUgICAgICAgOiBcInRleHRcIixcblx0XHRcdFx0dmFsdWUgICAgICA6IGNvbmZpZy5sYWJlbCgpLFxuXHRcdFx0XHRvbmNoYW5nZSAgIDogbS53aXRoQXR0cigndmFsdWUnLCBjb25maWcubGFiZWwpLFxuXHRcdFx0XHRwbGFjZWhvbGRlcjogY29uZmlnLnRpdGxlKClcblx0XHRcdH0pXG5cdFx0XSk7XG5cdH07XG5cblx0ci5kZWZhdWx0VmFsdWUgPSBmdW5jdGlvbiAoY29uZmlnKSB7XG5cdFx0cmV0dXJuIG0oXCJkaXZcIiwgW1xuXHRcdFx0bShcImxhYmVsXCIsIFwiRGVmYXVsdCBWYWx1ZVwiKSxcblx0XHRcdG0oXCJpbnB1dC53aWRlZmF0XCIsIHtcblx0XHRcdFx0dHlwZSAgIDogXCJ0ZXh0XCIsXG5cdFx0XHRcdHZhbHVlICA6IGNvbmZpZy52YWx1ZSgpLFxuXHRcdFx0XHRvbmtleXVwOiBtLndpdGhBdHRyKCd2YWx1ZScsIGNvbmZpZy52YWx1ZSlcblx0XHRcdH0pXG5cdFx0XSk7XG5cdH07XG5cblx0ci5udW1iZXJNaW5NYXggPSBmdW5jdGlvbiAoY29uZmlnKSB7XG5cdFx0cmV0dXJuIG0oJ2RpdicsIFtcblx0XHRcdG0oJ2Rpdi5yb3cnLCBbXG5cdFx0XHRcdG0oJ2Rpdi5jb2wuY29sLTMnLCBbXG5cdFx0XHRcdFx0bSgnbGFiZWwnLCBcIk1pblwiKSxcblx0XHRcdFx0XHRtKCdpbnB1dCcsIHt0eXBlOiAnbnVtYmVyJywgb25jaGFuZ2U6IG0ud2l0aEF0dHIoJ3ZhbHVlJywgY29uZmlnLm1pbil9KVxuXHRcdFx0XHRdKSxcblx0XHRcdFx0bSgnZGl2LmNvbC5jb2wtMycsIFtcblx0XHRcdFx0XHRtKCdsYWJlbCcsICdNYXgnKSxcblx0XHRcdFx0XHRtKCdpbnB1dCcsIHt0eXBlOiAnbnVtYmVyJywgb25jaGFuZ2U6IG0ud2l0aEF0dHIoJ3ZhbHVlJywgY29uZmlnLm1heCl9KVxuXHRcdFx0XHRdKVxuXHRcdFx0XSlcblx0XHRdKVxuXHR9O1xuXG5cblx0ci5pc1JlcXVpcmVkID0gZnVuY3Rpb24gKGNvbmZpZykge1xuXHRcdHJldHVybiBtKCdkaXYnLCBbXG5cdFx0XHRtKCdsYWJlbC5jYi13cmFwJywgW1xuXHRcdFx0XHRtKCdpbnB1dCcsIHtcblx0XHRcdFx0XHR0eXBlICAgIDogJ2NoZWNrYm94Jyxcblx0XHRcdFx0XHRjaGVja2VkIDogY29uZmlnLnJlcXVpcmVkKCksXG5cdFx0XHRcdFx0b25jaGFuZ2U6IG0ud2l0aEF0dHIoJ2NoZWNrZWQnLCBjb25maWcucmVxdWlyZWQpXG5cdFx0XHRcdH0pLFxuXHRcdFx0XHRcIklzIHRoaXMgZmllbGQgcmVxdWlyZWQ/XCJcblx0XHRcdF0pXG5cdFx0XSk7XG5cdH07XG5cblx0ci51c2VQbGFjZWhvbGRlciA9IGZ1bmN0aW9uIChjb25maWcpIHtcblxuXHRcdGlmIChjb25maWcudmFsdWUoKS5sZW5ndGggPiAwKSB7XG5cdFx0XHRyZXR1cm4gbShcImRpdlwiLCBbXG5cdFx0XHRcdG0oXCJsYWJlbC5jYi13cmFwXCIsIFtcblx0XHRcdFx0XHRtKFwiaW5wdXRcIiwge1xuXHRcdFx0XHRcdFx0dHlwZSAgICA6ICdjaGVja2JveCcsXG5cdFx0XHRcdFx0XHRjaGVja2VkIDogY29uZmlnLnBsYWNlaG9sZGVyKCksXG5cdFx0XHRcdFx0XHRvbmNoYW5nZTogbS53aXRoQXR0cignY2hlY2tlZCcsIGNvbmZpZy5wbGFjZWhvbGRlcilcblx0XHRcdFx0XHR9KSxcblx0XHRcdFx0XHRcIlVzZSBcXFwiXCIgKyBjb25maWcudmFsdWUoKSArIFwiXFxcIiBhcyBwbGFjZWhvbGRlciBmb3IgdGhlIGZpZWxkLlwiXG5cdFx0XHRcdF0pXG5cdFx0XHRdKTtcblx0XHR9XG5cdH07XG5cblx0ci51c2VQYXJhZ3JhcGhzID0gZnVuY3Rpb24gKGNvbmZpZykge1xuXHRcdHJldHVybiBtKCdkaXYnLCBbXG5cdFx0XHRtKCdsYWJlbC5jYi13cmFwJywgW1xuXHRcdFx0XHRtKCdpbnB1dCcsIHtcblx0XHRcdFx0XHR0eXBlICAgIDogJ2NoZWNrYm94Jyxcblx0XHRcdFx0XHRjaGVja2VkIDogY29uZmlnLndyYXAoKSxcblx0XHRcdFx0XHRvbmNoYW5nZTogbS53aXRoQXR0cignY2hlY2tlZCcsIGNvbmZpZy53cmFwKVxuXHRcdFx0XHR9KSxcblx0XHRcdFx0XCJXcmFwIGluIHBhcmFncmFwaCB0YWdzP1wiXG5cdFx0XHRdKVxuXHRcdF0pO1xuXHR9O1xuXG5cdHIuY2hvaWNlVHlwZSA9IGZ1bmN0aW9uIChjb25maWcpIHtcblx0XHRyZXR1cm4gbSgnZGl2JywgW1xuXHRcdFx0bSgnbGFiZWwnLCBcIkNob2ljZSBUeXBlXCIpLFxuXHRcdFx0bSgnc2VsZWN0Jywge1xuXHRcdFx0XHR2YWx1ZSAgIDogY29uZmlnLnR5cGUoKSxcblx0XHRcdFx0b25jaGFuZ2U6IG0ud2l0aEF0dHIoJ3ZhbHVlJywgY29uZmlnLnR5cGUpXG5cdFx0XHR9LCBbXG5cdFx0XHRcdG0oJ29wdGlvbicsIHtcblx0XHRcdFx0XHR2YWx1ZSAgIDogJ3NlbGVjdCcsXG5cdFx0XHRcdFx0c2VsZWN0ZWQ6IGNvbmZpZy50eXBlKCkgPT09ICdzZWxlY3QnID8gJ3NlbGVjdGVkJyA6IGZhbHNlXG5cdFx0XHRcdH0sICdEcm9wZG93bicpLFxuXHRcdFx0XHRtKCdvcHRpb24nLCB7XG5cdFx0XHRcdFx0dmFsdWUgICA6ICdyYWRpbycsXG5cdFx0XHRcdFx0c2VsZWN0ZWQ6IGNvbmZpZy50eXBlKCkgPT09ICdyYWRpbycgPyAnc2VsZWN0ZWQnIDogZmFsc2Vcblx0XHRcdFx0fSwgJ1JhZGlvIEJ1dHRvbicpLFxuXHRcdFx0XHRtKCdvcHRpb24nLCB7XG5cdFx0XHRcdFx0dmFsdWUgICA6ICdjaGVja2JveCcsXG5cdFx0XHRcdFx0c2VsZWN0ZWQ6IGNvbmZpZy50eXBlKCkgPT09ICdjaGVja2JveCcgPyAnc2VsZWN0ZWQnIDogZmFsc2Vcblx0XHRcdFx0fSwgJ0NoZWNrYm94ZXMnKVxuXHRcdFx0XSlcblx0XHRdKTtcblx0fTtcblxuXHRyLmNob2ljZXMgPSBmdW5jdGlvbiAoY29uZmlnKSB7XG5cblxuXHRcdHJldHVybiBtKCdkaXYnLCBbXG5cdFx0XHRtKCdsYWJlbCcsIFwiQ2hvaWNlc1wiKSxcblx0XHRcdG0oJ2Rpdi5saW1pdC1oZWlnaHQnLCBbXG5cdFx0XHRcdG0oXCJ0YWJsZVwiLCBbXG5cblx0XHRcdFx0XHQvLyB0YWJsZSBib2R5XG5cdFx0XHRcdFx0Y29uZmlnLmNob2ljZXMoKS5tYXAoZnVuY3Rpb24gKGNob2ljZSwgaW5kZXgpIHtcblx0XHRcdFx0XHRcdHJldHVybiBtKCd0cicsIHtcblx0XHRcdFx0XHRcdFx0J2RhdGEtaWQnOiBpbmRleFxuXHRcdFx0XHRcdFx0fSwgW1xuXHRcdFx0XHRcdFx0XHRtKCd0ZC5jYicsIG0oJ2lucHV0Jywge1xuXHRcdFx0XHRcdFx0XHRcdFx0bmFtZSAgICA6ICdzZWxlY3RlZCcsXG5cdFx0XHRcdFx0XHRcdFx0XHR0eXBlICAgIDogKGNvbmZpZy50eXBlKCkgPT09ICdjaGVja2JveCcgKSA/ICdjaGVja2JveCcgOiAncmFkaW8nLFxuXHRcdFx0XHRcdFx0XHRcdFx0b25jaGFuZ2U6IG0ud2l0aEF0dHIoJ3ZhbHVlJywgY29uZmlnLnNlbGVjdENob2ljZS5iaW5kKGNvbmZpZykpLFxuXHRcdFx0XHRcdFx0XHRcdFx0Y2hlY2tlZDogY2hvaWNlLnNlbGVjdGVkKCksXG5cdFx0XHRcdFx0XHRcdFx0XHR2YWx1ZTogY2hvaWNlLnZhbHVlKClcblx0XHRcdFx0XHRcdFx0XHR9KVxuXHRcdFx0XHRcdFx0XHQpLFxuXHRcdFx0XHRcdFx0XHRtKCd0ZC5zdHJldGNoJywgbSgnaW5wdXQud2lkZWZhdCcsIHtcblx0XHRcdFx0XHRcdFx0XHR0eXBlICAgICAgIDogJ3RleHQnLFxuXHRcdFx0XHRcdFx0XHRcdHZhbHVlICAgICAgOiBjaG9pY2UubGFiZWwoKSxcblx0XHRcdFx0XHRcdFx0XHRwbGFjZWhvbGRlcjogY2hvaWNlLnRpdGxlKCksXG5cdFx0XHRcdFx0XHRcdFx0b25jaGFuZ2UgICA6IG0ud2l0aEF0dHIoJ3ZhbHVlJywgY2hvaWNlLmxhYmVsKVxuXHRcdFx0XHRcdFx0XHR9KSksXG5cdFx0XHRcdFx0XHRcdG0oJ3RkJywgbSgnc3BhbicsIHtcblx0XHRcdFx0XHRcdFx0XHRcImNsYXNzXCI6ICdkYXNoaWNvbnMgZGFzaGljb25zLW5vLWFsdCBob3Zlci1hY3RpdmF0ZWQnLFxuXHRcdFx0XHRcdFx0XHRcdG9uY2xpY2s6IGZ1bmN0aW9uIChrZXkpIHtcblx0XHRcdFx0XHRcdFx0XHRcdHRoaXMuY2hvaWNlcygpLnNwbGljZShrZXksIDEpO1xuXHRcdFx0XHRcdFx0XHRcdH0uYmluZChjb25maWcsIGluZGV4KVxuXHRcdFx0XHRcdFx0XHR9LCAnJykpXG5cdFx0XHRcdFx0XHRdKVxuXHRcdFx0XHRcdH0pXG5cdFx0XHRcdF0pIC8vIGVuZCBvZiB0YWJsZVxuXHRcdFx0XSkgLy8gZW5kIG9mIGxpbWl0LWhlaWdodCBkaXZcblx0XHRdKTtcblx0fTtcblxuXHRyZXR1cm4gcjtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gcm93czsiLCJ2YXIgZm9ybXMgPSBmdW5jdGlvbihtKSB7XG5cdHZhciBmb3JtcyA9IHt9O1xuXHR2YXIgcm93cyA9IHJlcXVpcmUoJy4vZmllbGQtZm9ybXMtcm93cy5qcycpKG0pO1xuXG5cdC8vIHJvdXRlIHRvIG9uZSBvZiB0aGUgb3RoZXIgZm9ybSBjb25maWdzLCBkZWZhdWx0IHRvIFwidGV4dFwiXG5cdGZvcm1zLnJlbmRlciA9IGZ1bmN0aW9uKGNvbmZpZykge1xuXG5cdFx0dmFyIHR5cGUgPSBjb25maWcudHlwZSgpO1xuXG5cdFx0aWYoIHR5cGVvZiggZm9ybXNbdHlwZV0gKSA9PT0gXCJmdW5jdGlvblwiICkge1xuXHRcdFx0cmV0dXJuIGZvcm1zWyB0eXBlIF0oY29uZmlnKTtcblx0XHR9XG5cblx0XHRzd2l0Y2goIHR5cGUgKSB7XG5cdFx0XHRjYXNlICdzZWxlY3QnOlxuXHRcdFx0Y2FzZSAncmFkaW8nOlxuXHRcdFx0Y2FzZSAnY2hlY2tib3gnOlxuXHRcdFx0XHRyZXR1cm4gZm9ybXMuY2hvaWNlKGNvbmZpZyk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdH1cblxuXHRcdC8vIGZhbGxiYWNrIHRvIGdvb2Qgb2xkIHRleHQgZmllbGRcblx0XHRyZXR1cm4gZm9ybXMudGV4dChjb25maWcpO1xuXHR9O1xuXG5cblx0Zm9ybXMudGV4dCA9IGZ1bmN0aW9uKGNvbmZpZykge1xuXHRcdHJldHVybiBbXG5cdFx0XHRyb3dzLmxhYmVsKGNvbmZpZyksXG5cdFx0XHRyb3dzLmRlZmF1bHRWYWx1ZShjb25maWcpLFxuXHRcdFx0cm93cy51c2VQbGFjZWhvbGRlcihjb25maWcpLFxuXHRcdFx0cm93cy5pc1JlcXVpcmVkKGNvbmZpZyksXG5cdFx0XHRyb3dzLnVzZVBhcmFncmFwaHMoY29uZmlnKVxuXHRcdF1cblx0fTtcblxuXHRmb3Jtcy5jaG9pY2UgPSBmdW5jdGlvbihjb25maWcpIHtcblx0XHRyZXR1cm4gW1xuXHRcdFx0cm93cy5sYWJlbChjb25maWcpLFxuXHRcdFx0cm93cy5jaG9pY2VUeXBlKGNvbmZpZyksXG5cdFx0XHRyb3dzLmNob2ljZXMoY29uZmlnKSxcblx0XHRcdHJvd3MudXNlUGFyYWdyYXBocyhjb25maWcpXG5cdFx0XVxuXHR9O1xuXG5cdGZvcm1zLmhpZGRlbiA9IGZ1bmN0aW9uKCBjb25maWcgKSB7XG5cdFx0cmV0dXJuIFtcblx0XHRcdHJvd3MuZGVmYXVsdFZhbHVlKGNvbmZpZylcblx0XHRdXG5cdH07XG5cblx0Zm9ybXMuc3VibWl0ID0gZnVuY3Rpb24oY29uZmlnKSB7XG5cblx0XHRjb25maWcubGFiZWwoJycpO1xuXHRcdGNvbmZpZy5wbGFjZWhvbGRlcihmYWxzZSk7XG5cblx0XHRyZXR1cm4gW1xuXHRcdFx0cm93cy5kZWZhdWx0VmFsdWUoY29uZmlnKSxcblx0XHRcdHJvd3MudXNlUGFyYWdyYXBocyhjb25maWcpXG5cdFx0XVxuXHR9O1xuXG5cdGZvcm1zLm51bWJlciA9IGZ1bmN0aW9uKGNvbmZpZykge1xuXG5cdFx0cmV0dXJuIFtcblx0XHRcdGZvcm1zLnRleHQoY29uZmlnKSxcblx0XHRcdHJvd3MubnVtYmVyTWluTWF4KGNvbmZpZylcblx0XHRdO1xuXHR9O1xuXG5cdHJldHVybiBmb3Jtcztcbn07XG5cblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZvcm1zOyIsInZhciBnID0gZnVuY3Rpb24obSkge1xuXHQndXNlIHN0cmljdCc7XG5cblx0dmFyIHJlbmRlciA9IHJlcXVpcmUoJy4uL3RoaXJkLXBhcnR5L3JlbmRlci5qcycpO1xuXHR2YXIgaHRtbF9iZWF1dGlmeSA9IHJlcXVpcmUoJy4uL3RoaXJkLXBhcnR5L2JlYXV0aWZ5LWh0bWwuanMnKTtcblx0dmFyIGdlbmVyYXRvcnMgPSB7fTtcblxuXHQvKipcblx0ICogR2VuZXJhdGVzIGEgPHNlbGVjdD4gZmllbGRcblx0ICogQHBhcmFtIGNvbmZpZ1xuXHQgKiBAcmV0dXJucyB7Kn1cblx0ICovXG5cdGdlbmVyYXRvcnMuc2VsZWN0ID0gZnVuY3Rpb24gKGNvbmZpZykge1xuXHRcdHZhciBmaWVsZCA9IG0oJ3NlbGVjdCcsIHtuYW1lOiBjb25maWcubmFtZSgpfSwgW1xuXHRcdFx0Y29uZmlnLmNob2ljZXMoKS5tYXAoZnVuY3Rpb24gKGNob2ljZSkge1xuXHRcdFx0XHRyZXR1cm4gbSgnb3B0aW9uJywge1xuXHRcdFx0XHRcdHZhbHVlICAgOiAoIGNob2ljZS52YWx1ZSgpICE9PSBjaG9pY2UubGFiZWwoKSApID8gY2hvaWNlLnZhbHVlKCkgOiB1bmRlZmluZWQsXG5cdFx0XHRcdFx0XCJzZWxlY3RlZFwiOiBjaG9pY2Uuc2VsZWN0ZWQoKVxuXHRcdFx0XHR9LCBjaG9pY2UubGFiZWwoKSlcblx0XHRcdH0pXG5cdFx0XSk7XG5cdFx0cmV0dXJuIGZpZWxkO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBHZW5lcmF0ZXMgYSBjaGVja2JveCBvciByYWRpbyB0eXBlIGlucHV0IGZpZWxkLlxuXHQgKlxuXHQgKiBAcGFyYW0gY29uZmlnXG5cdCAqIEByZXR1cm5zIHsqfVxuXHQgKi9cblx0Z2VuZXJhdG9ycy5jaGVja2JveCA9IGZ1bmN0aW9uIChjb25maWcpIHtcblxuXG5cdFx0dmFyIGZpZWxkID0gY29uZmlnLmNob2ljZXMoKS5tYXAoZnVuY3Rpb24gKGNob2ljZSkge1xuXHRcdFx0cmV0dXJuIG0oJ2xhYmVsJywgW1xuXHRcdFx0XHRcdG0oJ2lucHV0Jywge1xuXHRcdFx0XHRcdFx0bmFtZSAgICA6IGNvbmZpZy5uYW1lKCkgKyAoIGNvbmZpZy50eXBlKCkgPT09ICdjaGVja2JveCcgPyAnW10nIDogJycgKSxcblx0XHRcdFx0XHRcdHR5cGUgICAgOiBjb25maWcudHlwZSgpLFxuXHRcdFx0XHRcdFx0dmFsdWUgICA6IGNob2ljZS52YWx1ZSgpLFxuXHRcdFx0XHRcdFx0Y2hlY2tlZCA6IGNob2ljZS5zZWxlY3RlZCgpXG5cdFx0XHRcdFx0fSksXG5cdFx0XHRcdFx0bSgnc3BhbicsIGNob2ljZS5sYWJlbCgpKVxuXHRcdFx0XHRdXG5cdFx0XHQpXG5cdFx0fSk7XG5cdFx0cmV0dXJuIGZpZWxkO1xuXHR9O1xuXHRnZW5lcmF0b3JzLnJhZGlvID0gZ2VuZXJhdG9ycy5jaGVja2JveDtcblxuXHQvKipcblx0ICogR2VuZXJhdGVzIGEgZGVmYXVsdCBmaWVsZFxuXHQgKlxuXHQgKiAtIHRleHQsIHVybCwgbnVtYmVyLCBlbWFpbCwgZGF0ZVxuXHQgKlxuXHQgKiBAcGFyYW0gY29uZmlnXG5cdCAqIEByZXR1cm5zIHsqfVxuXHQgKi9cblx0Z2VuZXJhdG9yc1snZGVmYXVsdCddID0gZnVuY3Rpb24gKGNvbmZpZykge1xuXG5cdFx0dmFyIGF0dHJpYnV0ZXMgPSB7XG5cdFx0XHR0eXBlOiBjb25maWcudHlwZSgpXG5cdFx0fTtcblx0XHR2YXIgZmllbGQ7XG5cblx0XHRpZiAoY29uZmlnLm5hbWUoKSkge1xuXHRcdFx0YXR0cmlidXRlcy5uYW1lID0gY29uZmlnLm5hbWUoKTtcblx0XHR9XG5cblx0XHRpZiAoY29uZmlnLm1pbigpKSB7XG5cdFx0XHRhdHRyaWJ1dGVzLm1pbiA9IGNvbmZpZy5taW4oKTtcblx0XHR9XG5cblx0XHRpZiAoY29uZmlnLm1heCgpKSB7XG5cdFx0XHRhdHRyaWJ1dGVzLm1heCA9IGNvbmZpZy5tYXgoKTtcblx0XHR9XG5cblx0XHRpZiAoY29uZmlnLnZhbHVlKCkubGVuZ3RoID4gMCkge1xuXHRcdFx0aWYgKGNvbmZpZy5wbGFjZWhvbGRlcigpKSB7XG5cdFx0XHRcdGF0dHJpYnV0ZXMucGxhY2Vob2xkZXIgPSBjb25maWcudmFsdWUoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGF0dHJpYnV0ZXMudmFsdWUgPSBjb25maWcudmFsdWUoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRhdHRyaWJ1dGVzLnJlcXVpcmVkID0gY29uZmlnLnJlcXVpcmVkKCk7XG5cblx0XHRmaWVsZCA9IG0oJ2lucHV0JywgYXR0cmlidXRlcyk7XG5cdFx0cmV0dXJuIGZpZWxkO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBHZW5lcmF0ZXMgYW4gSFRNTCBzdHJpbmcgYmFzZWQgb24gYSBmaWVsZCAoY29uZmlnKSBvYmplY3Rcblx0ICpcblx0ICogQHBhcmFtIGNvbmZpZ1xuXHQgKiBAcmV0dXJucyB7Kn1cblx0ICovXG5cdGZ1bmN0aW9uIGdlbmVyYXRlKGNvbmZpZykge1xuXHRcdHZhciBsYWJlbCwgZmllbGQsIGh0bWxUZW1wbGF0ZSwgaHRtbDtcblxuXHRcdGxhYmVsID0gY29uZmlnLmxhYmVsKCkubGVuZ3RoID8gbShcImxhYmVsXCIsIGNvbmZpZy5sYWJlbCgpKSA6ICcnO1xuXHRcdGZpZWxkID0gdHlwZW9mKGdlbmVyYXRvcnNbY29uZmlnLnR5cGUoKV0pID09PSBcImZ1bmN0aW9uXCIgPyBnZW5lcmF0b3JzW2NvbmZpZy50eXBlKCldKGNvbmZpZykgOiBnZW5lcmF0b3JzWydkZWZhdWx0J10oY29uZmlnKTtcblxuXHRcdGh0bWxUZW1wbGF0ZSA9IGNvbmZpZy53cmFwKCkgPyBtKCdwJywgW2xhYmVsLCBmaWVsZF0pIDogW2xhYmVsLCBmaWVsZF07XG5cblx0XHQvLyByZW5kZXIgSFRNTCBvbiBtZW1vcnkgbm9kZVxuXHRcdGh0bWwgPSByZW5kZXIoaHRtbFRlbXBsYXRlKTtcblxuXHRcdC8vIHByZXR0aWZ5IGh0bWxcblx0XHRodG1sID0gaHRtbF9iZWF1dGlmeShodG1sKTtcblxuXHRcdHJldHVybiBodG1sICsgXCJcXG5cIjtcblx0fVxuXG5cdHJldHVybiBnZW5lcmF0ZTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZzsiLCJ2YXIgRmllbGRIZWxwZXIgPSBmdW5jdGlvbihtLCB0YWJzLCBlZGl0b3IsIGZpZWxkcykge1xuXHQndXNlIHN0cmljdCc7XG5cblx0dmFyIGdlbmVyYXRlID0gcmVxdWlyZSgnLi9maWVsZC1nZW5lcmF0b3IuanMnKShtKTtcblx0dmFyIG92ZXJsYXkgPSByZXF1aXJlKCcuL292ZXJsYXkuanMnKShtKTtcblx0dmFyIGZvcm1zID0gcmVxdWlyZSgnLi9maWVsZC1mb3Jtcy5qcycpKG0pO1xuXHR2YXIgZmllbGRDb25maWc7XG5cblx0ZWRpdG9yLm9uKCdibHVyJywgbS5yZWRyYXcpO1xuXG5cdC8qKlxuXHQgKiBDaG9vc2UgYSBmaWVsZCB0byBvcGVuIHRoZSBoZWxwZXIgZm9ybSBmb3Jcblx0ICpcblx0ICogQHBhcmFtIGluZGV4XG5cdCAqIEByZXR1cm5zIHsqfVxuXHQgKi9cblx0ZnVuY3Rpb24gc2V0QWN0aXZlRmllbGQoaW5kZXgpIHtcblx0XHRmaWVsZENvbmZpZyA9IGZpZWxkcy5nZXQoaW5kZXgpO1xuXHRcdG0ucmVkcmF3KCk7XG5cdH1cblxuXG5cdC8qKlxuXHQgKiBDb250cm9sbGVyXG5cdCAqL1xuXHRmdW5jdGlvbiBjb250cm9sbGVyKCkge1xuXG5cdH1cblxuXHQvKipcblx0ICogQ3JlYXRlIEhUTUwgYmFzZWQgb24gY3VycmVudCBjb25maWcgb2JqZWN0XG5cdCAqL1xuXHRmdW5jdGlvbiBjcmVhdGVGaWVsZEhUTUxBbmRBZGRUb0Zvcm0oKSB7XG5cblx0XHQvLyBnZW5lcmF0ZSBodG1sXG5cdFx0dmFyIGh0bWwgPSBnZW5lcmF0ZShmaWVsZENvbmZpZyk7XG5cblx0XHQvLyBhZGQgdG8gZWRpdG9yXG5cdFx0ZWRpdG9yLmluc2VydCggaHRtbCApO1xuXG5cdFx0Ly8gcmVzZXQgZmllbGQgZm9ybVxuXHRcdHNldEFjdGl2ZUZpZWxkKCcnKTtcblxuXHRcdC8vIHJlZHJhd1xuXHRcdG0ucmVkcmF3KCk7XG5cdH1cblxuXHQvKipcblx0ICogVmlld1xuXHQgKiBAcmV0dXJucyB7Kn1cblx0ICovXG5cdGZ1bmN0aW9uIHZpZXcoKSB7XG5cblx0XHQvLyBidWlsZCBET00gZm9yIGZpZWxkcyBjaG9pY2Vcblx0XHR2YXIgYXZhaWxhYmxlRmllbGRzID0gZmllbGRzLmdldEFsbCgpO1xuXG5cdFx0dmFyIGZpZWxkc0Nob2ljZSA9IG0oIFwiZGl2LmF2YWlsYWJsZS1maWVsZHMuc21hbGwtbWFyZ2luXCIsIFtcblx0XHRcdG0oXCJzdHJvbmdcIiwgXCJDaG9vc2UgYSBNYWlsQ2hpbXAgZmllbGQgdG8gYWRkIHRvIHRoZSBmb3JtXCIpLFxuXG5cdFx0XHQoYXZhaWxhYmxlRmllbGRzLmxlbmd0aCkgP1xuXG5cdFx0XHRcdC8vIHJlbmRlciBmaWVsZHNcblx0XHRcdFx0YXZhaWxhYmxlRmllbGRzLm1hcChmdW5jdGlvbihmaWVsZCwgaW5kZXgpIHtcblxuXHRcdFx0XHRcdHZhciBjbGFzc05hbWUgPSBcImJ1dHRvblwiO1xuXHRcdFx0XHRcdGlmKCBmaWVsZC5yZXF1aXJlZCgpICkge1xuXHRcdFx0XHRcdFx0Y2xhc3NOYW1lICs9IFwiIGlzLXJlcXVpcmVkXCI7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dmFyIGluRm9ybSA9IGZpZWxkLmluRm9ybUNvbnRlbnQoKTtcblx0XHRcdFx0XHRpZiggaW5Gb3JtICE9PSBudWxsICkge1xuXHRcdFx0XHRcdFx0Y2xhc3NOYW1lICs9IFwiIFwiICsgKCBpbkZvcm0gPyAnaW4tZm9ybScgOiAnbm90LWluLWZvcm0nICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0cmV0dXJuIG0oXCJidXR0b25cIiwge1xuXHRcdFx0XHRcdFx0XHRcImNsYXNzXCI6IGNsYXNzTmFtZSxcblx0XHRcdFx0XHRcdFx0dHlwZSAgIDogJ2J1dHRvbicsXG5cdFx0XHRcdFx0XHRcdG9uY2xpY2s6IG0ud2l0aEF0dHIoXCJ2YWx1ZVwiLCBzZXRBY3RpdmVGaWVsZCksXG5cdFx0XHRcdFx0XHRcdHZhbHVlICA6IGluZGV4XG5cdFx0XHRcdFx0XHR9LCBmaWVsZC50aXRsZSgpICk7XG5cdFx0XHRcdH0pXG5cblx0XHRcdFx0OlxuXG5cdFx0XHRcdC8vIG5vIGZpZWxkc1xuXHRcdFx0XHRtKCBcInBcIiwgW1xuXHRcdFx0XHRcdFwiTm8gZmllbGRzLCBkaWQgeW91IFwiLFxuXHRcdFx0XHRcdG0oXCJhXCIsIHtcblx0XHRcdFx0XHRcdG9uY2xpY2s6IGZ1bmN0aW9uKCkgeyB0YWJzLm9wZW4oJ3NldHRpbmdzJyk7IH1cblx0XHRcdFx0XHR9LCBcInNlbGVjdCBhIE1haWxDaGltcCBsaXN0IGluIHRoZSBmb3JtIHNldHRpbmdzP1wiKVxuXHRcdFx0XHRdKVxuXHRcdF0pO1xuXG5cdFx0Ly8gYnVpbGQgRE9NIGZvciBvdmVybGF5XG5cdFx0dmFyIGZvcm0gPSBudWxsO1xuXHRcdGlmKCBmaWVsZENvbmZpZyApIHtcblx0XHRcdGZvcm0gPSBvdmVybGF5KFxuXHRcdFx0XHQvLyBmaWVsZCB3aXphcmRcblx0XHRcdFx0bShcImRpdi5maWVsZC13aXphcmRcIiwgW1xuXG5cdFx0XHRcdFx0Ly9oZWFkaW5nXG5cdFx0XHRcdFx0bShcImgzXCIsIFtcblx0XHRcdFx0XHRcdGZpZWxkQ29uZmlnLnRpdGxlKCksXG5cdFx0XHRcdFx0XHRmaWVsZENvbmZpZy5yZXF1aXJlZCgpID8gbSgnc3Bhbi5yZWQnLCAnKicgKSA6ICcnLFxuXHRcdFx0XHRcdFx0ZmllbGRDb25maWcubmFtZSgpLmxlbmd0aCA/IG0oXCJjb2RlXCIsIGZpZWxkQ29uZmlnLm5hbWUoKSkgOiAnJ1xuXHRcdFx0XHRcdF0pLFxuXG5cdFx0XHRcdFx0Ly8gaGVscCB0ZXh0XG5cdFx0XHRcdFx0KCBmaWVsZENvbmZpZy5oZWxwKCkubGVuZ3RoICkgPyBtKCdwJywgbS50cnVzdCggZmllbGRDb25maWcuaGVscCgpICkgKSA6ICcnLFxuXG5cdFx0XHRcdFx0Ly8gYWN0dWFsIGZvcm1cblx0XHRcdFx0XHRmb3Jtcy5yZW5kZXIoZmllbGRDb25maWcpLFxuXG5cdFx0XHRcdFx0Ly8gYWRkIHRvIGZvcm0gYnV0dG9uXG5cdFx0XHRcdFx0bShcInBcIiwgW1xuXHRcdFx0XHRcdFx0bShcImJ1dHRvblwiLCB7XG5cdFx0XHRcdFx0XHRcdFwiY2xhc3NcIjogXCJidXR0b24tcHJpbWFyeVwiLFxuXHRcdFx0XHRcdFx0XHR0eXBlOiBcImJ1dHRvblwiLFxuXHRcdFx0XHRcdFx0XHRvbmNsaWNrOiBjcmVhdGVGaWVsZEhUTUxBbmRBZGRUb0Zvcm1cblx0XHRcdFx0XHRcdH0sIFwiQWRkIHRvIGZvcm1cIiApXG5cdFx0XHRcdFx0XSlcblx0XHRcdFx0XSksIHNldEFjdGl2ZUZpZWxkKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gW1xuXHRcdFx0ZmllbGRzQ2hvaWNlLFxuXHRcdFx0Zm9ybVxuXHRcdF07XG5cdH1cblxuXHQvLyBleHBvc2Ugc29tZSB2YXJpYWJsZXNcblx0cmV0dXJuIHtcblx0XHR2aWV3OiB2aWV3LFxuXHRcdGNvbnRyb2xsZXI6IGNvbnRyb2xsZXJcblx0fVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBGaWVsZEhlbHBlcjsiLCJ2YXIgRmllbGRGYWN0b3J5ID0gZnVuY3Rpb24oc2V0dGluZ3MsIGZpZWxkcykge1xuXHQndXNlIHN0cmljdCc7XG5cblx0LyoqXG5cdCAqIEFycmF5IG9mIHJlZ2lzdGVyZWQgZmllbGRzXG5cdCAqXG5cdCAqIEB0eXBlIHtBcnJheX1cblx0ICovXG5cdHZhciByZWdpc3RlcmVkRmllbGRzID0gW107XG5cblx0LyoqXG5cdCAqIFJlc2V0IGFsbCBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgZmllbGRzXG5cdCAqL1xuXHRmdW5jdGlvbiByZXNldCgpIHtcblx0XHQvLyBjbGVhciBhbGwgb2Ygb3VyIGZpZWxkc1xuXHRcdHJlZ2lzdGVyZWRGaWVsZHMuZm9yRWFjaChmdW5jdGlvbihmaWVsZCkge1xuXHRcdFx0ZmllbGRzLmRlcmVnaXN0ZXIoZmllbGQpO1xuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIEhlbHBlciBmdW5jdGlvbiB0byBxdWlja2x5IHJlZ2lzdGVyIGEgZmllbGQgYW5kIHN0b3JlIGl0IGluIGxvY2FsIHNjb3BlXG5cdCAqXG5cdCAqIEBwYXJhbSBkYXRhXG5cdCAqL1xuXHRmdW5jdGlvbiByZWdpc3RlcihkYXRhKSB7XG5cdFx0dmFyIGZpZWxkID0gZmllbGRzLnJlZ2lzdGVyKGRhdGEpO1xuXHRcdHJlZ2lzdGVyZWRGaWVsZHMucHVzaChmaWVsZCk7XG5cdH1cblxuXHQvKipcblx0ICogTm9ybWFsaXplcyB0aGUgZmllbGQgdHlwZSB3aGljaCBpcyBwYXNzZWQgYnkgTWFpbENoaW1wXG5cdCAqXG5cdCAqIEB0b2RvIE1heWJlIGRvIHRoaXMgc2VydmVyLXNpZGU/XG5cdCAqXG5cdCAqIEBwYXJhbSB0eXBlXG5cdCAqIEByZXR1cm5zIHsqfVxuXHQgKi9cblx0ZnVuY3Rpb24gZ2V0RmllbGRUeXBlKHR5cGUpIHtcblx0XHRzd2l0Y2godHlwZSkge1xuXHRcdFx0Y2FzZSAncGhvbmUnOlxuXHRcdFx0XHRyZXR1cm4gJ3RlbCc7XG5cdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRjYXNlICdkcm9wZG93bic6XG5cdFx0XHRcdHJldHVybiAnc2VsZWN0JztcblxuXHRcdFx0Y2FzZSAnY2hlY2tib3hlcyc6XG5cdFx0XHRcdHJldHVybiAnY2hlY2tib3gnO1xuXHRcdH1cblxuXHRcdHJldHVybiB0eXBlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlZ2lzdGVyIHRoZSB2YXJpb3VzIGZpZWxkcyBmb3IgYSBtZXJnZSB2YXJcblx0ICpcblx0ICogQHBhcmFtIG1lcmdlVmFyXG5cdCAqIEByZXR1cm5zIHtib29sZWFufVxuXHQgKi9cblx0ZnVuY3Rpb24gcmVnaXN0ZXJNZXJnZVZhcihtZXJnZVZhcikge1xuXG5cdFx0Ly8gb25seSByZWdpc3RlciBtZXJnZSB2YXIgZmllbGQgaWYgaXQncyBwdWJsaWNcblx0XHRpZiggISBtZXJnZVZhci5wdWJsaWMgKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0Ly8gbmFtZSwgdHlwZSwgdGl0bGUsIHZhbHVlLCByZXF1aXJlZCwgbGFiZWwsIHBsYWNlaG9sZGVyLCBjaG9pY2VzLCB3cmFwXG5cdFx0dmFyIGRhdGEgPSB7XG5cdFx0XHRuYW1lOiBtZXJnZVZhci50YWcsXG5cdFx0XHR0aXRsZTogbWVyZ2VWYXIubmFtZSxcblx0XHRcdHJlcXVpcmVkOiBtZXJnZVZhci5yZXF1aXJlZCxcblx0XHRcdHR5cGU6IGdldEZpZWxkVHlwZShtZXJnZVZhci5maWVsZF90eXBlKSxcblx0XHRcdGNob2ljZXM6IG1lcmdlVmFyLmNob2ljZXNcblx0XHR9O1xuXG5cdFx0aWYoIGRhdGEudHlwZSAhPT0gJ2FkZHJlc3MnICkge1xuXHRcdFx0cmVnaXN0ZXIoZGF0YSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlZ2lzdGVyKHsgbmFtZTogZGF0YS5uYW1lICsgJ1thZGRyMV0nLCB0eXBlOiAndGV4dCcsIHRpdGxlOiAnU3RyZWV0IEFkZHJlc3MnIH0pO1xuXHRcdFx0cmVnaXN0ZXIoeyBuYW1lOiBkYXRhLm5hbWUgKyAnW2NpdHldJywgdHlwZTogJ3RleHQnLCB0aXRsZTogJ0NpdHknIH0pO1xuXHRcdFx0cmVnaXN0ZXIoeyBuYW1lOiBkYXRhLm5hbWUgKyAnW3N0YXRlXScsIHR5cGU6ICd0ZXh0JywgdGl0bGU6ICdTdGF0ZScgfSk7XG5cdFx0XHRyZWdpc3Rlcih7IG5hbWU6IGRhdGEubmFtZSArICdbemlwXScsIHR5cGU6ICd0ZXh0JywgdGl0bGU6ICdaSVAnIH0pO1xuXHRcdFx0cmVnaXN0ZXIoeyBuYW1lOiBkYXRhLm5hbWUgKyAnW2NvdW50cnldJywgdHlwZTogJ3NlbGVjdCcsIHRpdGxlOiAnQ291bnRyeScsIGNob2ljZXM6IG1jNHdwX3ZhcnMuY291bnRyaWVzIH0pO1xuXHRcdH1cblxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlZ2lzdGVyIGEgZmllbGQgZm9yIGEgTWFpbENoaW1wIGdyb3VwaW5nXG5cdCAqXG5cdCAqIEBwYXJhbSBncm91cGluZ1xuXHQgKi9cblx0ZnVuY3Rpb24gcmVnaXN0ZXJHcm91cGluZyhncm91cGluZyl7XG5cblx0XHR2YXIgZGF0YSA9IHtcblx0XHRcdHRpdGxlOiBncm91cGluZy5uYW1lLFxuXHRcdFx0bmFtZTogJ0dST1VQSU5HU1snICsgZ3JvdXBpbmcuaWQgKyAnXScsXG5cdFx0XHR0eXBlOiBnZXRGaWVsZFR5cGUoZ3JvdXBpbmcuZmllbGRfdHlwZSksXG5cdFx0XHRjaG9pY2VzOiBncm91cGluZy5ncm91cHNcblx0XHR9O1xuXHRcdHJlZ2lzdGVyKGRhdGEpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlZ2lzdGVyIGFsbCBmaWVsZHMgYmVsb25naW5nIHRvIGEgbGlzdFxuXHQgKlxuXHQgKiBAcGFyYW0gbGlzdFxuXHQgKi9cblx0ZnVuY3Rpb24gcmVnaXN0ZXJMaXN0RmllbGRzKGxpc3QpIHtcblx0XHQvLyBsb29wIHRocm91Z2ggbWVyZ2UgdmFyc1xuXHRcdGxpc3QubWVyZ2VfdmFycy5mb3JFYWNoKHJlZ2lzdGVyTWVyZ2VWYXIpO1xuXG5cdFx0Ly8gbG9vcCB0aHJvdWdoIGdyb3VwaW5nc1xuXHRcdGxpc3QuZ3JvdXBpbmdzLmZvckVhY2gocmVnaXN0ZXJHcm91cGluZyk7XG5cdH1cblxuXHRmdW5jdGlvbiByZWdpc3RlckN1c3RvbUZpZWxkcyhsaXN0cykge1xuXG5cdFx0dmFyIGNob2ljZXM7XG5cblx0XHQvLyByZWdpc3RlciBzdWJtaXQgYnV0dG9uXG5cdFx0cmVnaXN0ZXIoe1xuXHRcdFx0bmFtZTogJycsXG5cdFx0XHR2YWx1ZTogXCJTdWJzY3JpYmVcIixcblx0XHRcdHR5cGU6IFwic3VibWl0XCIsXG5cdFx0XHR0aXRsZTogXCJTdWJtaXQgQnV0dG9uXCJcblx0XHR9KTtcblxuXHRcdC8vIHJlZ2lzdGVyIGxpc3RzIGNob2ljZSBmaWVsZFxuXHRcdGNob2ljZXMgPSB7fTtcblx0XHRsaXN0cy5mb3JFYWNoKGZ1bmN0aW9uKGxpc3QpIHtcblx0XHRcdGNob2ljZXNbbGlzdC5pZF0gPSBsaXN0Lm5hbWU7XG5cdFx0fSk7XG5cdFx0cmVnaXN0ZXIoe1xuXHRcdFx0bmFtZTogJ19tYzR3cF9saXN0cycsXG5cdFx0XHR0eXBlOiAnY2hlY2tib3gnLFxuXHRcdFx0dGl0bGU6IFwiTGlzdCBDaG9pY2VcIixcblx0XHRcdGNob2ljZXM6IGNob2ljZXMsXG5cdFx0XHRoZWxwOiAnVGhpcyBmaWVsZCB3aWxsIGFsbG93IHlvdXIgdmlzaXRvcnMgdG8gY2hvb3NlIGEgbGlzdCB0byBzdWJzY3JpYmUgdG8uIDxhIGhyZWY9XCIjXCIgZGF0YS10YWI9XCJzZXR0aW5nc1wiIGNsYXNzPVwidGFiLWxpbmtcIj5DbGljayBoZXJlIHRvIHNlbGVjdCBtb3JlIGxpc3RzIHRvIHNob3c8L2E+Lidcblx0XHR9KTtcblxuXHRcdGNob2ljZXMgPSB7XG5cdFx0XHQnc3Vic2NyaWJlJzogXCJTdWJzY3JpYmVcIixcblx0XHRcdCd1bnN1YnNjcmliZSc6IFwiVW5zdWJzY3JpYmVcIlxuXHRcdH07XG5cdFx0cmVnaXN0ZXIoe1xuXHRcdFx0bmFtZTogJ19tYzR3cF9hY3Rpb24nLFxuXHRcdFx0dHlwZTogJ3JhZGlvJyxcblx0XHRcdHRpdGxlOiBcIlN1YnNjcmliZSAvIFVuc3Vic2NyaWJlXCIsXG5cdFx0XHRjaG9pY2VzOiBjaG9pY2VzLFxuXHRcdFx0dmFsdWU6ICdzdWJzY3JpYmUnLFxuXHRcdFx0aGVscDogJ1RoaXMgZmllbGQgd2lsbCBhbGxvdyB5b3VyIHZpc2l0b3JzIHRvIGNob29zZSB3aGV0aGVyIHRoZXkgd291bGQgbGlrZSB0byBzdWJzY3JpYmUgb3IgdW5zdWJzY3JpYmUnXG5cdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogVXBkYXRlIGxpc3QgZmllbGRzXG5cdCAqXG5cdCAqIEBwYXJhbSBsaXN0c1xuXHQgKi9cblx0ZnVuY3Rpb24gd29yayhsaXN0cykge1xuXG5cdFx0Ly8gY2xlYXIgb3VyIGZpZWxkc1xuXHRcdHJlc2V0KCk7XG5cblx0XHQvLyByZWdpc3RlciBsaXN0IHNwZWNpZmljIGZpZWxkc1xuXHRcdGxpc3RzLmZvckVhY2gocmVnaXN0ZXJMaXN0RmllbGRzKTtcblxuXHRcdC8vIHJlZ2lzdGVyIGdsb2JhbCBmaWVsZHMgbGlrZSBcInN1Ym1pdFwiICYgXCJsaXN0IGNob2ljZVwiXG5cdFx0cmVnaXN0ZXJDdXN0b21GaWVsZHMobGlzdHMpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEV4cG9zZSBzb21lIG1ldGhvZHNcblx0ICovXG5cdHJldHVybiB7XG5cdFx0J3dvcmsnOiB3b3JrXG5cdH1cblxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBGaWVsZEZhY3Rvcnk7IiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihtLCBldmVudHMpIHtcblx0J3VzZSBzdHJpY3QnO1xuXG5cdC8qKlxuXHQgKiBAaW50ZXJuYWxcblx0ICpcblx0ICpcblx0ICogQHBhcmFtIGRhdGFcblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqL1xuXHR2YXIgRmllbGQgPSBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdHRoaXMubmFtZSA9IG0ucHJvcChkYXRhLm5hbWUpO1xuXHRcdHRoaXMudGl0bGUgPSBtLnByb3AoZGF0YS50aXRsZSB8fCBkYXRhLm5hbWUpO1xuXG5cdFx0dGhpcy50eXBlID0gbS5wcm9wKGRhdGEudHlwZSk7XG5cdFx0dGhpcy5sYWJlbCA9IG0ucHJvcChkYXRhLnRpdGxlIHx8ICcnKTtcblx0XHR0aGlzLnZhbHVlID0gbS5wcm9wKGRhdGEudmFsdWUgfHwgJycpO1xuXHRcdHRoaXMucGxhY2Vob2xkZXIgPSBtLnByb3AoZGF0YS5wbGFjZWhvbGRlciB8fCB0cnVlKTtcblx0XHR0aGlzLnJlcXVpcmVkID0gbS5wcm9wKGRhdGEucmVxdWlyZWQgfHwgZmFsc2UpO1xuXHRcdHRoaXMud3JhcCA9IG0ucHJvcChkYXRhLndyYXAgfHwgdHJ1ZSk7XG5cdFx0dGhpcy5taW4gPSBtLnByb3AoZGF0YS5taW4gfHwgbnVsbCk7XG5cdFx0dGhpcy5tYXggPSBtLnByb3AoZGF0YS5tYXggfHwgbnVsbCk7XG5cdFx0dGhpcy5oZWxwID0gbS5wcm9wKGRhdGEuaGVscCB8fCAnJyk7XG5cdFx0dGhpcy5jaG9pY2VzID0gbS5wcm9wKGRhdGEuY2hvaWNlcyB8fCBbXSk7XG5cdFx0dGhpcy5pbkZvcm1Db250ZW50ID0gbS5wcm9wKG51bGwpO1xuXG5cdFx0dGhpcy5zZWxlY3RDaG9pY2UgPSBmdW5jdGlvbih2YWx1ZSkge1xuXHRcdFx0dmFyIGZpZWxkID0gdGhpcztcblxuXHRcdFx0dGhpcy5jaG9pY2VzKHRoaXMuY2hvaWNlcygpLm1hcChmdW5jdGlvbihjaG9pY2UpIHtcblxuXHRcdFx0XHRpZiggY2hvaWNlLnZhbHVlKCkgPT09IHZhbHVlICkge1xuXHRcdFx0XHRcdGNob2ljZS5zZWxlY3RlZCh0cnVlKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQvLyBvbmx5IGNoZWNrYm94ZXMgYWxsb3cgZm9yIG11bHRpcGxlIHNlbGVjdGlvbnNcblx0XHRcdFx0XHRpZihmaWVsZC50eXBlKCkgIT09ICdjaGVja2JveCcgKSB7XG5cdFx0XHRcdFx0XHRjaG9pY2Uuc2VsZWN0ZWQoZmFsc2UpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldHVybiBjaG9pY2U7XG5cblx0XHRcdH0pICk7XG5cdFx0fVxuXHR9O1xuXG5cdC8qKlxuXHQgKiBAaW50ZXJuYWxcblx0ICpcblx0ICogQHBhcmFtIGRhdGFcblx0ICogQGNvbnN0cnVjdG9yXG5cdCAqL1xuXHR2YXIgRmllbGRDaG9pY2UgPSBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdHRoaXMubGFiZWwgPSBtLnByb3AoZGF0YS5sYWJlbCk7XG5cdFx0dGhpcy50aXRsZSA9IG0ucHJvcChkYXRhLnRpdGxlIHx8IGRhdGEubGFiZWwpO1xuXHRcdHRoaXMuc2VsZWN0ZWQgPSBtLnByb3AoZGF0YS5zZWxlY3RlZCB8fCBmYWxzZSk7XG5cdFx0dGhpcy52YWx1ZSA9IG0ucHJvcChkYXRhLnZhbHVlIHx8IGRhdGEubGFiZWwpO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIEBhcGlcblx0ICpcblx0ICogQHJldHVybnMge3tmaWVsZHM6IHt9LCBnZXQ6IGdldCwgZ2V0QWxsOiBnZXRBbGwsIGRlcmVnaXN0ZXI6IGRlcmVnaXN0ZXIsIHJlZ2lzdGVyOiByZWdpc3Rlcn19XG5cdCAqIEBjb25zdHJ1Y3RvclxuXHQgKi9cblx0dmFyIGZpZWxkcyA9IFtdO1xuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIEZpZWxkQ2hvaWNlIG9iamVjdHMgZnJvbSBhbiAoYXNzb2NpYXRpdmUpIGFycmF5IG9mIGRhdGEgb2JqZWN0c1xuXHQgKlxuXHQgKiBAcGFyYW0gZGF0YVxuXHQgKiBAcmV0dXJucyB7QXJyYXl9XG5cdCAqL1xuXHRmdW5jdGlvbiBjcmVhdGVDaG9pY2VzKGRhdGEpIHtcblx0XHR2YXIgY2hvaWNlcyA9IFtdO1xuXHRcdGlmICh0eXBlb2YoIGRhdGEubWFwICkgPT09IFwiZnVuY3Rpb25cIikge1xuXHRcdFx0Y2hvaWNlcyA9IGRhdGEubWFwKGZ1bmN0aW9uIChjaG9pY2VMYWJlbCkge1xuXHRcdFx0XHRyZXR1cm4gbmV3IEZpZWxkQ2hvaWNlKHtsYWJlbDogY2hvaWNlTGFiZWx9KTtcblx0XHRcdH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjaG9pY2VzID0gT2JqZWN0LmtleXMoZGF0YSkubWFwKGZ1bmN0aW9uIChrZXkpIHtcblx0XHRcdFx0dmFyIGNob2ljZUxhYmVsID0gZGF0YVtrZXldO1xuXHRcdFx0XHRyZXR1cm4gbmV3IEZpZWxkQ2hvaWNlKHtsYWJlbDogY2hvaWNlTGFiZWwsIHZhbHVlOiBrZXl9KTtcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdHJldHVybiBjaG9pY2VzO1xuXHR9XG5cblx0LyoqXG5cdCAqIEZhY3RvcnkgbWV0aG9kXG5cdCAqXG5cdCAqIEBhcGlcblx0ICpcblx0ICogQHBhcmFtIGRhdGFcblx0ICogQHJldHVybnMge0ZpZWxkfVxuXHQgKi9cblx0ZnVuY3Rpb24gcmVnaXN0ZXIoZGF0YSkge1xuXHRcdHZhciBmaWVsZDtcblx0XHR2YXIgZXhpc3RpbmdGaWVsZCA9IGdldEFsbFdoZXJlKCduYW1lJywgZGF0YS5uYW1lKS5zaGlmdCgpO1xuXG5cdFx0Ly8gYSBmaWVsZCB3aXRoIHRoZSBzYW1lIFwibmFtZVwiIGFscmVhZHkgZXhpc3RzXG5cdFx0aWYoZXhpc3RpbmdGaWVsZCkge1xuXG5cdFx0XHQvLyB1cGRhdGUgXCJyZXF1aXJlZFwiIHN0YXR1c1xuXHRcdFx0aWYoICEgZXhpc3RpbmdGaWVsZC5yZXF1aXJlZCgpICYmIGRhdGEucmVxdWlyZWQgKSB7XG5cdFx0XHRcdGV4aXN0aW5nRmllbGQucmVxdWlyZWQodHJ1ZSk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIGJhaWxcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fVxuXG5cdFx0Ly8gYXJyYXkgb2YgY2hvaWNlcyBnaXZlbj8gY29udmVydCB0byBGaWVsZENob2ljZSBvYmplY3RzXG5cdFx0aWYgKGRhdGEuY2hvaWNlcykge1xuXHRcdFx0ZGF0YS5jaG9pY2VzID0gY3JlYXRlQ2hvaWNlcyhkYXRhLmNob2ljZXMpO1xuXG5cdFx0XHRpZiggZGF0YS52YWx1ZSkge1xuXHRcdFx0XHRkYXRhLmNob2ljZXMgPSBkYXRhLmNob2ljZXMubWFwKGZ1bmN0aW9uKGNob2ljZSkge1xuXHRcdFx0XHRcdGlmKGNob2ljZS52YWx1ZSgpID09PSBkYXRhLnZhbHVlKSB7XG5cdFx0XHRcdFx0XHRjaG9pY2Uuc2VsZWN0ZWQodHJ1ZSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiBjaG9pY2U7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIGNyZWF0ZSBGaWVsZCBvYmplY3Rcblx0XHRmaWVsZCA9IG5ldyBGaWVsZChkYXRhKTtcblx0XHRmaWVsZHMucHVzaChmaWVsZCk7XG5cblx0XHQvLyByZWRyYXcgdmlld1xuXHRcdG0ucmVkcmF3KCk7XG5cblx0XHQvLyB0cmlnZ2VyIGV2ZW50XG5cdFx0ZXZlbnRzLnRyaWdnZXIoJ2ZpZWxkcy5jaGFuZ2UnKTtcblxuXHRcdHJldHVybiBmaWVsZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBAYXBpXG5cdCAqXG5cdCAqIEBwYXJhbSBmaWVsZFxuXHQgKi9cblx0ZnVuY3Rpb24gZGVyZWdpc3RlcihmaWVsZCkge1xuXHRcdHZhciBpbmRleCA9IGZpZWxkcy5pbmRleE9mKGZpZWxkKTtcblx0XHRpZiAoaW5kZXggPiAtMSkge1xuXHRcdFx0ZGVsZXRlIGZpZWxkc1tpbmRleF07XG5cdFx0XHRtLnJlZHJhdygpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBHZXQgYSBmaWVsZCBjb25maWcgb2JqZWN0XG5cdCAqXG5cdCAqIEBwYXJhbSBuYW1lXG5cdCAqIEByZXR1cm5zIHsqfVxuXHQgKi9cblx0ZnVuY3Rpb24gZ2V0KG5hbWUpIHtcblx0XHRyZXR1cm4gZmllbGRzW25hbWVdO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldCBhbGwgZmllbGQgY29uZmlnIG9iamVjdHNcblx0ICpcblx0ICogQHJldHVybnMge0FycmF5fCp9XG5cdCAqL1xuXHRmdW5jdGlvbiBnZXRBbGwoKSB7XG5cdFx0cmV0dXJuIGZpZWxkcztcblx0fVxuXG5cdC8qKlxuXHQgKiBHZXQgYWxsIGZpZWxkcyB3aGVyZSBhIHByb3BlcnR5IG1hdGNoZXMgdGhlIGdpdmVuIHZhbHVlXG5cdCAqXG5cdCAqIEBwYXJhbSBzZWFyY2hLZXlcblx0ICogQHBhcmFtIHNlYXJjaFZhbHVlXG5cdCAqIEByZXR1cm5zIHtBcnJheXwqfVxuXHQgKi9cblx0ZnVuY3Rpb24gZ2V0QWxsV2hlcmUoc2VhcmNoS2V5LCBzZWFyY2hWYWx1ZSkge1xuXHRcdHJldHVybiBmaWVsZHMuZmlsdGVyKGZ1bmN0aW9uIChmaWVsZCkge1xuXHRcdFx0cmV0dXJuIGZpZWxkW3NlYXJjaEtleV0oKSA9PT0gc2VhcmNoVmFsdWU7XG5cdFx0fSk7XG5cdH1cblxuXG5cdC8qKlxuXHQgKiBFeHBvc2VkIG1ldGhvZHNcblx0ICovXG5cdHJldHVybiB7XG5cdFx0J2ZpZWxkcycgICAgIDogZmllbGRzLFxuXHRcdCdnZXQnICAgICAgICA6IGdldCxcblx0XHQnZ2V0QWxsJyAgICAgOiBnZXRBbGwsXG5cdFx0J2RlcmVnaXN0ZXInIDogZGVyZWdpc3Rlcixcblx0XHQncmVnaXN0ZXInICAgOiByZWdpc3Rlcixcblx0XHQnZ2V0QWxsV2hlcmUnOiBnZXRBbGxXaGVyZVxuXHR9O1xufTsiLCIvKiBFZGl0b3IgKi9cbnZhciBGb3JtRWRpdG9yID0gZnVuY3Rpb24oZWxlbWVudCkge1xuXG5cdC8vIGNyZWF0ZSBkb20gcmVwcmVzZW50YXRpb24gb2YgZm9ybVxuXHR2YXIgX2RvbSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2Zvcm0nKVxuXHRcdCwgZG9tRGlydHkgPSBmYWxzZSxcblx0XHRyID0ge30sXG5cdFx0ZWRpdG9yO1xuXHRfZG9tLmlubmVySFRNTCA9IGVsZW1lbnQudmFsdWUudG9Mb3dlckNhc2UoKTtcblxuXHQvLyBsb2FkIENvZGVNaXJyb3IgJiBwbHVnaW5zXG5cdHZhciBDb2RlTWlycm9yID0gcmVxdWlyZSgnY29kZW1pcnJvcicpO1xuXHRyZXF1aXJlKCdjb2RlbWlycm9yL21vZGUveG1sL3htbCcpO1xuXHRyZXF1aXJlKCdjb2RlbWlycm9yL21vZGUvamF2YXNjcmlwdC9qYXZhc2NyaXB0Jyk7XG5cdHJlcXVpcmUoJ2NvZGVtaXJyb3IvbW9kZS9jc3MvY3NzJyk7XG5cdHJlcXVpcmUoJ2NvZGVtaXJyb3IvbW9kZS9odG1sbWl4ZWQvaHRtbG1peGVkJyk7XG5cdHJlcXVpcmUoJ2NvZGVtaXJyb3IvYWRkb24vZm9sZC94bWwtZm9sZCcpO1xuXHRyZXF1aXJlKCdjb2RlbWlycm9yL2FkZG9uL2VkaXQvbWF0Y2h0YWdzJyk7XG5cdHJlcXVpcmUoJ2NvZGVtaXJyb3IvYWRkb24vZWRpdC9jbG9zZXRhZy5qcycpO1xuXG5cdGlmKCBDb2RlTWlycm9yICkge1xuXHRcdGVkaXRvciA9IENvZGVNaXJyb3IuZnJvbVRleHRBcmVhKGVsZW1lbnQsIHtcblx0XHRcdHNlbGVjdGlvblBvaW50ZXI6IHRydWUsXG5cdFx0XHRtYXRjaFRhZ3M6IHsgYm90aFRhZ3M6IHRydWUgfSxcblx0XHRcdG1vZGU6IFwiaHRtbG1peGVkXCIsXG5cdFx0XHRodG1sTW9kZTogdHJ1ZSxcblx0XHRcdGF1dG9DbG9zZVRhZ3M6IHRydWUsXG5cdFx0XHRhdXRvUmVmcmVzaDogdHJ1ZVxuXHRcdH0pO1xuXG5cdFx0Ly8gZGlzcGF0Y2ggcmVndWxhciBcImNoYW5nZVwiIG9uIGVsZW1lbnQgZXZlbnQgZXZlcnkgdGltZSBlZGl0b3IgY2hhbmdlcyAoSUU5KyBvbmx5KVxuXHRcdHdpbmRvdy5kaXNwYXRjaEV2ZW50ICYmIGVkaXRvci5vbignY2hhbmdlJyxmdW5jdGlvbigpIHtcblx0XHRcdGlmKHR5cGVvZihFdmVudCkgPT09IFwiZnVuY3Rpb25cIikge1xuXHRcdFx0XHQvLyBDcmVhdGUgYSBuZXcgJ2NoYW5nZScgZXZlbnRcblx0XHRcdFx0dmFyIGV2ZW50ID0gbmV3IEV2ZW50KCdjaGFuZ2UnLCB7IGJ1YmJsZXM6IHRydWUgfSk7XG5cdFx0XHRcdGVsZW1lbnQuZGlzcGF0Y2hFdmVudChldmVudCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHQvLyBzZXQgZG9tRGlydHkgdG8gdHJ1ZSBldmVyeXRpbWUgdGhlIFwiY2hhbmdlXCIgZXZlbnQgZmlyZXMgKGEgbG90Li4pXG5cdGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lciAmJiBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsZnVuY3Rpb24oKSB7XG5cdFx0ZG9tRGlydHkgPSB0cnVlO1xuXHR9KTtcblxuXHRmdW5jdGlvbiBkb20oKSB7XG5cdFx0aWYoIGRvbURpcnR5ICkge1xuXHRcdFx0X2RvbS5pbm5lckhUTUwgPSByLmdldFZhbHVlKCkudG9Mb3dlckNhc2UoKTtcblx0XHRcdGRvbURpcnR5ID0gZmFsc2U7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIF9kb207XG5cdH1cblxuXHRyLmdldFZhbHVlID0gZnVuY3Rpb24oKSB7XG5cdFx0aWYoIGVkaXRvciApIHtcblx0XHRcdHJldHVybiBlZGl0b3IuZ2V0VmFsdWUoKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZWxlbWVudC52YWx1ZTtcblx0fTtcblxuXHRyLnF1ZXJ5ID0gZnVuY3Rpb24ocXVlcnkpIHtcblx0XHRyZXR1cm4gZG9tKCkucXVlcnlTZWxlY3RvckFsbChxdWVyeSk7XG5cdH07XG5cblx0ci5jb250YWluc0ZpZWxkID0gZnVuY3Rpb24oZmllbGROYW1lKXtcblx0XHRyZXR1cm4gci5xdWVyeSgnW25hbWVePVwiJysgZmllbGROYW1lLnRvTG93ZXJDYXNlKCkgKydcIl0nKS5sZW5ndGggPiAwO1xuXHR9O1xuXG5cdHIuaW5zZXJ0ID0gZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0aWYoIGVkaXRvciApIHtcblx0XHRcdGVkaXRvci5yZXBsYWNlU2VsZWN0aW9uKCBodG1sICk7XG5cdFx0XHRlZGl0b3IuZm9jdXMoKTtcblx0XHR9XG5cblx0XHRlbGVtZW50LnZhbHVlICs9IGh0bWw7XG5cdH07XG5cblx0ci5vbiA9IGZ1bmN0aW9uKGV2ZW50LGNhbGxiYWNrKSB7XG5cdFx0aWYoIGVkaXRvciApIHtcblxuXHRcdFx0Ly8gdHJhbnNsYXRlIFwiaW5wdXRcIiBldmVudCBmb3IgQ29kZU1pcnJvclxuXHRcdFx0aWYoIGV2ZW50ID09PSAnaW5wdXQnICkge1xuXHRcdFx0XHRldmVudCA9ICdjaGFuZ2VzJztcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGVkaXRvci5vbihldmVudCxjYWxsYmFjayk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudCxjYWxsYmFjayk7XG5cdH07XG5cblx0ci5yZWZyZXNoID0gZnVuY3Rpb24oKSB7XG5cdFx0aWYoIGVkaXRvciApIHtcblx0XHRcdGVkaXRvci5yZWZyZXNoKCk7XG5cdFx0fVxuXHR9O1xuXG5cdHJldHVybiByO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBGb3JtRWRpdG9yOyIsInZhciBGb3JtV2F0Y2hlciA9IGZ1bmN0aW9uKG0sIGVkaXRvciwgc2V0dGluZ3MsIGZpZWxkcywgZXZlbnRzKSB7XG5cdCd1c2Ugc3RyaWN0JztcblxuXHR2YXIgbWlzc2luZ0ZpZWxkc05vdGljZSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtaXNzaW5nLWZpZWxkcy1ub3RpY2UnKTtcblx0dmFyIG1pc3NpbmdGaWVsZHNOb3RpY2VMaXN0ID0gbWlzc2luZ0ZpZWxkc05vdGljZS5xdWVyeVNlbGVjdG9yKCd1bCcpO1xuXHR2YXIgcmVxdWlyZWRGaWVsZHNJbnB1dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdyZXF1aXJlZC1maWVsZHMnKTtcblxuXHQvLyBwb2xsaW5nXG5cdGZ1bmN0aW9uIGRlYm91bmNlKGZ1bmMsIHdhaXQsIGltbWVkaWF0ZSkge1xuXHRcdHZhciB0aW1lb3V0O1xuXHRcdHJldHVybiBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBjb250ZXh0ID0gdGhpcywgYXJncyA9IGFyZ3VtZW50cztcblx0XHRcdHZhciBsYXRlciA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHR0aW1lb3V0ID0gbnVsbDtcblx0XHRcdFx0aWYgKCFpbW1lZGlhdGUpIGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG5cdFx0XHR9O1xuXHRcdFx0dmFyIGNhbGxOb3cgPSBpbW1lZGlhdGUgJiYgIXRpbWVvdXQ7XG5cdFx0XHRjbGVhclRpbWVvdXQodGltZW91dCk7XG5cdFx0XHR0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgd2FpdCk7XG5cdFx0XHRpZiAoY2FsbE5vdykgZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcblx0XHR9O1xuXHR9XG5cblx0ZnVuY3Rpb24gdXBkYXRlRmllbGRzKCkge1xuXHRcdGZpZWxkcy5nZXRBbGwoKS5mb3JFYWNoKGZ1bmN0aW9uKGZpZWxkKSB7XG5cdFx0XHQvLyBkb24ndCBydW4gZm9yIGVtcHR5IGZpZWxkIG5hbWVzXG5cdFx0XHRpZihmaWVsZC5uYW1lKCkubGVuZ3RoIDw9IDApIHJldHVybjtcblxuXHRcdFx0dmFyIGluRm9ybSA9IGVkaXRvci5jb250YWluc0ZpZWxkKCBmaWVsZC5uYW1lKCkgKTtcblx0XHRcdGZpZWxkLmluRm9ybUNvbnRlbnQoIGluRm9ybSApO1xuXHRcdH0pO1xuXG5cdFx0Y2hlY2tSZXF1aXJlZEZpZWxkcygpO1xuXG5cdFx0bS5yZWRyYXcoKTtcblx0fVxuXG5cdC8vIGZ1bmN0aW9uc1xuXHRmdW5jdGlvbiBjaGVja1JlcXVpcmVkRmllbGRzKCkge1xuXG5cdFx0dmFyIHJlcXVpcmVkRmllbGRzID0gZmllbGRzLmdldEFsbFdoZXJlKCdyZXF1aXJlZCcsIHRydWUpO1xuXG5cdFx0Ly8gY2hlY2sgcHJlc2VuY2UgZm9yIGVhY2ggcmVxdWlyZWQgZmllbGRcblx0XHR2YXIgbWlzc2luZ0ZpZWxkcyA9IFtdO1xuXHRcdHJlcXVpcmVkRmllbGRzLmZvckVhY2goZnVuY3Rpb24oZmllbGQpIHtcblx0XHRcdGlmKCAhIGZpZWxkLmluRm9ybUNvbnRlbnQoKSApIHtcblx0XHRcdFx0bWlzc2luZ0ZpZWxkcy5wdXNoKGZpZWxkKTtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdC8vIGRvIG5vdGhpbmcgaWYgbm8gZmllbGRzIGFyZSBtaXNzaW5nXG5cdFx0aWYoIG1pc3NpbmdGaWVsZHMubGVuZ3RoID09PSAwICkge1xuXHRcdFx0bWlzc2luZ0ZpZWxkc05vdGljZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIHNob3cgbm90aWNlXG5cdFx0dmFyIGxpc3RJdGVtcyA9ICcnO1xuXHRcdG1pc3NpbmdGaWVsZHMuZm9yRWFjaChmdW5jdGlvbiggZmllbGQgKSB7XG5cdFx0XHRsaXN0SXRlbXMgKz0gXCI8bGk+XCIgKyBmaWVsZC5sYWJlbCgpICsgXCIgKDxjb2RlPlwiICsgZmllbGQubmFtZSgpICsgXCI8L2NvZGU+KTwvbGk+XCI7XG5cdFx0fSk7XG5cblx0XHRtaXNzaW5nRmllbGRzTm90aWNlTGlzdC5pbm5lckhUTUwgPSBsaXN0SXRlbXM7XG5cdFx0bWlzc2luZ0ZpZWxkc05vdGljZS5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcblx0fVxuXG5cdGZ1bmN0aW9uIGZpbmRSZXF1aXJlZEZpZWxkcygpIHtcblxuXHRcdC8vIHF1ZXJ5IGZpZWxkcyByZXF1aXJlZCBieSBNYWlsQ2hpbXBcblx0XHR2YXIgcmVxdWlyZWRGaWVsZHMgPSBmaWVsZHMuZ2V0QWxsV2hlcmUoJ3JlcXVpcmVkJywgdHJ1ZSkubWFwKGZ1bmN0aW9uKGYpIHtcblx0XHRcdHJldHVybiBmLm5hbWUoKS50b1VwcGVyQ2FzZ