@bestcodetools/graphql-playground 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,122 @@
1
+ ((app) => {
2
+ const TEMPLATE_VERSION = '20260409e';
3
+
4
+ app.component('configEditor', {
5
+ templateUrl: `components/config-editor.html?v=${TEMPLATE_VERSION}`,
6
+ bindings: {
7
+ exportWorkspace: '&?',
8
+ importWorkspace: '&?'
9
+ },
10
+ controller: ['AppState', 'I18nService', '$scope', function (AppState, I18nService, scope) {
11
+ const $ctrl = this;
12
+
13
+ $ctrl.t = function (key) {
14
+ return I18nService.t(key);
15
+ };
16
+
17
+ $ctrl.tabs = [
18
+ { id: 'headers', titleKey: 'config.shared_headers' },
19
+ { id: 'other', titleKey: 'config.other' }
20
+ ];
21
+ $ctrl.activeTab = 'headers';
22
+ $ctrl.headers = AppState.getKey('sharedHeaders') || [];
23
+
24
+ $ctrl.setActiveTab = function (tabId) {
25
+ $ctrl.activeTab = tabId;
26
+ };
27
+
28
+ $ctrl.addHeader = function () {
29
+ $ctrl.headers.push({ key: '', value: '' });
30
+ AppState.saveKey('sharedHeaders', $ctrl.headers);
31
+ };
32
+
33
+ $ctrl.removeHeader = function (index) {
34
+ $ctrl.headers.splice(index, 1);
35
+ AppState.saveKey('sharedHeaders', $ctrl.headers);
36
+ };
37
+
38
+ $ctrl.getWorkspaceLabel = function (key) {
39
+ const isPtBr = I18nService.getLocale() === 'pt-BR';
40
+ const labels = {
41
+ export: isPtBr ? 'Exportar Workspace' : 'Export Workspace',
42
+ import: isPtBr ? 'Importar Workspace' : 'Import Workspace',
43
+ note: isPtBr
44
+ ? 'Exporte e importe seu workspace completo, incluindo abas e configurações.'
45
+ : 'Export and import your full workspace, including tabs and settings.',
46
+ importError: isPtBr
47
+ ? 'Não foi possível importar este arquivo de workspace.'
48
+ : 'Could not import this workspace file.'
49
+ };
50
+
51
+ return labels[key] || '';
52
+ };
53
+
54
+ $ctrl.handleExportWorkspace = function () {
55
+ if ($ctrl.exportWorkspace) {
56
+ $ctrl.exportWorkspace();
57
+ }
58
+ };
59
+
60
+ $ctrl.triggerImportWorkspace = function () {
61
+ const input = document.getElementById('workspace-import-input');
62
+ if (input) {
63
+ input.value = '';
64
+ input.click();
65
+ }
66
+ };
67
+
68
+ $ctrl.handleImportWorkspaceFile = function (event) {
69
+ const input = event && event.target;
70
+ const file = input && input.files && input.files[0];
71
+
72
+ if (!file) {
73
+ return;
74
+ }
75
+
76
+ const reader = new FileReader();
77
+ const showImportErrorToast = function () {
78
+ if (typeof window !== 'undefined' && window.Swal && typeof window.Swal.fire === 'function') {
79
+ window.Swal.fire({
80
+ toast: true,
81
+ position: 'top-end',
82
+ icon: 'error',
83
+ title: $ctrl.getWorkspaceLabel('importError'),
84
+ showConfirmButton: false,
85
+ timer: 3500,
86
+ timerProgressBar: true
87
+ });
88
+ return;
89
+ }
90
+
91
+ window.alert($ctrl.getWorkspaceLabel('importError'));
92
+ };
93
+
94
+ reader.onload = function (loadEvent) {
95
+ try {
96
+ const parsed = JSON.parse(loadEvent.target.result);
97
+ if ($ctrl.importWorkspace) {
98
+ $ctrl.importWorkspace({ workspace: parsed });
99
+ }
100
+ } catch (error) {
101
+ showImportErrorToast();
102
+ } finally {
103
+ if (input) {
104
+ input.value = '';
105
+ }
106
+ }
107
+ };
108
+ reader.onerror = function () {
109
+ showImportErrorToast();
110
+ if (input) {
111
+ input.value = '';
112
+ }
113
+ };
114
+ reader.readAsText(file);
115
+ };
116
+
117
+ scope.$watch(() => $ctrl.headers, (newHeaders) => {
118
+ AppState.saveKey('sharedHeaders', newHeaders);
119
+ }, true);
120
+ }]
121
+ });
122
+ })(angular.module('app'));
@@ -0,0 +1,562 @@
1
+ ((app) => {
2
+ const TEMPLATE_VERSION = '20260409g';
3
+ const CUSTOM_HEADERS_COOKIE = 'custom_request_headers';
4
+ const COMMON_HEADERS = [
5
+ { key: 'Authorization', value: '', display: 'Authorization' },
6
+ { key: 'Authorization', value: 'Bearer ', display: 'Authorization: Bearer Token' },
7
+ { key: 'Authorization', value: 'Basic ', display: 'Authorization: Basic Auth' },
8
+ { key: 'Accept', value: 'application/json', display: 'Accept' },
9
+ { key: 'Content-Type', value: 'application/json', display: 'Content-Type' },
10
+ { key: 'X-App-Token', value: '', display: 'X-App-Token' },
11
+ { key: 'X-App-Key', value: '', display: 'X-App-Key' },
12
+ { key: 'X-API-Token', value: '', display: 'X-API-Token' },
13
+ { key: 'X-API-Key', value: '', display: 'X-API-Key' },
14
+ { key: 'X-Request-Id', value: '', display: 'X-Request-Id' },
15
+ { key: 'X-Correlation-Id', value: '', display: 'X-Correlation-Id' },
16
+ { key: 'X-Tenant-Id', value: '', display: 'X-Tenant-Id' },
17
+ { key: 'X-User-Id', value: '', display: 'X-User-Id' },
18
+ { key: 'X-Client-Id', value: '', display: 'X-Client-Id' },
19
+ { key: 'Api-Key', value: '', display: 'Api-Key' },
20
+ { key: 'apikey', value: '', display: 'apikey' }
21
+ ];
22
+
23
+ app.component('headersEditor', {
24
+ templateUrl: `components/headers-editor.html?v=${TEMPLATE_VERSION}`,
25
+ bindings: {
26
+ headers: '=',
27
+ api: '=?',
28
+ onChange: '&?'
29
+ },
30
+ controller: ['$element', function ($element) {
31
+ const $ctrl = this;
32
+ let editor = null;
33
+ let resizeHandler = null;
34
+
35
+ function readCustomHeadersFromCookie() {
36
+ if (typeof document === 'undefined' || !document.cookie) {
37
+ return [];
38
+ }
39
+
40
+ const cookieEntry = document.cookie
41
+ .split('; ')
42
+ .find((entry) => entry.startsWith(`${CUSTOM_HEADERS_COOKIE}=`));
43
+
44
+ if (!cookieEntry) {
45
+ return [];
46
+ }
47
+
48
+ const rawValue = cookieEntry.substring(CUSTOM_HEADERS_COOKIE.length + 1);
49
+
50
+ try {
51
+ const parsed = JSON.parse(decodeURIComponent(rawValue));
52
+ return Array.isArray(parsed) ? parsed.filter((item) => typeof item === 'string' && item.trim()) : [];
53
+ } catch (error) {
54
+ return [];
55
+ }
56
+ }
57
+
58
+ function writeCustomHeadersToCookie(headerNames) {
59
+ if (typeof document === 'undefined') {
60
+ return;
61
+ }
62
+
63
+ const normalized = Array.from(new Set(headerNames.map((name) => name.trim()).filter(Boolean))).slice(0, 50);
64
+ const encoded = encodeURIComponent(JSON.stringify(normalized));
65
+ const maxAge = 60 * 60 * 24 * 365;
66
+
67
+ document.cookie = `${CUSTOM_HEADERS_COOKIE}=${encoded}; path=/; max-age=${maxAge}; SameSite=Lax`;
68
+ }
69
+
70
+ function getCustomHeaderSuggestions() {
71
+ return readCustomHeadersFromCookie().map((headerName) => ({
72
+ key: headerName,
73
+ value: '',
74
+ display: `${headerName} (custom)`
75
+ }));
76
+ }
77
+
78
+ function saveCustomHeadersFromText(text) {
79
+ try {
80
+ const parsed = JSON.parse(text || '{}');
81
+
82
+ if (!parsed || Array.isArray(parsed) || typeof parsed !== 'object') {
83
+ return;
84
+ }
85
+
86
+ const knownHeaderNames = new Set(COMMON_HEADERS.map((header) => header.key.toLowerCase()));
87
+ const existingCustom = readCustomHeadersFromCookie();
88
+ const nextCustom = [
89
+ ...existingCustom,
90
+ ...Object.keys(parsed).filter((key) => !knownHeaderNames.has(key.toLowerCase()))
91
+ ];
92
+
93
+ writeCustomHeadersToCookie(nextCustom);
94
+ } catch (error) {
95
+ // Ignore invalid JSON while the user is editing.
96
+ }
97
+ }
98
+
99
+ function ensureHeadersMode() {
100
+ if (typeof window.CodeMirror === 'undefined') {
101
+ return;
102
+ }
103
+
104
+ if (window.CodeMirror.modes && window.CodeMirror.modes['request-headers']) {
105
+ return;
106
+ }
107
+
108
+ window.CodeMirror.defineMode('request-headers', function () {
109
+ return {
110
+ startState() {
111
+ return {
112
+ inString: false,
113
+ escaped: false
114
+ };
115
+ },
116
+ token(stream, state) {
117
+ if (state.inString) {
118
+ let next;
119
+
120
+ while ((next = stream.next()) != null) {
121
+ if (next === '"' && !state.escaped) {
122
+ state.inString = false;
123
+ break;
124
+ }
125
+
126
+ state.escaped = !state.escaped && next === '\\';
127
+ }
128
+
129
+ return 'string';
130
+ }
131
+
132
+ if (stream.eatSpace()) {
133
+ return null;
134
+ }
135
+
136
+ if (stream.peek() === '"') {
137
+ stream.next();
138
+ state.inString = true;
139
+ state.escaped = false;
140
+ return 'string';
141
+ }
142
+
143
+ if (stream.match(/^(?:true|false|null)\b/)) {
144
+ return 'atom';
145
+ }
146
+
147
+ if (stream.match(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/)) {
148
+ return 'number';
149
+ }
150
+
151
+ if (stream.match(/^[{}\[\],:]/)) {
152
+ return 'bracket';
153
+ }
154
+
155
+ stream.next();
156
+ return null;
157
+ }
158
+ };
159
+ });
160
+ }
161
+
162
+ function getExistingRootKeys(text) {
163
+ const keys = new Set();
164
+ let depth = 0;
165
+ let inString = false;
166
+ let escaped = false;
167
+ let pendingKey = null;
168
+
169
+ for (let index = 0; index < text.length; index += 1) {
170
+ const char = text[index];
171
+
172
+ if (inString) {
173
+ if (char === '"' && !escaped) {
174
+ inString = false;
175
+ }
176
+
177
+ escaped = !escaped && char === '\\';
178
+ continue;
179
+ }
180
+
181
+ if (char === '"') {
182
+ inString = true;
183
+ escaped = false;
184
+
185
+ let end = index + 1;
186
+ let key = '';
187
+ let localEscaped = false;
188
+
189
+ while (end < text.length) {
190
+ const next = text[end];
191
+
192
+ if (next === '"' && !localEscaped) {
193
+ break;
194
+ }
195
+
196
+ key += next;
197
+ localEscaped = !localEscaped && next === '\\';
198
+ end += 1;
199
+ }
200
+
201
+ pendingKey = key;
202
+ continue;
203
+ }
204
+
205
+ if (char === '{') {
206
+ depth += 1;
207
+ } else if (char === '}') {
208
+ depth = Math.max(0, depth - 1);
209
+ } else if (char === ':' && depth === 1 && pendingKey) {
210
+ keys.add(pendingKey);
211
+ pendingKey = null;
212
+ } else if (!/\s/.test(char)) {
213
+ pendingKey = null;
214
+ }
215
+ }
216
+
217
+ return keys;
218
+ }
219
+
220
+ function getRootInsertionContext(text, cursorIndex) {
221
+ const openBraceIndex = text.indexOf('{');
222
+ const closeBraceIndex = text.lastIndexOf('}');
223
+
224
+ if (openBraceIndex === -1 || closeBraceIndex === -1 || cursorIndex < openBraceIndex || cursorIndex > closeBraceIndex) {
225
+ return null;
226
+ }
227
+
228
+ let depth = 0;
229
+ let inString = false;
230
+ let escaped = false;
231
+
232
+ for (let index = 0; index < cursorIndex; index += 1) {
233
+ const char = text[index];
234
+
235
+ if (inString) {
236
+ if (char === '"' && !escaped) {
237
+ inString = false;
238
+ }
239
+
240
+ escaped = !escaped && char === '\\';
241
+ continue;
242
+ }
243
+
244
+ if (char === '"') {
245
+ inString = true;
246
+ escaped = false;
247
+ continue;
248
+ }
249
+
250
+ if (char === '{') {
251
+ depth += 1;
252
+ } else if (char === '}') {
253
+ depth = Math.max(0, depth - 1);
254
+ }
255
+ }
256
+
257
+ if (depth !== 1) {
258
+ return null;
259
+ }
260
+
261
+ let from = cursorIndex;
262
+ while (from > openBraceIndex && /[A-Za-z0-9_\-"]/.test(text[from - 1])) {
263
+ from -= 1;
264
+ }
265
+
266
+ let to = cursorIndex;
267
+ while (to < closeBraceIndex && /[A-Za-z0-9_\-"]/.test(text[to])) {
268
+ to += 1;
269
+ }
270
+
271
+ return {
272
+ from,
273
+ to,
274
+ openBraceIndex,
275
+ closeBraceIndex
276
+ };
277
+ }
278
+
279
+ function buildHeaderSnippet(header) {
280
+ const keyText = `"${header.key}": `;
281
+ const valueText = JSON.stringify(header.value);
282
+ const cursorOffset = header.value ? keyText.length + 1 + header.value.length : keyText.length + 1;
283
+
284
+ return {
285
+ text: `${keyText}${valueText}`,
286
+ cursorOffset
287
+ };
288
+ }
289
+
290
+ function applyHeaderCompletion(cm, data, completion) {
291
+ const text = cm.getValue();
292
+ const cursor = cm.getCursor();
293
+ const cursorIndex = cm.indexFromPos(cursor);
294
+ const context = getRootInsertionContext(text, cursorIndex);
295
+
296
+ if (!context) {
297
+ const fallback = `"${completion.header.key}": ${JSON.stringify(completion.header.value)}`;
298
+ cm.replaceRange(fallback, data.from, data.to);
299
+ return;
300
+ }
301
+
302
+ const baseIndent = ' ';
303
+ const snippet = buildHeaderSnippet(completion.header);
304
+ const before = text.slice(context.openBraceIndex + 1, context.from);
305
+ const after = text.slice(context.to, context.closeBraceIndex);
306
+ const needsCommaBefore = /[}\]"0-9a-zA-Z]/.test(before.trim().slice(-1)) && !before.trim().endsWith(',');
307
+ const needsCommaAfter = after.trim() && !after.trim().startsWith('}') && !after.trim().startsWith(',');
308
+ const lineStartIndex = text.lastIndexOf('\n', Math.max(0, context.from - 1)) + 1;
309
+ const currentLineText = text.slice(lineStartIndex, context.from);
310
+ const shouldReuseCurrentLine = currentLineText.trim() === '';
311
+ const prefix = before.trim() ? `\n${baseIndent}` : '\n ';
312
+ let commaAttachIndex = context.from;
313
+
314
+ if (needsCommaBefore) {
315
+ let previousValueIndex = context.from - 1;
316
+
317
+ while (previousValueIndex > context.openBraceIndex && /\s/.test(text[previousValueIndex])) {
318
+ previousValueIndex -= 1;
319
+ }
320
+
321
+ commaAttachIndex = previousValueIndex + 1;
322
+ }
323
+
324
+ if (shouldReuseCurrentLine) {
325
+ let insertionShift = 0;
326
+
327
+ if (needsCommaBefore) {
328
+ cm.replaceRange(',', cm.posFromIndex(commaAttachIndex), cm.posFromIndex(commaAttachIndex));
329
+ if (commaAttachIndex < lineStartIndex) {
330
+ insertionShift = 1;
331
+ }
332
+ }
333
+
334
+ const lineInsertion = `${baseIndent}${snippet.text}${needsCommaAfter ? ',' : ''}`;
335
+ const adjustedLineStartIndex = lineStartIndex + insertionShift;
336
+ const adjustedContextTo = context.to + insertionShift;
337
+ const lineEndIndex = text.indexOf('\n', adjustedLineStartIndex);
338
+ const replaceToIndex = lineEndIndex === -1 ? adjustedContextTo : Math.min(adjustedContextTo, lineEndIndex);
339
+
340
+ cm.replaceRange(lineInsertion, cm.posFromIndex(adjustedLineStartIndex), cm.posFromIndex(replaceToIndex));
341
+
342
+ const startIndex = adjustedLineStartIndex + lineInsertion.indexOf(snippet.text) + snippet.cursorOffset;
343
+ cm.setCursor(cm.posFromIndex(startIndex));
344
+ return;
345
+ }
346
+
347
+ const insertLeadingCommaInline = needsCommaBefore && !shouldReuseCurrentLine;
348
+ const insertionPrefix = `${insertLeadingCommaInline ? ',' : ''}${prefix}`;
349
+ const insertion = `${insertionPrefix}${snippet.text}${needsCommaAfter ? ',' : ''}`;
350
+ const replaceFromIndex = commaAttachIndex;
351
+
352
+ cm.replaceRange(insertion, cm.posFromIndex(replaceFromIndex), cm.posFromIndex(context.to));
353
+
354
+ const startIndex = replaceFromIndex + insertion.indexOf(snippet.text) + snippet.cursorOffset;
355
+ cm.setCursor(cm.posFromIndex(startIndex));
356
+ }
357
+
358
+ function buildHeaderCompletions(currentText) {
359
+ const existingKeys = getExistingRootKeys(currentText);
360
+ const allHeaders = [...COMMON_HEADERS, ...getCustomHeaderSuggestions()];
361
+
362
+ return allHeaders
363
+ .filter((header) => !existingKeys.has(header.key) || header.key === 'Authorization')
364
+ .map((header) => ({
365
+ text: header.key,
366
+ displayText: header.display,
367
+ className: 'cm-hint-field',
368
+ header,
369
+ hint(cm, data, completion) {
370
+ applyHeaderCompletion(cm, data, completion);
371
+ }
372
+ }));
373
+ }
374
+
375
+ function getHeaderHints(cm) {
376
+ const cursor = cm.getCursor();
377
+ const cursorIndex = cm.indexFromPos(cursor);
378
+ const text = cm.getValue();
379
+ const context = getRootInsertionContext(text, cursorIndex);
380
+ const token = cm.getTokenAt(cursor);
381
+ const rawToken = token && typeof token.string === 'string' ? token.string.replace(/"/g, '') : '';
382
+ const prefix = /^[A-Za-z_\-][A-Za-z0-9_\-]*$/.test(rawToken) ? rawToken.slice(0, Math.max(0, cursor.ch - token.start)) : '';
383
+ const suggestions = buildHeaderCompletions(text).filter((completion) => {
384
+ if (!prefix) {
385
+ return true;
386
+ }
387
+
388
+ return completion.header.key.toLowerCase().startsWith(prefix.toLowerCase())
389
+ || completion.displayText.toLowerCase().startsWith(prefix.toLowerCase());
390
+ });
391
+
392
+ return {
393
+ list: suggestions,
394
+ from: context ? cm.posFromIndex(context.from) : cursor,
395
+ to: context ? cm.posFromIndex(context.to) : cursor
396
+ };
397
+ }
398
+
399
+ function triggerAutocomplete(cm) {
400
+ if (typeof cm.showHint !== 'function') {
401
+ return;
402
+ }
403
+
404
+ cm.showHint({
405
+ completeSingle: false,
406
+ hint: getHeaderHints
407
+ });
408
+ }
409
+
410
+ function formatEditor() {
411
+ if (!editor) {
412
+ return false;
413
+ }
414
+
415
+ try {
416
+ const parsed = JSON.parse(editor.getValue() || '{}');
417
+ const formatted = JSON.stringify(parsed, null, 2);
418
+
419
+ if (editor.getValue() !== formatted) {
420
+ editor.setValue(formatted);
421
+ }
422
+
423
+ return true;
424
+ } catch (error) {
425
+ return false;
426
+ }
427
+ }
428
+
429
+ function createEditor() {
430
+ const textarea = $element[0].querySelector('textarea');
431
+
432
+ if (!textarea || typeof window.CodeMirror === 'undefined') {
433
+ return;
434
+ }
435
+
436
+ ensureHeadersMode();
437
+
438
+ editor = window.CodeMirror.fromTextArea(textarea, {
439
+ mode: 'request-headers',
440
+ lineNumbers: true,
441
+ lineWrapping: true,
442
+ matchBrackets: true,
443
+ indentUnit: 2,
444
+ tabSize: 2,
445
+ extraKeys: {
446
+ Tab(cm) {
447
+ if (cm.state.completionActive) {
448
+ cm.execCommand('pick');
449
+ return;
450
+ }
451
+
452
+ cm.replaceSelection(' ', 'end');
453
+ },
454
+ 'Ctrl-Space'(cm) {
455
+ triggerAutocomplete(cm);
456
+ }
457
+ }
458
+ });
459
+
460
+ editor.setValue($ctrl.headers || '{}');
461
+
462
+ editor.on('change', (instance) => {
463
+ const nextValue = instance.getValue();
464
+
465
+ if ($ctrl.headers === nextValue) {
466
+ return;
467
+ }
468
+
469
+ $ctrl.headers = nextValue;
470
+ saveCustomHeadersFromText(nextValue);
471
+
472
+ if ($ctrl.onChange) {
473
+ $ctrl.onChange();
474
+ }
475
+
476
+ const rootScope = $element.scope();
477
+ if (rootScope && !rootScope.$$phase) {
478
+ rootScope.$applyAsync();
479
+ }
480
+ });
481
+
482
+ editor.on('inputRead', (cm, change) => {
483
+ if (!change || change.origin === 'setValue' || typeof cm.showHint !== 'function') {
484
+ return;
485
+ }
486
+
487
+ const insertedText = Array.isArray(change.text) ? change.text.join('') : '';
488
+
489
+ if (/^[A-Za-z_\-"]$/.test(insertedText)) {
490
+ triggerAutocomplete(cm);
491
+ }
492
+ });
493
+
494
+ scheduleRefresh();
495
+ }
496
+
497
+ function scheduleRefresh() {
498
+ if (!editor) {
499
+ return;
500
+ }
501
+
502
+ window.requestAnimationFrame(() => {
503
+ if (editor) {
504
+ editor.refresh();
505
+ }
506
+ });
507
+ }
508
+
509
+ $ctrl.$postLink = function () {
510
+ $ctrl.api = $ctrl.api || {};
511
+ $ctrl.api.format = formatEditor;
512
+ $ctrl.api.refresh = scheduleRefresh;
513
+ createEditor();
514
+ resizeHandler = () => scheduleRefresh();
515
+ window.addEventListener('resize', resizeHandler);
516
+ window.setTimeout(scheduleRefresh, 0);
517
+ window.setTimeout(scheduleRefresh, 120);
518
+ };
519
+
520
+ $ctrl.$onChanges = function (changes) {
521
+ if (!editor || !changes.headers) {
522
+ return;
523
+ }
524
+
525
+ const nextValue = changes.headers.currentValue || '{}';
526
+
527
+ if (editor.getValue() !== nextValue) {
528
+ const cursor = editor.getCursor();
529
+ editor.setValue(nextValue);
530
+ editor.setCursor(cursor);
531
+ }
532
+ };
533
+
534
+ $ctrl.$doCheck = function () {
535
+ if (!editor) {
536
+ return;
537
+ }
538
+
539
+ const nextValue = typeof $ctrl.headers === 'string' ? $ctrl.headers : '{}';
540
+
541
+ if (editor.getValue() === nextValue) {
542
+ return;
543
+ }
544
+
545
+ const cursor = editor.getCursor();
546
+ editor.setValue(nextValue);
547
+ editor.setCursor(cursor);
548
+ };
549
+
550
+ $ctrl.$onDestroy = function () {
551
+ if (resizeHandler) {
552
+ window.removeEventListener('resize', resizeHandler);
553
+ resizeHandler = null;
554
+ }
555
+ if (editor) {
556
+ editor.toTextArea();
557
+ editor = null;
558
+ }
559
+ };
560
+ }]
561
+ });
562
+ })(angular.module('app'));