UNPKG

308 kBJavaScriptView Raw
1
2/**
3 * @vue/test-utils v2.4.6
4 * (c) 2024 Lachlan Miller
5 * Released under the MIT License
6 */
7
8'use strict';
9
10var Vue = require('vue');
11var compilerDom = require('@vue/compiler-dom');
12var serverRenderer = require('@vue/server-renderer');
13
14function _interopNamespaceDefault(e) {
15 var n = Object.create(null);
16 if (e) {
17 Object.keys(e).forEach(function (k) {
18 if (k !== 'default') {
19 var d = Object.getOwnPropertyDescriptor(e, k);
20 Object.defineProperty(n, k, d.get ? d : {
21 enumerable: true,
22 get: function () { return e[k]; }
23 });
24 }
25 });
26 }
27 n.default = e;
28 return Object.freeze(n);
29}
30
31var Vue__namespace = /*#__PURE__*/_interopNamespaceDefault(Vue);
32
33/******************************************************************************
34Copyright (c) Microsoft Corporation.
35
36Permission to use, copy, modify, and/or distribute this software for any
37purpose with or without fee is hereby granted.
38
39THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
40REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
41AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
42INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
43LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
44OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
45PERFORMANCE OF THIS SOFTWARE.
46***************************************************************************** */
47/* global Reflect, Promise, SuppressedError, Symbol */
48
49var extendStatics = function(d, b) {
50 extendStatics = Object.setPrototypeOf ||
51 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
52 function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
53 return extendStatics(d, b);
54};
55
56function __extends(d, b) {
57 if (typeof b !== "function" && b !== null)
58 throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
59 extendStatics(d, b);
60 function __() { this.constructor = d; }
61 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
62}
63
64var __assign = function() {
65 __assign = Object.assign || function __assign(t) {
66 for (var s, i = 1, n = arguments.length; i < n; i++) {
67 s = arguments[i];
68 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
69 }
70 return t;
71 };
72 return __assign.apply(this, arguments);
73};
74
75function __awaiter(thisArg, _arguments, P, generator) {
76 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
77 return new (P || (P = Promise))(function (resolve, reject) {
78 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
79 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
80 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
81 step((generator = generator.apply(thisArg, _arguments || [])).next());
82 });
83}
84
85function __generator(thisArg, body) {
86 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
87 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
88 function verb(n) { return function (v) { return step([n, v]); }; }
89 function step(op) {
90 if (f) throw new TypeError("Generator is already executing.");
91 while (g && (g = 0, op[0] && (_ = 0)), _) try {
92 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
93 if (y = 0, t) op = [op[0] & 2, t.value];
94 switch (op[0]) {
95 case 0: case 1: t = op; break;
96 case 4: _.label++; return { value: op[1], done: false };
97 case 5: _.label++; y = op[1]; op = [0]; continue;
98 case 7: op = _.ops.pop(); _.trys.pop(); continue;
99 default:
100 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
101 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
102 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
103 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
104 if (t[2]) _.ops.pop();
105 _.trys.pop(); continue;
106 }
107 op = body.call(thisArg, _);
108 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
109 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
110 }
111}
112
113function __spreadArray(to, from, pack) {
114 if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
115 if (ar || !(i in from)) {
116 if (!ar) ar = Array.prototype.slice.call(from, 0, i);
117 ar[i] = from[i];
118 }
119 }
120 return to.concat(ar || Array.prototype.slice.call(from));
121}
122
123typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
124 var e = new Error(message);
125 return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
126};
127
128var Pluggable = /** @class */ (function () {
129 function Pluggable() {
130 this.installedPlugins = [];
131 }
132 Pluggable.prototype.install = function (handler, options) {
133 if (typeof handler !== 'function') {
134 console.error('plugin.install must receive a function');
135 handler = function () { return ({}); };
136 }
137 this.installedPlugins.push({ handler: handler, options: options });
138 };
139 Pluggable.prototype.extend = function (instance) {
140 var invokeSetup = function (_a) {
141 var handler = _a.handler, options = _a.options;
142 return handler(instance, options); // invoke the setup method passed to install
143 };
144 var bindProperty = function (_a) {
145 var property = _a[0], value = _a[1];
146 instance[property] =
147 typeof value === 'function' ? value.bind(instance) : value;
148 };
149 var addAllPropertiesFromSetup = function (setupResult) {
150 setupResult = typeof setupResult === 'object' ? setupResult : {};
151 Object.entries(setupResult).forEach(bindProperty);
152 };
153 this.installedPlugins.map(invokeSetup).forEach(addAllPropertiesFromSetup);
154 };
155 /** For testing */
156 Pluggable.prototype.reset = function () {
157 this.installedPlugins = [];
158 };
159 return Pluggable;
160}());
161var config = {
162 global: {
163 stubs: {
164 transition: true,
165 'transition-group': true
166 },
167 provide: {},
168 components: {},
169 config: {},
170 directives: {},
171 mixins: [],
172 mocks: {},
173 plugins: [],
174 renderStubDefaultSlot: false
175 },
176 plugins: {
177 VueWrapper: new Pluggable(),
178 DOMWrapper: new Pluggable()
179 }
180};
181
182function mergeStubs(target, source) {
183 if (source.stubs) {
184 if (Array.isArray(source.stubs)) {
185 source.stubs.forEach(function (x) { return (target[x] = true); });
186 }
187 else {
188 for (var _i = 0, _a = Object.entries(source.stubs); _i < _a.length; _i++) {
189 var _b = _a[_i], k = _b[0], v = _b[1];
190 target[k] = v;
191 }
192 }
193 }
194}
195// perform 1-level-deep-pseudo-clone merge in order to prevent config leaks
196// example: vue-router overwrites globalProperties.$router
197function mergeAppConfig(configGlobalConfig, mountGlobalConfig) {
198 return __assign(__assign(__assign({}, configGlobalConfig), mountGlobalConfig), { globalProperties: __assign(__assign({}, configGlobalConfig === null || configGlobalConfig === void 0 ? void 0 : configGlobalConfig.globalProperties), mountGlobalConfig === null || mountGlobalConfig === void 0 ? void 0 : mountGlobalConfig.globalProperties) });
199}
200function mergeGlobalProperties(mountGlobal) {
201 var _a, _b, _c;
202 if (mountGlobal === void 0) { mountGlobal = {}; }
203 var stubs = {};
204 var configGlobal = (_a = config === null || config === void 0 ? void 0 : config.global) !== null && _a !== void 0 ? _a : {};
205 mergeStubs(stubs, configGlobal);
206 mergeStubs(stubs, mountGlobal);
207 var renderStubDefaultSlot = (_c = (_b = mountGlobal.renderStubDefaultSlot) !== null && _b !== void 0 ? _b : (configGlobal.renderStubDefaultSlot || (config === null || config === void 0 ? void 0 : config.renderStubDefaultSlot))) !== null && _c !== void 0 ? _c : false;
208 if (config.renderStubDefaultSlot === true) {
209 console.warn('config.renderStubDefaultSlot is deprecated, use config.global.renderStubDefaultSlot instead');
210 }
211 return {
212 mixins: __spreadArray(__spreadArray([], (configGlobal.mixins || []), true), (mountGlobal.mixins || []), true),
213 plugins: __spreadArray(__spreadArray([], (configGlobal.plugins || []), true), (mountGlobal.plugins || []), true),
214 stubs: stubs,
215 components: __assign(__assign({}, configGlobal.components), mountGlobal.components),
216 provide: __assign(__assign({}, configGlobal.provide), mountGlobal.provide),
217 mocks: __assign(__assign({}, configGlobal.mocks), mountGlobal.mocks),
218 config: mergeAppConfig(configGlobal.config, mountGlobal.config),
219 directives: __assign(__assign({}, configGlobal.directives), mountGlobal.directives),
220 renderStubDefaultSlot: renderStubDefaultSlot
221 };
222}
223var isObject = function (obj) {
224 return !!obj && typeof obj === 'object';
225};
226function isClass(obj) {
227 if (!(obj instanceof Object))
228 return;
229 var isCtorClass = obj.constructor && obj.constructor.toString().substring(0, 5) === 'class';
230 if (!('prototype' in obj)) {
231 return isCtorClass;
232 }
233 var prototype = obj.prototype;
234 var isPrototypeCtorClass = prototype.constructor &&
235 prototype.constructor.toString &&
236 prototype.constructor.toString().substring(0, 5) === 'class';
237 return isCtorClass || isPrototypeCtorClass;
238}
239// https://stackoverflow.com/a/48218209
240var mergeDeep = function (target, source) {
241 var _a;
242 if (!isObject(target) || !isObject(source)) {
243 return source;
244 }
245 Object.keys(source)
246 .concat(isClass(source)
247 ? Object.getOwnPropertyNames((_a = Object.getPrototypeOf(source)) !== null && _a !== void 0 ? _a : {})
248 : Object.getOwnPropertyNames(source))
249 .forEach(function (key) {
250 var targetValue = target[key];
251 var sourceValue = source[key];
252 if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
253 target[key] = sourceValue;
254 }
255 else if (sourceValue instanceof Date) {
256 target[key] = sourceValue;
257 }
258 else if (isObject(targetValue) && isObject(sourceValue)) {
259 target[key] = mergeDeep(Object.assign({}, targetValue), sourceValue);
260 }
261 else {
262 target[key] = sourceValue;
263 }
264 });
265 return target;
266};
267function isClassComponent(component) {
268 return typeof component === 'function' && '__vccOpts' in component;
269}
270function isComponent(component) {
271 return Boolean(component &&
272 (typeof component === 'object' || typeof component === 'function'));
273}
274function isFunctionalComponent(component) {
275 return typeof component === 'function' && !isClassComponent(component);
276}
277function isObjectComponent(component) {
278 return Boolean(component && typeof component === 'object');
279}
280function textContent(element) {
281 var _a, _b;
282 // we check if the element is a comment first
283 // to return an empty string in that case, instead of the comment content
284 return element.nodeType !== Node.COMMENT_NODE
285 ? (_b = (_a = element.textContent) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : ''
286 : '';
287}
288function hasOwnProperty(obj, prop) {
289 return obj.hasOwnProperty(prop);
290}
291function isNotNullOrUndefined(obj) {
292 return Boolean(obj);
293}
294function isRefSelector(selector) {
295 return typeof selector === 'object' && 'ref' in selector;
296}
297function convertStubsToRecord(stubs) {
298 if (Array.isArray(stubs)) {
299 // ['Foo', 'Bar'] => { Foo: true, Bar: true }
300 return stubs.reduce(function (acc, current) {
301 acc[current] = true;
302 return acc;
303 }, {});
304 }
305 return stubs;
306}
307var isDirectiveKey = function (key) { return key.match(/^v[A-Z].*/); };
308function getComponentsFromStubs(stubs) {
309 var normalizedStubs = convertStubsToRecord(stubs);
310 return Object.fromEntries(Object.entries(normalizedStubs).filter(function (_a) {
311 var key = _a[0];
312 return !isDirectiveKey(key);
313 }));
314}
315function getDirectivesFromStubs(stubs) {
316 var normalizedStubs = convertStubsToRecord(stubs);
317 return Object.fromEntries(Object.entries(normalizedStubs)
318 .filter(function (_a) {
319 var key = _a[0], value = _a[1];
320 return isDirectiveKey(key) && value !== false;
321 })
322 .map(function (_a) {
323 var key = _a[0], value = _a[1];
324 return [key.substring(1), value];
325 }));
326}
327function hasSetupState(vm) {
328 return (vm &&
329 vm.$.devtoolsRawSetupState);
330}
331function isScriptSetup(vm) {
332 return (vm && vm.$.setupState.__isScriptSetup);
333}
334var _globalThis;
335var getGlobalThis = function () {
336 return (_globalThis ||
337 (_globalThis =
338 typeof globalThis !== 'undefined'
339 ? globalThis
340 : typeof self !== 'undefined'
341 ? self
342 : typeof window !== 'undefined'
343 ? window
344 : typeof global !== 'undefined'
345 ? global
346 : {}));
347};
348
349var ignorableKeyModifiers = [
350 'stop',
351 'prevent',
352 'self',
353 'exact',
354 'prevent',
355 'capture'
356];
357var systemKeyModifiers = ['ctrl', 'shift', 'alt', 'meta'];
358var mouseKeyModifiers = ['left', 'middle', 'right'];
359var keyCodesByKeyName = {
360 backspace: 8,
361 tab: 9,
362 enter: 13,
363 esc: 27,
364 space: 32,
365 pageup: 33,
366 pagedown: 34,
367 end: 35,
368 home: 36,
369 left: 37,
370 up: 38,
371 right: 39,
372 down: 40,
373 insert: 45,
374 delete: 46
375};
376var domEvents = {
377 abort: {
378 eventInterface: 'Event',
379 bubbles: false,
380 cancelable: false
381 },
382 afterprint: {
383 eventInterface: 'Event',
384 bubbles: false,
385 cancelable: false
386 },
387 animationend: {
388 eventInterface: 'AnimationEvent',
389 bubbles: true,
390 cancelable: false
391 },
392 animationiteration: {
393 eventInterface: 'AnimationEvent',
394 bubbles: true,
395 cancelable: false
396 },
397 animationstart: {
398 eventInterface: 'AnimationEvent',
399 bubbles: true,
400 cancelable: false
401 },
402 appinstalled: {
403 eventInterface: 'Event',
404 bubbles: false,
405 cancelable: false
406 },
407 /**
408 * @deprecated
409 */
410 audioprocess: {
411 eventInterface: 'AudioProcessingEvent',
412 bubbles: false,
413 cancelable: false
414 },
415 audioend: {
416 eventInterface: 'Event',
417 bubbles: false,
418 cancelable: false
419 },
420 audiostart: {
421 eventInterface: 'Event',
422 bubbles: false,
423 cancelable: false
424 },
425 beforeprint: {
426 eventInterface: 'Event',
427 bubbles: false,
428 cancelable: false
429 },
430 beforeunload: {
431 eventInterface: 'BeforeUnloadEvent',
432 bubbles: false,
433 cancelable: true
434 },
435 beginEvent: {
436 eventInterface: 'TimeEvent',
437 bubbles: false,
438 cancelable: false
439 },
440 blur: {
441 eventInterface: 'FocusEvent',
442 bubbles: false,
443 cancelable: false
444 },
445 boundary: {
446 eventInterface: 'SpeechSynthesisEvent',
447 bubbles: false,
448 cancelable: false
449 },
450 cached: {
451 eventInterface: 'Event',
452 bubbles: false,
453 cancelable: false
454 },
455 canplay: {
456 eventInterface: 'Event',
457 bubbles: false,
458 cancelable: false
459 },
460 canplaythrough: {
461 eventInterface: 'Event',
462 bubbles: false,
463 cancelable: false
464 },
465 change: {
466 eventInterface: 'Event',
467 bubbles: true,
468 cancelable: false
469 },
470 chargingchange: {
471 eventInterface: 'Event',
472 bubbles: false,
473 cancelable: false
474 },
475 chargingtimechange: {
476 eventInterface: 'Event',
477 bubbles: false,
478 cancelable: false
479 },
480 checking: {
481 eventInterface: 'Event',
482 bubbles: false,
483 cancelable: false
484 },
485 click: {
486 eventInterface: 'MouseEvent',
487 bubbles: true,
488 cancelable: true
489 },
490 close: {
491 eventInterface: 'Event',
492 bubbles: false,
493 cancelable: false
494 },
495 complete: {
496 eventInterface: 'OfflineAudioCompletionEvent',
497 bubbles: false,
498 cancelable: false
499 },
500 compositionend: {
501 eventInterface: 'CompositionEvent',
502 bubbles: true,
503 cancelable: true
504 },
505 compositionstart: {
506 eventInterface: 'CompositionEvent',
507 bubbles: true,
508 cancelable: true
509 },
510 compositionupdate: {
511 eventInterface: 'CompositionEvent',
512 bubbles: true,
513 cancelable: false
514 },
515 contextmenu: {
516 eventInterface: 'MouseEvent',
517 bubbles: true,
518 cancelable: true
519 },
520 copy: {
521 eventInterface: 'ClipboardEvent',
522 bubbles: true,
523 cancelable: true
524 },
525 cut: {
526 eventInterface: 'ClipboardEvent',
527 bubbles: true,
528 cancelable: true
529 },
530 dblclick: {
531 eventInterface: 'MouseEvent',
532 bubbles: true,
533 cancelable: true
534 },
535 devicechange: {
536 eventInterface: 'Event',
537 bubbles: false,
538 cancelable: false
539 },
540 devicelight: {
541 eventInterface: 'DeviceLightEvent',
542 bubbles: false,
543 cancelable: false
544 },
545 devicemotion: {
546 eventInterface: 'DeviceMotionEvent',
547 bubbles: false,
548 cancelable: false
549 },
550 deviceorientation: {
551 eventInterface: 'DeviceOrientationEvent',
552 bubbles: false,
553 cancelable: false
554 },
555 deviceproximity: {
556 eventInterface: 'DeviceProximityEvent',
557 bubbles: false,
558 cancelable: false
559 },
560 dischargingtimechange: {
561 eventInterface: 'Event',
562 bubbles: false,
563 cancelable: false
564 },
565 DOMActivate: {
566 eventInterface: 'UIEvent',
567 bubbles: true,
568 cancelable: true
569 },
570 DOMAttributeNameChanged: {
571 eventInterface: 'MutationNameEvent',
572 bubbles: true,
573 cancelable: true
574 },
575 DOMAttrModified: {
576 eventInterface: 'MutationEvent',
577 bubbles: true,
578 cancelable: true
579 },
580 DOMCharacterDataModified: {
581 eventInterface: 'MutationEvent',
582 bubbles: true,
583 cancelable: true
584 },
585 DOMContentLoaded: {
586 eventInterface: 'Event',
587 bubbles: true,
588 cancelable: true
589 },
590 DOMElementNameChanged: {
591 eventInterface: 'MutationNameEvent',
592 bubbles: true,
593 cancelable: true
594 },
595 DOMFocusIn: {
596 eventInterface: 'FocusEvent',
597 bubbles: true,
598 cancelable: true
599 },
600 DOMFocusOut: {
601 eventInterface: 'FocusEvent',
602 bubbles: true,
603 cancelable: true
604 },
605 DOMNodeInserted: {
606 eventInterface: 'MutationEvent',
607 bubbles: true,
608 cancelable: true
609 },
610 DOMNodeInsertedIntoDocument: {
611 eventInterface: 'MutationEvent',
612 bubbles: true,
613 cancelable: true
614 },
615 DOMNodeRemoved: {
616 eventInterface: 'MutationEvent',
617 bubbles: true,
618 cancelable: true
619 },
620 DOMNodeRemovedFromDocument: {
621 eventInterface: 'MutationEvent',
622 bubbles: true,
623 cancelable: true
624 },
625 /**
626 * @deprecated
627 */
628 DOMSubtreeModified: {
629 eventInterface: 'MutationEvent',
630 bubbles: true,
631 cancelable: false
632 },
633 downloading: {
634 eventInterface: 'Event',
635 bubbles: false,
636 cancelable: false
637 },
638 drag: {
639 eventInterface: 'DragEvent',
640 bubbles: true,
641 cancelable: true
642 },
643 dragend: {
644 eventInterface: 'DragEvent',
645 bubbles: true,
646 cancelable: false
647 },
648 dragenter: {
649 eventInterface: 'DragEvent',
650 bubbles: true,
651 cancelable: true
652 },
653 dragleave: {
654 eventInterface: 'DragEvent',
655 bubbles: true,
656 cancelable: false
657 },
658 dragover: {
659 eventInterface: 'DragEvent',
660 bubbles: true,
661 cancelable: true
662 },
663 dragstart: {
664 eventInterface: 'DragEvent',
665 bubbles: true,
666 cancelable: true
667 },
668 drop: {
669 eventInterface: 'DragEvent',
670 bubbles: true,
671 cancelable: true
672 },
673 durationchange: {
674 eventInterface: 'Event',
675 bubbles: false,
676 cancelable: false
677 },
678 emptied: {
679 eventInterface: 'Event',
680 bubbles: false,
681 cancelable: false
682 },
683 end: {
684 eventInterface: 'Event',
685 bubbles: false,
686 cancelable: false
687 },
688 ended: {
689 eventInterface: 'Event',
690 bubbles: false,
691 cancelable: false
692 },
693 endEvent: {
694 eventInterface: 'TimeEvent',
695 bubbles: false,
696 cancelable: false
697 },
698 error: {
699 eventInterface: 'Event',
700 bubbles: false,
701 cancelable: false
702 },
703 focus: {
704 eventInterface: 'FocusEvent',
705 bubbles: false,
706 cancelable: false
707 },
708 focusin: {
709 eventInterface: 'FocusEvent',
710 bubbles: true,
711 cancelable: false
712 },
713 focusout: {
714 eventInterface: 'FocusEvent',
715 bubbles: true,
716 cancelable: false
717 },
718 fullscreenchange: {
719 eventInterface: 'Event',
720 bubbles: true,
721 cancelable: false
722 },
723 fullscreenerror: {
724 eventInterface: 'Event',
725 bubbles: true,
726 cancelable: false
727 },
728 gamepadconnected: {
729 eventInterface: 'GamepadEvent',
730 bubbles: false,
731 cancelable: false
732 },
733 gamepaddisconnected: {
734 eventInterface: 'GamepadEvent',
735 bubbles: false,
736 cancelable: false
737 },
738 gotpointercapture: {
739 eventInterface: 'PointerEvent',
740 bubbles: false,
741 cancelable: false
742 },
743 hashchange: {
744 eventInterface: 'HashChangeEvent',
745 bubbles: true,
746 cancelable: false
747 },
748 lostpointercapture: {
749 eventInterface: 'PointerEvent',
750 bubbles: false,
751 cancelable: false
752 },
753 input: {
754 eventInterface: 'Event',
755 bubbles: true,
756 cancelable: false
757 },
758 invalid: {
759 eventInterface: 'Event',
760 cancelable: true,
761 bubbles: false
762 },
763 keydown: {
764 eventInterface: 'KeyboardEvent',
765 bubbles: true,
766 cancelable: true
767 },
768 keypress: {
769 eventInterface: 'KeyboardEvent',
770 bubbles: true,
771 cancelable: true
772 },
773 keyup: {
774 eventInterface: 'KeyboardEvent',
775 bubbles: true,
776 cancelable: true
777 },
778 languagechange: {
779 eventInterface: 'Event',
780 bubbles: false,
781 cancelable: false
782 },
783 levelchange: {
784 eventInterface: 'Event',
785 bubbles: false,
786 cancelable: false
787 },
788 load: {
789 eventInterface: 'UIEvent',
790 bubbles: false,
791 cancelable: false
792 },
793 loadeddata: {
794 eventInterface: 'Event',
795 bubbles: false,
796 cancelable: false
797 },
798 loadedmetadata: {
799 eventInterface: 'Event',
800 bubbles: false,
801 cancelable: false
802 },
803 loadend: {
804 eventInterface: 'ProgressEvent',
805 bubbles: false,
806 cancelable: false
807 },
808 loadstart: {
809 eventInterface: 'ProgressEvent',
810 bubbles: false,
811 cancelable: false
812 },
813 mark: {
814 eventInterface: 'SpeechSynthesisEvent',
815 bubbles: false,
816 cancelable: false
817 },
818 message: {
819 eventInterface: 'MessageEvent',
820 bubbles: false,
821 cancelable: false
822 },
823 messageerror: {
824 eventInterface: 'MessageEvent',
825 bubbles: false,
826 cancelable: false
827 },
828 mousedown: {
829 eventInterface: 'MouseEvent',
830 bubbles: true,
831 cancelable: true
832 },
833 mouseenter: {
834 eventInterface: 'MouseEvent',
835 bubbles: false,
836 cancelable: false
837 },
838 mouseleave: {
839 eventInterface: 'MouseEvent',
840 bubbles: false,
841 cancelable: false
842 },
843 mousemove: {
844 eventInterface: 'MouseEvent',
845 bubbles: true,
846 cancelable: true
847 },
848 mouseout: {
849 eventInterface: 'MouseEvent',
850 bubbles: true,
851 cancelable: true
852 },
853 mouseover: {
854 eventInterface: 'MouseEvent',
855 bubbles: true,
856 cancelable: true
857 },
858 mouseup: {
859 eventInterface: 'MouseEvent',
860 bubbles: true,
861 cancelable: true
862 },
863 nomatch: {
864 eventInterface: 'SpeechRecognitionEvent',
865 bubbles: false,
866 cancelable: false
867 },
868 notificationclick: {
869 eventInterface: 'NotificationEvent',
870 bubbles: false,
871 cancelable: false
872 },
873 noupdate: {
874 eventInterface: 'Event',
875 bubbles: false,
876 cancelable: false
877 },
878 obsolete: {
879 eventInterface: 'Event',
880 bubbles: false,
881 cancelable: false
882 },
883 offline: {
884 eventInterface: 'Event',
885 bubbles: false,
886 cancelable: false
887 },
888 online: {
889 eventInterface: 'Event',
890 bubbles: false,
891 cancelable: false
892 },
893 open: {
894 eventInterface: 'Event',
895 bubbles: false,
896 cancelable: false
897 },
898 orientationchange: {
899 eventInterface: 'Event',
900 bubbles: false,
901 cancelable: false
902 },
903 pagehide: {
904 eventInterface: 'PageTransitionEvent',
905 bubbles: false,
906 cancelable: false
907 },
908 pageshow: {
909 eventInterface: 'PageTransitionEvent',
910 bubbles: false,
911 cancelable: false
912 },
913 paste: {
914 eventInterface: 'ClipboardEvent',
915 bubbles: true,
916 cancelable: true
917 },
918 pause: {
919 eventInterface: 'SpeechSynthesisEvent',
920 bubbles: false,
921 cancelable: false
922 },
923 pointercancel: {
924 eventInterface: 'PointerEvent',
925 bubbles: true,
926 cancelable: false
927 },
928 pointerdown: {
929 eventInterface: 'PointerEvent',
930 bubbles: true,
931 cancelable: true
932 },
933 pointerenter: {
934 eventInterface: 'PointerEvent',
935 bubbles: false,
936 cancelable: false
937 },
938 pointerleave: {
939 eventInterface: 'PointerEvent',
940 bubbles: false,
941 cancelable: false
942 },
943 pointerlockchange: {
944 eventInterface: 'Event',
945 bubbles: true,
946 cancelable: false
947 },
948 pointerlockerror: {
949 eventInterface: 'Event',
950 bubbles: true,
951 cancelable: false
952 },
953 pointermove: {
954 eventInterface: 'PointerEvent',
955 bubbles: true,
956 cancelable: true
957 },
958 pointerout: {
959 eventInterface: 'PointerEvent',
960 bubbles: true,
961 cancelable: true
962 },
963 pointerover: {
964 eventInterface: 'PointerEvent',
965 bubbles: true,
966 cancelable: true
967 },
968 pointerup: {
969 eventInterface: 'PointerEvent',
970 bubbles: true,
971 cancelable: true
972 },
973 play: {
974 eventInterface: 'Event',
975 bubbles: false,
976 cancelable: false
977 },
978 playing: {
979 eventInterface: 'Event',
980 bubbles: false,
981 cancelable: false
982 },
983 popstate: {
984 eventInterface: 'PopStateEvent',
985 bubbles: true,
986 cancelable: false
987 },
988 progress: {
989 eventInterface: 'ProgressEvent',
990 bubbles: false,
991 cancelable: false
992 },
993 push: {
994 eventInterface: 'PushEvent',
995 bubbles: false,
996 cancelable: false
997 },
998 pushsubscriptionchange: {
999 eventInterface: 'PushEvent',
1000 bubbles: false,
1001 cancelable: false
1002 },
1003 ratechange: {
1004 eventInterface: 'Event',
1005 bubbles: false,
1006 cancelable: false
1007 },
1008 readystatechange: {
1009 eventInterface: 'Event',
1010 bubbles: false,
1011 cancelable: false
1012 },
1013 repeatEvent: {
1014 eventInterface: 'TimeEvent',
1015 bubbles: false,
1016 cancelable: false
1017 },
1018 reset: {
1019 eventInterface: 'Event',
1020 bubbles: true,
1021 cancelable: true
1022 },
1023 resize: {
1024 eventInterface: 'UIEvent',
1025 bubbles: false,
1026 cancelable: false
1027 },
1028 resourcetimingbufferfull: {
1029 eventInterface: 'Performance',
1030 bubbles: true,
1031 cancelable: true
1032 },
1033 result: {
1034 eventInterface: 'SpeechRecognitionEvent',
1035 bubbles: false,
1036 cancelable: false
1037 },
1038 resume: {
1039 eventInterface: 'SpeechSynthesisEvent',
1040 bubbles: false,
1041 cancelable: false
1042 },
1043 scroll: {
1044 eventInterface: 'UIEvent',
1045 bubbles: false,
1046 cancelable: false
1047 },
1048 seeked: {
1049 eventInterface: 'Event',
1050 bubbles: false,
1051 cancelable: false
1052 },
1053 seeking: {
1054 eventInterface: 'Event',
1055 bubbles: false,
1056 cancelable: false
1057 },
1058 select: {
1059 eventInterface: 'UIEvent',
1060 bubbles: true,
1061 cancelable: false
1062 },
1063 selectstart: {
1064 eventInterface: 'Event',
1065 bubbles: true,
1066 cancelable: true
1067 },
1068 selectionchange: {
1069 eventInterface: 'Event',
1070 bubbles: false,
1071 cancelable: false
1072 },
1073 show: {
1074 eventInterface: 'MouseEvent',
1075 bubbles: false,
1076 cancelable: false
1077 },
1078 slotchange: {
1079 eventInterface: 'Event',
1080 bubbles: true,
1081 cancelable: false
1082 },
1083 soundend: {
1084 eventInterface: 'Event',
1085 bubbles: false,
1086 cancelable: false
1087 },
1088 soundstart: {
1089 eventInterface: 'Event',
1090 bubbles: false,
1091 cancelable: false
1092 },
1093 speechend: {
1094 eventInterface: 'Event',
1095 bubbles: false,
1096 cancelable: false
1097 },
1098 speechstart: {
1099 eventInterface: 'Event',
1100 bubbles: false,
1101 cancelable: false
1102 },
1103 stalled: {
1104 eventInterface: 'Event',
1105 bubbles: false,
1106 cancelable: false
1107 },
1108 start: {
1109 eventInterface: 'SpeechSynthesisEvent',
1110 bubbles: false,
1111 cancelable: false
1112 },
1113 storage: {
1114 eventInterface: 'StorageEvent',
1115 bubbles: false,
1116 cancelable: false
1117 },
1118 submit: {
1119 eventInterface: 'Event',
1120 bubbles: true,
1121 cancelable: true
1122 },
1123 success: {
1124 eventInterface: 'Event',
1125 bubbles: false,
1126 cancelable: false
1127 },
1128 suspend: {
1129 eventInterface: 'Event',
1130 bubbles: false,
1131 cancelable: false
1132 },
1133 SVGAbort: {
1134 eventInterface: 'SVGEvent',
1135 bubbles: true,
1136 cancelable: false
1137 },
1138 SVGError: {
1139 eventInterface: 'SVGEvent',
1140 bubbles: true,
1141 cancelable: false
1142 },
1143 SVGLoad: {
1144 eventInterface: 'SVGEvent',
1145 bubbles: false,
1146 cancelable: false
1147 },
1148 SVGResize: {
1149 eventInterface: 'SVGEvent',
1150 bubbles: true,
1151 cancelable: false
1152 },
1153 SVGScroll: {
1154 eventInterface: 'SVGEvent',
1155 bubbles: true,
1156 cancelable: false
1157 },
1158 SVGUnload: {
1159 eventInterface: 'SVGEvent',
1160 bubbles: false,
1161 cancelable: false
1162 },
1163 SVGZoom: {
1164 eventInterface: 'SVGZoomEvent',
1165 bubbles: true,
1166 cancelable: false
1167 },
1168 timeout: {
1169 eventInterface: 'ProgressEvent',
1170 bubbles: false,
1171 cancelable: false
1172 },
1173 timeupdate: {
1174 eventInterface: 'Event',
1175 bubbles: false,
1176 cancelable: false
1177 },
1178 touchcancel: {
1179 eventInterface: 'TouchEvent',
1180 bubbles: true,
1181 cancelable: false
1182 },
1183 touchend: {
1184 eventInterface: 'TouchEvent',
1185 bubbles: true,
1186 cancelable: true
1187 },
1188 touchmove: {
1189 eventInterface: 'TouchEvent',
1190 bubbles: true,
1191 cancelable: true
1192 },
1193 touchstart: {
1194 eventInterface: 'TouchEvent',
1195 bubbles: true,
1196 cancelable: true
1197 },
1198 transitionend: {
1199 eventInterface: 'TransitionEvent',
1200 bubbles: true,
1201 cancelable: true
1202 },
1203 unload: {
1204 eventInterface: 'UIEvent',
1205 bubbles: false,
1206 cancelable: false
1207 },
1208 updateready: {
1209 eventInterface: 'Event',
1210 bubbles: false,
1211 cancelable: false
1212 },
1213 userproximity: {
1214 eventInterface: 'UserProximityEvent',
1215 bubbles: false,
1216 cancelable: false
1217 },
1218 voiceschanged: {
1219 eventInterface: 'Event',
1220 bubbles: false,
1221 cancelable: false
1222 },
1223 visibilitychange: {
1224 eventInterface: 'Event',
1225 bubbles: true,
1226 cancelable: false
1227 },
1228 volumechange: {
1229 eventInterface: 'Event',
1230 bubbles: false,
1231 cancelable: false
1232 },
1233 waiting: {
1234 eventInterface: 'Event',
1235 bubbles: false,
1236 cancelable: false
1237 },
1238 wheel: {
1239 eventInterface: 'WheelEvent',
1240 bubbles: true,
1241 cancelable: true
1242 }
1243};
1244
1245/**
1246 * Groups modifiers into lists
1247 */
1248function generateModifiers(modifiers, isOnClick) {
1249 var keyModifiers = [];
1250 var systemModifiers = [];
1251 for (var i = 0; i < modifiers.length; i++) {
1252 var modifier = modifiers[i];
1253 // addEventListener() options, e.g. .passive & .capture, that we dont need to handle
1254 if (ignorableKeyModifiers.includes(modifier)) {
1255 continue;
1256 }
1257 // modifiers that require special conversion
1258 // if passed a left/right key modifier with onClick, add it here as well.
1259 if (systemKeyModifiers.includes(modifier) ||
1260 (mouseKeyModifiers.includes(modifier) &&
1261 isOnClick)) {
1262 systemModifiers.push(modifier);
1263 }
1264 else {
1265 keyModifiers.push(modifier);
1266 }
1267 }
1268 return {
1269 keyModifiers: keyModifiers,
1270 systemModifiers: systemModifiers
1271 };
1272}
1273function getEventProperties(eventParams) {
1274 var modifiers = eventParams.modifiers, _a = eventParams.options, options = _a === void 0 ? {} : _a, eventType = eventParams.eventType;
1275 var isOnClick = eventType === 'click';
1276 var _b = generateModifiers(modifiers, isOnClick), keyModifiers = _b.keyModifiers, systemModifiers = _b.systemModifiers;
1277 if (isOnClick) {
1278 // if it's a right click, it should fire a `contextmenu` event
1279 if (systemModifiers.includes('right')) {
1280 eventType = 'contextmenu';
1281 options.button = 2;
1282 // if its a middle click, fire a `mouseup` event
1283 }
1284 else if (systemModifiers.includes('middle')) {
1285 eventType = 'mouseup';
1286 options.button = 1;
1287 }
1288 }
1289 var meta = domEvents[eventType] || {
1290 eventInterface: 'Event',
1291 cancelable: true,
1292 bubbles: true
1293 };
1294 // convert `shift, ctrl` to `shiftKey, ctrlKey`
1295 // allows trigger('keydown.shift.ctrl.n') directly
1296 var systemModifiersMeta = systemModifiers.reduce(function (all, key) {
1297 all["".concat(key, "Key")] = true;
1298 return all;
1299 }, {});
1300 // get the keyCode for backwards compat
1301 var keyCode = keyCodesByKeyName[keyModifiers[0]] ||
1302 (options && (options.keyCode || options.code));
1303 var eventProperties = __assign(__assign(__assign(__assign({}, systemModifiersMeta), options), { bubbles: meta.bubbles, cancelable: meta.cancelable,
1304 // Any derived options should go here
1305 keyCode: keyCode, code: keyCode }), (keyModifiers[0] ? { key: keyModifiers[0] } : {}));
1306 return {
1307 eventProperties: eventProperties,
1308 meta: meta,
1309 eventType: eventType
1310 };
1311}
1312function createEvent(eventParams) {
1313 var _a = getEventProperties(eventParams), eventProperties = _a.eventProperties, meta = _a.meta, eventType = _a.eventType;
1314 // user defined eventInterface
1315 var eventInterface = meta.eventInterface;
1316 var metaEventInterface = window[eventInterface];
1317 var SupportedEventInterface = typeof metaEventInterface === 'function' ? metaEventInterface : window.Event;
1318 return new SupportedEventInterface(eventType,
1319 // event properties can only be added when the event is instantiated
1320 // custom properties must be added after the event has been instantiated
1321 eventProperties);
1322}
1323function createDOMEvent(eventString, options) {
1324 // split eventString like `keydown.ctrl.shift` into `keydown` and array of modifiers
1325 var _a = eventString.split('.'), eventType = _a[0], modifiers = _a.slice(1);
1326 var eventParams = {
1327 eventType: eventType,
1328 modifiers: modifiers,
1329 options: options
1330 };
1331 var event = createEvent(eventParams);
1332 var eventPrototype = Object.getPrototypeOf(event);
1333 // attach custom options to the event, like `relatedTarget` and so on.
1334 options &&
1335 Object.keys(options).forEach(function (key) {
1336 var propertyDescriptor = Object.getOwnPropertyDescriptor(eventPrototype, key);
1337 var canSetProperty = !(propertyDescriptor && propertyDescriptor.set === undefined);
1338 if (canSetProperty) {
1339 event[key] = options[key];
1340 }
1341 });
1342 return event;
1343}
1344
1345// Stubbing occurs when in vnode transformer we're swapping
1346// component vnode type due to stubbing either component
1347// or directive on component
1348// In order to be able to find components we need to track pairs
1349// stub --> original component
1350// Having this as global might feel unsafe at first point
1351// One can assume that sharing stub map across mounts might
1352// lead to false matches, however our vnode mappers always
1353// produce new nodeTypes for each mount even if you're reusing
1354// same stub, so we're safe and do not need to pass these stubs
1355// for each mount operation
1356var stubs = new WeakMap();
1357function registerStub(_a) {
1358 var source = _a.source, stub = _a.stub;
1359 stubs.set(stub, source);
1360}
1361function getOriginalComponentFromStub(stub) {
1362 return stubs.get(stub);
1363}
1364
1365var cacheStringFunction = function (fn) {
1366 var cache = Object.create(null);
1367 return (function (str) {
1368 var hit = cache[str];
1369 return hit || (cache[str] = fn(str));
1370 });
1371};
1372var camelizeRE = /-(\w)/g;
1373var camelize = cacheStringFunction(function (str) {
1374 return str.replace(camelizeRE, function (_, c) { return (c ? c.toUpperCase() : ''); });
1375});
1376var capitalize = cacheStringFunction(function (str) {
1377 return str.charAt(0).toUpperCase() + str.slice(1);
1378});
1379var hyphenateRE = /\B([A-Z])/g;
1380var hyphenate = cacheStringFunction(function (str) {
1381 return str.replace(hyphenateRE, '-$1').toLowerCase();
1382});
1383
1384function matchName(target, sourceName) {
1385 var camelized = camelize(target);
1386 var capitalized = capitalize(camelized);
1387 return (!!sourceName &&
1388 (sourceName === target ||
1389 sourceName === camelized ||
1390 sourceName === capitalized ||
1391 capitalize(camelize(sourceName)) === capitalized));
1392}
1393
1394function isCompatEnabled(key) {
1395 var _a, _b;
1396 return (_b = (_a = Vue__namespace.compatUtils) === null || _a === void 0 ? void 0 : _a.isCompatEnabled(key)) !== null && _b !== void 0 ? _b : false;
1397}
1398function isLegacyExtendedComponent(component) {
1399 if (!isCompatEnabled('GLOBAL_EXTEND') || typeof component !== 'function') {
1400 return false;
1401 }
1402 return (hasOwnProperty(component, 'super') &&
1403 component.super.extend({}).super === component.super);
1404}
1405function unwrapLegacyVueExtendComponent(selector) {
1406 return isLegacyExtendedComponent(selector) ? selector.options : selector;
1407}
1408function isLegacyFunctionalComponent(component) {
1409 return Boolean(component &&
1410 typeof component === 'object' &&
1411 hasOwnProperty(component, 'functional') &&
1412 component.functional);
1413}
1414
1415var getComponentNameInSetup = function (instance, type) {
1416 return Object.keys((instance === null || instance === void 0 ? void 0 : instance.setupState) || {}).find(function (key) { var _a; return ((_a = Object.getOwnPropertyDescriptor(instance.setupState, key)) === null || _a === void 0 ? void 0 : _a.value) === type; });
1417};
1418var getComponentRegisteredName = function (instance, type) {
1419 if (!instance || !instance.parent)
1420 return null;
1421 // try to infer the name based on local resolution
1422 var registry = instance.type.components;
1423 for (var key in registry) {
1424 if (registry[key] === type) {
1425 return key;
1426 }
1427 }
1428 // try to retrieve name imported in script setup
1429 return getComponentNameInSetup(instance.parent, type) || null;
1430};
1431var getComponentName = function (instance, type) {
1432 if (isObjectComponent(type)) {
1433 return (
1434 // If the component we stub is a script setup component and is automatically
1435 // imported by unplugin-vue-components we can only get its name through
1436 // the `__name` property.
1437 getComponentNameInSetup(instance, type) || type.name || type.__name || '');
1438 }
1439 if (isLegacyExtendedComponent(type)) {
1440 return unwrapLegacyVueExtendComponent(type).name || '';
1441 }
1442 if (isFunctionalComponent(type)) {
1443 return type.displayName || type.name;
1444 }
1445 return '';
1446};
1447
1448/**
1449 * Detect whether a selector matches a VNode
1450 * @param node
1451 * @param selector
1452 * @return {boolean | ((value: any) => boolean)}
1453 */
1454function matches(node, rawSelector) {
1455 var _a, _b, _c;
1456 var selector = unwrapLegacyVueExtendComponent(rawSelector);
1457 // do not return none Vue components
1458 if (!node.component)
1459 return false;
1460 var nodeType = node.type;
1461 if (!isComponent(nodeType))
1462 return false;
1463 if (typeof selector === 'string') {
1464 return (_b = (_a = node.el) === null || _a === void 0 ? void 0 : _a.matches) === null || _b === void 0 ? void 0 : _b.call(_a, selector);
1465 }
1466 // When we're using stubs we want user to be able to
1467 // find stubbed components both by original component
1468 // or stub definition. That's why we are trying to
1469 // extract original component and also stub, which was
1470 // used to create specialized stub for render
1471 var nodeTypeCandidates = [
1472 nodeType,
1473 getOriginalComponentFromStub(nodeType)
1474 ].filter(Boolean);
1475 // our selector might be a stub itself
1476 var target = (_c = getOriginalComponentFromStub(selector)) !== null && _c !== void 0 ? _c : selector;
1477 if (nodeTypeCandidates.includes(target)) {
1478 return true;
1479 }
1480 var componentName;
1481 componentName = getComponentName(node.component, nodeType);
1482 var selectorName = selector.name;
1483 // the component and selector both have a name
1484 if (componentName && selectorName) {
1485 return matchName(selectorName, componentName);
1486 }
1487 componentName =
1488 getComponentRegisteredName(node.component, nodeType) || undefined;
1489 // if a name is missing, then check the locally registered components in the parent
1490 if (node.component.parent) {
1491 var registry = node.component.parent.type.components;
1492 for (var key in registry) {
1493 // is it the selector
1494 if (!selectorName && registry[key] === selector) {
1495 selectorName = key;
1496 }
1497 // is it the component
1498 if (!componentName && registry[key] === nodeType) {
1499 componentName = key;
1500 }
1501 }
1502 }
1503 if (selectorName && componentName) {
1504 return matchName(selectorName, componentName);
1505 }
1506 return false;
1507}
1508/**
1509 * Filters out the null, undefined and primitive values,
1510 * to only keep VNode and VNodeArrayChildren values
1511 * @param value
1512 */
1513function nodesAsObject(value) {
1514 return !!value && typeof value === 'object';
1515}
1516/**
1517 * Collect all children
1518 * @param nodes
1519 * @param children
1520 */
1521function aggregateChildren(nodes, children) {
1522 if (children && Array.isArray(children)) {
1523 var reversedNodes = __spreadArray([], children, true).reverse().filter(nodesAsObject);
1524 reversedNodes.forEach(function (node) {
1525 if (Array.isArray(node)) {
1526 aggregateChildren(nodes, node);
1527 }
1528 else {
1529 nodes.unshift(node);
1530 }
1531 });
1532 }
1533}
1534function findAllVNodes(vnode, selector) {
1535 var matchingNodes = [];
1536 var nodes = [vnode];
1537 while (nodes.length) {
1538 var node = nodes.shift();
1539 aggregateChildren(nodes, node.children);
1540 if (node.component) {
1541 aggregateChildren(nodes, [node.component.subTree]);
1542 }
1543 if (node.suspense) {
1544 // match children if component is Suspense
1545 var activeBranch = node.suspense.activeBranch;
1546 aggregateChildren(nodes, [activeBranch]);
1547 }
1548 if (matches(node, selector) && !matchingNodes.includes(node)) {
1549 matchingNodes.push(node);
1550 }
1551 }
1552 return matchingNodes;
1553}
1554function find(root, selector) {
1555 var matchingVNodes = findAllVNodes(root, selector);
1556 if (typeof selector === 'string') {
1557 // When searching by CSS selector we want only one (topmost) vnode for each el`
1558 matchingVNodes = matchingVNodes.filter(function (vnode) { var _a; return ((_a = vnode.component.parent) === null || _a === void 0 ? void 0 : _a.vnode.el) !== vnode.el; });
1559 }
1560 return matchingVNodes.map(function (vnode) { return vnode.component; });
1561}
1562
1563function createWrapperError(wrapperType) {
1564 return new Proxy(Object.create(null), {
1565 get: function (obj, prop) {
1566 switch (prop) {
1567 case 'then':
1568 // allows for better errors when wrapping `find` in `await`
1569 // https://github.com/vuejs/test-utils/issues/638
1570 return;
1571 case 'exists':
1572 return function () { return false; };
1573 default:
1574 throw new Error("Cannot call ".concat(String(prop), " on an empty ").concat(wrapperType, "."));
1575 }
1576 }
1577 });
1578}
1579
1580/*!
1581 * isElementVisible
1582 * Adapted from https://github.com/testing-library/jest-dom
1583 * Licensed under the MIT License.
1584 */
1585function isStyleVisible(element) {
1586 if (!(element instanceof HTMLElement) && !(element instanceof SVGElement)) {
1587 return false;
1588 }
1589 var _a = getComputedStyle(element), display = _a.display, visibility = _a.visibility, opacity = _a.opacity;
1590 return (display !== 'none' &&
1591 visibility !== 'hidden' &&
1592 visibility !== 'collapse' &&
1593 opacity !== '0');
1594}
1595function isAttributeVisible(element) {
1596 return (!element.hasAttribute('hidden') &&
1597 (element.nodeName === 'DETAILS' ? element.hasAttribute('open') : true));
1598}
1599function isElementVisible(element) {
1600 return (element.nodeName !== '#comment' &&
1601 isStyleVisible(element) &&
1602 isAttributeVisible(element) &&
1603 (!element.parentElement || isElementVisible(element.parentElement)));
1604}
1605
1606function isElement(element) {
1607 return element instanceof Element;
1608}
1609
1610var WrapperType;
1611(function (WrapperType) {
1612 WrapperType[WrapperType["DOMWrapper"] = 0] = "DOMWrapper";
1613 WrapperType[WrapperType["VueWrapper"] = 1] = "VueWrapper";
1614})(WrapperType || (WrapperType = {}));
1615var factories = {};
1616function registerFactory(type, fn) {
1617 factories[type] = fn;
1618}
1619var createDOMWrapper = function (element) {
1620 return factories[WrapperType.DOMWrapper](element);
1621};
1622var createVueWrapper = function (app, vm, setProps) {
1623 return factories[WrapperType.VueWrapper](app, vm, setProps);
1624};
1625
1626function stringifyNode(node) {
1627 return node instanceof Element
1628 ? node.outerHTML
1629 : new XMLSerializer().serializeToString(node);
1630}
1631
1632function getDefaultExportFromCjs (x) {
1633 return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
1634}
1635
1636var js = {exports: {}};
1637
1638var src = {};
1639
1640var javascript = {exports: {}};
1641
1642var beautifier$2 = {};
1643
1644var output = {};
1645
1646/*jshint node:true */
1647
1648var hasRequiredOutput;
1649
1650function requireOutput () {
1651 if (hasRequiredOutput) return output;
1652 hasRequiredOutput = 1;
1653
1654 function OutputLine(parent) {
1655 this.__parent = parent;
1656 this.__character_count = 0;
1657 // use indent_count as a marker for this.__lines that have preserved indentation
1658 this.__indent_count = -1;
1659 this.__alignment_count = 0;
1660 this.__wrap_point_index = 0;
1661 this.__wrap_point_character_count = 0;
1662 this.__wrap_point_indent_count = -1;
1663 this.__wrap_point_alignment_count = 0;
1664
1665 this.__items = [];
1666 }
1667
1668 OutputLine.prototype.clone_empty = function() {
1669 var line = new OutputLine(this.__parent);
1670 line.set_indent(this.__indent_count, this.__alignment_count);
1671 return line;
1672 };
1673
1674 OutputLine.prototype.item = function(index) {
1675 if (index < 0) {
1676 return this.__items[this.__items.length + index];
1677 } else {
1678 return this.__items[index];
1679 }
1680 };
1681
1682 OutputLine.prototype.has_match = function(pattern) {
1683 for (var lastCheckedOutput = this.__items.length - 1; lastCheckedOutput >= 0; lastCheckedOutput--) {
1684 if (this.__items[lastCheckedOutput].match(pattern)) {
1685 return true;
1686 }
1687 }
1688 return false;
1689 };
1690
1691 OutputLine.prototype.set_indent = function(indent, alignment) {
1692 if (this.is_empty()) {
1693 this.__indent_count = indent || 0;
1694 this.__alignment_count = alignment || 0;
1695 this.__character_count = this.__parent.get_indent_size(this.__indent_count, this.__alignment_count);
1696 }
1697 };
1698
1699 OutputLine.prototype._set_wrap_point = function() {
1700 if (this.__parent.wrap_line_length) {
1701 this.__wrap_point_index = this.__items.length;
1702 this.__wrap_point_character_count = this.__character_count;
1703 this.__wrap_point_indent_count = this.__parent.next_line.__indent_count;
1704 this.__wrap_point_alignment_count = this.__parent.next_line.__alignment_count;
1705 }
1706 };
1707
1708 OutputLine.prototype._should_wrap = function() {
1709 return this.__wrap_point_index &&
1710 this.__character_count > this.__parent.wrap_line_length &&
1711 this.__wrap_point_character_count > this.__parent.next_line.__character_count;
1712 };
1713
1714 OutputLine.prototype._allow_wrap = function() {
1715 if (this._should_wrap()) {
1716 this.__parent.add_new_line();
1717 var next = this.__parent.current_line;
1718 next.set_indent(this.__wrap_point_indent_count, this.__wrap_point_alignment_count);
1719 next.__items = this.__items.slice(this.__wrap_point_index);
1720 this.__items = this.__items.slice(0, this.__wrap_point_index);
1721
1722 next.__character_count += this.__character_count - this.__wrap_point_character_count;
1723 this.__character_count = this.__wrap_point_character_count;
1724
1725 if (next.__items[0] === " ") {
1726 next.__items.splice(0, 1);
1727 next.__character_count -= 1;
1728 }
1729 return true;
1730 }
1731 return false;
1732 };
1733
1734 OutputLine.prototype.is_empty = function() {
1735 return this.__items.length === 0;
1736 };
1737
1738 OutputLine.prototype.last = function() {
1739 if (!this.is_empty()) {
1740 return this.__items[this.__items.length - 1];
1741 } else {
1742 return null;
1743 }
1744 };
1745
1746 OutputLine.prototype.push = function(item) {
1747 this.__items.push(item);
1748 var last_newline_index = item.lastIndexOf('\n');
1749 if (last_newline_index !== -1) {
1750 this.__character_count = item.length - last_newline_index;
1751 } else {
1752 this.__character_count += item.length;
1753 }
1754 };
1755
1756 OutputLine.prototype.pop = function() {
1757 var item = null;
1758 if (!this.is_empty()) {
1759 item = this.__items.pop();
1760 this.__character_count -= item.length;
1761 }
1762 return item;
1763 };
1764
1765
1766 OutputLine.prototype._remove_indent = function() {
1767 if (this.__indent_count > 0) {
1768 this.__indent_count -= 1;
1769 this.__character_count -= this.__parent.indent_size;
1770 }
1771 };
1772
1773 OutputLine.prototype._remove_wrap_indent = function() {
1774 if (this.__wrap_point_indent_count > 0) {
1775 this.__wrap_point_indent_count -= 1;
1776 }
1777 };
1778 OutputLine.prototype.trim = function() {
1779 while (this.last() === ' ') {
1780 this.__items.pop();
1781 this.__character_count -= 1;
1782 }
1783 };
1784
1785 OutputLine.prototype.toString = function() {
1786 var result = '';
1787 if (this.is_empty()) {
1788 if (this.__parent.indent_empty_lines) {
1789 result = this.__parent.get_indent_string(this.__indent_count);
1790 }
1791 } else {
1792 result = this.__parent.get_indent_string(this.__indent_count, this.__alignment_count);
1793 result += this.__items.join('');
1794 }
1795 return result;
1796 };
1797
1798 function IndentStringCache(options, baseIndentString) {
1799 this.__cache = [''];
1800 this.__indent_size = options.indent_size;
1801 this.__indent_string = options.indent_char;
1802 if (!options.indent_with_tabs) {
1803 this.__indent_string = new Array(options.indent_size + 1).join(options.indent_char);
1804 }
1805
1806 // Set to null to continue support for auto detection of base indent
1807 baseIndentString = baseIndentString || '';
1808 if (options.indent_level > 0) {
1809 baseIndentString = new Array(options.indent_level + 1).join(this.__indent_string);
1810 }
1811
1812 this.__base_string = baseIndentString;
1813 this.__base_string_length = baseIndentString.length;
1814 }
1815
1816 IndentStringCache.prototype.get_indent_size = function(indent, column) {
1817 var result = this.__base_string_length;
1818 column = column || 0;
1819 if (indent < 0) {
1820 result = 0;
1821 }
1822 result += indent * this.__indent_size;
1823 result += column;
1824 return result;
1825 };
1826
1827 IndentStringCache.prototype.get_indent_string = function(indent_level, column) {
1828 var result = this.__base_string;
1829 column = column || 0;
1830 if (indent_level < 0) {
1831 indent_level = 0;
1832 result = '';
1833 }
1834 column += indent_level * this.__indent_size;
1835 this.__ensure_cache(column);
1836 result += this.__cache[column];
1837 return result;
1838 };
1839
1840 IndentStringCache.prototype.__ensure_cache = function(column) {
1841 while (column >= this.__cache.length) {
1842 this.__add_column();
1843 }
1844 };
1845
1846 IndentStringCache.prototype.__add_column = function() {
1847 var column = this.__cache.length;
1848 var indent = 0;
1849 var result = '';
1850 if (this.__indent_size && column >= this.__indent_size) {
1851 indent = Math.floor(column / this.__indent_size);
1852 column -= indent * this.__indent_size;
1853 result = new Array(indent + 1).join(this.__indent_string);
1854 }
1855 if (column) {
1856 result += new Array(column + 1).join(' ');
1857 }
1858
1859 this.__cache.push(result);
1860 };
1861
1862 function Output(options, baseIndentString) {
1863 this.__indent_cache = new IndentStringCache(options, baseIndentString);
1864 this.raw = false;
1865 this._end_with_newline = options.end_with_newline;
1866 this.indent_size = options.indent_size;
1867 this.wrap_line_length = options.wrap_line_length;
1868 this.indent_empty_lines = options.indent_empty_lines;
1869 this.__lines = [];
1870 this.previous_line = null;
1871 this.current_line = null;
1872 this.next_line = new OutputLine(this);
1873 this.space_before_token = false;
1874 this.non_breaking_space = false;
1875 this.previous_token_wrapped = false;
1876 // initialize
1877 this.__add_outputline();
1878 }
1879
1880 Output.prototype.__add_outputline = function() {
1881 this.previous_line = this.current_line;
1882 this.current_line = this.next_line.clone_empty();
1883 this.__lines.push(this.current_line);
1884 };
1885
1886 Output.prototype.get_line_number = function() {
1887 return this.__lines.length;
1888 };
1889
1890 Output.prototype.get_indent_string = function(indent, column) {
1891 return this.__indent_cache.get_indent_string(indent, column);
1892 };
1893
1894 Output.prototype.get_indent_size = function(indent, column) {
1895 return this.__indent_cache.get_indent_size(indent, column);
1896 };
1897
1898 Output.prototype.is_empty = function() {
1899 return !this.previous_line && this.current_line.is_empty();
1900 };
1901
1902 Output.prototype.add_new_line = function(force_newline) {
1903 // never newline at the start of file
1904 // otherwise, newline only if we didn't just add one or we're forced
1905 if (this.is_empty() ||
1906 (!force_newline && this.just_added_newline())) {
1907 return false;
1908 }
1909
1910 // if raw output is enabled, don't print additional newlines,
1911 // but still return True as though you had
1912 if (!this.raw) {
1913 this.__add_outputline();
1914 }
1915 return true;
1916 };
1917
1918 Output.prototype.get_code = function(eol) {
1919 this.trim(true);
1920
1921 // handle some edge cases where the last tokens
1922 // has text that ends with newline(s)
1923 var last_item = this.current_line.pop();
1924 if (last_item) {
1925 if (last_item[last_item.length - 1] === '\n') {
1926 last_item = last_item.replace(/\n+$/g, '');
1927 }
1928 this.current_line.push(last_item);
1929 }
1930
1931 if (this._end_with_newline) {
1932 this.__add_outputline();
1933 }
1934
1935 var sweet_code = this.__lines.join('\n');
1936
1937 if (eol !== '\n') {
1938 sweet_code = sweet_code.replace(/[\n]/g, eol);
1939 }
1940 return sweet_code;
1941 };
1942
1943 Output.prototype.set_wrap_point = function() {
1944 this.current_line._set_wrap_point();
1945 };
1946
1947 Output.prototype.set_indent = function(indent, alignment) {
1948 indent = indent || 0;
1949 alignment = alignment || 0;
1950
1951 // Next line stores alignment values
1952 this.next_line.set_indent(indent, alignment);
1953
1954 // Never indent your first output indent at the start of the file
1955 if (this.__lines.length > 1) {
1956 this.current_line.set_indent(indent, alignment);
1957 return true;
1958 }
1959
1960 this.current_line.set_indent();
1961 return false;
1962 };
1963
1964 Output.prototype.add_raw_token = function(token) {
1965 for (var x = 0; x < token.newlines; x++) {
1966 this.__add_outputline();
1967 }
1968 this.current_line.set_indent(-1);
1969 this.current_line.push(token.whitespace_before);
1970 this.current_line.push(token.text);
1971 this.space_before_token = false;
1972 this.non_breaking_space = false;
1973 this.previous_token_wrapped = false;
1974 };
1975
1976 Output.prototype.add_token = function(printable_token) {
1977 this.__add_space_before_token();
1978 this.current_line.push(printable_token);
1979 this.space_before_token = false;
1980 this.non_breaking_space = false;
1981 this.previous_token_wrapped = this.current_line._allow_wrap();
1982 };
1983
1984 Output.prototype.__add_space_before_token = function() {
1985 if (this.space_before_token && !this.just_added_newline()) {
1986 if (!this.non_breaking_space) {
1987 this.set_wrap_point();
1988 }
1989 this.current_line.push(' ');
1990 }
1991 };
1992
1993 Output.prototype.remove_indent = function(index) {
1994 var output_length = this.__lines.length;
1995 while (index < output_length) {
1996 this.__lines[index]._remove_indent();
1997 index++;
1998 }
1999 this.current_line._remove_wrap_indent();
2000 };
2001
2002 Output.prototype.trim = function(eat_newlines) {
2003 eat_newlines = (eat_newlines === undefined) ? false : eat_newlines;
2004
2005 this.current_line.trim();
2006
2007 while (eat_newlines && this.__lines.length > 1 &&
2008 this.current_line.is_empty()) {
2009 this.__lines.pop();
2010 this.current_line = this.__lines[this.__lines.length - 1];
2011 this.current_line.trim();
2012 }
2013
2014 this.previous_line = this.__lines.length > 1 ?
2015 this.__lines[this.__lines.length - 2] : null;
2016 };
2017
2018 Output.prototype.just_added_newline = function() {
2019 return this.current_line.is_empty();
2020 };
2021
2022 Output.prototype.just_added_blankline = function() {
2023 return this.is_empty() ||
2024 (this.current_line.is_empty() && this.previous_line.is_empty());
2025 };
2026
2027 Output.prototype.ensure_empty_line_above = function(starts_with, ends_with) {
2028 var index = this.__lines.length - 2;
2029 while (index >= 0) {
2030 var potentialEmptyLine = this.__lines[index];
2031 if (potentialEmptyLine.is_empty()) {
2032 break;
2033 } else if (potentialEmptyLine.item(0).indexOf(starts_with) !== 0 &&
2034 potentialEmptyLine.item(-1) !== ends_with) {
2035 this.__lines.splice(index + 1, 0, new OutputLine(this));
2036 this.previous_line = this.__lines[this.__lines.length - 2];
2037 break;
2038 }
2039 index--;
2040 }
2041 };
2042
2043 output.Output = Output;
2044 return output;
2045}
2046
2047var token = {};
2048
2049/*jshint node:true */
2050
2051var hasRequiredToken;
2052
2053function requireToken () {
2054 if (hasRequiredToken) return token;
2055 hasRequiredToken = 1;
2056
2057 function Token(type, text, newlines, whitespace_before) {
2058 this.type = type;
2059 this.text = text;
2060
2061 // comments_before are
2062 // comments that have a new line before them
2063 // and may or may not have a newline after
2064 // this is a set of comments before
2065 this.comments_before = null; /* inline comment*/
2066
2067
2068 // this.comments_after = new TokenStream(); // no new line before and newline after
2069 this.newlines = newlines || 0;
2070 this.whitespace_before = whitespace_before || '';
2071 this.parent = null;
2072 this.next = null;
2073 this.previous = null;
2074 this.opened = null;
2075 this.closed = null;
2076 this.directives = null;
2077 }
2078
2079
2080 token.Token = Token;
2081 return token;
2082}
2083
2084var acorn = {};
2085
2086/* jshint node: true, curly: false */
2087
2088var hasRequiredAcorn;
2089
2090function requireAcorn () {
2091 if (hasRequiredAcorn) return acorn;
2092 hasRequiredAcorn = 1;
2093 (function (exports) {
2094
2095 // acorn used char codes to squeeze the last bit of performance out
2096 // Beautifier is okay without that, so we're using regex
2097 // permit # (23), $ (36), and @ (64). @ is used in ES7 decorators.
2098 // 65 through 91 are uppercase letters.
2099 // permit _ (95).
2100 // 97 through 123 are lowercase letters.
2101 var baseASCIIidentifierStartChars = "\\x23\\x24\\x40\\x41-\\x5a\\x5f\\x61-\\x7a";
2102
2103 // inside an identifier @ is not allowed but 0-9 are.
2104 var baseASCIIidentifierChars = "\\x24\\x30-\\x39\\x41-\\x5a\\x5f\\x61-\\x7a";
2105
2106 // Big ugly regular expressions that match characters in the
2107 // whitespace, identifier, and identifier-start categories. These
2108 // are only applied when a character is found to actually have a
2109 // code point above 128.
2110 var nonASCIIidentifierStartChars = "\\xaa\\xb5\\xba\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u02c1\\u02c6-\\u02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0370-\\u0374\\u0376\\u0377\\u037a-\\u037d\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5\\u03f7-\\u0481\\u048a-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05d0-\\u05ea\\u05f0-\\u05f2\\u0620-\\u064a\\u066e\\u066f\\u0671-\\u06d3\\u06d5\\u06e5\\u06e6\\u06ee\\u06ef\\u06fa-\\u06fc\\u06ff\\u0710\\u0712-\\u072f\\u074d-\\u07a5\\u07b1\\u07ca-\\u07ea\\u07f4\\u07f5\\u07fa\\u0800-\\u0815\\u081a\\u0824\\u0828\\u0840-\\u0858\\u08a0\\u08a2-\\u08ac\\u0904-\\u0939\\u093d\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097f\\u0985-\\u098c\\u098f\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bd\\u09ce\\u09dc\\u09dd\\u09df-\\u09e1\\u09f0\\u09f1\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39\\u0a59-\\u0a5c\\u0a5e\\u0a72-\\u0a74\\u0a85-\\u0a8d\\u0a8f-\\u0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0abd\\u0ad0\\u0ae0\\u0ae1\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3d\\u0b5c\\u0b5d\\u0b5f-\\u0b61\\u0b71\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u0baa\\u0bae-\\u0bb9\\u0bd0\\u0c05-\\u0c0c\\u0c0e-\\u0c10\\u0c12-\\u0c28\\u0c2a-\\u0c33\\u0c35-\\u0c39\\u0c3d\\u0c58\\u0c59\\u0c60\\u0c61\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbd\\u0cde\\u0ce0\\u0ce1\\u0cf1\\u0cf2\\u0d05-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d3a\\u0d3d\\u0d4e\\u0d60\\u0d61\\u0d7a-\\u0d7f\\u0d85-\\u0d96\\u0d9a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0e01-\\u0e30\\u0e32\\u0e33\\u0e40-\\u0e46\\u0e81\\u0e82\\u0e84\\u0e87\\u0e88\\u0e8a\\u0e8d\\u0e94-\\u0e97\\u0e99-\\u0e9f\\u0ea1-\\u0ea3\\u0ea5\\u0ea7\\u0eaa\\u0eab\\u0ead-\\u0eb0\\u0eb2\\u0eb3\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0edc-\\u0edf\\u0f00\\u0f40-\\u0f47\\u0f49-\\u0f6c\\u0f88-\\u0f8c\\u1000-\\u102a\\u103f\\u1050-\\u1055\\u105a-\\u105d\\u1061\\u1065\\u1066\\u106e-\\u1070\\u1075-\\u1081\\u108e\\u10a0-\\u10c5\\u10c7\\u10cd\\u10d0-\\u10fa\\u10fc-\\u1248\\u124a-\\u124d\\u1250-\\u1256\\u1258\\u125a-\\u125d\\u1260-\\u1288\\u128a-\\u128d\\u1290-\\u12b0\\u12b2-\\u12b5\\u12b8-\\u12be\\u12c0\\u12c2-\\u12c5\\u12c8-\\u12d6\\u12d8-\\u1310\\u1312-\\u1315\\u1318-\\u135a\\u1380-\\u138f\\u13a0-\\u13f4\\u1401-\\u166c\\u166f-\\u167f\\u1681-\\u169a\\u16a0-\\u16ea\\u16ee-\\u16f0\\u1700-\\u170c\\u170e-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176c\\u176e-\\u1770\\u1780-\\u17b3\\u17d7\\u17dc\\u1820-\\u1877\\u1880-\\u18a8\\u18aa\\u18b0-\\u18f5\\u1900-\\u191c\\u1950-\\u196d\\u1970-\\u1974\\u1980-\\u19ab\\u19c1-\\u19c7\\u1a00-\\u1a16\\u1a20-\\u1a54\\u1aa7\\u1b05-\\u1b33\\u1b45-\\u1b4b\\u1b83-\\u1ba0\\u1bae\\u1baf\\u1bba-\\u1be5\\u1c00-\\u1c23\\u1c4d-\\u1c4f\\u1c5a-\\u1c7d\\u1ce9-\\u1cec\\u1cee-\\u1cf1\\u1cf5\\u1cf6\\u1d00-\\u1dbf\\u1e00-\\u1f15\\u1f18-\\u1f1d\\u1f20-\\u1f45\\u1f48-\\u1f4d\\u1f50-\\u1f57\\u1f59\\u1f5b\\u1f5d\\u1f5f-\\u1f7d\\u1f80-\\u1fb4\\u1fb6-\\u1fbc\\u1fbe\\u1fc2-\\u1fc4\\u1fc6-\\u1fcc\\u1fd0-\\u1fd3\\u1fd6-\\u1fdb\\u1fe0-\\u1fec\\u1ff2-\\u1ff4\\u1ff6-\\u1ffc\\u2071\\u207f\\u2090-\\u209c\\u2102\\u2107\\u210a-\\u2113\\u2115\\u2119-\\u211d\\u2124\\u2126\\u2128\\u212a-\\u212d\\u212f-\\u2139\\u213c-\\u213f\\u2145-\\u2149\\u214e\\u2160-\\u2188\\u2c00-\\u2c2e\\u2c30-\\u2c5e\\u2c60-\\u2ce4\\u2ceb-\\u2cee\\u2cf2\\u2cf3\\u2d00-\\u2d25\\u2d27\\u2d2d\\u2d30-\\u2d67\\u2d6f\\u2d80-\\u2d96\\u2da0-\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u2e2f\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303c\\u3041-\\u3096\\u309d-\\u309f\\u30a1-\\u30fa\\u30fc-\\u30ff\\u3105-\\u312d\\u3131-\\u318e\\u31a0-\\u31ba\\u31f0-\\u31ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\ua000-\\ua48c\\ua4d0-\\ua4fd\\ua500-\\ua60c\\ua610-\\ua61f\\ua62a\\ua62b\\ua640-\\ua66e\\ua67f-\\ua697\\ua6a0-\\ua6ef\\ua717-\\ua71f\\ua722-\\ua788\\ua78b-\\ua78e\\ua790-\\ua793\\ua7a0-\\ua7aa\\ua7f8-\\ua801\\ua803-\\ua805\\ua807-\\ua80a\\ua80c-\\ua822\\ua840-\\ua873\\ua882-\\ua8b3\\ua8f2-\\ua8f7\\ua8fb\\ua90a-\\ua925\\ua930-\\ua946\\ua960-\\ua97c\\ua984-\\ua9b2\\ua9cf\\uaa00-\\uaa28\\uaa40-\\uaa42\\uaa44-\\uaa4b\\uaa60-\\uaa76\\uaa7a\\uaa80-\\uaaaf\\uaab1\\uaab5\\uaab6\\uaab9-\\uaabd\\uaac0\\uaac2\\uaadb-\\uaadd\\uaae0-\\uaaea\\uaaf2-\\uaaf4\\uab01-\\uab06\\uab09-\\uab0e\\uab11-\\uab16\\uab20-\\uab26\\uab28-\\uab2e\\uabc0-\\uabe2\\uac00-\\ud7a3\\ud7b0-\\ud7c6\\ud7cb-\\ud7fb\\uf900-\\ufa6d\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d\\ufb1f-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\ufb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb\\ufe70-\\ufe74\\ufe76-\\ufefc\\uff21-\\uff3a\\uff41-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd7\\uffda-\\uffdc";
2111 var nonASCIIidentifierChars = "\\u0300-\\u036f\\u0483-\\u0487\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u0620-\\u0649\\u0672-\\u06d3\\u06e7-\\u06e8\\u06fb-\\u06fc\\u0730-\\u074a\\u0800-\\u0814\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0840-\\u0857\\u08e4-\\u08fe\\u0900-\\u0903\\u093a-\\u093c\\u093e-\\u094f\\u0951-\\u0957\\u0962-\\u0963\\u0966-\\u096f\\u0981-\\u0983\\u09bc\\u09be-\\u09c4\\u09c7\\u09c8\\u09d7\\u09df-\\u09e0\\u0a01-\\u0a03\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a66-\\u0a71\\u0a75\\u0a81-\\u0a83\\u0abc\\u0abe-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ae2-\\u0ae3\\u0ae6-\\u0aef\\u0b01-\\u0b03\\u0b3c\\u0b3e-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b5f-\\u0b60\\u0b66-\\u0b6f\\u0b82\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd7\\u0be6-\\u0bef\\u0c01-\\u0c03\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62-\\u0c63\\u0c66-\\u0c6f\\u0c82\\u0c83\\u0cbc\\u0cbe-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0ce2-\\u0ce3\\u0ce6-\\u0cef\\u0d02\\u0d03\\u0d46-\\u0d48\\u0d57\\u0d62-\\u0d63\\u0d66-\\u0d6f\\u0d82\\u0d83\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0df2\\u0df3\\u0e34-\\u0e3a\\u0e40-\\u0e45\\u0e50-\\u0e59\\u0eb4-\\u0eb9\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f41-\\u0f47\\u0f71-\\u0f84\\u0f86-\\u0f87\\u0f8d-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u1000-\\u1029\\u1040-\\u1049\\u1067-\\u106d\\u1071-\\u1074\\u1082-\\u108d\\u108f-\\u109d\\u135d-\\u135f\\u170e-\\u1710\\u1720-\\u1730\\u1740-\\u1750\\u1772\\u1773\\u1780-\\u17b2\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u1810-\\u1819\\u1920-\\u192b\\u1930-\\u193b\\u1951-\\u196d\\u19b0-\\u19c0\\u19c8-\\u19c9\\u19d0-\\u19d9\\u1a00-\\u1a15\\u1a20-\\u1a53\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1b46-\\u1b4b\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1bb0-\\u1bb9\\u1be6-\\u1bf3\\u1c00-\\u1c22\\u1c40-\\u1c49\\u1c5b-\\u1c7d\\u1cd0-\\u1cd2\\u1d00-\\u1dbe\\u1e01-\\u1f15\\u200c\\u200d\\u203f\\u2040\\u2054\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\u2d81-\\u2d96\\u2de0-\\u2dff\\u3021-\\u3028\\u3099\\u309a\\ua640-\\ua66d\\ua674-\\ua67d\\ua69f\\ua6f0-\\ua6f1\\ua7f8-\\ua800\\ua806\\ua80b\\ua823-\\ua827\\ua880-\\ua881\\ua8b4-\\ua8c4\\ua8d0-\\ua8d9\\ua8f3-\\ua8f7\\ua900-\\ua909\\ua926-\\ua92d\\ua930-\\ua945\\ua980-\\ua983\\ua9b3-\\ua9c0\\uaa00-\\uaa27\\uaa40-\\uaa41\\uaa4c-\\uaa4d\\uaa50-\\uaa59\\uaa7b\\uaae0-\\uaae9\\uaaf2-\\uaaf3\\uabc0-\\uabe1\\uabec\\uabed\\uabf0-\\uabf9\\ufb20-\\ufb28\\ufe00-\\ufe0f\\ufe20-\\ufe26\\ufe33\\ufe34\\ufe4d-\\ufe4f\\uff10-\\uff19\\uff3f";
2112 //var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
2113 //var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
2114
2115 var identifierStart = "(?:\\\\u[0-9a-fA-F]{4}|[" + baseASCIIidentifierStartChars + nonASCIIidentifierStartChars + "])";
2116 var identifierChars = "(?:\\\\u[0-9a-fA-F]{4}|[" + baseASCIIidentifierChars + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "])*";
2117
2118 exports.identifier = new RegExp(identifierStart + identifierChars, 'g');
2119 exports.identifierStart = new RegExp(identifierStart);
2120 exports.identifierMatch = new RegExp("(?:\\\\u[0-9a-fA-F]{4}|[" + baseASCIIidentifierChars + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "])+");
2121
2122 // Whether a single character denotes a newline.
2123
2124 exports.newline = /[\n\r\u2028\u2029]/;
2125
2126 // Matches a whole line break (where CRLF is considered a single
2127 // line break). Used to count lines.
2128
2129 // in javascript, these two differ
2130 // in python they are the same, different methods are called on them
2131 exports.lineBreak = new RegExp('\r\n|' + exports.newline.source);
2132 exports.allLineBreaks = new RegExp(exports.lineBreak.source, 'g');
2133 } (acorn));
2134 return acorn;
2135}
2136
2137var options$3 = {};
2138
2139var options$2 = {};
2140
2141/*jshint node:true */
2142
2143var hasRequiredOptions$3;
2144
2145function requireOptions$3 () {
2146 if (hasRequiredOptions$3) return options$2;
2147 hasRequiredOptions$3 = 1;
2148
2149 function Options(options, merge_child_field) {
2150 this.raw_options = _mergeOpts(options, merge_child_field);
2151
2152 // Support passing the source text back with no change
2153 this.disabled = this._get_boolean('disabled');
2154
2155 this.eol = this._get_characters('eol', 'auto');
2156 this.end_with_newline = this._get_boolean('end_with_newline');
2157 this.indent_size = this._get_number('indent_size', 4);
2158 this.indent_char = this._get_characters('indent_char', ' ');
2159 this.indent_level = this._get_number('indent_level');
2160
2161 this.preserve_newlines = this._get_boolean('preserve_newlines', true);
2162 this.max_preserve_newlines = this._get_number('max_preserve_newlines', 32786);
2163 if (!this.preserve_newlines) {
2164 this.max_preserve_newlines = 0;
2165 }
2166
2167 this.indent_with_tabs = this._get_boolean('indent_with_tabs', this.indent_char === '\t');
2168 if (this.indent_with_tabs) {
2169 this.indent_char = '\t';
2170
2171 // indent_size behavior changed after 1.8.6
2172 // It used to be that indent_size would be
2173 // set to 1 for indent_with_tabs. That is no longer needed and
2174 // actually doesn't make sense - why not use spaces? Further,
2175 // that might produce unexpected behavior - tabs being used
2176 // for single-column alignment. So, when indent_with_tabs is true
2177 // and indent_size is 1, reset indent_size to 4.
2178 if (this.indent_size === 1) {
2179 this.indent_size = 4;
2180 }
2181 }
2182
2183 // Backwards compat with 1.3.x
2184 this.wrap_line_length = this._get_number('wrap_line_length', this._get_number('max_char'));
2185
2186 this.indent_empty_lines = this._get_boolean('indent_empty_lines');
2187
2188 // valid templating languages ['django', 'erb', 'handlebars', 'php', 'smarty']
2189 // For now, 'auto' = all off for javascript, all on for html (and inline javascript).
2190 // other values ignored
2191 this.templating = this._get_selection_list('templating', ['auto', 'none', 'django', 'erb', 'handlebars', 'php', 'smarty'], ['auto']);
2192 }
2193
2194 Options.prototype._get_array = function(name, default_value) {
2195 var option_value = this.raw_options[name];
2196 var result = default_value || [];
2197 if (typeof option_value === 'object') {
2198 if (option_value !== null && typeof option_value.concat === 'function') {
2199 result = option_value.concat();
2200 }
2201 } else if (typeof option_value === 'string') {
2202 result = option_value.split(/[^a-zA-Z0-9_\/\-]+/);
2203 }
2204 return result;
2205 };
2206
2207 Options.prototype._get_boolean = function(name, default_value) {
2208 var option_value = this.raw_options[name];
2209 var result = option_value === undefined ? !!default_value : !!option_value;
2210 return result;
2211 };
2212
2213 Options.prototype._get_characters = function(name, default_value) {
2214 var option_value = this.raw_options[name];
2215 var result = default_value || '';
2216 if (typeof option_value === 'string') {
2217 result = option_value.replace(/\\r/, '\r').replace(/\\n/, '\n').replace(/\\t/, '\t');
2218 }
2219 return result;
2220 };
2221
2222 Options.prototype._get_number = function(name, default_value) {
2223 var option_value = this.raw_options[name];
2224 default_value = parseInt(default_value, 10);
2225 if (isNaN(default_value)) {
2226 default_value = 0;
2227 }
2228 var result = parseInt(option_value, 10);
2229 if (isNaN(result)) {
2230 result = default_value;
2231 }
2232 return result;
2233 };
2234
2235 Options.prototype._get_selection = function(name, selection_list, default_value) {
2236 var result = this._get_selection_list(name, selection_list, default_value);
2237 if (result.length !== 1) {
2238 throw new Error(
2239 "Invalid Option Value: The option '" + name + "' can only be one of the following values:\n" +
2240 selection_list + "\nYou passed in: '" + this.raw_options[name] + "'");
2241 }
2242
2243 return result[0];
2244 };
2245
2246
2247 Options.prototype._get_selection_list = function(name, selection_list, default_value) {
2248 if (!selection_list || selection_list.length === 0) {
2249 throw new Error("Selection list cannot be empty.");
2250 }
2251
2252 default_value = default_value || [selection_list[0]];
2253 if (!this._is_valid_selection(default_value, selection_list)) {
2254 throw new Error("Invalid Default Value!");
2255 }
2256
2257 var result = this._get_array(name, default_value);
2258 if (!this._is_valid_selection(result, selection_list)) {
2259 throw new Error(
2260 "Invalid Option Value: The option '" + name + "' can contain only the following values:\n" +
2261 selection_list + "\nYou passed in: '" + this.raw_options[name] + "'");
2262 }
2263
2264 return result;
2265 };
2266
2267 Options.prototype._is_valid_selection = function(result, selection_list) {
2268 return result.length && selection_list.length &&
2269 !result.some(function(item) { return selection_list.indexOf(item) === -1; });
2270 };
2271
2272
2273 // merges child options up with the parent options object
2274 // Example: obj = {a: 1, b: {a: 2}}
2275 // mergeOpts(obj, 'b')
2276 //
2277 // Returns: {a: 2}
2278 function _mergeOpts(allOptions, childFieldName) {
2279 var finalOpts = {};
2280 allOptions = _normalizeOpts(allOptions);
2281 var name;
2282
2283 for (name in allOptions) {
2284 if (name !== childFieldName) {
2285 finalOpts[name] = allOptions[name];
2286 }
2287 }
2288
2289 //merge in the per type settings for the childFieldName
2290 if (childFieldName && allOptions[childFieldName]) {
2291 for (name in allOptions[childFieldName]) {
2292 finalOpts[name] = allOptions[childFieldName][name];
2293 }
2294 }
2295 return finalOpts;
2296 }
2297
2298 function _normalizeOpts(options) {
2299 var convertedOpts = {};
2300 var key;
2301
2302 for (key in options) {
2303 var newKey = key.replace(/-/g, "_");
2304 convertedOpts[newKey] = options[key];
2305 }
2306 return convertedOpts;
2307 }
2308
2309 options$2.Options = Options;
2310 options$2.normalizeOpts = _normalizeOpts;
2311 options$2.mergeOpts = _mergeOpts;
2312 return options$2;
2313}
2314
2315/*jshint node:true */
2316
2317var hasRequiredOptions$2;
2318
2319function requireOptions$2 () {
2320 if (hasRequiredOptions$2) return options$3;
2321 hasRequiredOptions$2 = 1;
2322
2323 var BaseOptions = requireOptions$3().Options;
2324
2325 var validPositionValues = ['before-newline', 'after-newline', 'preserve-newline'];
2326
2327 function Options(options) {
2328 BaseOptions.call(this, options, 'js');
2329
2330 // compatibility, re
2331 var raw_brace_style = this.raw_options.brace_style || null;
2332 if (raw_brace_style === "expand-strict") { //graceful handling of deprecated option
2333 this.raw_options.brace_style = "expand";
2334 } else if (raw_brace_style === "collapse-preserve-inline") { //graceful handling of deprecated option
2335 this.raw_options.brace_style = "collapse,preserve-inline";
2336 } else if (this.raw_options.braces_on_own_line !== undefined) { //graceful handling of deprecated option
2337 this.raw_options.brace_style = this.raw_options.braces_on_own_line ? "expand" : "collapse";
2338 // } else if (!raw_brace_style) { //Nothing exists to set it
2339 // raw_brace_style = "collapse";
2340 }
2341
2342 //preserve-inline in delimited string will trigger brace_preserve_inline, everything
2343 //else is considered a brace_style and the last one only will have an effect
2344
2345 var brace_style_split = this._get_selection_list('brace_style', ['collapse', 'expand', 'end-expand', 'none', 'preserve-inline']);
2346
2347 this.brace_preserve_inline = false; //Defaults in case one or other was not specified in meta-option
2348 this.brace_style = "collapse";
2349
2350 for (var bs = 0; bs < brace_style_split.length; bs++) {
2351 if (brace_style_split[bs] === "preserve-inline") {
2352 this.brace_preserve_inline = true;
2353 } else {
2354 this.brace_style = brace_style_split[bs];
2355 }
2356 }
2357
2358 this.unindent_chained_methods = this._get_boolean('unindent_chained_methods');
2359 this.break_chained_methods = this._get_boolean('break_chained_methods');
2360 this.space_in_paren = this._get_boolean('space_in_paren');
2361 this.space_in_empty_paren = this._get_boolean('space_in_empty_paren');
2362 this.jslint_happy = this._get_boolean('jslint_happy');
2363 this.space_after_anon_function = this._get_boolean('space_after_anon_function');
2364 this.space_after_named_function = this._get_boolean('space_after_named_function');
2365 this.keep_array_indentation = this._get_boolean('keep_array_indentation');
2366 this.space_before_conditional = this._get_boolean('space_before_conditional', true);
2367 this.unescape_strings = this._get_boolean('unescape_strings');
2368 this.e4x = this._get_boolean('e4x');
2369 this.comma_first = this._get_boolean('comma_first');
2370 this.operator_position = this._get_selection('operator_position', validPositionValues);
2371
2372 // For testing of beautify preserve:start directive
2373 this.test_output_raw = this._get_boolean('test_output_raw');
2374
2375 // force this._options.space_after_anon_function to true if this._options.jslint_happy
2376 if (this.jslint_happy) {
2377 this.space_after_anon_function = true;
2378 }
2379
2380 }
2381 Options.prototype = new BaseOptions();
2382
2383
2384
2385 options$3.Options = Options;
2386 return options$3;
2387}
2388
2389var tokenizer$2 = {};
2390
2391var inputscanner = {};
2392
2393/*jshint node:true */
2394
2395var hasRequiredInputscanner;
2396
2397function requireInputscanner () {
2398 if (hasRequiredInputscanner) return inputscanner;
2399 hasRequiredInputscanner = 1;
2400
2401 var regexp_has_sticky = RegExp.prototype.hasOwnProperty('sticky');
2402
2403 function InputScanner(input_string) {
2404 this.__input = input_string || '';
2405 this.__input_length = this.__input.length;
2406 this.__position = 0;
2407 }
2408
2409 InputScanner.prototype.restart = function() {
2410 this.__position = 0;
2411 };
2412
2413 InputScanner.prototype.back = function() {
2414 if (this.__position > 0) {
2415 this.__position -= 1;
2416 }
2417 };
2418
2419 InputScanner.prototype.hasNext = function() {
2420 return this.__position < this.__input_length;
2421 };
2422
2423 InputScanner.prototype.next = function() {
2424 var val = null;
2425 if (this.hasNext()) {
2426 val = this.__input.charAt(this.__position);
2427 this.__position += 1;
2428 }
2429 return val;
2430 };
2431
2432 InputScanner.prototype.peek = function(index) {
2433 var val = null;
2434 index = index || 0;
2435 index += this.__position;
2436 if (index >= 0 && index < this.__input_length) {
2437 val = this.__input.charAt(index);
2438 }
2439 return val;
2440 };
2441
2442 // This is a JavaScript only helper function (not in python)
2443 // Javascript doesn't have a match method
2444 // and not all implementation support "sticky" flag.
2445 // If they do not support sticky then both this.match() and this.test() method
2446 // must get the match and check the index of the match.
2447 // If sticky is supported and set, this method will use it.
2448 // Otherwise it will check that global is set, and fall back to the slower method.
2449 InputScanner.prototype.__match = function(pattern, index) {
2450 pattern.lastIndex = index;
2451 var pattern_match = pattern.exec(this.__input);
2452
2453 if (pattern_match && !(regexp_has_sticky && pattern.sticky)) {
2454 if (pattern_match.index !== index) {
2455 pattern_match = null;
2456 }
2457 }
2458
2459 return pattern_match;
2460 };
2461
2462 InputScanner.prototype.test = function(pattern, index) {
2463 index = index || 0;
2464 index += this.__position;
2465
2466 if (index >= 0 && index < this.__input_length) {
2467 return !!this.__match(pattern, index);
2468 } else {
2469 return false;
2470 }
2471 };
2472
2473 InputScanner.prototype.testChar = function(pattern, index) {
2474 // test one character regex match
2475 var val = this.peek(index);
2476 pattern.lastIndex = 0;
2477 return val !== null && pattern.test(val);
2478 };
2479
2480 InputScanner.prototype.match = function(pattern) {
2481 var pattern_match = this.__match(pattern, this.__position);
2482 if (pattern_match) {
2483 this.__position += pattern_match[0].length;
2484 } else {
2485 pattern_match = null;
2486 }
2487 return pattern_match;
2488 };
2489
2490 InputScanner.prototype.read = function(starting_pattern, until_pattern, until_after) {
2491 var val = '';
2492 var match;
2493 if (starting_pattern) {
2494 match = this.match(starting_pattern);
2495 if (match) {
2496 val += match[0];
2497 }
2498 }
2499 if (until_pattern && (match || !starting_pattern)) {
2500 val += this.readUntil(until_pattern, until_after);
2501 }
2502 return val;
2503 };
2504
2505 InputScanner.prototype.readUntil = function(pattern, until_after) {
2506 var val = '';
2507 var match_index = this.__position;
2508 pattern.lastIndex = this.__position;
2509 var pattern_match = pattern.exec(this.__input);
2510 if (pattern_match) {
2511 match_index = pattern_match.index;
2512 if (until_after) {
2513 match_index += pattern_match[0].length;
2514 }
2515 } else {
2516 match_index = this.__input_length;
2517 }
2518
2519 val = this.__input.substring(this.__position, match_index);
2520 this.__position = match_index;
2521 return val;
2522 };
2523
2524 InputScanner.prototype.readUntilAfter = function(pattern) {
2525 return this.readUntil(pattern, true);
2526 };
2527
2528 InputScanner.prototype.get_regexp = function(pattern, match_from) {
2529 var result = null;
2530 var flags = 'g';
2531 if (match_from && regexp_has_sticky) {
2532 flags = 'y';
2533 }
2534 // strings are converted to regexp
2535 if (typeof pattern === "string" && pattern !== '') {
2536 // result = new RegExp(pattern.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), flags);
2537 result = new RegExp(pattern, flags);
2538 } else if (pattern) {
2539 result = new RegExp(pattern.source, flags);
2540 }
2541 return result;
2542 };
2543
2544 InputScanner.prototype.get_literal_regexp = function(literal_string) {
2545 return RegExp(literal_string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'));
2546 };
2547
2548 /* css beautifier legacy helpers */
2549 InputScanner.prototype.peekUntilAfter = function(pattern) {
2550 var start = this.__position;
2551 var val = this.readUntilAfter(pattern);
2552 this.__position = start;
2553 return val;
2554 };
2555
2556 InputScanner.prototype.lookBack = function(testVal) {
2557 var start = this.__position - 1;
2558 return start >= testVal.length && this.__input.substring(start - testVal.length, start)
2559 .toLowerCase() === testVal;
2560 };
2561
2562 inputscanner.InputScanner = InputScanner;
2563 return inputscanner;
2564}
2565
2566var tokenizer$1 = {};
2567
2568var tokenstream = {};
2569
2570/*jshint node:true */
2571
2572var hasRequiredTokenstream;
2573
2574function requireTokenstream () {
2575 if (hasRequiredTokenstream) return tokenstream;
2576 hasRequiredTokenstream = 1;
2577
2578 function TokenStream(parent_token) {
2579 // private
2580 this.__tokens = [];
2581 this.__tokens_length = this.__tokens.length;
2582 this.__position = 0;
2583 this.__parent_token = parent_token;
2584 }
2585
2586 TokenStream.prototype.restart = function() {
2587 this.__position = 0;
2588 };
2589
2590 TokenStream.prototype.isEmpty = function() {
2591 return this.__tokens_length === 0;
2592 };
2593
2594 TokenStream.prototype.hasNext = function() {
2595 return this.__position < this.__tokens_length;
2596 };
2597
2598 TokenStream.prototype.next = function() {
2599 var val = null;
2600 if (this.hasNext()) {
2601 val = this.__tokens[this.__position];
2602 this.__position += 1;
2603 }
2604 return val;
2605 };
2606
2607 TokenStream.prototype.peek = function(index) {
2608 var val = null;
2609 index = index || 0;
2610 index += this.__position;
2611 if (index >= 0 && index < this.__tokens_length) {
2612 val = this.__tokens[index];
2613 }
2614 return val;
2615 };
2616
2617 TokenStream.prototype.add = function(token) {
2618 if (this.__parent_token) {
2619 token.parent = this.__parent_token;
2620 }
2621 this.__tokens.push(token);
2622 this.__tokens_length += 1;
2623 };
2624
2625 tokenstream.TokenStream = TokenStream;
2626 return tokenstream;
2627}
2628
2629var whitespacepattern = {};
2630
2631var pattern = {};
2632
2633/*jshint node:true */
2634
2635var hasRequiredPattern;
2636
2637function requirePattern () {
2638 if (hasRequiredPattern) return pattern;
2639 hasRequiredPattern = 1;
2640
2641 function Pattern(input_scanner, parent) {
2642 this._input = input_scanner;
2643 this._starting_pattern = null;
2644 this._match_pattern = null;
2645 this._until_pattern = null;
2646 this._until_after = false;
2647
2648 if (parent) {
2649 this._starting_pattern = this._input.get_regexp(parent._starting_pattern, true);
2650 this._match_pattern = this._input.get_regexp(parent._match_pattern, true);
2651 this._until_pattern = this._input.get_regexp(parent._until_pattern);
2652 this._until_after = parent._until_after;
2653 }
2654 }
2655
2656 Pattern.prototype.read = function() {
2657 var result = this._input.read(this._starting_pattern);
2658 if (!this._starting_pattern || result) {
2659 result += this._input.read(this._match_pattern, this._until_pattern, this._until_after);
2660 }
2661 return result;
2662 };
2663
2664 Pattern.prototype.read_match = function() {
2665 return this._input.match(this._match_pattern);
2666 };
2667
2668 Pattern.prototype.until_after = function(pattern) {
2669 var result = this._create();
2670 result._until_after = true;
2671 result._until_pattern = this._input.get_regexp(pattern);
2672 result._update();
2673 return result;
2674 };
2675
2676 Pattern.prototype.until = function(pattern) {
2677 var result = this._create();
2678 result._until_after = false;
2679 result._until_pattern = this._input.get_regexp(pattern);
2680 result._update();
2681 return result;
2682 };
2683
2684 Pattern.prototype.starting_with = function(pattern) {
2685 var result = this._create();
2686 result._starting_pattern = this._input.get_regexp(pattern, true);
2687 result._update();
2688 return result;
2689 };
2690
2691 Pattern.prototype.matching = function(pattern) {
2692 var result = this._create();
2693 result._match_pattern = this._input.get_regexp(pattern, true);
2694 result._update();
2695 return result;
2696 };
2697
2698 Pattern.prototype._create = function() {
2699 return new Pattern(this._input, this);
2700 };
2701
2702 Pattern.prototype._update = function() {};
2703
2704 pattern.Pattern = Pattern;
2705 return pattern;
2706}
2707
2708/*jshint node:true */
2709
2710var hasRequiredWhitespacepattern;
2711
2712function requireWhitespacepattern () {
2713 if (hasRequiredWhitespacepattern) return whitespacepattern;
2714 hasRequiredWhitespacepattern = 1;
2715
2716 var Pattern = requirePattern().Pattern;
2717
2718 function WhitespacePattern(input_scanner, parent) {
2719 Pattern.call(this, input_scanner, parent);
2720 if (parent) {
2721 this._line_regexp = this._input.get_regexp(parent._line_regexp);
2722 } else {
2723 this.__set_whitespace_patterns('', '');
2724 }
2725
2726 this.newline_count = 0;
2727 this.whitespace_before_token = '';
2728 }
2729 WhitespacePattern.prototype = new Pattern();
2730
2731 WhitespacePattern.prototype.__set_whitespace_patterns = function(whitespace_chars, newline_chars) {
2732 whitespace_chars += '\\t ';
2733 newline_chars += '\\n\\r';
2734
2735 this._match_pattern = this._input.get_regexp(
2736 '[' + whitespace_chars + newline_chars + ']+', true);
2737 this._newline_regexp = this._input.get_regexp(
2738 '\\r\\n|[' + newline_chars + ']');
2739 };
2740
2741 WhitespacePattern.prototype.read = function() {
2742 this.newline_count = 0;
2743 this.whitespace_before_token = '';
2744
2745 var resulting_string = this._input.read(this._match_pattern);
2746 if (resulting_string === ' ') {
2747 this.whitespace_before_token = ' ';
2748 } else if (resulting_string) {
2749 var matches = this.__split(this._newline_regexp, resulting_string);
2750 this.newline_count = matches.length - 1;
2751 this.whitespace_before_token = matches[this.newline_count];
2752 }
2753
2754 return resulting_string;
2755 };
2756
2757 WhitespacePattern.prototype.matching = function(whitespace_chars, newline_chars) {
2758 var result = this._create();
2759 result.__set_whitespace_patterns(whitespace_chars, newline_chars);
2760 result._update();
2761 return result;
2762 };
2763
2764 WhitespacePattern.prototype._create = function() {
2765 return new WhitespacePattern(this._input, this);
2766 };
2767
2768 WhitespacePattern.prototype.__split = function(regexp, input_string) {
2769 regexp.lastIndex = 0;
2770 var start_index = 0;
2771 var result = [];
2772 var next_match = regexp.exec(input_string);
2773 while (next_match) {
2774 result.push(input_string.substring(start_index, next_match.index));
2775 start_index = next_match.index + next_match[0].length;
2776 next_match = regexp.exec(input_string);
2777 }
2778
2779 if (start_index < input_string.length) {
2780 result.push(input_string.substring(start_index, input_string.length));
2781 } else {
2782 result.push('');
2783 }
2784
2785 return result;
2786 };
2787
2788
2789
2790 whitespacepattern.WhitespacePattern = WhitespacePattern;
2791 return whitespacepattern;
2792}
2793
2794/*jshint node:true */
2795
2796var hasRequiredTokenizer$2;
2797
2798function requireTokenizer$2 () {
2799 if (hasRequiredTokenizer$2) return tokenizer$1;
2800 hasRequiredTokenizer$2 = 1;
2801
2802 var InputScanner = requireInputscanner().InputScanner;
2803 var Token = requireToken().Token;
2804 var TokenStream = requireTokenstream().TokenStream;
2805 var WhitespacePattern = requireWhitespacepattern().WhitespacePattern;
2806
2807 var TOKEN = {
2808 START: 'TK_START',
2809 RAW: 'TK_RAW',
2810 EOF: 'TK_EOF'
2811 };
2812
2813 var Tokenizer = function(input_string, options) {
2814 this._input = new InputScanner(input_string);
2815 this._options = options || {};
2816 this.__tokens = null;
2817
2818 this._patterns = {};
2819 this._patterns.whitespace = new WhitespacePattern(this._input);
2820 };
2821
2822 Tokenizer.prototype.tokenize = function() {
2823 this._input.restart();
2824 this.__tokens = new TokenStream();
2825
2826 this._reset();
2827
2828 var current;
2829 var previous = new Token(TOKEN.START, '');
2830 var open_token = null;
2831 var open_stack = [];
2832 var comments = new TokenStream();
2833
2834 while (previous.type !== TOKEN.EOF) {
2835 current = this._get_next_token(previous, open_token);
2836 while (this._is_comment(current)) {
2837 comments.add(current);
2838 current = this._get_next_token(previous, open_token);
2839 }
2840
2841 if (!comments.isEmpty()) {
2842 current.comments_before = comments;
2843 comments = new TokenStream();
2844 }
2845
2846 current.parent = open_token;
2847
2848 if (this._is_opening(current)) {
2849 open_stack.push(open_token);
2850 open_token = current;
2851 } else if (open_token && this._is_closing(current, open_token)) {
2852 current.opened = open_token;
2853 open_token.closed = current;
2854 open_token = open_stack.pop();
2855 current.parent = open_token;
2856 }
2857
2858 current.previous = previous;
2859 previous.next = current;
2860
2861 this.__tokens.add(current);
2862 previous = current;
2863 }
2864
2865 return this.__tokens;
2866 };
2867
2868
2869 Tokenizer.prototype._is_first_token = function() {
2870 return this.__tokens.isEmpty();
2871 };
2872
2873 Tokenizer.prototype._reset = function() {};
2874
2875 Tokenizer.prototype._get_next_token = function(previous_token, open_token) { // jshint unused:false
2876 this._readWhitespace();
2877 var resulting_string = this._input.read(/.+/g);
2878 if (resulting_string) {
2879 return this._create_token(TOKEN.RAW, resulting_string);
2880 } else {
2881 return this._create_token(TOKEN.EOF, '');
2882 }
2883 };
2884
2885 Tokenizer.prototype._is_comment = function(current_token) { // jshint unused:false
2886 return false;
2887 };
2888
2889 Tokenizer.prototype._is_opening = function(current_token) { // jshint unused:false
2890 return false;
2891 };
2892
2893 Tokenizer.prototype._is_closing = function(current_token, open_token) { // jshint unused:false
2894 return false;
2895 };
2896
2897 Tokenizer.prototype._create_token = function(type, text) {
2898 var token = new Token(type, text,
2899 this._patterns.whitespace.newline_count,
2900 this._patterns.whitespace.whitespace_before_token);
2901 return token;
2902 };
2903
2904 Tokenizer.prototype._readWhitespace = function() {
2905 return this._patterns.whitespace.read();
2906 };
2907
2908
2909
2910 tokenizer$1.Tokenizer = Tokenizer;
2911 tokenizer$1.TOKEN = TOKEN;
2912 return tokenizer$1;
2913}
2914
2915var directives = {};
2916
2917/*jshint node:true */
2918
2919var hasRequiredDirectives;
2920
2921function requireDirectives () {
2922 if (hasRequiredDirectives) return directives;
2923 hasRequiredDirectives = 1;
2924
2925 function Directives(start_block_pattern, end_block_pattern) {
2926 start_block_pattern = typeof start_block_pattern === 'string' ? start_block_pattern : start_block_pattern.source;
2927 end_block_pattern = typeof end_block_pattern === 'string' ? end_block_pattern : end_block_pattern.source;
2928 this.__directives_block_pattern = new RegExp(start_block_pattern + / beautify( \w+[:]\w+)+ /.source + end_block_pattern, 'g');
2929 this.__directive_pattern = / (\w+)[:](\w+)/g;
2930
2931 this.__directives_end_ignore_pattern = new RegExp(start_block_pattern + /\sbeautify\signore:end\s/.source + end_block_pattern, 'g');
2932 }
2933
2934 Directives.prototype.get_directives = function(text) {
2935 if (!text.match(this.__directives_block_pattern)) {
2936 return null;
2937 }
2938
2939 var directives = {};
2940 this.__directive_pattern.lastIndex = 0;
2941 var directive_match = this.__directive_pattern.exec(text);
2942
2943 while (directive_match) {
2944 directives[directive_match[1]] = directive_match[2];
2945 directive_match = this.__directive_pattern.exec(text);
2946 }
2947
2948 return directives;
2949 };
2950
2951 Directives.prototype.readIgnored = function(input) {
2952 return input.readUntilAfter(this.__directives_end_ignore_pattern);
2953 };
2954
2955
2956 directives.Directives = Directives;
2957 return directives;
2958}
2959
2960var templatablepattern = {};
2961
2962/*jshint node:true */
2963
2964var hasRequiredTemplatablepattern;
2965
2966function requireTemplatablepattern () {
2967 if (hasRequiredTemplatablepattern) return templatablepattern;
2968 hasRequiredTemplatablepattern = 1;
2969
2970 var Pattern = requirePattern().Pattern;
2971
2972
2973 var template_names = {
2974 django: false,
2975 erb: false,
2976 handlebars: false,
2977 php: false,
2978 smarty: false
2979 };
2980
2981 // This lets templates appear anywhere we would do a readUntil
2982 // The cost is higher but it is pay to play.
2983 function TemplatablePattern(input_scanner, parent) {
2984 Pattern.call(this, input_scanner, parent);
2985 this.__template_pattern = null;
2986 this._disabled = Object.assign({}, template_names);
2987 this._excluded = Object.assign({}, template_names);
2988
2989 if (parent) {
2990 this.__template_pattern = this._input.get_regexp(parent.__template_pattern);
2991 this._excluded = Object.assign(this._excluded, parent._excluded);
2992 this._disabled = Object.assign(this._disabled, parent._disabled);
2993 }
2994 var pattern = new Pattern(input_scanner);
2995 this.__patterns = {
2996 handlebars_comment: pattern.starting_with(/{{!--/).until_after(/--}}/),
2997 handlebars_unescaped: pattern.starting_with(/{{{/).until_after(/}}}/),
2998 handlebars: pattern.starting_with(/{{/).until_after(/}}/),
2999 php: pattern.starting_with(/<\?(?:[= ]|php)/).until_after(/\?>/),
3000 erb: pattern.starting_with(/<%[^%]/).until_after(/[^%]%>/),
3001 // django coflicts with handlebars a bit.
3002 django: pattern.starting_with(/{%/).until_after(/%}/),
3003 django_value: pattern.starting_with(/{{/).until_after(/}}/),
3004 django_comment: pattern.starting_with(/{#/).until_after(/#}/),
3005 smarty: pattern.starting_with(/{(?=[^}{\s\n])/).until_after(/[^\s\n]}/),
3006 smarty_comment: pattern.starting_with(/{\*/).until_after(/\*}/),
3007 smarty_literal: pattern.starting_with(/{literal}/).until_after(/{\/literal}/)
3008 };
3009 }
3010 TemplatablePattern.prototype = new Pattern();
3011
3012 TemplatablePattern.prototype._create = function() {
3013 return new TemplatablePattern(this._input, this);
3014 };
3015
3016 TemplatablePattern.prototype._update = function() {
3017 this.__set_templated_pattern();
3018 };
3019
3020 TemplatablePattern.prototype.disable = function(language) {
3021 var result = this._create();
3022 result._disabled[language] = true;
3023 result._update();
3024 return result;
3025 };
3026
3027 TemplatablePattern.prototype.read_options = function(options) {
3028 var result = this._create();
3029 for (var language in template_names) {
3030 result._disabled[language] = options.templating.indexOf(language) === -1;
3031 }
3032 result._update();
3033 return result;
3034 };
3035
3036 TemplatablePattern.prototype.exclude = function(language) {
3037 var result = this._create();
3038 result._excluded[language] = true;
3039 result._update();
3040 return result;
3041 };
3042
3043 TemplatablePattern.prototype.read = function() {
3044 var result = '';
3045 if (this._match_pattern) {
3046 result = this._input.read(this._starting_pattern);
3047 } else {
3048 result = this._input.read(this._starting_pattern, this.__template_pattern);
3049 }
3050 var next = this._read_template();
3051 while (next) {
3052 if (this._match_pattern) {
3053 next += this._input.read(this._match_pattern);
3054 } else {
3055 next += this._input.readUntil(this.__template_pattern);
3056 }
3057 result += next;
3058 next = this._read_template();
3059 }
3060
3061 if (this._until_after) {
3062 result += this._input.readUntilAfter(this._until_pattern);
3063 }
3064 return result;
3065 };
3066
3067 TemplatablePattern.prototype.__set_templated_pattern = function() {
3068 var items = [];
3069
3070 if (!this._disabled.php) {
3071 items.push(this.__patterns.php._starting_pattern.source);
3072 }
3073 if (!this._disabled.handlebars) {
3074 items.push(this.__patterns.handlebars._starting_pattern.source);
3075 }
3076 if (!this._disabled.erb) {
3077 items.push(this.__patterns.erb._starting_pattern.source);
3078 }
3079 if (!this._disabled.django) {
3080 items.push(this.__patterns.django._starting_pattern.source);
3081 // The starting pattern for django is more complex because it has different
3082 // patterns for value, comment, and other sections
3083 items.push(this.__patterns.django_value._starting_pattern.source);
3084 items.push(this.__patterns.django_comment._starting_pattern.source);
3085 }
3086 if (!this._disabled.smarty) {
3087 items.push(this.__patterns.smarty._starting_pattern.source);
3088 }
3089
3090 if (this._until_pattern) {
3091 items.push(this._until_pattern.source);
3092 }
3093 this.__template_pattern = this._input.get_regexp('(?:' + items.join('|') + ')');
3094 };
3095
3096 TemplatablePattern.prototype._read_template = function() {
3097 var resulting_string = '';
3098 var c = this._input.peek();
3099 if (c === '<') {
3100 var peek1 = this._input.peek(1);
3101 //if we're in a comment, do something special
3102 // We treat all comments as literals, even more than preformatted tags
3103 // we just look for the appropriate close tag
3104 if (!this._disabled.php && !this._excluded.php && peek1 === '?') {
3105 resulting_string = resulting_string ||
3106 this.__patterns.php.read();
3107 }
3108 if (!this._disabled.erb && !this._excluded.erb && peek1 === '%') {
3109 resulting_string = resulting_string ||
3110 this.__patterns.erb.read();
3111 }
3112 } else if (c === '{') {
3113 if (!this._disabled.handlebars && !this._excluded.handlebars) {
3114 resulting_string = resulting_string ||
3115 this.__patterns.handlebars_comment.read();
3116 resulting_string = resulting_string ||
3117 this.__patterns.handlebars_unescaped.read();
3118 resulting_string = resulting_string ||
3119 this.__patterns.handlebars.read();
3120 }
3121 if (!this._disabled.django) {
3122 // django coflicts with handlebars a bit.
3123 if (!this._excluded.django && !this._excluded.handlebars) {
3124 resulting_string = resulting_string ||
3125 this.__patterns.django_value.read();
3126 }
3127 if (!this._excluded.django) {
3128 resulting_string = resulting_string ||
3129 this.__patterns.django_comment.read();
3130 resulting_string = resulting_string ||
3131 this.__patterns.django.read();
3132 }
3133 }
3134 if (!this._disabled.smarty) {
3135 // smarty cannot be enabled with django or handlebars enabled
3136 if (this._disabled.django && this._disabled.handlebars) {
3137 resulting_string = resulting_string ||
3138 this.__patterns.smarty_comment.read();
3139 resulting_string = resulting_string ||
3140 this.__patterns.smarty_literal.read();
3141 resulting_string = resulting_string ||
3142 this.__patterns.smarty.read();
3143 }
3144 }
3145 }
3146 return resulting_string;
3147 };
3148
3149
3150 templatablepattern.TemplatablePattern = TemplatablePattern;
3151 return templatablepattern;
3152}
3153
3154/*jshint node:true */
3155
3156var hasRequiredTokenizer$1;
3157
3158function requireTokenizer$1 () {
3159 if (hasRequiredTokenizer$1) return tokenizer$2;
3160 hasRequiredTokenizer$1 = 1;
3161
3162 var InputScanner = requireInputscanner().InputScanner;
3163 var BaseTokenizer = requireTokenizer$2().Tokenizer;
3164 var BASETOKEN = requireTokenizer$2().TOKEN;
3165 var Directives = requireDirectives().Directives;
3166 var acorn = requireAcorn();
3167 var Pattern = requirePattern().Pattern;
3168 var TemplatablePattern = requireTemplatablepattern().TemplatablePattern;
3169
3170
3171 function in_array(what, arr) {
3172 return arr.indexOf(what) !== -1;
3173 }
3174
3175
3176 var TOKEN = {
3177 START_EXPR: 'TK_START_EXPR',
3178 END_EXPR: 'TK_END_EXPR',
3179 START_BLOCK: 'TK_START_BLOCK',
3180 END_BLOCK: 'TK_END_BLOCK',
3181 WORD: 'TK_WORD',
3182 RESERVED: 'TK_RESERVED',
3183 SEMICOLON: 'TK_SEMICOLON',
3184 STRING: 'TK_STRING',
3185 EQUALS: 'TK_EQUALS',
3186 OPERATOR: 'TK_OPERATOR',
3187 COMMA: 'TK_COMMA',
3188 BLOCK_COMMENT: 'TK_BLOCK_COMMENT',
3189 COMMENT: 'TK_COMMENT',
3190 DOT: 'TK_DOT',
3191 UNKNOWN: 'TK_UNKNOWN',
3192 START: BASETOKEN.START,
3193 RAW: BASETOKEN.RAW,
3194 EOF: BASETOKEN.EOF
3195 };
3196
3197
3198 var directives_core = new Directives(/\/\*/, /\*\//);
3199
3200 var number_pattern = /0[xX][0123456789abcdefABCDEF_]*n?|0[oO][01234567_]*n?|0[bB][01_]*n?|\d[\d_]*n|(?:\.\d[\d_]*|\d[\d_]*\.?[\d_]*)(?:[eE][+-]?[\d_]+)?/;
3201
3202 var digit = /[0-9]/;
3203
3204 // Dot "." must be distinguished from "..." and decimal
3205 var dot_pattern = /[^\d\.]/;
3206
3207 var positionable_operators = (
3208 ">>> === !== &&= ??= ||= " +
3209 "<< && >= ** != == <= >> || ?? |> " +
3210 "< / - + > : & % ? ^ | *").split(' ');
3211
3212 // IMPORTANT: this must be sorted longest to shortest or tokenizing many not work.
3213 // Also, you must update possitionable operators separately from punct
3214 var punct =
3215 ">>>= " +
3216 "... >>= <<= === >>> !== **= &&= ??= ||= " +
3217 "=> ^= :: /= << <= == && -= >= >> != -- += ** || ?? ++ %= &= *= |= |> " +
3218 "= ! ? > < : / ^ - + * & % ~ |";
3219
3220 punct = punct.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&");
3221 // ?. but not if followed by a number
3222 punct = '\\?\\.(?!\\d) ' + punct;
3223 punct = punct.replace(/ /g, '|');
3224
3225 var punct_pattern = new RegExp(punct);
3226
3227 // words which should always start on new line.
3228 var line_starters = 'continue,try,throw,return,var,let,const,if,switch,case,default,for,while,break,function,import,export'.split(',');
3229 var reserved_words = line_starters.concat(['do', 'in', 'of', 'else', 'get', 'set', 'new', 'catch', 'finally', 'typeof', 'yield', 'async', 'await', 'from', 'as', 'class', 'extends']);
3230 var reserved_word_pattern = new RegExp('^(?:' + reserved_words.join('|') + ')$');
3231
3232 // var template_pattern = /(?:(?:<\?php|<\?=)[\s\S]*?\?>)|(?:<%[\s\S]*?%>)/g;
3233
3234 var in_html_comment;
3235
3236 var Tokenizer = function(input_string, options) {
3237 BaseTokenizer.call(this, input_string, options);
3238
3239 this._patterns.whitespace = this._patterns.whitespace.matching(
3240 /\u00A0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff/.source,
3241 /\u2028\u2029/.source);
3242
3243 var pattern_reader = new Pattern(this._input);
3244 var templatable = new TemplatablePattern(this._input)
3245 .read_options(this._options);
3246
3247 this.__patterns = {
3248 template: templatable,
3249 identifier: templatable.starting_with(acorn.identifier).matching(acorn.identifierMatch),
3250 number: pattern_reader.matching(number_pattern),
3251 punct: pattern_reader.matching(punct_pattern),
3252 // comment ends just before nearest linefeed or end of file
3253 comment: pattern_reader.starting_with(/\/\//).until(/[\n\r\u2028\u2029]/),
3254 // /* ... */ comment ends with nearest */ or end of file
3255 block_comment: pattern_reader.starting_with(/\/\*/).until_after(/\*\//),
3256 html_comment_start: pattern_reader.matching(/<!--/),
3257 html_comment_end: pattern_reader.matching(/-->/),
3258 include: pattern_reader.starting_with(/#include/).until_after(acorn.lineBreak),
3259 shebang: pattern_reader.starting_with(/#!/).until_after(acorn.lineBreak),
3260 xml: pattern_reader.matching(/[\s\S]*?<(\/?)([-a-zA-Z:0-9_.]+|{[^}]+?}|!\[CDATA\[[^\]]*?\]\]|)(\s*{[^}]+?}|\s+[-a-zA-Z:0-9_.]+|\s+[-a-zA-Z:0-9_.]+\s*=\s*('[^']*'|"[^"]*"|{([^{}]|{[^}]+?})+?}))*\s*(\/?)\s*>/),
3261 single_quote: templatable.until(/['\\\n\r\u2028\u2029]/),
3262 double_quote: templatable.until(/["\\\n\r\u2028\u2029]/),
3263 template_text: templatable.until(/[`\\$]/),
3264 template_expression: templatable.until(/[`}\\]/)
3265 };
3266
3267 };
3268 Tokenizer.prototype = new BaseTokenizer();
3269
3270 Tokenizer.prototype._is_comment = function(current_token) {
3271 return current_token.type === TOKEN.COMMENT || current_token.type === TOKEN.BLOCK_COMMENT || current_token.type === TOKEN.UNKNOWN;
3272 };
3273
3274 Tokenizer.prototype._is_opening = function(current_token) {
3275 return current_token.type === TOKEN.START_BLOCK || current_token.type === TOKEN.START_EXPR;
3276 };
3277
3278 Tokenizer.prototype._is_closing = function(current_token, open_token) {
3279 return (current_token.type === TOKEN.END_BLOCK || current_token.type === TOKEN.END_EXPR) &&
3280 (open_token && (
3281 (current_token.text === ']' && open_token.text === '[') ||
3282 (current_token.text === ')' && open_token.text === '(') ||
3283 (current_token.text === '}' && open_token.text === '{')));
3284 };
3285
3286 Tokenizer.prototype._reset = function() {
3287 in_html_comment = false;
3288 };
3289
3290 Tokenizer.prototype._get_next_token = function(previous_token, open_token) { // jshint unused:false
3291 var token = null;
3292 this._readWhitespace();
3293 var c = this._input.peek();
3294
3295 if (c === null) {
3296 return this._create_token(TOKEN.EOF, '');
3297 }
3298
3299 token = token || this._read_non_javascript(c);
3300 token = token || this._read_string(c);
3301 token = token || this._read_pair(c, this._input.peek(1)); // Issue #2062 hack for record type '#{'
3302 token = token || this._read_word(previous_token);
3303 token = token || this._read_singles(c);
3304 token = token || this._read_comment(c);
3305 token = token || this._read_regexp(c, previous_token);
3306 token = token || this._read_xml(c, previous_token);
3307 token = token || this._read_punctuation();
3308 token = token || this._create_token(TOKEN.UNKNOWN, this._input.next());
3309
3310 return token;
3311 };
3312
3313 Tokenizer.prototype._read_word = function(previous_token) {
3314 var resulting_string;
3315 resulting_string = this.__patterns.identifier.read();
3316 if (resulting_string !== '') {
3317 resulting_string = resulting_string.replace(acorn.allLineBreaks, '\n');
3318 if (!(previous_token.type === TOKEN.DOT ||
3319 (previous_token.type === TOKEN.RESERVED && (previous_token.text === 'set' || previous_token.text === 'get'))) &&
3320 reserved_word_pattern.test(resulting_string)) {
3321 if ((resulting_string === 'in' || resulting_string === 'of') &&
3322 (previous_token.type === TOKEN.WORD || previous_token.type === TOKEN.STRING)) { // hack for 'in' and 'of' operators
3323 return this._create_token(TOKEN.OPERATOR, resulting_string);
3324 }
3325 return this._create_token(TOKEN.RESERVED, resulting_string);
3326 }
3327 return this._create_token(TOKEN.WORD, resulting_string);
3328 }
3329
3330 resulting_string = this.__patterns.number.read();
3331 if (resulting_string !== '') {
3332 return this._create_token(TOKEN.WORD, resulting_string);
3333 }
3334 };
3335
3336 Tokenizer.prototype._read_singles = function(c) {
3337 var token = null;
3338 if (c === '(' || c === '[') {
3339 token = this._create_token(TOKEN.START_EXPR, c);
3340 } else if (c === ')' || c === ']') {
3341 token = this._create_token(TOKEN.END_EXPR, c);
3342 } else if (c === '{') {
3343 token = this._create_token(TOKEN.START_BLOCK, c);
3344 } else if (c === '}') {
3345 token = this._create_token(TOKEN.END_BLOCK, c);
3346 } else if (c === ';') {
3347 token = this._create_token(TOKEN.SEMICOLON, c);
3348 } else if (c === '.' && dot_pattern.test(this._input.peek(1))) {
3349 token = this._create_token(TOKEN.DOT, c);
3350 } else if (c === ',') {
3351 token = this._create_token(TOKEN.COMMA, c);
3352 }
3353
3354 if (token) {
3355 this._input.next();
3356 }
3357 return token;
3358 };
3359
3360 Tokenizer.prototype._read_pair = function(c, d) {
3361 var token = null;
3362 if (c === '#' && d === '{') {
3363 token = this._create_token(TOKEN.START_BLOCK, c + d);
3364 }
3365
3366 if (token) {
3367 this._input.next();
3368 this._input.next();
3369 }
3370 return token;
3371 };
3372
3373 Tokenizer.prototype._read_punctuation = function() {
3374 var resulting_string = this.__patterns.punct.read();
3375
3376 if (resulting_string !== '') {
3377 if (resulting_string === '=') {
3378 return this._create_token(TOKEN.EQUALS, resulting_string);
3379 } else if (resulting_string === '?.') {
3380 return this._create_token(TOKEN.DOT, resulting_string);
3381 } else {
3382 return this._create_token(TOKEN.OPERATOR, resulting_string);
3383 }
3384 }
3385 };
3386
3387 Tokenizer.prototype._read_non_javascript = function(c) {
3388 var resulting_string = '';
3389
3390 if (c === '#') {
3391 if (this._is_first_token()) {
3392 resulting_string = this.__patterns.shebang.read();
3393
3394 if (resulting_string) {
3395 return this._create_token(TOKEN.UNKNOWN, resulting_string.trim() + '\n');
3396 }
3397 }
3398
3399 // handles extendscript #includes
3400 resulting_string = this.__patterns.include.read();
3401
3402 if (resulting_string) {
3403 return this._create_token(TOKEN.UNKNOWN, resulting_string.trim() + '\n');
3404 }
3405
3406 c = this._input.next();
3407
3408 // Spidermonkey-specific sharp variables for circular references. Considered obsolete.
3409 var sharp = '#';
3410 if (this._input.hasNext() && this._input.testChar(digit)) {
3411 do {
3412 c = this._input.next();
3413 sharp += c;
3414 } while (this._input.hasNext() && c !== '#' && c !== '=');
3415 if (c === '#') ; else if (this._input.peek() === '[' && this._input.peek(1) === ']') {
3416 sharp += '[]';
3417 this._input.next();
3418 this._input.next();
3419 } else if (this._input.peek() === '{' && this._input.peek(1) === '}') {
3420 sharp += '{}';
3421 this._input.next();
3422 this._input.next();
3423 }
3424 return this._create_token(TOKEN.WORD, sharp);
3425 }
3426
3427 this._input.back();
3428
3429 } else if (c === '<' && this._is_first_token()) {
3430 resulting_string = this.__patterns.html_comment_start.read();
3431 if (resulting_string) {
3432 while (this._input.hasNext() && !this._input.testChar(acorn.newline)) {
3433 resulting_string += this._input.next();
3434 }
3435 in_html_comment = true;
3436 return this._create_token(TOKEN.COMMENT, resulting_string);
3437 }
3438 } else if (in_html_comment && c === '-') {
3439 resulting_string = this.__patterns.html_comment_end.read();
3440 if (resulting_string) {
3441 in_html_comment = false;
3442 return this._create_token(TOKEN.COMMENT, resulting_string);
3443 }
3444 }
3445
3446 return null;
3447 };
3448
3449 Tokenizer.prototype._read_comment = function(c) {
3450 var token = null;
3451 if (c === '/') {
3452 var comment = '';
3453 if (this._input.peek(1) === '*') {
3454 // peek for comment /* ... */
3455 comment = this.__patterns.block_comment.read();
3456 var directives = directives_core.get_directives(comment);
3457 if (directives && directives.ignore === 'start') {
3458 comment += directives_core.readIgnored(this._input);
3459 }
3460 comment = comment.replace(acorn.allLineBreaks, '\n');
3461 token = this._create_token(TOKEN.BLOCK_COMMENT, comment);
3462 token.directives = directives;
3463 } else if (this._input.peek(1) === '/') {
3464 // peek for comment // ...
3465 comment = this.__patterns.comment.read();
3466 token = this._create_token(TOKEN.COMMENT, comment);
3467 }
3468 }
3469 return token;
3470 };
3471
3472 Tokenizer.prototype._read_string = function(c) {
3473 if (c === '`' || c === "'" || c === '"') {
3474 var resulting_string = this._input.next();
3475 this.has_char_escapes = false;
3476
3477 if (c === '`') {
3478 resulting_string += this._read_string_recursive('`', true, '${');
3479 } else {
3480 resulting_string += this._read_string_recursive(c);
3481 }
3482
3483 if (this.has_char_escapes && this._options.unescape_strings) {
3484 resulting_string = unescape_string(resulting_string);
3485 }
3486
3487 if (this._input.peek() === c) {
3488 resulting_string += this._input.next();
3489 }
3490
3491 resulting_string = resulting_string.replace(acorn.allLineBreaks, '\n');
3492
3493 return this._create_token(TOKEN.STRING, resulting_string);
3494 }
3495
3496 return null;
3497 };
3498
3499 Tokenizer.prototype._allow_regexp_or_xml = function(previous_token) {
3500 // regex and xml can only appear in specific locations during parsing
3501 return (previous_token.type === TOKEN.RESERVED && in_array(previous_token.text, ['return', 'case', 'throw', 'else', 'do', 'typeof', 'yield'])) ||
3502 (previous_token.type === TOKEN.END_EXPR && previous_token.text === ')' &&
3503 previous_token.opened.previous.type === TOKEN.RESERVED && in_array(previous_token.opened.previous.text, ['if', 'while', 'for'])) ||
3504 (in_array(previous_token.type, [TOKEN.COMMENT, TOKEN.START_EXPR, TOKEN.START_BLOCK, TOKEN.START,
3505 TOKEN.END_BLOCK, TOKEN.OPERATOR, TOKEN.EQUALS, TOKEN.EOF, TOKEN.SEMICOLON, TOKEN.COMMA
3506 ]));
3507 };
3508
3509 Tokenizer.prototype._read_regexp = function(c, previous_token) {
3510
3511 if (c === '/' && this._allow_regexp_or_xml(previous_token)) {
3512 // handle regexp
3513 //
3514 var resulting_string = this._input.next();
3515 var esc = false;
3516
3517 var in_char_class = false;
3518 while (this._input.hasNext() &&
3519 ((esc || in_char_class || this._input.peek() !== c) &&
3520 !this._input.testChar(acorn.newline))) {
3521 resulting_string += this._input.peek();
3522 if (!esc) {
3523 esc = this._input.peek() === '\\';
3524 if (this._input.peek() === '[') {
3525 in_char_class = true;
3526 } else if (this._input.peek() === ']') {
3527 in_char_class = false;
3528 }
3529 } else {
3530 esc = false;
3531 }
3532 this._input.next();
3533 }
3534
3535 if (this._input.peek() === c) {
3536 resulting_string += this._input.next();
3537
3538 // regexps may have modifiers /regexp/MOD , so fetch those, too
3539 // Only [gim] are valid, but if the user puts in garbage, do what we can to take it.
3540 resulting_string += this._input.read(acorn.identifier);
3541 }
3542 return this._create_token(TOKEN.STRING, resulting_string);
3543 }
3544 return null;
3545 };
3546
3547 Tokenizer.prototype._read_xml = function(c, previous_token) {
3548
3549 if (this._options.e4x && c === "<" && this._allow_regexp_or_xml(previous_token)) {
3550 var xmlStr = '';
3551 var match = this.__patterns.xml.read_match();
3552 // handle e4x xml literals
3553 //
3554 if (match) {
3555 // Trim root tag to attempt to
3556 var rootTag = match[2].replace(/^{\s+/, '{').replace(/\s+}$/, '}');
3557 var isCurlyRoot = rootTag.indexOf('{') === 0;
3558 var depth = 0;
3559 while (match) {
3560 var isEndTag = !!match[1];
3561 var tagName = match[2];
3562 var isSingletonTag = (!!match[match.length - 1]) || (tagName.slice(0, 8) === "![CDATA[");
3563 if (!isSingletonTag &&
3564 (tagName === rootTag || (isCurlyRoot && tagName.replace(/^{\s+/, '{').replace(/\s+}$/, '}')))) {
3565 if (isEndTag) {
3566 --depth;
3567 } else {
3568 ++depth;
3569 }
3570 }
3571 xmlStr += match[0];
3572 if (depth <= 0) {
3573 break;
3574 }
3575 match = this.__patterns.xml.read_match();
3576 }
3577 // if we didn't close correctly, keep unformatted.
3578 if (!match) {
3579 xmlStr += this._input.match(/[\s\S]*/g)[0];
3580 }
3581 xmlStr = xmlStr.replace(acorn.allLineBreaks, '\n');
3582 return this._create_token(TOKEN.STRING, xmlStr);
3583 }
3584 }
3585
3586 return null;
3587 };
3588
3589 function unescape_string(s) {
3590 // You think that a regex would work for this
3591 // return s.replace(/\\x([0-9a-f]{2})/gi, function(match, val) {
3592 // return String.fromCharCode(parseInt(val, 16));
3593 // })
3594 // However, dealing with '\xff', '\\xff', '\\\xff' makes this more fun.
3595 var out = '',
3596 escaped = 0;
3597
3598 var input_scan = new InputScanner(s);
3599 var matched = null;
3600
3601 while (input_scan.hasNext()) {
3602 // Keep any whitespace, non-slash characters
3603 // also keep slash pairs.
3604 matched = input_scan.match(/([\s]|[^\\]|\\\\)+/g);
3605
3606 if (matched) {
3607 out += matched[0];
3608 }
3609
3610 if (input_scan.peek() === '\\') {
3611 input_scan.next();
3612 if (input_scan.peek() === 'x') {
3613 matched = input_scan.match(/x([0-9A-Fa-f]{2})/g);
3614 } else if (input_scan.peek() === 'u') {
3615 matched = input_scan.match(/u([0-9A-Fa-f]{4})/g);
3616 } else {
3617 out += '\\';
3618 if (input_scan.hasNext()) {
3619 out += input_scan.next();
3620 }
3621 continue;
3622 }
3623
3624 // If there's some error decoding, return the original string
3625 if (!matched) {
3626 return s;
3627 }
3628
3629 escaped = parseInt(matched[1], 16);
3630
3631 if (escaped > 0x7e && escaped <= 0xff && matched[0].indexOf('x') === 0) {
3632 // we bail out on \x7f..\xff,
3633 // leaving whole string escaped,
3634 // as it's probably completely binary
3635 return s;
3636 } else if (escaped >= 0x00 && escaped < 0x20) {
3637 // leave 0x00...0x1f escaped
3638 out += '\\' + matched[0];
3639 continue;
3640 } else if (escaped === 0x22 || escaped === 0x27 || escaped === 0x5c) {
3641 // single-quote, apostrophe, backslash - escape these
3642 out += '\\' + String.fromCharCode(escaped);
3643 } else {
3644 out += String.fromCharCode(escaped);
3645 }
3646 }
3647 }
3648
3649 return out;
3650 }
3651
3652 // handle string
3653 //
3654 Tokenizer.prototype._read_string_recursive = function(delimiter, allow_unescaped_newlines, start_sub) {
3655 var current_char;
3656 var pattern;
3657 if (delimiter === '\'') {
3658 pattern = this.__patterns.single_quote;
3659 } else if (delimiter === '"') {
3660 pattern = this.__patterns.double_quote;
3661 } else if (delimiter === '`') {
3662 pattern = this.__patterns.template_text;
3663 } else if (delimiter === '}') {
3664 pattern = this.__patterns.template_expression;
3665 }
3666
3667 var resulting_string = pattern.read();
3668 var next = '';
3669 while (this._input.hasNext()) {
3670 next = this._input.next();
3671 if (next === delimiter ||
3672 (!allow_unescaped_newlines && acorn.newline.test(next))) {
3673 this._input.back();
3674 break;
3675 } else if (next === '\\' && this._input.hasNext()) {
3676 current_char = this._input.peek();
3677
3678 if (current_char === 'x' || current_char === 'u') {
3679 this.has_char_escapes = true;
3680 } else if (current_char === '\r' && this._input.peek(1) === '\n') {
3681 this._input.next();
3682 }
3683 next += this._input.next();
3684 } else if (start_sub) {
3685 if (start_sub === '${' && next === '$' && this._input.peek() === '{') {
3686 next += this._input.next();
3687 }
3688
3689 if (start_sub === next) {
3690 if (delimiter === '`') {
3691 next += this._read_string_recursive('}', allow_unescaped_newlines, '`');
3692 } else {
3693 next += this._read_string_recursive('`', allow_unescaped_newlines, '${');
3694 }
3695 if (this._input.hasNext()) {
3696 next += this._input.next();
3697 }
3698 }
3699 }
3700 next += pattern.read();
3701 resulting_string += next;
3702 }
3703
3704 return resulting_string;
3705 };
3706
3707 tokenizer$2.Tokenizer = Tokenizer;
3708 tokenizer$2.TOKEN = TOKEN;
3709 tokenizer$2.positionable_operators = positionable_operators.slice();
3710 tokenizer$2.line_starters = line_starters.slice();
3711 return tokenizer$2;
3712}
3713
3714/*jshint node:true */
3715
3716var hasRequiredBeautifier$2;
3717
3718function requireBeautifier$2 () {
3719 if (hasRequiredBeautifier$2) return beautifier$2;
3720 hasRequiredBeautifier$2 = 1;
3721
3722 var Output = requireOutput().Output;
3723 var Token = requireToken().Token;
3724 var acorn = requireAcorn();
3725 var Options = requireOptions$2().Options;
3726 var Tokenizer = requireTokenizer$1().Tokenizer;
3727 var line_starters = requireTokenizer$1().line_starters;
3728 var positionable_operators = requireTokenizer$1().positionable_operators;
3729 var TOKEN = requireTokenizer$1().TOKEN;
3730
3731
3732 function in_array(what, arr) {
3733 return arr.indexOf(what) !== -1;
3734 }
3735
3736 function ltrim(s) {
3737 return s.replace(/^\s+/g, '');
3738 }
3739
3740 function generateMapFromStrings(list) {
3741 var result = {};
3742 for (var x = 0; x < list.length; x++) {
3743 // make the mapped names underscored instead of dash
3744 result[list[x].replace(/-/g, '_')] = list[x];
3745 }
3746 return result;
3747 }
3748
3749 function reserved_word(token, word) {
3750 return token && token.type === TOKEN.RESERVED && token.text === word;
3751 }
3752
3753 function reserved_array(token, words) {
3754 return token && token.type === TOKEN.RESERVED && in_array(token.text, words);
3755 }
3756 // Unsure of what they mean, but they work. Worth cleaning up in future.
3757 var special_words = ['case', 'return', 'do', 'if', 'throw', 'else', 'await', 'break', 'continue', 'async'];
3758
3759 var validPositionValues = ['before-newline', 'after-newline', 'preserve-newline'];
3760
3761 // Generate map from array
3762 var OPERATOR_POSITION = generateMapFromStrings(validPositionValues);
3763
3764 var OPERATOR_POSITION_BEFORE_OR_PRESERVE = [OPERATOR_POSITION.before_newline, OPERATOR_POSITION.preserve_newline];
3765
3766 var MODE = {
3767 BlockStatement: 'BlockStatement', // 'BLOCK'
3768 Statement: 'Statement', // 'STATEMENT'
3769 ObjectLiteral: 'ObjectLiteral', // 'OBJECT',
3770 ArrayLiteral: 'ArrayLiteral', //'[EXPRESSION]',
3771 ForInitializer: 'ForInitializer', //'(FOR-EXPRESSION)',
3772 Conditional: 'Conditional', //'(COND-EXPRESSION)',
3773 Expression: 'Expression' //'(EXPRESSION)'
3774 };
3775
3776 function remove_redundant_indentation(output, frame) {
3777 // This implementation is effective but has some issues:
3778 // - can cause line wrap to happen too soon due to indent removal
3779 // after wrap points are calculated
3780 // These issues are minor compared to ugly indentation.
3781
3782 if (frame.multiline_frame ||
3783 frame.mode === MODE.ForInitializer ||
3784 frame.mode === MODE.Conditional) {
3785 return;
3786 }
3787
3788 // remove one indent from each line inside this section
3789 output.remove_indent(frame.start_line_index);
3790 }
3791
3792 // we could use just string.split, but
3793 // IE doesn't like returning empty strings
3794 function split_linebreaks(s) {
3795 //return s.split(/\x0d\x0a|\x0a/);
3796
3797 s = s.replace(acorn.allLineBreaks, '\n');
3798 var out = [],
3799 idx = s.indexOf("\n");
3800 while (idx !== -1) {
3801 out.push(s.substring(0, idx));
3802 s = s.substring(idx + 1);
3803 idx = s.indexOf("\n");
3804 }
3805 if (s.length) {
3806 out.push(s);
3807 }
3808 return out;
3809 }
3810
3811 function is_array(mode) {
3812 return mode === MODE.ArrayLiteral;
3813 }
3814
3815 function is_expression(mode) {
3816 return in_array(mode, [MODE.Expression, MODE.ForInitializer, MODE.Conditional]);
3817 }
3818
3819 function all_lines_start_with(lines, c) {
3820 for (var i = 0; i < lines.length; i++) {
3821 var line = lines[i].trim();
3822 if (line.charAt(0) !== c) {
3823 return false;
3824 }
3825 }
3826 return true;
3827 }
3828
3829 function each_line_matches_indent(lines, indent) {
3830 var i = 0,
3831 len = lines.length,
3832 line;
3833 for (; i < len; i++) {
3834 line = lines[i];
3835 // allow empty lines to pass through
3836 if (line && line.indexOf(indent) !== 0) {
3837 return false;
3838 }
3839 }
3840 return true;
3841 }
3842
3843
3844 function Beautifier(source_text, options) {
3845 options = options || {};
3846 this._source_text = source_text || '';
3847
3848 this._output = null;
3849 this._tokens = null;
3850 this._last_last_text = null;
3851 this._flags = null;
3852 this._previous_flags = null;
3853
3854 this._flag_store = null;
3855 this._options = new Options(options);
3856 }
3857
3858 Beautifier.prototype.create_flags = function(flags_base, mode) {
3859 var next_indent_level = 0;
3860 if (flags_base) {
3861 next_indent_level = flags_base.indentation_level;
3862 if (!this._output.just_added_newline() &&
3863 flags_base.line_indent_level > next_indent_level) {
3864 next_indent_level = flags_base.line_indent_level;
3865 }
3866 }
3867
3868 var next_flags = {
3869 mode: mode,
3870 parent: flags_base,
3871 last_token: flags_base ? flags_base.last_token : new Token(TOKEN.START_BLOCK, ''), // last token text
3872 last_word: flags_base ? flags_base.last_word : '', // last TOKEN.WORD passed
3873 declaration_statement: false,
3874 declaration_assignment: false,
3875 multiline_frame: false,
3876 inline_frame: false,
3877 if_block: false,
3878 else_block: false,
3879 class_start_block: false, // class A { INSIDE HERE } or class B extends C { INSIDE HERE }
3880 do_block: false,
3881 do_while: false,
3882 import_block: false,
3883 in_case_statement: false, // switch(..){ INSIDE HERE }
3884 in_case: false, // we're on the exact line with "case 0:"
3885 case_body: false, // the indented case-action block
3886 case_block: false, // the indented case-action block is wrapped with {}
3887 indentation_level: next_indent_level,
3888 alignment: 0,
3889 line_indent_level: flags_base ? flags_base.line_indent_level : next_indent_level,
3890 start_line_index: this._output.get_line_number(),
3891 ternary_depth: 0
3892 };
3893 return next_flags;
3894 };
3895
3896 Beautifier.prototype._reset = function(source_text) {
3897 var baseIndentString = source_text.match(/^[\t ]*/)[0];
3898
3899 this._last_last_text = ''; // pre-last token text
3900 this._output = new Output(this._options, baseIndentString);
3901
3902 // If testing the ignore directive, start with output disable set to true
3903 this._output.raw = this._options.test_output_raw;
3904
3905
3906 // Stack of parsing/formatting states, including MODE.
3907 // We tokenize, parse, and output in an almost purely a forward-only stream of token input
3908 // and formatted output. This makes the beautifier less accurate than full parsers
3909 // but also far more tolerant of syntax errors.
3910 //
3911 // For example, the default mode is MODE.BlockStatement. If we see a '{' we push a new frame of type
3912 // MODE.BlockStatement on the the stack, even though it could be object literal. If we later
3913 // encounter a ":", we'll switch to to MODE.ObjectLiteral. If we then see a ";",
3914 // most full parsers would die, but the beautifier gracefully falls back to
3915 // MODE.BlockStatement and continues on.
3916 this._flag_store = [];
3917 this.set_mode(MODE.BlockStatement);
3918 var tokenizer = new Tokenizer(source_text, this._options);
3919 this._tokens = tokenizer.tokenize();
3920 return source_text;
3921 };
3922
3923 Beautifier.prototype.beautify = function() {
3924 // if disabled, return the input unchanged.
3925 if (this._options.disabled) {
3926 return this._source_text;
3927 }
3928
3929 var sweet_code;
3930 var source_text = this._reset(this._source_text);
3931
3932 var eol = this._options.eol;
3933 if (this._options.eol === 'auto') {
3934 eol = '\n';
3935 if (source_text && acorn.lineBreak.test(source_text || '')) {
3936 eol = source_text.match(acorn.lineBreak)[0];
3937 }
3938 }
3939
3940 var current_token = this._tokens.next();
3941 while (current_token) {
3942 this.handle_token(current_token);
3943
3944 this._last_last_text = this._flags.last_token.text;
3945 this._flags.last_token = current_token;
3946
3947 current_token = this._tokens.next();
3948 }
3949
3950 sweet_code = this._output.get_code(eol);
3951
3952 return sweet_code;
3953 };
3954
3955 Beautifier.prototype.handle_token = function(current_token, preserve_statement_flags) {
3956 if (current_token.type === TOKEN.START_EXPR) {
3957 this.handle_start_expr(current_token);
3958 } else if (current_token.type === TOKEN.END_EXPR) {
3959 this.handle_end_expr(current_token);
3960 } else if (current_token.type === TOKEN.START_BLOCK) {
3961 this.handle_start_block(current_token);
3962 } else if (current_token.type === TOKEN.END_BLOCK) {
3963 this.handle_end_block(current_token);
3964 } else if (current_token.type === TOKEN.WORD) {
3965 this.handle_word(current_token);
3966 } else if (current_token.type === TOKEN.RESERVED) {
3967 this.handle_word(current_token);
3968 } else if (current_token.type === TOKEN.SEMICOLON) {
3969 this.handle_semicolon(current_token);
3970 } else if (current_token.type === TOKEN.STRING) {
3971 this.handle_string(current_token);
3972 } else if (current_token.type === TOKEN.EQUALS) {
3973 this.handle_equals(current_token);
3974 } else if (current_token.type === TOKEN.OPERATOR) {
3975 this.handle_operator(current_token);
3976 } else if (current_token.type === TOKEN.COMMA) {
3977 this.handle_comma(current_token);
3978 } else if (current_token.type === TOKEN.BLOCK_COMMENT) {
3979 this.handle_block_comment(current_token, preserve_statement_flags);
3980 } else if (current_token.type === TOKEN.COMMENT) {
3981 this.handle_comment(current_token, preserve_statement_flags);
3982 } else if (current_token.type === TOKEN.DOT) {
3983 this.handle_dot(current_token);
3984 } else if (current_token.type === TOKEN.EOF) {
3985 this.handle_eof(current_token);
3986 } else if (current_token.type === TOKEN.UNKNOWN) {
3987 this.handle_unknown(current_token, preserve_statement_flags);
3988 } else {
3989 this.handle_unknown(current_token, preserve_statement_flags);
3990 }
3991 };
3992
3993 Beautifier.prototype.handle_whitespace_and_comments = function(current_token, preserve_statement_flags) {
3994 var newlines = current_token.newlines;
3995 var keep_whitespace = this._options.keep_array_indentation && is_array(this._flags.mode);
3996
3997 if (current_token.comments_before) {
3998 var comment_token = current_token.comments_before.next();
3999 while (comment_token) {
4000 // The cleanest handling of inline comments is to treat them as though they aren't there.
4001 // Just continue formatting and the behavior should be logical.
4002 // Also ignore unknown tokens. Again, this should result in better behavior.
4003 this.handle_whitespace_and_comments(comment_token, preserve_statement_flags);
4004 this.handle_token(comment_token, preserve_statement_flags);
4005 comment_token = current_token.comments_before.next();
4006 }
4007 }
4008
4009 if (keep_whitespace) {
4010 for (var i = 0; i < newlines; i += 1) {
4011 this.print_newline(i > 0, preserve_statement_flags);
4012 }
4013 } else {
4014 if (this._options.max_preserve_newlines && newlines > this._options.max_preserve_newlines) {
4015 newlines = this._options.max_preserve_newlines;
4016 }
4017
4018 if (this._options.preserve_newlines) {
4019 if (newlines > 1) {
4020 this.print_newline(false, preserve_statement_flags);
4021 for (var j = 1; j < newlines; j += 1) {
4022 this.print_newline(true, preserve_statement_flags);
4023 }
4024 }
4025 }
4026 }
4027
4028 };
4029
4030 var newline_restricted_tokens = ['async', 'break', 'continue', 'return', 'throw', 'yield'];
4031
4032 Beautifier.prototype.allow_wrap_or_preserved_newline = function(current_token, force_linewrap) {
4033 force_linewrap = (force_linewrap === undefined) ? false : force_linewrap;
4034
4035 // Never wrap the first token on a line
4036 if (this._output.just_added_newline()) {
4037 return;
4038 }
4039
4040 var shouldPreserveOrForce = (this._options.preserve_newlines && current_token.newlines) || force_linewrap;
4041 var operatorLogicApplies = in_array(this._flags.last_token.text, positionable_operators) ||
4042 in_array(current_token.text, positionable_operators);
4043
4044 if (operatorLogicApplies) {
4045 var shouldPrintOperatorNewline = (
4046 in_array(this._flags.last_token.text, positionable_operators) &&
4047 in_array(this._options.operator_position, OPERATOR_POSITION_BEFORE_OR_PRESERVE)
4048 ) ||
4049 in_array(current_token.text, positionable_operators);
4050 shouldPreserveOrForce = shouldPreserveOrForce && shouldPrintOperatorNewline;
4051 }
4052
4053 if (shouldPreserveOrForce) {
4054 this.print_newline(false, true);
4055 } else if (this._options.wrap_line_length) {
4056 if (reserved_array(this._flags.last_token, newline_restricted_tokens)) {
4057 // These tokens should never have a newline inserted
4058 // between them and the following expression.
4059 return;
4060 }
4061 this._output.set_wrap_point();
4062 }
4063 };
4064
4065 Beautifier.prototype.print_newline = function(force_newline, preserve_statement_flags) {
4066 if (!preserve_statement_flags) {
4067 if (this._flags.last_token.text !== ';' && this._flags.last_token.text !== ',' && this._flags.last_token.text !== '=' && (this._flags.last_token.type !== TOKEN.OPERATOR || this._flags.last_token.text === '--' || this._flags.last_token.text === '++')) {
4068 var next_token = this._tokens.peek();
4069 while (this._flags.mode === MODE.Statement &&
4070 !(this._flags.if_block && reserved_word(next_token, 'else')) &&
4071 !this._flags.do_block) {
4072 this.restore_mode();
4073 }
4074 }
4075 }
4076
4077 if (this._output.add_new_line(force_newline)) {
4078 this._flags.multiline_frame = true;
4079 }
4080 };
4081
4082 Beautifier.prototype.print_token_line_indentation = function(current_token) {
4083 if (this._output.just_added_newline()) {
4084 if (this._options.keep_array_indentation &&
4085 current_token.newlines &&
4086 (current_token.text === '[' || is_array(this._flags.mode))) {
4087 this._output.current_line.set_indent(-1);
4088 this._output.current_line.push(current_token.whitespace_before);
4089 this._output.space_before_token = false;
4090 } else if (this._output.set_indent(this._flags.indentation_level, this._flags.alignment)) {
4091 this._flags.line_indent_level = this._flags.indentation_level;
4092 }
4093 }
4094 };
4095
4096 Beautifier.prototype.print_token = function(current_token) {
4097 if (this._output.raw) {
4098 this._output.add_raw_token(current_token);
4099 return;
4100 }
4101
4102 if (this._options.comma_first && current_token.previous && current_token.previous.type === TOKEN.COMMA &&
4103 this._output.just_added_newline()) {
4104 if (this._output.previous_line.last() === ',') {
4105 var popped = this._output.previous_line.pop();
4106 // if the comma was already at the start of the line,
4107 // pull back onto that line and reprint the indentation
4108 if (this._output.previous_line.is_empty()) {
4109 this._output.previous_line.push(popped);
4110 this._output.trim(true);
4111 this._output.current_line.pop();
4112 this._output.trim();
4113 }
4114
4115 // add the comma in front of the next token
4116 this.print_token_line_indentation(current_token);
4117 this._output.add_token(',');
4118 this._output.space_before_token = true;
4119 }
4120 }
4121
4122 this.print_token_line_indentation(current_token);
4123 this._output.non_breaking_space = true;
4124 this._output.add_token(current_token.text);
4125 if (this._output.previous_token_wrapped) {
4126 this._flags.multiline_frame = true;
4127 }
4128 };
4129
4130 Beautifier.prototype.indent = function() {
4131 this._flags.indentation_level += 1;
4132 this._output.set_indent(this._flags.indentation_level, this._flags.alignment);
4133 };
4134
4135 Beautifier.prototype.deindent = function() {
4136 if (this._flags.indentation_level > 0 &&
4137 ((!this._flags.parent) || this._flags.indentation_level > this._flags.parent.indentation_level)) {
4138 this._flags.indentation_level -= 1;
4139 this._output.set_indent(this._flags.indentation_level, this._flags.alignment);
4140 }
4141 };
4142
4143 Beautifier.prototype.set_mode = function(mode) {
4144 if (this._flags) {
4145 this._flag_store.push(this._flags);
4146 this._previous_flags = this._flags;
4147 } else {
4148 this._previous_flags = this.create_flags(null, mode);
4149 }
4150
4151 this._flags = this.create_flags(this._previous_flags, mode);
4152 this._output.set_indent(this._flags.indentation_level, this._flags.alignment);
4153 };
4154
4155
4156 Beautifier.prototype.restore_mode = function() {
4157 if (this._flag_store.length > 0) {
4158 this._previous_flags = this._flags;
4159 this._flags = this._flag_store.pop();
4160 if (this._previous_flags.mode === MODE.Statement) {
4161 remove_redundant_indentation(this._output, this._previous_flags);
4162 }
4163 this._output.set_indent(this._flags.indentation_level, this._flags.alignment);
4164 }
4165 };
4166
4167 Beautifier.prototype.start_of_object_property = function() {
4168 return this._flags.parent.mode === MODE.ObjectLiteral && this._flags.mode === MODE.Statement && (
4169 (this._flags.last_token.text === ':' && this._flags.ternary_depth === 0) || (reserved_array(this._flags.last_token, ['get', 'set'])));
4170 };
4171
4172 Beautifier.prototype.start_of_statement = function(current_token) {
4173 var start = false;
4174 start = start || reserved_array(this._flags.last_token, ['var', 'let', 'const']) && current_token.type === TOKEN.WORD;
4175 start = start || reserved_word(this._flags.last_token, 'do');
4176 start = start || (!(this._flags.parent.mode === MODE.ObjectLiteral && this._flags.mode === MODE.Statement)) && reserved_array(this._flags.last_token, newline_restricted_tokens) && !current_token.newlines;
4177 start = start || reserved_word(this._flags.last_token, 'else') &&
4178 !(reserved_word(current_token, 'if') && !current_token.comments_before);
4179 start = start || (this._flags.last_token.type === TOKEN.END_EXPR && (this._previous_flags.mode === MODE.ForInitializer || this._previous_flags.mode === MODE.Conditional));
4180 start = start || (this._flags.last_token.type === TOKEN.WORD && this._flags.mode === MODE.BlockStatement &&
4181 !this._flags.in_case &&
4182 !(current_token.text === '--' || current_token.text === '++') &&
4183 this._last_last_text !== 'function' &&
4184 current_token.type !== TOKEN.WORD && current_token.type !== TOKEN.RESERVED);
4185 start = start || (this._flags.mode === MODE.ObjectLiteral && (
4186 (this._flags.last_token.text === ':' && this._flags.ternary_depth === 0) || reserved_array(this._flags.last_token, ['get', 'set'])));
4187
4188 if (start) {
4189 this.set_mode(MODE.Statement);
4190 this.indent();
4191
4192 this.handle_whitespace_and_comments(current_token, true);
4193
4194 // Issue #276:
4195 // If starting a new statement with [if, for, while, do], push to a new line.
4196 // if (a) if (b) if(c) d(); else e(); else f();
4197 if (!this.start_of_object_property()) {
4198 this.allow_wrap_or_preserved_newline(current_token,
4199 reserved_array(current_token, ['do', 'for', 'if', 'while']));
4200 }
4201 return true;
4202 }
4203 return false;
4204 };
4205
4206 Beautifier.prototype.handle_start_expr = function(current_token) {
4207 // The conditional starts the statement if appropriate.
4208 if (!this.start_of_statement(current_token)) {
4209 this.handle_whitespace_and_comments(current_token);
4210 }
4211
4212 var next_mode = MODE.Expression;
4213 if (current_token.text === '[') {
4214
4215 if (this._flags.last_token.type === TOKEN.WORD || this._flags.last_token.text === ')') {
4216 // this is array index specifier, break immediately
4217 // a[x], fn()[x]
4218 if (reserved_array(this._flags.last_token, line_starters)) {
4219 this._output.space_before_token = true;
4220 }
4221 this.print_token(current_token);
4222 this.set_mode(next_mode);
4223 this.indent();
4224 if (this._options.space_in_paren) {
4225 this._output.space_before_token = true;
4226 }
4227 return;
4228 }
4229
4230 next_mode = MODE.ArrayLiteral;
4231 if (is_array(this._flags.mode)) {
4232 if (this._flags.last_token.text === '[' ||
4233 (this._flags.last_token.text === ',' && (this._last_last_text === ']' || this._last_last_text === '}'))) {
4234 // ], [ goes to new line
4235 // }, [ goes to new line
4236 if (!this._options.keep_array_indentation) {
4237 this.print_newline();
4238 }
4239 }
4240 }
4241
4242 if (!in_array(this._flags.last_token.type, [TOKEN.START_EXPR, TOKEN.END_EXPR, TOKEN.WORD, TOKEN.OPERATOR, TOKEN.DOT])) {
4243 this._output.space_before_token = true;
4244 }
4245 } else {
4246 if (this._flags.last_token.type === TOKEN.RESERVED) {
4247 if (this._flags.last_token.text === 'for') {
4248 this._output.space_before_token = this._options.space_before_conditional;
4249 next_mode = MODE.ForInitializer;
4250 } else if (in_array(this._flags.last_token.text, ['if', 'while', 'switch'])) {
4251 this._output.space_before_token = this._options.space_before_conditional;
4252 next_mode = MODE.Conditional;
4253 } else if (in_array(this._flags.last_word, ['await', 'async'])) {
4254 // Should be a space between await and an IIFE, or async and an arrow function
4255 this._output.space_before_token = true;
4256 } else if (this._flags.last_token.text === 'import' && current_token.whitespace_before === '') {
4257 this._output.space_before_token = false;
4258 } else if (in_array(this._flags.last_token.text, line_starters) || this._flags.last_token.text === 'catch') {
4259 this._output.space_before_token = true;
4260 }
4261 } else if (this._flags.last_token.type === TOKEN.EQUALS || this._flags.last_token.type === TOKEN.OPERATOR) {
4262 // Support of this kind of newline preservation.
4263 // a = (b &&
4264 // (c || d));
4265 if (!this.start_of_object_property()) {
4266 this.allow_wrap_or_preserved_newline(current_token);
4267 }
4268 } else if (this._flags.last_token.type === TOKEN.WORD) {
4269 this._output.space_before_token = false;
4270
4271 // function name() vs function name ()
4272 // function* name() vs function* name ()
4273 // async name() vs async name ()
4274 // In ES6, you can also define the method properties of an object
4275 // var obj = {a: function() {}}
4276 // It can be abbreviated
4277 // var obj = {a() {}}
4278 // var obj = { a() {}} vs var obj = { a () {}}
4279 // var obj = { * a() {}} vs var obj = { * a () {}}
4280 var peek_back_two = this._tokens.peek(-3);
4281 if (this._options.space_after_named_function && peek_back_two) {
4282 // peek starts at next character so -1 is current token
4283 var peek_back_three = this._tokens.peek(-4);
4284 if (reserved_array(peek_back_two, ['async', 'function']) ||
4285 (peek_back_two.text === '*' && reserved_array(peek_back_three, ['async', 'function']))) {
4286 this._output.space_before_token = true;
4287 } else if (this._flags.mode === MODE.ObjectLiteral) {
4288 if ((peek_back_two.text === '{' || peek_back_two.text === ',') ||
4289 (peek_back_two.text === '*' && (peek_back_three.text === '{' || peek_back_three.text === ','))) {
4290 this._output.space_before_token = true;
4291 }
4292 } else if (this._flags.parent && this._flags.parent.class_start_block) {
4293 this._output.space_before_token = true;
4294 }
4295 }
4296 } else {
4297 // Support preserving wrapped arrow function expressions
4298 // a.b('c',
4299 // () => d.e
4300 // )
4301 this.allow_wrap_or_preserved_newline(current_token);
4302 }
4303
4304 // function() vs function ()
4305 // yield*() vs yield* ()
4306 // function*() vs function* ()
4307 if ((this._flags.last_token.type === TOKEN.RESERVED && (this._flags.last_word === 'function' || this._flags.last_word === 'typeof')) ||
4308 (this._flags.last_token.text === '*' &&
4309 (in_array(this._last_last_text, ['function', 'yield']) ||
4310 (this._flags.mode === MODE.ObjectLiteral && in_array(this._last_last_text, ['{', ',']))))) {
4311 this._output.space_before_token = this._options.space_after_anon_function;
4312 }
4313 }
4314
4315 if (this._flags.last_token.text === ';' || this._flags.last_token.type === TOKEN.START_BLOCK) {
4316 this.print_newline();
4317 } else if (this._flags.last_token.type === TOKEN.END_EXPR || this._flags.last_token.type === TOKEN.START_EXPR || this._flags.last_token.type === TOKEN.END_BLOCK || this._flags.last_token.text === '.' || this._flags.last_token.type === TOKEN.COMMA) {
4318 // do nothing on (( and )( and ][ and ]( and .(
4319 // TODO: Consider whether forcing this is required. Review failing tests when removed.
4320 this.allow_wrap_or_preserved_newline(current_token, current_token.newlines);
4321 }
4322
4323 this.print_token(current_token);
4324 this.set_mode(next_mode);
4325 if (this._options.space_in_paren) {
4326 this._output.space_before_token = true;
4327 }
4328
4329 // In all cases, if we newline while inside an expression it should be indented.
4330 this.indent();
4331 };
4332
4333 Beautifier.prototype.handle_end_expr = function(current_token) {
4334 // statements inside expressions are not valid syntax, but...
4335 // statements must all be closed when their container closes
4336 while (this._flags.mode === MODE.Statement) {
4337 this.restore_mode();
4338 }
4339
4340 this.handle_whitespace_and_comments(current_token);
4341
4342 if (this._flags.multiline_frame) {
4343 this.allow_wrap_or_preserved_newline(current_token,
4344 current_token.text === ']' && is_array(this._flags.mode) && !this._options.keep_array_indentation);
4345 }
4346
4347 if (this._options.space_in_paren) {
4348 if (this._flags.last_token.type === TOKEN.START_EXPR && !this._options.space_in_empty_paren) {
4349 // () [] no inner space in empty parens like these, ever, ref #320
4350 this._output.trim();
4351 this._output.space_before_token = false;
4352 } else {
4353 this._output.space_before_token = true;
4354 }
4355 }
4356 this.deindent();
4357 this.print_token(current_token);
4358 this.restore_mode();
4359
4360 remove_redundant_indentation(this._output, this._previous_flags);
4361
4362 // do {} while () // no statement required after
4363 if (this._flags.do_while && this._previous_flags.mode === MODE.Conditional) {
4364 this._previous_flags.mode = MODE.Expression;
4365 this._flags.do_block = false;
4366 this._flags.do_while = false;
4367
4368 }
4369 };
4370
4371 Beautifier.prototype.handle_start_block = function(current_token) {
4372 this.handle_whitespace_and_comments(current_token);
4373
4374 // Check if this is should be treated as a ObjectLiteral
4375 var next_token = this._tokens.peek();
4376 var second_token = this._tokens.peek(1);
4377 if (this._flags.last_word === 'switch' && this._flags.last_token.type === TOKEN.END_EXPR) {
4378 this.set_mode(MODE.BlockStatement);
4379 this._flags.in_case_statement = true;
4380 } else if (this._flags.case_body) {
4381 this.set_mode(MODE.BlockStatement);
4382 } else if (second_token && (
4383 (in_array(second_token.text, [':', ',']) && in_array(next_token.type, [TOKEN.STRING, TOKEN.WORD, TOKEN.RESERVED])) ||
4384 (in_array(next_token.text, ['get', 'set', '...']) && in_array(second_token.type, [TOKEN.WORD, TOKEN.RESERVED]))
4385 )) {
4386 // We don't support TypeScript,but we didn't break it for a very long time.
4387 // We'll try to keep not breaking it.
4388 if (in_array(this._last_last_text, ['class', 'interface']) && !in_array(second_token.text, [':', ','])) {
4389 this.set_mode(MODE.BlockStatement);
4390 } else {
4391 this.set_mode(MODE.ObjectLiteral);
4392 }
4393 } else if (this._flags.last_token.type === TOKEN.OPERATOR && this._flags.last_token.text === '=>') {
4394 // arrow function: (param1, paramN) => { statements }
4395 this.set_mode(MODE.BlockStatement);
4396 } else if (in_array(this._flags.last_token.type, [TOKEN.EQUALS, TOKEN.START_EXPR, TOKEN.COMMA, TOKEN.OPERATOR]) ||
4397 reserved_array(this._flags.last_token, ['return', 'throw', 'import', 'default'])
4398 ) {
4399 // Detecting shorthand function syntax is difficult by scanning forward,
4400 // so check the surrounding context.
4401 // If the block is being returned, imported, export default, passed as arg,
4402 // assigned with = or assigned in a nested object, treat as an ObjectLiteral.
4403 this.set_mode(MODE.ObjectLiteral);
4404 } else {
4405 this.set_mode(MODE.BlockStatement);
4406 }
4407
4408 if (this._flags.last_token) {
4409 if (reserved_array(this._flags.last_token.previous, ['class', 'extends'])) {
4410 this._flags.class_start_block = true;
4411 }
4412 }
4413
4414 var empty_braces = !next_token.comments_before && next_token.text === '}';
4415 var empty_anonymous_function = empty_braces && this._flags.last_word === 'function' &&
4416 this._flags.last_token.type === TOKEN.END_EXPR;
4417
4418 if (this._options.brace_preserve_inline) // check for inline, set inline_frame if so
4419 {
4420 // search forward for a newline wanted inside this block
4421 var index = 0;
4422 var check_token = null;
4423 this._flags.inline_frame = true;
4424 do {
4425 index += 1;
4426 check_token = this._tokens.peek(index - 1);
4427 if (check_token.newlines) {
4428 this._flags.inline_frame = false;
4429 break;
4430 }
4431 } while (check_token.type !== TOKEN.EOF &&
4432 !(check_token.type === TOKEN.END_BLOCK && check_token.opened === current_token));
4433 }
4434
4435 if ((this._options.brace_style === "expand" ||
4436 (this._options.brace_style === "none" && current_token.newlines)) &&
4437 !this._flags.inline_frame) {
4438 if (this._flags.last_token.type !== TOKEN.OPERATOR &&
4439 (empty_anonymous_function ||
4440 this._flags.last_token.type === TOKEN.EQUALS ||
4441 (reserved_array(this._flags.last_token, special_words) && this._flags.last_token.text !== 'else'))) {
4442 this._output.space_before_token = true;
4443 } else {
4444 this.print_newline(false, true);
4445 }
4446 } else { // collapse || inline_frame
4447 if (is_array(this._previous_flags.mode) && (this._flags.last_token.type === TOKEN.START_EXPR || this._flags.last_token.type === TOKEN.COMMA)) {
4448 if (this._flags.last_token.type === TOKEN.COMMA || this._options.space_in_paren) {
4449 this._output.space_before_token = true;
4450 }
4451
4452 if (this._flags.last_token.type === TOKEN.COMMA || (this._flags.last_token.type === TOKEN.START_EXPR && this._flags.inline_frame)) {
4453 this.allow_wrap_or_preserved_newline(current_token);
4454 this._previous_flags.multiline_frame = this._previous_flags.multiline_frame || this._flags.multiline_frame;
4455 this._flags.multiline_frame = false;
4456 }
4457 }
4458 if (this._flags.last_token.type !== TOKEN.OPERATOR && this._flags.last_token.type !== TOKEN.START_EXPR) {
4459 if (in_array(this._flags.last_token.type, [TOKEN.START_BLOCK, TOKEN.SEMICOLON]) && !this._flags.inline_frame) {
4460 this.print_newline();
4461 } else {
4462 this._output.space_before_token = true;
4463 }
4464 }
4465 }
4466 this.print_token(current_token);
4467 this.indent();
4468
4469 // Except for specific cases, open braces are followed by a new line.
4470 if (!empty_braces && !(this._options.brace_preserve_inline && this._flags.inline_frame)) {
4471 this.print_newline();
4472 }
4473 };
4474
4475 Beautifier.prototype.handle_end_block = function(current_token) {
4476 // statements must all be closed when their container closes
4477 this.handle_whitespace_and_comments(current_token);
4478
4479 while (this._flags.mode === MODE.Statement) {
4480 this.restore_mode();
4481 }
4482
4483 var empty_braces = this._flags.last_token.type === TOKEN.START_BLOCK;
4484
4485 if (this._flags.inline_frame && !empty_braces) { // try inline_frame (only set if this._options.braces-preserve-inline) first
4486 this._output.space_before_token = true;
4487 } else if (this._options.brace_style === "expand") {
4488 if (!empty_braces) {
4489 this.print_newline();
4490 }
4491 } else {
4492 // skip {}
4493 if (!empty_braces) {
4494 if (is_array(this._flags.mode) && this._options.keep_array_indentation) {
4495 // we REALLY need a newline here, but newliner would skip that
4496 this._options.keep_array_indentation = false;
4497 this.print_newline();
4498 this._options.keep_array_indentation = true;
4499
4500 } else {
4501 this.print_newline();
4502 }
4503 }
4504 }
4505 this.restore_mode();
4506 this.print_token(current_token);
4507 };
4508
4509 Beautifier.prototype.handle_word = function(current_token) {
4510 if (current_token.type === TOKEN.RESERVED) {
4511 if (in_array(current_token.text, ['set', 'get']) && this._flags.mode !== MODE.ObjectLiteral) {
4512 current_token.type = TOKEN.WORD;
4513 } else if (current_token.text === 'import' && in_array(this._tokens.peek().text, ['(', '.'])) {
4514 current_token.type = TOKEN.WORD;
4515 } else if (in_array(current_token.text, ['as', 'from']) && !this._flags.import_block) {
4516 current_token.type = TOKEN.WORD;
4517 } else if (this._flags.mode === MODE.ObjectLiteral) {
4518 var next_token = this._tokens.peek();
4519 if (next_token.text === ':') {
4520 current_token.type = TOKEN.WORD;
4521 }
4522 }
4523 }
4524
4525 if (this.start_of_statement(current_token)) {
4526 // The conditional starts the statement if appropriate.
4527 if (reserved_array(this._flags.last_token, ['var', 'let', 'const']) && current_token.type === TOKEN.WORD) {
4528 this._flags.declaration_statement = true;
4529 }
4530 } else if (current_token.newlines && !is_expression(this._flags.mode) &&
4531 (this._flags.last_token.type !== TOKEN.OPERATOR || (this._flags.last_token.text === '--' || this._flags.last_token.text === '++')) &&
4532 this._flags.last_token.type !== TOKEN.EQUALS &&
4533 (this._options.preserve_newlines || !reserved_array(this._flags.last_token, ['var', 'let', 'const', 'set', 'get']))) {
4534 this.handle_whitespace_and_comments(current_token);
4535 this.print_newline();
4536 } else {
4537 this.handle_whitespace_and_comments(current_token);
4538 }
4539
4540 if (this._flags.do_block && !this._flags.do_while) {
4541 if (reserved_word(current_token, 'while')) {
4542 // do {} ## while ()
4543 this._output.space_before_token = true;
4544 this.print_token(current_token);
4545 this._output.space_before_token = true;
4546 this._flags.do_while = true;
4547 return;
4548 } else {
4549 // do {} should always have while as the next word.
4550 // if we don't see the expected while, recover
4551 this.print_newline();
4552 this._flags.do_block = false;
4553 }
4554 }
4555
4556 // if may be followed by else, or not
4557 // Bare/inline ifs are tricky
4558 // Need to unwind the modes correctly: if (a) if (b) c(); else d(); else e();
4559 if (this._flags.if_block) {
4560 if (!this._flags.else_block && reserved_word(current_token, 'else')) {
4561 this._flags.else_block = true;
4562 } else {
4563 while (this._flags.mode === MODE.Statement) {
4564 this.restore_mode();
4565 }
4566 this._flags.if_block = false;
4567 this._flags.else_block = false;
4568 }
4569 }
4570
4571 if (this._flags.in_case_statement && reserved_array(current_token, ['case', 'default'])) {
4572 this.print_newline();
4573 if (!this._flags.case_block && (this._flags.case_body || this._options.jslint_happy)) {
4574 // switch cases following one another
4575 this.deindent();
4576 }
4577 this._flags.case_body = false;
4578
4579 this.print_token(current_token);
4580 this._flags.in_case = true;
4581 return;
4582 }
4583
4584 if (this._flags.last_token.type === TOKEN.COMMA || this._flags.last_token.type === TOKEN.START_EXPR || this._flags.last_token.type === TOKEN.EQUALS || this._flags.last_token.type === TOKEN.OPERATOR) {
4585 if (!this.start_of_object_property()) {
4586 this.allow_wrap_or_preserved_newline(current_token);
4587 }
4588 }
4589
4590 if (reserved_word(current_token, 'function')) {
4591 if (in_array(this._flags.last_token.text, ['}', ';']) ||
4592 (this._output.just_added_newline() && !(in_array(this._flags.last_token.text, ['(', '[', '{', ':', '=', ',']) || this._flags.last_token.type === TOKEN.OPERATOR))) {
4593 // make sure there is a nice clean space of at least one blank line
4594 // before a new function definition
4595 if (!this._output.just_added_blankline() && !current_token.comments_before) {
4596 this.print_newline();
4597 this.print_newline(true);
4598 }
4599 }
4600 if (this._flags.last_token.type === TOKEN.RESERVED || this._flags.last_token.type === TOKEN.WORD) {
4601 if (reserved_array(this._flags.last_token, ['get', 'set', 'new', 'export']) ||
4602 reserved_array(this._flags.last_token, newline_restricted_tokens)) {
4603 this._output.space_before_token = true;
4604 } else if (reserved_word(this._flags.last_token, 'default') && this._last_last_text === 'export') {
4605 this._output.space_before_token = true;
4606 } else if (this._flags.last_token.text === 'declare') {
4607 // accomodates Typescript declare function formatting
4608 this._output.space_before_token = true;
4609 } else {
4610 this.print_newline();
4611 }
4612 } else if (this._flags.last_token.type === TOKEN.OPERATOR || this._flags.last_token.text === '=') {
4613 // foo = function
4614 this._output.space_before_token = true;
4615 } else if (!this._flags.multiline_frame && (is_expression(this._flags.mode) || is_array(this._flags.mode))) ; else {
4616 this.print_newline();
4617 }
4618
4619 this.print_token(current_token);
4620 this._flags.last_word = current_token.text;
4621 return;
4622 }
4623
4624 var prefix = 'NONE';
4625
4626 if (this._flags.last_token.type === TOKEN.END_BLOCK) {
4627
4628 if (this._previous_flags.inline_frame) {
4629 prefix = 'SPACE';
4630 } else if (!reserved_array(current_token, ['else', 'catch', 'finally', 'from'])) {
4631 prefix = 'NEWLINE';
4632 } else {
4633 if (this._options.brace_style === "expand" ||
4634 this._options.brace_style === "end-expand" ||
4635 (this._options.brace_style === "none" && current_token.newlines)) {
4636 prefix = 'NEWLINE';
4637 } else {
4638 prefix = 'SPACE';
4639 this._output.space_before_token = true;
4640 }
4641 }
4642 } else if (this._flags.last_token.type === TOKEN.SEMICOLON && this._flags.mode === MODE.BlockStatement) {
4643 // TODO: Should this be for STATEMENT as well?
4644 prefix = 'NEWLINE';
4645 } else if (this._flags.last_token.type === TOKEN.SEMICOLON && is_expression(this._flags.mode)) {
4646 prefix = 'SPACE';
4647 } else if (this._flags.last_token.type === TOKEN.STRING) {
4648 prefix = 'NEWLINE';
4649 } else if (this._flags.last_token.type === TOKEN.RESERVED || this._flags.last_token.type === TOKEN.WORD ||
4650 (this._flags.last_token.text === '*' &&
4651 (in_array(this._last_last_text, ['function', 'yield']) ||
4652 (this._flags.mode === MODE.ObjectLiteral && in_array(this._last_last_text, ['{', ',']))))) {
4653 prefix = 'SPACE';
4654 } else if (this._flags.last_token.type === TOKEN.START_BLOCK) {
4655 if (this._flags.inline_frame) {
4656 prefix = 'SPACE';
4657 } else {
4658 prefix = 'NEWLINE';
4659 }
4660 } else if (this._flags.last_token.type === TOKEN.END_EXPR) {
4661 this._output.space_before_token = true;
4662 prefix = 'NEWLINE';
4663 }
4664
4665 if (reserved_array(current_token, line_starters) && this._flags.last_token.text !== ')') {
4666 if (this._flags.inline_frame || this._flags.last_token.text === 'else' || this._flags.last_token.text === 'export') {
4667 prefix = 'SPACE';
4668 } else {
4669 prefix = 'NEWLINE';
4670 }
4671
4672 }
4673
4674 if (reserved_array(current_token, ['else', 'catch', 'finally'])) {
4675 if ((!(this._flags.last_token.type === TOKEN.END_BLOCK && this._previous_flags.mode === MODE.BlockStatement) ||
4676 this._options.brace_style === "expand" ||
4677 this._options.brace_style === "end-expand" ||
4678 (this._options.brace_style === "none" && current_token.newlines)) &&
4679 !this._flags.inline_frame) {
4680 this.print_newline();
4681 } else {
4682 this._output.trim(true);
4683 var line = this._output.current_line;
4684 // If we trimmed and there's something other than a close block before us
4685 // put a newline back in. Handles '} // comment' scenario.
4686 if (line.last() !== '}') {
4687 this.print_newline();
4688 }
4689 this._output.space_before_token = true;
4690 }
4691 } else if (prefix === 'NEWLINE') {
4692 if (reserved_array(this._flags.last_token, special_words)) {
4693 // no newline between 'return nnn'
4694 this._output.space_before_token = true;
4695 } else if (this._flags.last_token.text === 'declare' && reserved_array(current_token, ['var', 'let', 'const'])) {
4696 // accomodates Typescript declare formatting
4697 this._output.space_before_token = true;
4698 } else if (this._flags.last_token.type !== TOKEN.END_EXPR) {
4699 if ((this._flags.last_token.type !== TOKEN.START_EXPR || !reserved_array(current_token, ['var', 'let', 'const'])) && this._flags.last_token.text !== ':') {
4700 // no need to force newline on 'var': for (var x = 0...)
4701 if (reserved_word(current_token, 'if') && reserved_word(current_token.previous, 'else')) {
4702 // no newline for } else if {
4703 this._output.space_before_token = true;
4704 } else {
4705 this.print_newline();
4706 }
4707 }
4708 } else if (reserved_array(current_token, line_starters) && this._flags.last_token.text !== ')') {
4709 this.print_newline();
4710 }
4711 } else if (this._flags.multiline_frame && is_array(this._flags.mode) && this._flags.last_token.text === ',' && this._last_last_text === '}') {
4712 this.print_newline(); // }, in lists get a newline treatment
4713 } else if (prefix === 'SPACE') {
4714 this._output.space_before_token = true;
4715 }
4716 if (current_token.previous && (current_token.previous.type === TOKEN.WORD || current_token.previous.type === TOKEN.RESERVED)) {
4717 this._output.space_before_token = true;
4718 }
4719 this.print_token(current_token);
4720 this._flags.last_word = current_token.text;
4721
4722 if (current_token.type === TOKEN.RESERVED) {
4723 if (current_token.text === 'do') {
4724 this._flags.do_block = true;
4725 } else if (current_token.text === 'if') {
4726 this._flags.if_block = true;
4727 } else if (current_token.text === 'import') {
4728 this._flags.import_block = true;
4729 } else if (this._flags.import_block && reserved_word(current_token, 'from')) {
4730 this._flags.import_block = false;
4731 }
4732 }
4733 };
4734
4735 Beautifier.prototype.handle_semicolon = function(current_token) {
4736 if (this.start_of_statement(current_token)) {
4737 // The conditional starts the statement if appropriate.
4738 // Semicolon can be the start (and end) of a statement
4739 this._output.space_before_token = false;
4740 } else {
4741 this.handle_whitespace_and_comments(current_token);
4742 }
4743
4744 var next_token = this._tokens.peek();
4745 while (this._flags.mode === MODE.Statement &&
4746 !(this._flags.if_block && reserved_word(next_token, 'else')) &&
4747 !this._flags.do_block) {
4748 this.restore_mode();
4749 }
4750
4751 // hacky but effective for the moment
4752 if (this._flags.import_block) {
4753 this._flags.import_block = false;
4754 }
4755 this.print_token(current_token);
4756 };
4757
4758 Beautifier.prototype.handle_string = function(current_token) {
4759 if (current_token.text.startsWith("`") && current_token.newlines === 0 && current_token.whitespace_before === '' && (current_token.previous.text === ')' || this._flags.last_token.type === TOKEN.WORD)) ; else if (this.start_of_statement(current_token)) {
4760 // The conditional starts the statement if appropriate.
4761 // One difference - strings want at least a space before
4762 this._output.space_before_token = true;
4763 } else {
4764 this.handle_whitespace_and_comments(current_token);
4765 if (this._flags.last_token.type === TOKEN.RESERVED || this._flags.last_token.type === TOKEN.WORD || this._flags.inline_frame) {
4766 this._output.space_before_token = true;
4767 } else if (this._flags.last_token.type === TOKEN.COMMA || this._flags.last_token.type === TOKEN.START_EXPR || this._flags.last_token.type === TOKEN.EQUALS || this._flags.last_token.type === TOKEN.OPERATOR) {
4768 if (!this.start_of_object_property()) {
4769 this.allow_wrap_or_preserved_newline(current_token);
4770 }
4771 } else if ((current_token.text.startsWith("`") && this._flags.last_token.type === TOKEN.END_EXPR && (current_token.previous.text === ']' || current_token.previous.text === ')') && current_token.newlines === 0)) {
4772 this._output.space_before_token = true;
4773 } else {
4774 this.print_newline();
4775 }
4776 }
4777 this.print_token(current_token);
4778 };
4779
4780 Beautifier.prototype.handle_equals = function(current_token) {
4781 if (this.start_of_statement(current_token)) ; else {
4782 this.handle_whitespace_and_comments(current_token);
4783 }
4784
4785 if (this._flags.declaration_statement) {
4786 // just got an '=' in a var-line, different formatting/line-breaking, etc will now be done
4787 this._flags.declaration_assignment = true;
4788 }
4789 this._output.space_before_token = true;
4790 this.print_token(current_token);
4791 this._output.space_before_token = true;
4792 };
4793
4794 Beautifier.prototype.handle_comma = function(current_token) {
4795 this.handle_whitespace_and_comments(current_token, true);
4796
4797 this.print_token(current_token);
4798 this._output.space_before_token = true;
4799 if (this._flags.declaration_statement) {
4800 if (is_expression(this._flags.parent.mode)) {
4801 // do not break on comma, for(var a = 1, b = 2)
4802 this._flags.declaration_assignment = false;
4803 }
4804
4805 if (this._flags.declaration_assignment) {
4806 this._flags.declaration_assignment = false;
4807 this.print_newline(false, true);
4808 } else if (this._options.comma_first) {
4809 // for comma-first, we want to allow a newline before the comma
4810 // to turn into a newline after the comma, which we will fixup later
4811 this.allow_wrap_or_preserved_newline(current_token);
4812 }
4813 } else if (this._flags.mode === MODE.ObjectLiteral ||
4814 (this._flags.mode === MODE.Statement && this._flags.parent.mode === MODE.ObjectLiteral)) {
4815 if (this._flags.mode === MODE.Statement) {
4816 this.restore_mode();
4817 }
4818
4819 if (!this._flags.inline_frame) {
4820 this.print_newline();
4821 }
4822 } else if (this._options.comma_first) {
4823 // EXPR or DO_BLOCK
4824 // for comma-first, we want to allow a newline before the comma
4825 // to turn into a newline after the comma, which we will fixup later
4826 this.allow_wrap_or_preserved_newline(current_token);
4827 }
4828 };
4829
4830 Beautifier.prototype.handle_operator = function(current_token) {
4831 var isGeneratorAsterisk = current_token.text === '*' &&
4832 (reserved_array(this._flags.last_token, ['function', 'yield']) ||
4833 (in_array(this._flags.last_token.type, [TOKEN.START_BLOCK, TOKEN.COMMA, TOKEN.END_BLOCK, TOKEN.SEMICOLON]))
4834 );
4835 var isUnary = in_array(current_token.text, ['-', '+']) && (
4836 in_array(this._flags.last_token.type, [TOKEN.START_BLOCK, TOKEN.START_EXPR, TOKEN.EQUALS, TOKEN.OPERATOR]) ||
4837 in_array(this._flags.last_token.text, line_starters) ||
4838 this._flags.last_token.text === ','
4839 );
4840
4841 if (this.start_of_statement(current_token)) ; else {
4842 var preserve_statement_flags = !isGeneratorAsterisk;
4843 this.handle_whitespace_and_comments(current_token, preserve_statement_flags);
4844 }
4845
4846 // hack for actionscript's import .*;
4847 if (current_token.text === '*' && this._flags.last_token.type === TOKEN.DOT) {
4848 this.print_token(current_token);
4849 return;
4850 }
4851
4852 if (current_token.text === '::') {
4853 // no spaces around exotic namespacing syntax operator
4854 this.print_token(current_token);
4855 return;
4856 }
4857
4858 // Allow line wrapping between operators when operator_position is
4859 // set to before or preserve
4860 if (this._flags.last_token.type === TOKEN.OPERATOR && in_array(this._options.operator_position, OPERATOR_POSITION_BEFORE_OR_PRESERVE)) {
4861 this.allow_wrap_or_preserved_newline(current_token);
4862 }
4863
4864 if (current_token.text === ':' && this._flags.in_case) {
4865 this.print_token(current_token);
4866
4867 this._flags.in_case = false;
4868 this._flags.case_body = true;
4869 if (this._tokens.peek().type !== TOKEN.START_BLOCK) {
4870 this.indent();
4871 this.print_newline();
4872 this._flags.case_block = false;
4873 } else {
4874 this._flags.case_block = true;
4875 this._output.space_before_token = true;
4876 }
4877 return;
4878 }
4879
4880 var space_before = true;
4881 var space_after = true;
4882 var in_ternary = false;
4883 if (current_token.text === ':') {
4884 if (this._flags.ternary_depth === 0) {
4885 // Colon is invalid javascript outside of ternary and object, but do our best to guess what was meant.
4886 space_before = false;
4887 } else {
4888 this._flags.ternary_depth -= 1;
4889 in_ternary = true;
4890 }
4891 } else if (current_token.text === '?') {
4892 this._flags.ternary_depth += 1;
4893 }
4894
4895 // let's handle the operator_position option prior to any conflicting logic
4896 if (!isUnary && !isGeneratorAsterisk && this._options.preserve_newlines && in_array(current_token.text, positionable_operators)) {
4897 var isColon = current_token.text === ':';
4898 var isTernaryColon = (isColon && in_ternary);
4899 var isOtherColon = (isColon && !in_ternary);
4900
4901 switch (this._options.operator_position) {
4902 case OPERATOR_POSITION.before_newline:
4903 // if the current token is : and it's not a ternary statement then we set space_before to false
4904 this._output.space_before_token = !isOtherColon;
4905
4906 this.print_token(current_token);
4907
4908 if (!isColon || isTernaryColon) {
4909 this.allow_wrap_or_preserved_newline(current_token);
4910 }
4911
4912 this._output.space_before_token = true;
4913 return;
4914
4915 case OPERATOR_POSITION.after_newline:
4916 // if the current token is anything but colon, or (via deduction) it's a colon and in a ternary statement,
4917 // then print a newline.
4918
4919 this._output.space_before_token = true;
4920
4921 if (!isColon || isTernaryColon) {
4922 if (this._tokens.peek().newlines) {
4923 this.print_newline(false, true);
4924 } else {
4925 this.allow_wrap_or_preserved_newline(current_token);
4926 }
4927 } else {
4928 this._output.space_before_token = false;
4929 }
4930
4931 this.print_token(current_token);
4932
4933 this._output.space_before_token = true;
4934 return;
4935
4936 case OPERATOR_POSITION.preserve_newline:
4937 if (!isOtherColon) {
4938 this.allow_wrap_or_preserved_newline(current_token);
4939 }
4940
4941 // if we just added a newline, or the current token is : and it's not a ternary statement,
4942 // then we set space_before to false
4943 space_before = !(this._output.just_added_newline() || isOtherColon);
4944
4945 this._output.space_before_token = space_before;
4946 this.print_token(current_token);
4947 this._output.space_before_token = true;
4948 return;
4949 }
4950 }
4951
4952 if (isGeneratorAsterisk) {
4953 this.allow_wrap_or_preserved_newline(current_token);
4954 space_before = false;
4955 var next_token = this._tokens.peek();
4956 space_after = next_token && in_array(next_token.type, [TOKEN.WORD, TOKEN.RESERVED]);
4957 } else if (current_token.text === '...') {
4958 this.allow_wrap_or_preserved_newline(current_token);
4959 space_before = this._flags.last_token.type === TOKEN.START_BLOCK;
4960 space_after = false;
4961 } else if (in_array(current_token.text, ['--', '++', '!', '~']) || isUnary) {
4962 // unary operators (and binary +/- pretending to be unary) special cases
4963 if (this._flags.last_token.type === TOKEN.COMMA || this._flags.last_token.type === TOKEN.START_EXPR) {
4964 this.allow_wrap_or_preserved_newline(current_token);
4965 }
4966
4967 space_before = false;
4968 space_after = false;
4969
4970 // http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.1
4971 // if there is a newline between -- or ++ and anything else we should preserve it.
4972 if (current_token.newlines && (current_token.text === '--' || current_token.text === '++' || current_token.text === '~')) {
4973 var new_line_needed = reserved_array(this._flags.last_token, special_words) && current_token.newlines;
4974 if (new_line_needed && (this._previous_flags.if_block || this._previous_flags.else_block)) {
4975 this.restore_mode();
4976 }
4977 this.print_newline(new_line_needed, true);
4978 }
4979
4980 if (this._flags.last_token.text === ';' && is_expression(this._flags.mode)) {
4981 // for (;; ++i)
4982 // ^^^
4983 space_before = true;
4984 }
4985
4986 if (this._flags.last_token.type === TOKEN.RESERVED) {
4987 space_before = true;
4988 } else if (this._flags.last_token.type === TOKEN.END_EXPR) {
4989 space_before = !(this._flags.last_token.text === ']' && (current_token.text === '--' || current_token.text === '++'));
4990 } else if (this._flags.last_token.type === TOKEN.OPERATOR) {
4991 // a++ + ++b;
4992 // a - -b
4993 space_before = in_array(current_token.text, ['--', '-', '++', '+']) && in_array(this._flags.last_token.text, ['--', '-', '++', '+']);
4994 // + and - are not unary when preceeded by -- or ++ operator
4995 // a-- + b
4996 // a * +b
4997 // a - -b
4998 if (in_array(current_token.text, ['+', '-']) && in_array(this._flags.last_token.text, ['--', '++'])) {
4999 space_after = true;
5000 }
5001 }
5002
5003
5004 if (((this._flags.mode === MODE.BlockStatement && !this._flags.inline_frame) || this._flags.mode === MODE.Statement) &&
5005 (this._flags.last_token.text === '{' || this._flags.last_token.text === ';')) {
5006 // { foo; --i }
5007 // foo(); --bar;
5008 this.print_newline();
5009 }
5010 }
5011
5012 this._output.space_before_token = this._output.space_before_token || space_before;
5013 this.print_token(current_token);
5014 this._output.space_before_token = space_after;
5015 };
5016
5017 Beautifier.prototype.handle_block_comment = function(current_token, preserve_statement_flags) {
5018 if (this._output.raw) {
5019 this._output.add_raw_token(current_token);
5020 if (current_token.directives && current_token.directives.preserve === 'end') {
5021 // If we're testing the raw output behavior, do not allow a directive to turn it off.
5022 this._output.raw = this._options.test_output_raw;
5023 }
5024 return;
5025 }
5026
5027 if (current_token.directives) {
5028 this.print_newline(false, preserve_statement_flags);
5029 this.print_token(current_token);
5030 if (current_token.directives.preserve === 'start') {
5031 this._output.raw = true;
5032 }
5033 this.print_newline(false, true);
5034 return;
5035 }
5036
5037 // inline block
5038 if (!acorn.newline.test(current_token.text) && !current_token.newlines) {
5039 this._output.space_before_token = true;
5040 this.print_token(current_token);
5041 this._output.space_before_token = true;
5042 return;
5043 } else {
5044 this.print_block_commment(current_token, preserve_statement_flags);
5045 }
5046 };
5047
5048 Beautifier.prototype.print_block_commment = function(current_token, preserve_statement_flags) {
5049 var lines = split_linebreaks(current_token.text);
5050 var j; // iterator for this case
5051 var javadoc = false;
5052 var starless = false;
5053 var lastIndent = current_token.whitespace_before;
5054 var lastIndentLength = lastIndent.length;
5055
5056 // block comment starts with a new line
5057 this.print_newline(false, preserve_statement_flags);
5058
5059 // first line always indented
5060 this.print_token_line_indentation(current_token);
5061 this._output.add_token(lines[0]);
5062 this.print_newline(false, preserve_statement_flags);
5063
5064
5065 if (lines.length > 1) {
5066 lines = lines.slice(1);
5067 javadoc = all_lines_start_with(lines, '*');
5068 starless = each_line_matches_indent(lines, lastIndent);
5069
5070 if (javadoc) {
5071 this._flags.alignment = 1;
5072 }
5073
5074 for (j = 0; j < lines.length; j++) {
5075 if (javadoc) {
5076 // javadoc: reformat and re-indent
5077 this.print_token_line_indentation(current_token);
5078 this._output.add_token(ltrim(lines[j]));
5079 } else if (starless && lines[j]) {
5080 // starless: re-indent non-empty content, avoiding trim
5081 this.print_token_line_indentation(current_token);
5082 this._output.add_token(lines[j].substring(lastIndentLength));
5083 } else {
5084 // normal comments output raw
5085 this._output.current_line.set_indent(-1);
5086 this._output.add_token(lines[j]);
5087 }
5088
5089 // for comments on their own line or more than one line, make sure there's a new line after
5090 this.print_newline(false, preserve_statement_flags);
5091 }
5092
5093 this._flags.alignment = 0;
5094 }
5095 };
5096
5097
5098 Beautifier.prototype.handle_comment = function(current_token, preserve_statement_flags) {
5099 if (current_token.newlines) {
5100 this.print_newline(false, preserve_statement_flags);
5101 } else {
5102 this._output.trim(true);
5103 }
5104
5105 this._output.space_before_token = true;
5106 this.print_token(current_token);
5107 this.print_newline(false, preserve_statement_flags);
5108 };
5109
5110 Beautifier.prototype.handle_dot = function(current_token) {
5111 if (this.start_of_statement(current_token)) ; else {
5112 this.handle_whitespace_and_comments(current_token, true);
5113 }
5114
5115 if (this._flags.last_token.text.match('^[0-9]+$')) {
5116 this._output.space_before_token = true;
5117 }
5118
5119 if (reserved_array(this._flags.last_token, special_words)) {
5120 this._output.space_before_token = false;
5121 } else {
5122 // allow preserved newlines before dots in general
5123 // force newlines on dots after close paren when break_chained - for bar().baz()
5124 this.allow_wrap_or_preserved_newline(current_token,
5125 this._flags.last_token.text === ')' && this._options.break_chained_methods);
5126 }
5127
5128 // Only unindent chained method dot if this dot starts a new line.
5129 // Otherwise the automatic extra indentation removal will handle the over indent
5130 if (this._options.unindent_chained_methods && this._output.just_added_newline()) {
5131 this.deindent();
5132 }
5133
5134 this.print_token(current_token);
5135 };
5136
5137 Beautifier.prototype.handle_unknown = function(current_token, preserve_statement_flags) {
5138 this.print_token(current_token);
5139
5140 if (current_token.text[current_token.text.length - 1] === '\n') {
5141 this.print_newline(false, preserve_statement_flags);
5142 }
5143 };
5144
5145 Beautifier.prototype.handle_eof = function(current_token) {
5146 // Unwind any open statements
5147 while (this._flags.mode === MODE.Statement) {
5148 this.restore_mode();
5149 }
5150 this.handle_whitespace_and_comments(current_token);
5151 };
5152
5153 beautifier$2.Beautifier = Beautifier;
5154 return beautifier$2;
5155}
5156
5157/*jshint node:true */
5158
5159var hasRequiredJavascript;
5160
5161function requireJavascript () {
5162 if (hasRequiredJavascript) return javascript.exports;
5163 hasRequiredJavascript = 1;
5164
5165 var Beautifier = requireBeautifier$2().Beautifier,
5166 Options = requireOptions$2().Options;
5167
5168 function js_beautify(js_source_text, options) {
5169 var beautifier = new Beautifier(js_source_text, options);
5170 return beautifier.beautify();
5171 }
5172
5173 javascript.exports = js_beautify;
5174 javascript.exports.defaultOptions = function() {
5175 return new Options();
5176 };
5177 return javascript.exports;
5178}
5179
5180var css = {exports: {}};
5181
5182var beautifier$1 = {};
5183
5184var options$1 = {};
5185
5186/*jshint node:true */
5187
5188var hasRequiredOptions$1;
5189
5190function requireOptions$1 () {
5191 if (hasRequiredOptions$1) return options$1;
5192 hasRequiredOptions$1 = 1;
5193
5194 var BaseOptions = requireOptions$3().Options;
5195
5196 function Options(options) {
5197 BaseOptions.call(this, options, 'css');
5198
5199 this.selector_separator_newline = this._get_boolean('selector_separator_newline', true);
5200 this.newline_between_rules = this._get_boolean('newline_between_rules', true);
5201 var space_around_selector_separator = this._get_boolean('space_around_selector_separator');
5202 this.space_around_combinator = this._get_boolean('space_around_combinator') || space_around_selector_separator;
5203
5204 var brace_style_split = this._get_selection_list('brace_style', ['collapse', 'expand', 'end-expand', 'none', 'preserve-inline']);
5205 this.brace_style = 'collapse';
5206 for (var bs = 0; bs < brace_style_split.length; bs++) {
5207 if (brace_style_split[bs] !== 'expand') {
5208 // default to collapse, as only collapse|expand is implemented for now
5209 this.brace_style = 'collapse';
5210 } else {
5211 this.brace_style = brace_style_split[bs];
5212 }
5213 }
5214 }
5215 Options.prototype = new BaseOptions();
5216
5217
5218
5219 options$1.Options = Options;
5220 return options$1;
5221}
5222
5223/*jshint node:true */
5224
5225var hasRequiredBeautifier$1;
5226
5227function requireBeautifier$1 () {
5228 if (hasRequiredBeautifier$1) return beautifier$1;
5229 hasRequiredBeautifier$1 = 1;
5230
5231 var Options = requireOptions$1().Options;
5232 var Output = requireOutput().Output;
5233 var InputScanner = requireInputscanner().InputScanner;
5234 var Directives = requireDirectives().Directives;
5235
5236 var directives_core = new Directives(/\/\*/, /\*\//);
5237
5238 var lineBreak = /\r\n|[\r\n]/;
5239 var allLineBreaks = /\r\n|[\r\n]/g;
5240
5241 // tokenizer
5242 var whitespaceChar = /\s/;
5243 var whitespacePattern = /(?:\s|\n)+/g;
5244 var block_comment_pattern = /\/\*(?:[\s\S]*?)((?:\*\/)|$)/g;
5245 var comment_pattern = /\/\/(?:[^\n\r\u2028\u2029]*)/g;
5246
5247 function Beautifier(source_text, options) {
5248 this._source_text = source_text || '';
5249 // Allow the setting of language/file-type specific options
5250 // with inheritance of overall settings
5251 this._options = new Options(options);
5252 this._ch = null;
5253 this._input = null;
5254
5255 // https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule
5256 this.NESTED_AT_RULE = {
5257 "page": true,
5258 "font-face": true,
5259 "keyframes": true,
5260 // also in CONDITIONAL_GROUP_RULE below
5261 "media": true,
5262 "supports": true,
5263 "document": true
5264 };
5265 this.CONDITIONAL_GROUP_RULE = {
5266 "media": true,
5267 "supports": true,
5268 "document": true
5269 };
5270 this.NON_SEMICOLON_NEWLINE_PROPERTY = [
5271 "grid-template-areas",
5272 "grid-template"
5273 ];
5274
5275 }
5276
5277 Beautifier.prototype.eatString = function(endChars) {
5278 var result = '';
5279 this._ch = this._input.next();
5280 while (this._ch) {
5281 result += this._ch;
5282 if (this._ch === "\\") {
5283 result += this._input.next();
5284 } else if (endChars.indexOf(this._ch) !== -1 || this._ch === "\n") {
5285 break;
5286 }
5287 this._ch = this._input.next();
5288 }
5289 return result;
5290 };
5291
5292 // Skips any white space in the source text from the current position.
5293 // When allowAtLeastOneNewLine is true, will output new lines for each
5294 // newline character found; if the user has preserve_newlines off, only
5295 // the first newline will be output
5296 Beautifier.prototype.eatWhitespace = function(allowAtLeastOneNewLine) {
5297 var result = whitespaceChar.test(this._input.peek());
5298 var newline_count = 0;
5299 while (whitespaceChar.test(this._input.peek())) {
5300 this._ch = this._input.next();
5301 if (allowAtLeastOneNewLine && this._ch === '\n') {
5302 if (newline_count === 0 || newline_count < this._options.max_preserve_newlines) {
5303 newline_count++;
5304 this._output.add_new_line(true);
5305 }
5306 }
5307 }
5308 return result;
5309 };
5310
5311 // Nested pseudo-class if we are insideRule
5312 // and the next special character found opens
5313 // a new block
5314 Beautifier.prototype.foundNestedPseudoClass = function() {
5315 var openParen = 0;
5316 var i = 1;
5317 var ch = this._input.peek(i);
5318 while (ch) {
5319 if (ch === "{") {
5320 return true;
5321 } else if (ch === '(') {
5322 // pseudoclasses can contain ()
5323 openParen += 1;
5324 } else if (ch === ')') {
5325 if (openParen === 0) {
5326 return false;
5327 }
5328 openParen -= 1;
5329 } else if (ch === ";" || ch === "}") {
5330 return false;
5331 }
5332 i++;
5333 ch = this._input.peek(i);
5334 }
5335 return false;
5336 };
5337
5338 Beautifier.prototype.print_string = function(output_string) {
5339 this._output.set_indent(this._indentLevel);
5340 this._output.non_breaking_space = true;
5341 this._output.add_token(output_string);
5342 };
5343
5344 Beautifier.prototype.preserveSingleSpace = function(isAfterSpace) {
5345 if (isAfterSpace) {
5346 this._output.space_before_token = true;
5347 }
5348 };
5349
5350 Beautifier.prototype.indent = function() {
5351 this._indentLevel++;
5352 };
5353
5354 Beautifier.prototype.outdent = function() {
5355 if (this._indentLevel > 0) {
5356 this._indentLevel--;
5357 }
5358 };
5359
5360 /*_____________________--------------------_____________________*/
5361
5362 Beautifier.prototype.beautify = function() {
5363 if (this._options.disabled) {
5364 return this._source_text;
5365 }
5366
5367 var source_text = this._source_text;
5368 var eol = this._options.eol;
5369 if (eol === 'auto') {
5370 eol = '\n';
5371 if (source_text && lineBreak.test(source_text || '')) {
5372 eol = source_text.match(lineBreak)[0];
5373 }
5374 }
5375
5376
5377 // HACK: newline parsing inconsistent. This brute force normalizes the this._input.
5378 source_text = source_text.replace(allLineBreaks, '\n');
5379
5380 // reset
5381 var baseIndentString = source_text.match(/^[\t ]*/)[0];
5382
5383 this._output = new Output(this._options, baseIndentString);
5384 this._input = new InputScanner(source_text);
5385 this._indentLevel = 0;
5386 this._nestedLevel = 0;
5387
5388 this._ch = null;
5389 var parenLevel = 0;
5390
5391 var insideRule = false;
5392 // This is the value side of a property value pair (blue in the following ex)
5393 // label { content: blue }
5394 var insidePropertyValue = false;
5395 var enteringConditionalGroup = false;
5396 var insideNonNestedAtRule = false;
5397 var insideScssMap = false;
5398 var topCharacter = this._ch;
5399 var insideNonSemiColonValues = false;
5400 var whitespace;
5401 var isAfterSpace;
5402 var previous_ch;
5403
5404 while (true) {
5405 whitespace = this._input.read(whitespacePattern);
5406 isAfterSpace = whitespace !== '';
5407 previous_ch = topCharacter;
5408 this._ch = this._input.next();
5409 if (this._ch === '\\' && this._input.hasNext()) {
5410 this._ch += this._input.next();
5411 }
5412 topCharacter = this._ch;
5413
5414 if (!this._ch) {
5415 break;
5416 } else if (this._ch === '/' && this._input.peek() === '*') {
5417 // /* css comment */
5418 // Always start block comments on a new line.
5419 // This handles scenarios where a block comment immediately
5420 // follows a property definition on the same line or where
5421 // minified code is being beautified.
5422 this._output.add_new_line();
5423 this._input.back();
5424
5425 var comment = this._input.read(block_comment_pattern);
5426
5427 // Handle ignore directive
5428 var directives = directives_core.get_directives(comment);
5429 if (directives && directives.ignore === 'start') {
5430 comment += directives_core.readIgnored(this._input);
5431 }
5432
5433 this.print_string(comment);
5434
5435 // Ensures any new lines following the comment are preserved
5436 this.eatWhitespace(true);
5437
5438 // Block comments are followed by a new line so they don't
5439 // share a line with other properties
5440 this._output.add_new_line();
5441 } else if (this._ch === '/' && this._input.peek() === '/') {
5442 // // single line comment
5443 // Preserves the space before a comment
5444 // on the same line as a rule
5445 this._output.space_before_token = true;
5446 this._input.back();
5447 this.print_string(this._input.read(comment_pattern));
5448
5449 // Ensures any new lines following the comment are preserved
5450 this.eatWhitespace(true);
5451 } else if (this._ch === '$') {
5452 this.preserveSingleSpace(isAfterSpace);
5453
5454 this.print_string(this._ch);
5455
5456 // strip trailing space, if present, for hash property checks
5457 var variable = this._input.peekUntilAfter(/[: ,;{}()[\]\/='"]/g);
5458
5459 if (variable.match(/[ :]$/)) {
5460 // we have a variable or pseudo-class, add it and insert one space before continuing
5461 variable = this.eatString(": ").replace(/\s$/, '');
5462 this.print_string(variable);
5463 this._output.space_before_token = true;
5464 }
5465
5466 variable = variable.replace(/\s$/, '');
5467
5468 // might be sass variable
5469 if (parenLevel === 0 && variable.indexOf(':') !== -1) {
5470 insidePropertyValue = true;
5471 this.indent();
5472 }
5473 } else if (this._ch === '@') {
5474 this.preserveSingleSpace(isAfterSpace);
5475
5476 // deal with less property mixins @{...}
5477 if (this._input.peek() === '{') {
5478 this.print_string(this._ch + this.eatString('}'));
5479 } else {
5480 this.print_string(this._ch);
5481
5482 // strip trailing space, if present, for hash property checks
5483 var variableOrRule = this._input.peekUntilAfter(/[: ,;{}()[\]\/='"]/g);
5484
5485 if (variableOrRule.match(/[ :]$/)) {
5486 // we have a variable or pseudo-class, add it and insert one space before continuing
5487 variableOrRule = this.eatString(": ").replace(/\s$/, '');
5488 this.print_string(variableOrRule);
5489 this._output.space_before_token = true;
5490 }
5491
5492 variableOrRule = variableOrRule.replace(/\s$/, '');
5493
5494 // might be less variable
5495 if (parenLevel === 0 && variableOrRule.indexOf(':') !== -1) {
5496 insidePropertyValue = true;
5497 this.indent();
5498
5499 // might be a nesting at-rule
5500 } else if (variableOrRule in this.NESTED_AT_RULE) {
5501 this._nestedLevel += 1;
5502 if (variableOrRule in this.CONDITIONAL_GROUP_RULE) {
5503 enteringConditionalGroup = true;
5504 }
5505
5506 // might be a non-nested at-rule
5507 } else if (parenLevel === 0 && !insidePropertyValue) {
5508 insideNonNestedAtRule = true;
5509 }
5510 }
5511 } else if (this._ch === '#' && this._input.peek() === '{') {
5512 this.preserveSingleSpace(isAfterSpace);
5513 this.print_string(this._ch + this.eatString('}'));
5514 } else if (this._ch === '{') {
5515 if (insidePropertyValue) {
5516 insidePropertyValue = false;
5517 this.outdent();
5518 }
5519
5520 // non nested at rule becomes nested
5521 insideNonNestedAtRule = false;
5522
5523 // when entering conditional groups, only rulesets are allowed
5524 if (enteringConditionalGroup) {
5525 enteringConditionalGroup = false;
5526 insideRule = (this._indentLevel >= this._nestedLevel);
5527 } else {
5528 // otherwise, declarations are also allowed
5529 insideRule = (this._indentLevel >= this._nestedLevel - 1);
5530 }
5531 if (this._options.newline_between_rules && insideRule) {
5532 if (this._output.previous_line && this._output.previous_line.item(-1) !== '{') {
5533 this._output.ensure_empty_line_above('/', ',');
5534 }
5535 }
5536
5537 this._output.space_before_token = true;
5538
5539 // The difference in print_string and indent order is necessary to indent the '{' correctly
5540 if (this._options.brace_style === 'expand') {
5541 this._output.add_new_line();
5542 this.print_string(this._ch);
5543 this.indent();
5544 this._output.set_indent(this._indentLevel);
5545 } else {
5546 // inside mixin and first param is object
5547 if (previous_ch === '(') {
5548 this._output.space_before_token = false;
5549 } else if (previous_ch !== ',') {
5550 this.indent();
5551 }
5552 this.print_string(this._ch);
5553 }
5554
5555 this.eatWhitespace(true);
5556 this._output.add_new_line();
5557 } else if (this._ch === '}') {
5558 this.outdent();
5559 this._output.add_new_line();
5560 if (previous_ch === '{') {
5561 this._output.trim(true);
5562 }
5563
5564 if (insidePropertyValue) {
5565 this.outdent();
5566 insidePropertyValue = false;
5567 }
5568 this.print_string(this._ch);
5569 insideRule = false;
5570 if (this._nestedLevel) {
5571 this._nestedLevel--;
5572 }
5573
5574 this.eatWhitespace(true);
5575 this._output.add_new_line();
5576
5577 if (this._options.newline_between_rules && !this._output.just_added_blankline()) {
5578 if (this._input.peek() !== '}') {
5579 this._output.add_new_line(true);
5580 }
5581 }
5582 if (this._input.peek() === ')') {
5583 this._output.trim(true);
5584 if (this._options.brace_style === "expand") {
5585 this._output.add_new_line(true);
5586 }
5587 }
5588 } else if (this._ch === ":") {
5589
5590 for (var i = 0; i < this.NON_SEMICOLON_NEWLINE_PROPERTY.length; i++) {
5591 if (this._input.lookBack(this.NON_SEMICOLON_NEWLINE_PROPERTY[i])) {
5592 insideNonSemiColonValues = true;
5593 break;
5594 }
5595 }
5596
5597 if ((insideRule || enteringConditionalGroup) && !(this._input.lookBack("&") || this.foundNestedPseudoClass()) && !this._input.lookBack("(") && !insideNonNestedAtRule && parenLevel === 0) {
5598 // 'property: value' delimiter
5599 // which could be in a conditional group query
5600
5601 this.print_string(':');
5602 if (!insidePropertyValue) {
5603 insidePropertyValue = true;
5604 this._output.space_before_token = true;
5605 this.eatWhitespace(true);
5606 this.indent();
5607 }
5608 } else {
5609 // sass/less parent reference don't use a space
5610 // sass nested pseudo-class don't use a space
5611
5612 // preserve space before pseudoclasses/pseudoelements, as it means "in any child"
5613 if (this._input.lookBack(" ")) {
5614 this._output.space_before_token = true;
5615 }
5616 if (this._input.peek() === ":") {
5617 // pseudo-element
5618 this._ch = this._input.next();
5619 this.print_string("::");
5620 } else {
5621 // pseudo-class
5622 this.print_string(':');
5623 }
5624 }
5625 } else if (this._ch === '"' || this._ch === '\'') {
5626 var preserveQuoteSpace = previous_ch === '"' || previous_ch === '\'';
5627 this.preserveSingleSpace(preserveQuoteSpace || isAfterSpace);
5628 this.print_string(this._ch + this.eatString(this._ch));
5629 this.eatWhitespace(true);
5630 } else if (this._ch === ';') {
5631 insideNonSemiColonValues = false;
5632 if (parenLevel === 0) {
5633 if (insidePropertyValue) {
5634 this.outdent();
5635 insidePropertyValue = false;
5636 }
5637 insideNonNestedAtRule = false;
5638 this.print_string(this._ch);
5639 this.eatWhitespace(true);
5640
5641 // This maintains single line comments on the same
5642 // line. Block comments are also affected, but
5643 // a new line is always output before one inside
5644 // that section
5645 if (this._input.peek() !== '/') {
5646 this._output.add_new_line();
5647 }
5648 } else {
5649 this.print_string(this._ch);
5650 this.eatWhitespace(true);
5651 this._output.space_before_token = true;
5652 }
5653 } else if (this._ch === '(') { // may be a url
5654 if (this._input.lookBack("url")) {
5655 this.print_string(this._ch);
5656 this.eatWhitespace();
5657 parenLevel++;
5658 this.indent();
5659 this._ch = this._input.next();
5660 if (this._ch === ')' || this._ch === '"' || this._ch === '\'') {
5661 this._input.back();
5662 } else if (this._ch) {
5663 this.print_string(this._ch + this.eatString(')'));
5664 if (parenLevel) {
5665 parenLevel--;
5666 this.outdent();
5667 }
5668 }
5669 } else {
5670 var space_needed = false;
5671 if (this._input.lookBack("with")) {
5672 // look back is not an accurate solution, we need tokens to confirm without whitespaces
5673 space_needed = true;
5674 }
5675 this.preserveSingleSpace(isAfterSpace || space_needed);
5676 this.print_string(this._ch);
5677
5678 // handle scss/sass map
5679 if (insidePropertyValue && previous_ch === "$" && this._options.selector_separator_newline) {
5680 this._output.add_new_line();
5681 insideScssMap = true;
5682 } else {
5683 this.eatWhitespace();
5684 parenLevel++;
5685 this.indent();
5686 }
5687 }
5688 } else if (this._ch === ')') {
5689 if (parenLevel) {
5690 parenLevel--;
5691 this.outdent();
5692 }
5693 if (insideScssMap && this._input.peek() === ";" && this._options.selector_separator_newline) {
5694 insideScssMap = false;
5695 this.outdent();
5696 this._output.add_new_line();
5697 }
5698 this.print_string(this._ch);
5699 } else if (this._ch === ',') {
5700 this.print_string(this._ch);
5701 this.eatWhitespace(true);
5702 if (this._options.selector_separator_newline && (!insidePropertyValue || insideScssMap) && parenLevel === 0 && !insideNonNestedAtRule) {
5703 this._output.add_new_line();
5704 } else {
5705 this._output.space_before_token = true;
5706 }
5707 } else if ((this._ch === '>' || this._ch === '+' || this._ch === '~') && !insidePropertyValue && parenLevel === 0) {
5708 //handle combinator spacing
5709 if (this._options.space_around_combinator) {
5710 this._output.space_before_token = true;
5711 this.print_string(this._ch);
5712 this._output.space_before_token = true;
5713 } else {
5714 this.print_string(this._ch);
5715 this.eatWhitespace();
5716 // squash extra whitespace
5717 if (this._ch && whitespaceChar.test(this._ch)) {
5718 this._ch = '';
5719 }
5720 }
5721 } else if (this._ch === ']') {
5722 this.print_string(this._ch);
5723 } else if (this._ch === '[') {
5724 this.preserveSingleSpace(isAfterSpace);
5725 this.print_string(this._ch);
5726 } else if (this._ch === '=') { // no whitespace before or after
5727 this.eatWhitespace();
5728 this.print_string('=');
5729 if (whitespaceChar.test(this._ch)) {
5730 this._ch = '';
5731 }
5732 } else if (this._ch === '!' && !this._input.lookBack("\\")) { // !important
5733 this._output.space_before_token = true;
5734 this.print_string(this._ch);
5735 } else {
5736 var preserveAfterSpace = previous_ch === '"' || previous_ch === '\'';
5737 this.preserveSingleSpace(preserveAfterSpace || isAfterSpace);
5738 this.print_string(this._ch);
5739
5740 if (!this._output.just_added_newline() && this._input.peek() === '\n' && insideNonSemiColonValues) {
5741 this._output.add_new_line();
5742 }
5743 }
5744 }
5745
5746 var sweetCode = this._output.get_code(eol);
5747
5748 return sweetCode;
5749 };
5750
5751 beautifier$1.Beautifier = Beautifier;
5752 return beautifier$1;
5753}
5754
5755/*jshint node:true */
5756
5757var hasRequiredCss;
5758
5759function requireCss () {
5760 if (hasRequiredCss) return css.exports;
5761 hasRequiredCss = 1;
5762
5763 var Beautifier = requireBeautifier$1().Beautifier,
5764 Options = requireOptions$1().Options;
5765
5766 function css_beautify(source_text, options) {
5767 var beautifier = new Beautifier(source_text, options);
5768 return beautifier.beautify();
5769 }
5770
5771 css.exports = css_beautify;
5772 css.exports.defaultOptions = function() {
5773 return new Options();
5774 };
5775 return css.exports;
5776}
5777
5778var html = {exports: {}};
5779
5780var beautifier = {};
5781
5782var options = {};
5783
5784/*jshint node:true */
5785
5786var hasRequiredOptions;
5787
5788function requireOptions () {
5789 if (hasRequiredOptions) return options;
5790 hasRequiredOptions = 1;
5791
5792 var BaseOptions = requireOptions$3().Options;
5793
5794 function Options(options) {
5795 BaseOptions.call(this, options, 'html');
5796 if (this.templating.length === 1 && this.templating[0] === 'auto') {
5797 this.templating = ['django', 'erb', 'handlebars', 'php'];
5798 }
5799
5800 this.indent_inner_html = this._get_boolean('indent_inner_html');
5801 this.indent_body_inner_html = this._get_boolean('indent_body_inner_html', true);
5802 this.indent_head_inner_html = this._get_boolean('indent_head_inner_html', true);
5803
5804 this.indent_handlebars = this._get_boolean('indent_handlebars', true);
5805 this.wrap_attributes = this._get_selection('wrap_attributes',
5806 ['auto', 'force', 'force-aligned', 'force-expand-multiline', 'aligned-multiple', 'preserve', 'preserve-aligned']);
5807 this.wrap_attributes_min_attrs = this._get_number('wrap_attributes_min_attrs', 2);
5808 this.wrap_attributes_indent_size = this._get_number('wrap_attributes_indent_size', this.indent_size);
5809 this.extra_liners = this._get_array('extra_liners', ['head', 'body', '/html']);
5810
5811 // Block vs inline elements
5812 // https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
5813 // https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements
5814 // https://www.w3.org/TR/html5/dom.html#phrasing-content
5815 this.inline = this._get_array('inline', [
5816 'a', 'abbr', 'area', 'audio', 'b', 'bdi', 'bdo', 'br', 'button', 'canvas', 'cite',
5817 'code', 'data', 'datalist', 'del', 'dfn', 'em', 'embed', 'i', 'iframe', 'img',
5818 'input', 'ins', 'kbd', 'keygen', 'label', 'map', 'mark', 'math', 'meter', 'noscript',
5819 'object', 'output', 'progress', 'q', 'ruby', 's', 'samp', /* 'script', */ 'select', 'small',
5820 'span', 'strong', 'sub', 'sup', 'svg', 'template', 'textarea', 'time', 'u', 'var',
5821 'video', 'wbr', 'text',
5822 // obsolete inline tags
5823 'acronym', 'big', 'strike', 'tt'
5824 ]);
5825 this.inline_custom_elements = this._get_boolean('inline_custom_elements', true);
5826 this.void_elements = this._get_array('void_elements', [
5827 // HTLM void elements - aka self-closing tags - aka singletons
5828 // https://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements
5829 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
5830 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr',
5831 // NOTE: Optional tags are too complex for a simple list
5832 // they are hard coded in _do_optional_end_element
5833
5834 // Doctype and xml elements
5835 '!doctype', '?xml',
5836
5837 // obsolete tags
5838 // basefont: https://www.computerhope.com/jargon/h/html-basefont-tag.htm
5839 // isndex: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/isindex
5840 'basefont', 'isindex'
5841 ]);
5842 this.unformatted = this._get_array('unformatted', []);
5843 this.content_unformatted = this._get_array('content_unformatted', [
5844 'pre', 'textarea'
5845 ]);
5846 this.unformatted_content_delimiter = this._get_characters('unformatted_content_delimiter');
5847 this.indent_scripts = this._get_selection('indent_scripts', ['normal', 'keep', 'separate']);
5848
5849 }
5850 Options.prototype = new BaseOptions();
5851
5852
5853
5854 options.Options = Options;
5855 return options;
5856}
5857
5858var tokenizer = {};
5859
5860/*jshint node:true */
5861
5862var hasRequiredTokenizer;
5863
5864function requireTokenizer () {
5865 if (hasRequiredTokenizer) return tokenizer;
5866 hasRequiredTokenizer = 1;
5867
5868 var BaseTokenizer = requireTokenizer$2().Tokenizer;
5869 var BASETOKEN = requireTokenizer$2().TOKEN;
5870 var Directives = requireDirectives().Directives;
5871 var TemplatablePattern = requireTemplatablepattern().TemplatablePattern;
5872 var Pattern = requirePattern().Pattern;
5873
5874 var TOKEN = {
5875 TAG_OPEN: 'TK_TAG_OPEN',
5876 TAG_CLOSE: 'TK_TAG_CLOSE',
5877 ATTRIBUTE: 'TK_ATTRIBUTE',
5878 EQUALS: 'TK_EQUALS',
5879 VALUE: 'TK_VALUE',
5880 COMMENT: 'TK_COMMENT',
5881 TEXT: 'TK_TEXT',
5882 UNKNOWN: 'TK_UNKNOWN',
5883 START: BASETOKEN.START,
5884 RAW: BASETOKEN.RAW,
5885 EOF: BASETOKEN.EOF
5886 };
5887
5888 var directives_core = new Directives(/<\!--/, /-->/);
5889
5890 var Tokenizer = function(input_string, options) {
5891 BaseTokenizer.call(this, input_string, options);
5892 this._current_tag_name = '';
5893
5894 // Words end at whitespace or when a tag starts
5895 // if we are indenting handlebars, they are considered tags
5896 var templatable_reader = new TemplatablePattern(this._input).read_options(this._options);
5897 var pattern_reader = new Pattern(this._input);
5898
5899 this.__patterns = {
5900 word: templatable_reader.until(/[\n\r\t <]/),
5901 single_quote: templatable_reader.until_after(/'/),
5902 double_quote: templatable_reader.until_after(/"/),
5903 attribute: templatable_reader.until(/[\n\r\t =>]|\/>/),
5904 element_name: templatable_reader.until(/[\n\r\t >\/]/),
5905
5906 handlebars_comment: pattern_reader.starting_with(/{{!--/).until_after(/--}}/),
5907 handlebars: pattern_reader.starting_with(/{{/).until_after(/}}/),
5908 handlebars_open: pattern_reader.until(/[\n\r\t }]/),
5909 handlebars_raw_close: pattern_reader.until(/}}/),
5910 comment: pattern_reader.starting_with(/<!--/).until_after(/-->/),
5911 cdata: pattern_reader.starting_with(/<!\[CDATA\[/).until_after(/]]>/),
5912 // https://en.wikipedia.org/wiki/Conditional_comment
5913 conditional_comment: pattern_reader.starting_with(/<!\[/).until_after(/]>/),
5914 processing: pattern_reader.starting_with(/<\?/).until_after(/\?>/)
5915 };
5916
5917 if (this._options.indent_handlebars) {
5918 this.__patterns.word = this.__patterns.word.exclude('handlebars');
5919 }
5920
5921 this._unformatted_content_delimiter = null;
5922
5923 if (this._options.unformatted_content_delimiter) {
5924 var literal_regexp = this._input.get_literal_regexp(this._options.unformatted_content_delimiter);
5925 this.__patterns.unformatted_content_delimiter =
5926 pattern_reader.matching(literal_regexp)
5927 .until_after(literal_regexp);
5928 }
5929 };
5930 Tokenizer.prototype = new BaseTokenizer();
5931
5932 Tokenizer.prototype._is_comment = function(current_token) { // jshint unused:false
5933 return false; //current_token.type === TOKEN.COMMENT || current_token.type === TOKEN.UNKNOWN;
5934 };
5935
5936 Tokenizer.prototype._is_opening = function(current_token) {
5937 return current_token.type === TOKEN.TAG_OPEN;
5938 };
5939
5940 Tokenizer.prototype._is_closing = function(current_token, open_token) {
5941 return current_token.type === TOKEN.TAG_CLOSE &&
5942 (open_token && (
5943 ((current_token.text === '>' || current_token.text === '/>') && open_token.text[0] === '<') ||
5944 (current_token.text === '}}' && open_token.text[0] === '{' && open_token.text[1] === '{')));
5945 };
5946
5947 Tokenizer.prototype._reset = function() {
5948 this._current_tag_name = '';
5949 };
5950
5951 Tokenizer.prototype._get_next_token = function(previous_token, open_token) { // jshint unused:false
5952 var token = null;
5953 this._readWhitespace();
5954 var c = this._input.peek();
5955
5956 if (c === null) {
5957 return this._create_token(TOKEN.EOF, '');
5958 }
5959
5960 token = token || this._read_open_handlebars(c, open_token);
5961 token = token || this._read_attribute(c, previous_token, open_token);
5962 token = token || this._read_close(c, open_token);
5963 token = token || this._read_raw_content(c, previous_token, open_token);
5964 token = token || this._read_content_word(c);
5965 token = token || this._read_comment_or_cdata(c);
5966 token = token || this._read_processing(c);
5967 token = token || this._read_open(c, open_token);
5968 token = token || this._create_token(TOKEN.UNKNOWN, this._input.next());
5969
5970 return token;
5971 };
5972
5973 Tokenizer.prototype._read_comment_or_cdata = function(c) { // jshint unused:false
5974 var token = null;
5975 var resulting_string = null;
5976 var directives = null;
5977
5978 if (c === '<') {
5979 var peek1 = this._input.peek(1);
5980 // We treat all comments as literals, even more than preformatted tags
5981 // we only look for the appropriate closing marker
5982 if (peek1 === '!') {
5983 resulting_string = this.__patterns.comment.read();
5984
5985 // only process directive on html comments
5986 if (resulting_string) {
5987 directives = directives_core.get_directives(resulting_string);
5988 if (directives && directives.ignore === 'start') {
5989 resulting_string += directives_core.readIgnored(this._input);
5990 }
5991 } else {
5992 resulting_string = this.__patterns.cdata.read();
5993 }
5994 }
5995
5996 if (resulting_string) {
5997 token = this._create_token(TOKEN.COMMENT, resulting_string);
5998 token.directives = directives;
5999 }
6000 }
6001
6002 return token;
6003 };
6004
6005 Tokenizer.prototype._read_processing = function(c) { // jshint unused:false
6006 var token = null;
6007 var resulting_string = null;
6008 var directives = null;
6009
6010 if (c === '<') {
6011 var peek1 = this._input.peek(1);
6012 if (peek1 === '!' || peek1 === '?') {
6013 resulting_string = this.__patterns.conditional_comment.read();
6014 resulting_string = resulting_string || this.__patterns.processing.read();
6015 }
6016
6017 if (resulting_string) {
6018 token = this._create_token(TOKEN.COMMENT, resulting_string);
6019 token.directives = directives;
6020 }
6021 }
6022
6023 return token;
6024 };
6025
6026 Tokenizer.prototype._read_open = function(c, open_token) {
6027 var resulting_string = null;
6028 var token = null;
6029 if (!open_token) {
6030 if (c === '<') {
6031
6032 resulting_string = this._input.next();
6033 if (this._input.peek() === '/') {
6034 resulting_string += this._input.next();
6035 }
6036 resulting_string += this.__patterns.element_name.read();
6037 token = this._create_token(TOKEN.TAG_OPEN, resulting_string);
6038 }
6039 }
6040 return token;
6041 };
6042
6043 Tokenizer.prototype._read_open_handlebars = function(c, open_token) {
6044 var resulting_string = null;
6045 var token = null;
6046 if (!open_token) {
6047 if (this._options.indent_handlebars && c === '{' && this._input.peek(1) === '{') {
6048 if (this._input.peek(2) === '!') {
6049 resulting_string = this.__patterns.handlebars_comment.read();
6050 resulting_string = resulting_string || this.__patterns.handlebars.read();
6051 token = this._create_token(TOKEN.COMMENT, resulting_string);
6052 } else {
6053 resulting_string = this.__patterns.handlebars_open.read();
6054 token = this._create_token(TOKEN.TAG_OPEN, resulting_string);
6055 }
6056 }
6057 }
6058 return token;
6059 };
6060
6061
6062 Tokenizer.prototype._read_close = function(c, open_token) {
6063 var resulting_string = null;
6064 var token = null;
6065 if (open_token) {
6066 if (open_token.text[0] === '<' && (c === '>' || (c === '/' && this._input.peek(1) === '>'))) {
6067 resulting_string = this._input.next();
6068 if (c === '/') { // for close tag "/>"
6069 resulting_string += this._input.next();
6070 }
6071 token = this._create_token(TOKEN.TAG_CLOSE, resulting_string);
6072 } else if (open_token.text[0] === '{' && c === '}' && this._input.peek(1) === '}') {
6073 this._input.next();
6074 this._input.next();
6075 token = this._create_token(TOKEN.TAG_CLOSE, '}}');
6076 }
6077 }
6078
6079 return token;
6080 };
6081
6082 Tokenizer.prototype._read_attribute = function(c, previous_token, open_token) {
6083 var token = null;
6084 var resulting_string = '';
6085 if (open_token && open_token.text[0] === '<') {
6086
6087 if (c === '=') {
6088 token = this._create_token(TOKEN.EQUALS, this._input.next());
6089 } else if (c === '"' || c === "'") {
6090 var content = this._input.next();
6091 if (c === '"') {
6092 content += this.__patterns.double_quote.read();
6093 } else {
6094 content += this.__patterns.single_quote.read();
6095 }
6096 token = this._create_token(TOKEN.VALUE, content);
6097 } else {
6098 resulting_string = this.__patterns.attribute.read();
6099
6100 if (resulting_string) {
6101 if (previous_token.type === TOKEN.EQUALS) {
6102 token = this._create_token(TOKEN.VALUE, resulting_string);
6103 } else {
6104 token = this._create_token(TOKEN.ATTRIBUTE, resulting_string);
6105 }
6106 }
6107 }
6108 }
6109 return token;
6110 };
6111
6112 Tokenizer.prototype._is_content_unformatted = function(tag_name) {
6113 // void_elements have no content and so cannot have unformatted content
6114 // script and style tags should always be read as unformatted content
6115 // finally content_unformatted and unformatted element contents are unformatted
6116 return this._options.void_elements.indexOf(tag_name) === -1 &&
6117 (this._options.content_unformatted.indexOf(tag_name) !== -1 ||
6118 this._options.unformatted.indexOf(tag_name) !== -1);
6119 };
6120
6121
6122 Tokenizer.prototype._read_raw_content = function(c, previous_token, open_token) { // jshint unused:false
6123 var resulting_string = '';
6124 if (open_token && open_token.text[0] === '{') {
6125 resulting_string = this.__patterns.handlebars_raw_close.read();
6126 } else if (previous_token.type === TOKEN.TAG_CLOSE &&
6127 previous_token.opened.text[0] === '<' && previous_token.text[0] !== '/') {
6128 // ^^ empty tag has no content
6129 var tag_name = previous_token.opened.text.substr(1).toLowerCase();
6130 if (tag_name === 'script' || tag_name === 'style') {
6131 // Script and style tags are allowed to have comments wrapping their content
6132 // or just have regular content.
6133 var token = this._read_comment_or_cdata(c);
6134 if (token) {
6135 token.type = TOKEN.TEXT;
6136 return token;
6137 }
6138 resulting_string = this._input.readUntil(new RegExp('</' + tag_name + '[\\n\\r\\t ]*?>', 'ig'));
6139 } else if (this._is_content_unformatted(tag_name)) {
6140
6141 resulting_string = this._input.readUntil(new RegExp('</' + tag_name + '[\\n\\r\\t ]*?>', 'ig'));
6142 }
6143 }
6144
6145 if (resulting_string) {
6146 return this._create_token(TOKEN.TEXT, resulting_string);
6147 }
6148
6149 return null;
6150 };
6151
6152 Tokenizer.prototype._read_content_word = function(c) {
6153 var resulting_string = '';
6154 if (this._options.unformatted_content_delimiter) {
6155 if (c === this._options.unformatted_content_delimiter[0]) {
6156 resulting_string = this.__patterns.unformatted_content_delimiter.read();
6157 }
6158 }
6159
6160 if (!resulting_string) {
6161 resulting_string = this.__patterns.word.read();
6162 }
6163 if (resulting_string) {
6164 return this._create_token(TOKEN.TEXT, resulting_string);
6165 }
6166 };
6167
6168 tokenizer.Tokenizer = Tokenizer;
6169 tokenizer.TOKEN = TOKEN;
6170 return tokenizer;
6171}
6172
6173/*jshint node:true */
6174
6175var hasRequiredBeautifier;
6176
6177function requireBeautifier () {
6178 if (hasRequiredBeautifier) return beautifier;
6179 hasRequiredBeautifier = 1;
6180
6181 var Options = requireOptions().Options;
6182 var Output = requireOutput().Output;
6183 var Tokenizer = requireTokenizer().Tokenizer;
6184 var TOKEN = requireTokenizer().TOKEN;
6185
6186 var lineBreak = /\r\n|[\r\n]/;
6187 var allLineBreaks = /\r\n|[\r\n]/g;
6188
6189 var Printer = function(options, base_indent_string) { //handles input/output and some other printing functions
6190
6191 this.indent_level = 0;
6192 this.alignment_size = 0;
6193 this.max_preserve_newlines = options.max_preserve_newlines;
6194 this.preserve_newlines = options.preserve_newlines;
6195
6196 this._output = new Output(options, base_indent_string);
6197
6198 };
6199
6200 Printer.prototype.current_line_has_match = function(pattern) {
6201 return this._output.current_line.has_match(pattern);
6202 };
6203
6204 Printer.prototype.set_space_before_token = function(value, non_breaking) {
6205 this._output.space_before_token = value;
6206 this._output.non_breaking_space = non_breaking;
6207 };
6208
6209 Printer.prototype.set_wrap_point = function() {
6210 this._output.set_indent(this.indent_level, this.alignment_size);
6211 this._output.set_wrap_point();
6212 };
6213
6214
6215 Printer.prototype.add_raw_token = function(token) {
6216 this._output.add_raw_token(token);
6217 };
6218
6219 Printer.prototype.print_preserved_newlines = function(raw_token) {
6220 var newlines = 0;
6221 if (raw_token.type !== TOKEN.TEXT && raw_token.previous.type !== TOKEN.TEXT) {
6222 newlines = raw_token.newlines ? 1 : 0;
6223 }
6224
6225 if (this.preserve_newlines) {
6226 newlines = raw_token.newlines < this.max_preserve_newlines + 1 ? raw_token.newlines : this.max_preserve_newlines + 1;
6227 }
6228 for (var n = 0; n < newlines; n++) {
6229 this.print_newline(n > 0);
6230 }
6231
6232 return newlines !== 0;
6233 };
6234
6235 Printer.prototype.traverse_whitespace = function(raw_token) {
6236 if (raw_token.whitespace_before || raw_token.newlines) {
6237 if (!this.print_preserved_newlines(raw_token)) {
6238 this._output.space_before_token = true;
6239 }
6240 return true;
6241 }
6242 return false;
6243 };
6244
6245 Printer.prototype.previous_token_wrapped = function() {
6246 return this._output.previous_token_wrapped;
6247 };
6248
6249 Printer.prototype.print_newline = function(force) {
6250 this._output.add_new_line(force);
6251 };
6252
6253 Printer.prototype.print_token = function(token) {
6254 if (token.text) {
6255 this._output.set_indent(this.indent_level, this.alignment_size);
6256 this._output.add_token(token.text);
6257 }
6258 };
6259
6260 Printer.prototype.indent = function() {
6261 this.indent_level++;
6262 };
6263
6264 Printer.prototype.get_full_indent = function(level) {
6265 level = this.indent_level + (level || 0);
6266 if (level < 1) {
6267 return '';
6268 }
6269
6270 return this._output.get_indent_string(level);
6271 };
6272
6273 var get_type_attribute = function(start_token) {
6274 var result = null;
6275 var raw_token = start_token.next;
6276
6277 // Search attributes for a type attribute
6278 while (raw_token.type !== TOKEN.EOF && start_token.closed !== raw_token) {
6279 if (raw_token.type === TOKEN.ATTRIBUTE && raw_token.text === 'type') {
6280 if (raw_token.next && raw_token.next.type === TOKEN.EQUALS &&
6281 raw_token.next.next && raw_token.next.next.type === TOKEN.VALUE) {
6282 result = raw_token.next.next.text;
6283 }
6284 break;
6285 }
6286 raw_token = raw_token.next;
6287 }
6288
6289 return result;
6290 };
6291
6292 var get_custom_beautifier_name = function(tag_check, raw_token) {
6293 var typeAttribute = null;
6294 var result = null;
6295
6296 if (!raw_token.closed) {
6297 return null;
6298 }
6299
6300 if (tag_check === 'script') {
6301 typeAttribute = 'text/javascript';
6302 } else if (tag_check === 'style') {
6303 typeAttribute = 'text/css';
6304 }
6305
6306 typeAttribute = get_type_attribute(raw_token) || typeAttribute;
6307
6308 // For script and style tags that have a type attribute, only enable custom beautifiers for matching values
6309 // For those without a type attribute use default;
6310 if (typeAttribute.search('text/css') > -1) {
6311 result = 'css';
6312 } else if (typeAttribute.search(/module|((text|application|dojo)\/(x-)?(javascript|ecmascript|jscript|livescript|(ld\+)?json|method|aspect))/) > -1) {
6313 result = 'javascript';
6314 } else if (typeAttribute.search(/(text|application|dojo)\/(x-)?(html)/) > -1) {
6315 result = 'html';
6316 } else if (typeAttribute.search(/test\/null/) > -1) {
6317 // Test only mime-type for testing the beautifier when null is passed as beautifing function
6318 result = 'null';
6319 }
6320
6321 return result;
6322 };
6323
6324 function in_array(what, arr) {
6325 return arr.indexOf(what) !== -1;
6326 }
6327
6328 function TagFrame(parent, parser_token, indent_level) {
6329 this.parent = parent || null;
6330 this.tag = parser_token ? parser_token.tag_name : '';
6331 this.indent_level = indent_level || 0;
6332 this.parser_token = parser_token || null;
6333 }
6334
6335 function TagStack(printer) {
6336 this._printer = printer;
6337 this._current_frame = null;
6338 }
6339
6340 TagStack.prototype.get_parser_token = function() {
6341 return this._current_frame ? this._current_frame.parser_token : null;
6342 };
6343
6344 TagStack.prototype.record_tag = function(parser_token) { //function to record a tag and its parent in this.tags Object
6345 var new_frame = new TagFrame(this._current_frame, parser_token, this._printer.indent_level);
6346 this._current_frame = new_frame;
6347 };
6348
6349 TagStack.prototype._try_pop_frame = function(frame) { //function to retrieve the opening tag to the corresponding closer
6350 var parser_token = null;
6351
6352 if (frame) {
6353 parser_token = frame.parser_token;
6354 this._printer.indent_level = frame.indent_level;
6355 this._current_frame = frame.parent;
6356 }
6357
6358 return parser_token;
6359 };
6360
6361 TagStack.prototype._get_frame = function(tag_list, stop_list) { //function to retrieve the opening tag to the corresponding closer
6362 var frame = this._current_frame;
6363
6364 while (frame) { //till we reach '' (the initial value);
6365 if (tag_list.indexOf(frame.tag) !== -1) { //if this is it use it
6366 break;
6367 } else if (stop_list && stop_list.indexOf(frame.tag) !== -1) {
6368 frame = null;
6369 break;
6370 }
6371 frame = frame.parent;
6372 }
6373
6374 return frame;
6375 };
6376
6377 TagStack.prototype.try_pop = function(tag, stop_list) { //function to retrieve the opening tag to the corresponding closer
6378 var frame = this._get_frame([tag], stop_list);
6379 return this._try_pop_frame(frame);
6380 };
6381
6382 TagStack.prototype.indent_to_tag = function(tag_list) {
6383 var frame = this._get_frame(tag_list);
6384 if (frame) {
6385 this._printer.indent_level = frame.indent_level;
6386 }
6387 };
6388
6389 function Beautifier(source_text, options, js_beautify, css_beautify) {
6390 //Wrapper function to invoke all the necessary constructors and deal with the output.
6391 this._source_text = source_text || '';
6392 options = options || {};
6393 this._js_beautify = js_beautify;
6394 this._css_beautify = css_beautify;
6395 this._tag_stack = null;
6396
6397 // Allow the setting of language/file-type specific options
6398 // with inheritance of overall settings
6399 var optionHtml = new Options(options, 'html');
6400
6401 this._options = optionHtml;
6402
6403 this._is_wrap_attributes_force = this._options.wrap_attributes.substr(0, 'force'.length) === 'force';
6404 this._is_wrap_attributes_force_expand_multiline = (this._options.wrap_attributes === 'force-expand-multiline');
6405 this._is_wrap_attributes_force_aligned = (this._options.wrap_attributes === 'force-aligned');
6406 this._is_wrap_attributes_aligned_multiple = (this._options.wrap_attributes === 'aligned-multiple');
6407 this._is_wrap_attributes_preserve = this._options.wrap_attributes.substr(0, 'preserve'.length) === 'preserve';
6408 this._is_wrap_attributes_preserve_aligned = (this._options.wrap_attributes === 'preserve-aligned');
6409 }
6410
6411 Beautifier.prototype.beautify = function() {
6412
6413 // if disabled, return the input unchanged.
6414 if (this._options.disabled) {
6415 return this._source_text;
6416 }
6417
6418 var source_text = this._source_text;
6419 var eol = this._options.eol;
6420 if (this._options.eol === 'auto') {
6421 eol = '\n';
6422 if (source_text && lineBreak.test(source_text)) {
6423 eol = source_text.match(lineBreak)[0];
6424 }
6425 }
6426
6427 // HACK: newline parsing inconsistent. This brute force normalizes the input.
6428 source_text = source_text.replace(allLineBreaks, '\n');
6429
6430 var baseIndentString = source_text.match(/^[\t ]*/)[0];
6431
6432 var last_token = {
6433 text: '',
6434 type: ''
6435 };
6436
6437 var last_tag_token = new TagOpenParserToken();
6438
6439 var printer = new Printer(this._options, baseIndentString);
6440 var tokens = new Tokenizer(source_text, this._options).tokenize();
6441
6442 this._tag_stack = new TagStack(printer);
6443
6444 var parser_token = null;
6445 var raw_token = tokens.next();
6446 while (raw_token.type !== TOKEN.EOF) {
6447
6448 if (raw_token.type === TOKEN.TAG_OPEN || raw_token.type === TOKEN.COMMENT) {
6449 parser_token = this._handle_tag_open(printer, raw_token, last_tag_token, last_token, tokens);
6450 last_tag_token = parser_token;
6451 } else if ((raw_token.type === TOKEN.ATTRIBUTE || raw_token.type === TOKEN.EQUALS || raw_token.type === TOKEN.VALUE) ||
6452 (raw_token.type === TOKEN.TEXT && !last_tag_token.tag_complete)) {
6453 parser_token = this._handle_inside_tag(printer, raw_token, last_tag_token, last_token);
6454 } else if (raw_token.type === TOKEN.TAG_CLOSE) {
6455 parser_token = this._handle_tag_close(printer, raw_token, last_tag_token);
6456 } else if (raw_token.type === TOKEN.TEXT) {
6457 parser_token = this._handle_text(printer, raw_token, last_tag_token);
6458 } else {
6459 // This should never happen, but if it does. Print the raw token
6460 printer.add_raw_token(raw_token);
6461 }
6462
6463 last_token = parser_token;
6464
6465 raw_token = tokens.next();
6466 }
6467 var sweet_code = printer._output.get_code(eol);
6468
6469 return sweet_code;
6470 };
6471
6472 Beautifier.prototype._handle_tag_close = function(printer, raw_token, last_tag_token) {
6473 var parser_token = {
6474 text: raw_token.text,
6475 type: raw_token.type
6476 };
6477 printer.alignment_size = 0;
6478 last_tag_token.tag_complete = true;
6479
6480 printer.set_space_before_token(raw_token.newlines || raw_token.whitespace_before !== '', true);
6481 if (last_tag_token.is_unformatted) {
6482 printer.add_raw_token(raw_token);
6483 } else {
6484 if (last_tag_token.tag_start_char === '<') {
6485 printer.set_space_before_token(raw_token.text[0] === '/', true); // space before />, no space before >
6486 if (this._is_wrap_attributes_force_expand_multiline && last_tag_token.has_wrapped_attrs) {
6487 printer.print_newline(false);
6488 }
6489 }
6490 printer.print_token(raw_token);
6491
6492 }
6493
6494 if (last_tag_token.indent_content &&
6495 !(last_tag_token.is_unformatted || last_tag_token.is_content_unformatted)) {
6496 printer.indent();
6497
6498 // only indent once per opened tag
6499 last_tag_token.indent_content = false;
6500 }
6501
6502 if (!last_tag_token.is_inline_element &&
6503 !(last_tag_token.is_unformatted || last_tag_token.is_content_unformatted)) {
6504 printer.set_wrap_point();
6505 }
6506
6507 return parser_token;
6508 };
6509
6510 Beautifier.prototype._handle_inside_tag = function(printer, raw_token, last_tag_token, last_token) {
6511 var wrapped = last_tag_token.has_wrapped_attrs;
6512 var parser_token = {
6513 text: raw_token.text,
6514 type: raw_token.type
6515 };
6516
6517 printer.set_space_before_token(raw_token.newlines || raw_token.whitespace_before !== '', true);
6518 if (last_tag_token.is_unformatted) {
6519 printer.add_raw_token(raw_token);
6520 } else if (last_tag_token.tag_start_char === '{' && raw_token.type === TOKEN.TEXT) {
6521 // For the insides of handlebars allow newlines or a single space between open and contents
6522 if (printer.print_preserved_newlines(raw_token)) {
6523 raw_token.newlines = 0;
6524 printer.add_raw_token(raw_token);
6525 } else {
6526 printer.print_token(raw_token);
6527 }
6528 } else {
6529 if (raw_token.type === TOKEN.ATTRIBUTE) {
6530 printer.set_space_before_token(true);
6531 } else if (raw_token.type === TOKEN.EQUALS) { //no space before =
6532 printer.set_space_before_token(false);
6533 } else if (raw_token.type === TOKEN.VALUE && raw_token.previous.type === TOKEN.EQUALS) { //no space before value
6534 printer.set_space_before_token(false);
6535 }
6536
6537 if (raw_token.type === TOKEN.ATTRIBUTE && last_tag_token.tag_start_char === '<') {
6538 if (this._is_wrap_attributes_preserve || this._is_wrap_attributes_preserve_aligned) {
6539 printer.traverse_whitespace(raw_token);
6540 wrapped = wrapped || raw_token.newlines !== 0;
6541 }
6542
6543 // Wrap for 'force' options, and if the number of attributes is at least that specified in 'wrap_attributes_min_attrs':
6544 // 1. always wrap the second and beyond attributes
6545 // 2. wrap the first attribute only if 'force-expand-multiline' is specified
6546 if (this._is_wrap_attributes_force &&
6547 last_tag_token.attr_count >= this._options.wrap_attributes_min_attrs &&
6548 (last_token.type !== TOKEN.TAG_OPEN || // ie. second attribute and beyond
6549 this._is_wrap_attributes_force_expand_multiline)) {
6550 printer.print_newline(false);
6551 wrapped = true;
6552 }
6553 }
6554 printer.print_token(raw_token);
6555 wrapped = wrapped || printer.previous_token_wrapped();
6556 last_tag_token.has_wrapped_attrs = wrapped;
6557 }
6558 return parser_token;
6559 };
6560
6561 Beautifier.prototype._handle_text = function(printer, raw_token, last_tag_token) {
6562 var parser_token = {
6563 text: raw_token.text,
6564 type: 'TK_CONTENT'
6565 };
6566 if (last_tag_token.custom_beautifier_name) { //check if we need to format javascript
6567 this._print_custom_beatifier_text(printer, raw_token, last_tag_token);
6568 } else if (last_tag_token.is_unformatted || last_tag_token.is_content_unformatted) {
6569 printer.add_raw_token(raw_token);
6570 } else {
6571 printer.traverse_whitespace(raw_token);
6572 printer.print_token(raw_token);
6573 }
6574 return parser_token;
6575 };
6576
6577 Beautifier.prototype._print_custom_beatifier_text = function(printer, raw_token, last_tag_token) {
6578 var local = this;
6579 if (raw_token.text !== '') {
6580
6581 var text = raw_token.text,
6582 _beautifier,
6583 script_indent_level = 1,
6584 pre = '',
6585 post = '';
6586 if (last_tag_token.custom_beautifier_name === 'javascript' && typeof this._js_beautify === 'function') {
6587 _beautifier = this._js_beautify;
6588 } else if (last_tag_token.custom_beautifier_name === 'css' && typeof this._css_beautify === 'function') {
6589 _beautifier = this._css_beautify;
6590 } else if (last_tag_token.custom_beautifier_name === 'html') {
6591 _beautifier = function(html_source, options) {
6592 var beautifier = new Beautifier(html_source, options, local._js_beautify, local._css_beautify);
6593 return beautifier.beautify();
6594 };
6595 }
6596
6597 if (this._options.indent_scripts === "keep") {
6598 script_indent_level = 0;
6599 } else if (this._options.indent_scripts === "separate") {
6600 script_indent_level = -printer.indent_level;
6601 }
6602
6603 var indentation = printer.get_full_indent(script_indent_level);
6604
6605 // if there is at least one empty line at the end of this text, strip it
6606 // we'll be adding one back after the text but before the containing tag.
6607 text = text.replace(/\n[ \t]*$/, '');
6608
6609 // Handle the case where content is wrapped in a comment or cdata.
6610 if (last_tag_token.custom_beautifier_name !== 'html' &&
6611 text[0] === '<' && text.match(/^(<!--|<!\[CDATA\[)/)) {
6612 var matched = /^(<!--[^\n]*|<!\[CDATA\[)(\n?)([ \t\n]*)([\s\S]*)(-->|]]>)$/.exec(text);
6613
6614 // if we start to wrap but don't finish, print raw
6615 if (!matched) {
6616 printer.add_raw_token(raw_token);
6617 return;
6618 }
6619
6620 pre = indentation + matched[1] + '\n';
6621 text = matched[4];
6622 if (matched[5]) {
6623 post = indentation + matched[5];
6624 }
6625
6626 // if there is at least one empty line at the end of this text, strip it
6627 // we'll be adding one back after the text but before the containing tag.
6628 text = text.replace(/\n[ \t]*$/, '');
6629
6630 if (matched[2] || matched[3].indexOf('\n') !== -1) {
6631 // if the first line of the non-comment text has spaces
6632 // use that as the basis for indenting in null case.
6633 matched = matched[3].match(/[ \t]+$/);
6634 if (matched) {
6635 raw_token.whitespace_before = matched[0];
6636 }
6637 }
6638 }
6639
6640 if (text) {
6641 if (_beautifier) {
6642
6643 // call the Beautifier if avaliable
6644 var Child_options = function() {
6645 this.eol = '\n';
6646 };
6647 Child_options.prototype = this._options.raw_options;
6648 var child_options = new Child_options();
6649 text = _beautifier(indentation + text, child_options);
6650 } else {
6651 // simply indent the string otherwise
6652 var white = raw_token.whitespace_before;
6653 if (white) {
6654 text = text.replace(new RegExp('\n(' + white + ')?', 'g'), '\n');
6655 }
6656
6657 text = indentation + text.replace(/\n/g, '\n' + indentation);
6658 }
6659 }
6660
6661 if (pre) {
6662 if (!text) {
6663 text = pre + post;
6664 } else {
6665 text = pre + text + '\n' + post;
6666 }
6667 }
6668
6669 printer.print_newline(false);
6670 if (text) {
6671 raw_token.text = text;
6672 raw_token.whitespace_before = '';
6673 raw_token.newlines = 0;
6674 printer.add_raw_token(raw_token);
6675 printer.print_newline(true);
6676 }
6677 }
6678 };
6679
6680 Beautifier.prototype._handle_tag_open = function(printer, raw_token, last_tag_token, last_token, tokens) {
6681 var parser_token = this._get_tag_open_token(raw_token);
6682
6683 if ((last_tag_token.is_unformatted || last_tag_token.is_content_unformatted) &&
6684 !last_tag_token.is_empty_element &&
6685 raw_token.type === TOKEN.TAG_OPEN && !parser_token.is_start_tag) {
6686 // End element tags for unformatted or content_unformatted elements
6687 // are printed raw to keep any newlines inside them exactly the same.
6688 printer.add_raw_token(raw_token);
6689 parser_token.start_tag_token = this._tag_stack.try_pop(parser_token.tag_name);
6690 } else {
6691 printer.traverse_whitespace(raw_token);
6692 this._set_tag_position(printer, raw_token, parser_token, last_tag_token, last_token);
6693 if (!parser_token.is_inline_element) {
6694 printer.set_wrap_point();
6695 }
6696 printer.print_token(raw_token);
6697 }
6698
6699 // count the number of attributes
6700 if (parser_token.is_start_tag && this._is_wrap_attributes_force) {
6701 var peek_index = 0;
6702 var peek_token;
6703 do {
6704 peek_token = tokens.peek(peek_index);
6705 if (peek_token.type === TOKEN.ATTRIBUTE) {
6706 parser_token.attr_count += 1;
6707 }
6708 peek_index += 1;
6709 } while (peek_token.type !== TOKEN.EOF && peek_token.type !== TOKEN.TAG_CLOSE);
6710 }
6711
6712 //indent attributes an auto, forced, aligned or forced-align line-wrap
6713 if (this._is_wrap_attributes_force_aligned || this._is_wrap_attributes_aligned_multiple || this._is_wrap_attributes_preserve_aligned) {
6714 parser_token.alignment_size = raw_token.text.length + 1;
6715 }
6716
6717 if (!parser_token.tag_complete && !parser_token.is_unformatted) {
6718 printer.alignment_size = parser_token.alignment_size;
6719 }
6720
6721 return parser_token;
6722 };
6723
6724 var TagOpenParserToken = function(parent, raw_token) {
6725 this.parent = parent || null;
6726 this.text = '';
6727 this.type = 'TK_TAG_OPEN';
6728 this.tag_name = '';
6729 this.is_inline_element = false;
6730 this.is_unformatted = false;
6731 this.is_content_unformatted = false;
6732 this.is_empty_element = false;
6733 this.is_start_tag = false;
6734 this.is_end_tag = false;
6735 this.indent_content = false;
6736 this.multiline_content = false;
6737 this.custom_beautifier_name = null;
6738 this.start_tag_token = null;
6739 this.attr_count = 0;
6740 this.has_wrapped_attrs = false;
6741 this.alignment_size = 0;
6742 this.tag_complete = false;
6743 this.tag_start_char = '';
6744 this.tag_check = '';
6745
6746 if (!raw_token) {
6747 this.tag_complete = true;
6748 } else {
6749 var tag_check_match;
6750
6751 this.tag_start_char = raw_token.text[0];
6752 this.text = raw_token.text;
6753
6754 if (this.tag_start_char === '<') {
6755 tag_check_match = raw_token.text.match(/^<([^\s>]*)/);
6756 this.tag_check = tag_check_match ? tag_check_match[1] : '';
6757 } else {
6758 tag_check_match = raw_token.text.match(/^{{~?(?:[\^]|#\*?)?([^\s}]+)/);
6759 this.tag_check = tag_check_match ? tag_check_match[1] : '';
6760
6761 // handle "{{#> myPartial}}" or "{{~#> myPartial}}"
6762 if ((raw_token.text.startsWith('{{#>') || raw_token.text.startsWith('{{~#>')) && this.tag_check[0] === '>') {
6763 if (this.tag_check === '>' && raw_token.next !== null) {
6764 this.tag_check = raw_token.next.text.split(' ')[0];
6765 } else {
6766 this.tag_check = raw_token.text.split('>')[1];
6767 }
6768 }
6769 }
6770
6771 this.tag_check = this.tag_check.toLowerCase();
6772
6773 if (raw_token.type === TOKEN.COMMENT) {
6774 this.tag_complete = true;
6775 }
6776
6777 this.is_start_tag = this.tag_check.charAt(0) !== '/';
6778 this.tag_name = !this.is_start_tag ? this.tag_check.substr(1) : this.tag_check;
6779 this.is_end_tag = !this.is_start_tag ||
6780 (raw_token.closed && raw_token.closed.text === '/>');
6781
6782 // if whitespace handler ~ included (i.e. {{~#if true}}), handlebars tags start at pos 3 not pos 2
6783 var handlebar_starts = 2;
6784 if (this.tag_start_char === '{' && this.text.length >= 3) {
6785 if (this.text.charAt(2) === '~') {
6786 handlebar_starts = 3;
6787 }
6788 }
6789
6790 // handlebars tags that don't start with # or ^ are single_tags, and so also start and end.
6791 this.is_end_tag = this.is_end_tag ||
6792 (this.tag_start_char === '{' && (this.text.length < 3 || (/[^#\^]/.test(this.text.charAt(handlebar_starts)))));
6793 }
6794 };
6795
6796 Beautifier.prototype._get_tag_open_token = function(raw_token) { //function to get a full tag and parse its type
6797 var parser_token = new TagOpenParserToken(this._tag_stack.get_parser_token(), raw_token);
6798
6799 parser_token.alignment_size = this._options.wrap_attributes_indent_size;
6800
6801 parser_token.is_end_tag = parser_token.is_end_tag ||
6802 in_array(parser_token.tag_check, this._options.void_elements);
6803
6804 parser_token.is_empty_element = parser_token.tag_complete ||
6805 (parser_token.is_start_tag && parser_token.is_end_tag);
6806
6807 parser_token.is_unformatted = !parser_token.tag_complete && in_array(parser_token.tag_check, this._options.unformatted);
6808 parser_token.is_content_unformatted = !parser_token.is_empty_element && in_array(parser_token.tag_check, this._options.content_unformatted);
6809 parser_token.is_inline_element = in_array(parser_token.tag_name, this._options.inline) || (this._options.inline_custom_elements && parser_token.tag_name.includes("-")) || parser_token.tag_start_char === '{';
6810
6811 return parser_token;
6812 };
6813
6814 Beautifier.prototype._set_tag_position = function(printer, raw_token, parser_token, last_tag_token, last_token) {
6815
6816 if (!parser_token.is_empty_element) {
6817 if (parser_token.is_end_tag) { //this tag is a double tag so check for tag-ending
6818 parser_token.start_tag_token = this._tag_stack.try_pop(parser_token.tag_name); //remove it and all ancestors
6819 } else { // it's a start-tag
6820 // check if this tag is starting an element that has optional end element
6821 // and do an ending needed
6822 if (this._do_optional_end_element(parser_token)) {
6823 if (!parser_token.is_inline_element) {
6824 printer.print_newline(false);
6825 }
6826 }
6827
6828 this._tag_stack.record_tag(parser_token); //push it on the tag stack
6829
6830 if ((parser_token.tag_name === 'script' || parser_token.tag_name === 'style') &&
6831 !(parser_token.is_unformatted || parser_token.is_content_unformatted)) {
6832 parser_token.custom_beautifier_name = get_custom_beautifier_name(parser_token.tag_check, raw_token);
6833 }
6834 }
6835 }
6836
6837 if (in_array(parser_token.tag_check, this._options.extra_liners)) { //check if this double needs an extra line
6838 printer.print_newline(false);
6839 if (!printer._output.just_added_blankline()) {
6840 printer.print_newline(true);
6841 }
6842 }
6843
6844 if (parser_token.is_empty_element) { //if this tag name is a single tag type (either in the list or has a closing /)
6845
6846 // if you hit an else case, reset the indent level if you are inside an:
6847 // 'if', 'unless', or 'each' block.
6848 if (parser_token.tag_start_char === '{' && parser_token.tag_check === 'else') {
6849 this._tag_stack.indent_to_tag(['if', 'unless', 'each']);
6850 parser_token.indent_content = true;
6851 // Don't add a newline if opening {{#if}} tag is on the current line
6852 var foundIfOnCurrentLine = printer.current_line_has_match(/{{#if/);
6853 if (!foundIfOnCurrentLine) {
6854 printer.print_newline(false);
6855 }
6856 }
6857
6858 // Don't add a newline before elements that should remain where they are.
6859 if (parser_token.tag_name === '!--' && last_token.type === TOKEN.TAG_CLOSE &&
6860 last_tag_token.is_end_tag && parser_token.text.indexOf('\n') === -1) ; else {
6861 if (!(parser_token.is_inline_element || parser_token.is_unformatted)) {
6862 printer.print_newline(false);
6863 }
6864 this._calcluate_parent_multiline(printer, parser_token);
6865 }
6866 } else if (parser_token.is_end_tag) { //this tag is a double tag so check for tag-ending
6867 var do_end_expand = false;
6868
6869 // deciding whether a block is multiline should not be this hard
6870 do_end_expand = parser_token.start_tag_token && parser_token.start_tag_token.multiline_content;
6871 do_end_expand = do_end_expand || (!parser_token.is_inline_element &&
6872 !(last_tag_token.is_inline_element || last_tag_token.is_unformatted) &&
6873 !(last_token.type === TOKEN.TAG_CLOSE && parser_token.start_tag_token === last_tag_token) &&
6874 last_token.type !== 'TK_CONTENT'
6875 );
6876
6877 if (parser_token.is_content_unformatted || parser_token.is_unformatted) {
6878 do_end_expand = false;
6879 }
6880
6881 if (do_end_expand) {
6882 printer.print_newline(false);
6883 }
6884 } else { // it's a start-tag
6885 parser_token.indent_content = !parser_token.custom_beautifier_name;
6886
6887 if (parser_token.tag_start_char === '<') {
6888 if (parser_token.tag_name === 'html') {
6889 parser_token.indent_content = this._options.indent_inner_html;
6890 } else if (parser_token.tag_name === 'head') {
6891 parser_token.indent_content = this._options.indent_head_inner_html;
6892 } else if (parser_token.tag_name === 'body') {
6893 parser_token.indent_content = this._options.indent_body_inner_html;
6894 }
6895 }
6896
6897 if (!(parser_token.is_inline_element || parser_token.is_unformatted) &&
6898 (last_token.type !== 'TK_CONTENT' || parser_token.is_content_unformatted)) {
6899 printer.print_newline(false);
6900 }
6901
6902 this._calcluate_parent_multiline(printer, parser_token);
6903 }
6904 };
6905
6906 Beautifier.prototype._calcluate_parent_multiline = function(printer, parser_token) {
6907 if (parser_token.parent && printer._output.just_added_newline() &&
6908 !((parser_token.is_inline_element || parser_token.is_unformatted) && parser_token.parent.is_inline_element)) {
6909 parser_token.parent.multiline_content = true;
6910 }
6911 };
6912
6913 //To be used for <p> tag special case:
6914 var p_closers = ['address', 'article', 'aside', 'blockquote', 'details', 'div', 'dl', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hr', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul'];
6915 var p_parent_excludes = ['a', 'audio', 'del', 'ins', 'map', 'noscript', 'video'];
6916
6917 Beautifier.prototype._do_optional_end_element = function(parser_token) {
6918 var result = null;
6919 // NOTE: cases of "if there is no more content in the parent element"
6920 // are handled automatically by the beautifier.
6921 // It assumes parent or ancestor close tag closes all children.
6922 // https://www.w3.org/TR/html5/syntax.html#optional-tags
6923 if (parser_token.is_empty_element || !parser_token.is_start_tag || !parser_token.parent) {
6924 return;
6925
6926 }
6927
6928 if (parser_token.tag_name === 'body') {
6929 // A head element’s end tag may be omitted if the head element is not immediately followed by a space character or a comment.
6930 result = result || this._tag_stack.try_pop('head');
6931
6932 //} else if (parser_token.tag_name === 'body') {
6933 // DONE: A body element’s end tag may be omitted if the body element is not immediately followed by a comment.
6934
6935 } else if (parser_token.tag_name === 'li') {
6936 // An li element’s end tag may be omitted if the li element is immediately followed by another li element or if there is no more content in the parent element.
6937 result = result || this._tag_stack.try_pop('li', ['ol', 'ul', 'menu']);
6938
6939 } else if (parser_token.tag_name === 'dd' || parser_token.tag_name === 'dt') {
6940 // A dd element’s end tag may be omitted if the dd element is immediately followed by another dd element or a dt element, or if there is no more content in the parent element.
6941 // A dt element’s end tag may be omitted if the dt element is immediately followed by another dt element or a dd element.
6942 result = result || this._tag_stack.try_pop('dt', ['dl']);
6943 result = result || this._tag_stack.try_pop('dd', ['dl']);
6944
6945
6946 } else if (parser_token.parent.tag_name === 'p' && p_closers.indexOf(parser_token.tag_name) !== -1) {
6947 // IMPORTANT: this else-if works because p_closers has no overlap with any other element we look for in this method
6948 // check for the parent element is an HTML element that is not an <a>, <audio>, <del>, <ins>, <map>, <noscript>, or <video> element, or an autonomous custom element.
6949 // To do this right, this needs to be coded as an inclusion of the inverse of the exclusion above.
6950 // But to start with (if we ignore "autonomous custom elements") the exclusion would be fine.
6951 var p_parent = parser_token.parent.parent;
6952 if (!p_parent || p_parent_excludes.indexOf(p_parent.tag_name) === -1) {
6953 result = result || this._tag_stack.try_pop('p');
6954 }
6955 } else if (parser_token.tag_name === 'rp' || parser_token.tag_name === 'rt') {
6956 // An rt element’s end tag may be omitted if the rt element is immediately followed by an rt or rp element, or if there is no more content in the parent element.
6957 // An rp element’s end tag may be omitted if the rp element is immediately followed by an rt or rp element, or if there is no more content in the parent element.
6958 result = result || this._tag_stack.try_pop('rt', ['ruby', 'rtc']);
6959 result = result || this._tag_stack.try_pop('rp', ['ruby', 'rtc']);
6960
6961 } else if (parser_token.tag_name === 'optgroup') {
6962 // An optgroup element’s end tag may be omitted if the optgroup element is immediately followed by another optgroup element, or if there is no more content in the parent element.
6963 // An option element’s end tag may be omitted if the option element is immediately followed by another option element, or if it is immediately followed by an optgroup element, or if there is no more content in the parent element.
6964 result = result || this._tag_stack.try_pop('optgroup', ['select']);
6965 //result = result || this._tag_stack.try_pop('option', ['select']);
6966
6967 } else if (parser_token.tag_name === 'option') {
6968 // An option element’s end tag may be omitted if the option element is immediately followed by another option element, or if it is immediately followed by an optgroup element, or if there is no more content in the parent element.
6969 result = result || this._tag_stack.try_pop('option', ['select', 'datalist', 'optgroup']);
6970
6971 } else if (parser_token.tag_name === 'colgroup') {
6972 // DONE: A colgroup element’s end tag may be omitted if the colgroup element is not immediately followed by a space character or a comment.
6973 // A caption element's end tag may be ommitted if a colgroup, thead, tfoot, tbody, or tr element is started.
6974 result = result || this._tag_stack.try_pop('caption', ['table']);
6975
6976 } else if (parser_token.tag_name === 'thead') {
6977 // A colgroup element's end tag may be ommitted if a thead, tfoot, tbody, or tr element is started.
6978 // A caption element's end tag may be ommitted if a colgroup, thead, tfoot, tbody, or tr element is started.
6979 result = result || this._tag_stack.try_pop('caption', ['table']);
6980 result = result || this._tag_stack.try_pop('colgroup', ['table']);
6981
6982 //} else if (parser_token.tag_name === 'caption') {
6983 // DONE: A caption element’s end tag may be omitted if the caption element is not immediately followed by a space character or a comment.
6984
6985 } else if (parser_token.tag_name === 'tbody' || parser_token.tag_name === 'tfoot') {
6986 // A thead element’s end tag may be omitted if the thead element is immediately followed by a tbody or tfoot element.
6987 // A tbody element’s end tag may be omitted if the tbody element is immediately followed by a tbody or tfoot element, or if there is no more content in the parent element.
6988 // A colgroup element's end tag may be ommitted if a thead, tfoot, tbody, or tr element is started.
6989 // A caption element's end tag may be ommitted if a colgroup, thead, tfoot, tbody, or tr element is started.
6990 result = result || this._tag_stack.try_pop('caption', ['table']);
6991 result = result || this._tag_stack.try_pop('colgroup', ['table']);
6992 result = result || this._tag_stack.try_pop('thead', ['table']);
6993 result = result || this._tag_stack.try_pop('tbody', ['table']);
6994
6995 //} else if (parser_token.tag_name === 'tfoot') {
6996 // DONE: A tfoot element’s end tag may be omitted if there is no more content in the parent element.
6997
6998 } else if (parser_token.tag_name === 'tr') {
6999 // A tr element’s end tag may be omitted if the tr element is immediately followed by another tr element, or if there is no more content in the parent element.
7000 // A colgroup element's end tag may be ommitted if a thead, tfoot, tbody, or tr element is started.
7001 // A caption element's end tag may be ommitted if a colgroup, thead, tfoot, tbody, or tr element is started.
7002 result = result || this._tag_stack.try_pop('caption', ['table']);
7003 result = result || this._tag_stack.try_pop('colgroup', ['table']);
7004 result = result || this._tag_stack.try_pop('tr', ['table', 'thead', 'tbody', 'tfoot']);
7005
7006 } else if (parser_token.tag_name === 'th' || parser_token.tag_name === 'td') {
7007 // A td element’s end tag may be omitted if the td element is immediately followed by a td or th element, or if there is no more content in the parent element.
7008 // A th element’s end tag may be omitted if the th element is immediately followed by a td or th element, or if there is no more content in the parent element.
7009 result = result || this._tag_stack.try_pop('td', ['table', 'thead', 'tbody', 'tfoot', 'tr']);
7010 result = result || this._tag_stack.try_pop('th', ['table', 'thead', 'tbody', 'tfoot', 'tr']);
7011 }
7012
7013 // Start element omission not handled currently
7014 // A head element’s start tag may be omitted if the element is empty, or if the first thing inside the head element is an element.
7015 // A tbody element’s start tag may be omitted if the first thing inside the tbody element is a tr element, and if the element is not immediately preceded by a tbody, thead, or tfoot element whose end tag has been omitted. (It can’t be omitted if the element is empty.)
7016 // A colgroup element’s start tag may be omitted if the first thing inside the colgroup element is a col element, and if the element is not immediately preceded by another colgroup element whose end tag has been omitted. (It can’t be omitted if the element is empty.)
7017
7018 // Fix up the parent of the parser token
7019 parser_token.parent = this._tag_stack.get_parser_token();
7020
7021 return result;
7022 };
7023
7024 beautifier.Beautifier = Beautifier;
7025 return beautifier;
7026}
7027
7028/*jshint node:true */
7029
7030var hasRequiredHtml;
7031
7032function requireHtml () {
7033 if (hasRequiredHtml) return html.exports;
7034 hasRequiredHtml = 1;
7035
7036 var Beautifier = requireBeautifier().Beautifier,
7037 Options = requireOptions().Options;
7038
7039 function style_html(html_source, options, js_beautify, css_beautify) {
7040 var beautifier = new Beautifier(html_source, options, js_beautify, css_beautify);
7041 return beautifier.beautify();
7042 }
7043
7044 html.exports = style_html;
7045 html.exports.defaultOptions = function() {
7046 return new Options();
7047 };
7048 return html.exports;
7049}
7050
7051/*jshint node:true */
7052
7053var hasRequiredSrc;
7054
7055function requireSrc () {
7056 if (hasRequiredSrc) return src;
7057 hasRequiredSrc = 1;
7058
7059 var js_beautify = requireJavascript();
7060 var css_beautify = requireCss();
7061 var html_beautify = requireHtml();
7062
7063 function style_html(html_source, options, js, css) {
7064 js = js || js_beautify;
7065 css = css || css_beautify;
7066 return html_beautify(html_source, options, js, css);
7067 }
7068 style_html.defaultOptions = html_beautify.defaultOptions;
7069
7070 src.js = js_beautify;
7071 src.css = css_beautify;
7072 src.html = style_html;
7073 return src;
7074}
7075
7076/*jshint node:true */
7077
7078(function (module) {
7079
7080 /**
7081 The following batches are equivalent:
7082
7083 var beautify_js = require('js-beautify');
7084 var beautify_js = require('js-beautify').js;
7085 var beautify_js = require('js-beautify').js_beautify;
7086
7087 var beautify_css = require('js-beautify').css;
7088 var beautify_css = require('js-beautify').css_beautify;
7089
7090 var beautify_html = require('js-beautify').html;
7091 var beautify_html = require('js-beautify').html_beautify;
7092
7093 All methods returned accept two arguments, the source string and an options object.
7094 **/
7095
7096 function get_beautify(js_beautify, css_beautify, html_beautify) {
7097 // the default is js
7098 var beautify = function(src, config) {
7099 return js_beautify.js_beautify(src, config);
7100 };
7101
7102 // short aliases
7103 beautify.js = js_beautify.js_beautify;
7104 beautify.css = css_beautify.css_beautify;
7105 beautify.html = html_beautify.html_beautify;
7106
7107 // legacy aliases
7108 beautify.js_beautify = js_beautify.js_beautify;
7109 beautify.css_beautify = css_beautify.css_beautify;
7110 beautify.html_beautify = html_beautify.html_beautify;
7111
7112 return beautify;
7113 }
7114
7115 {
7116 (function(mod) {
7117 var beautifier = requireSrc();
7118 beautifier.js_beautify = beautifier.js;
7119 beautifier.css_beautify = beautifier.css;
7120 beautifier.html_beautify = beautifier.html;
7121
7122 mod.exports = get_beautify(beautifier, beautifier, beautifier);
7123
7124 })(module);
7125 }
7126} (js));
7127
7128var jsExports = js.exports;
7129var beautify = /*@__PURE__*/getDefaultExportFromCjs(jsExports);
7130
7131var BaseWrapper = /** @class */ (function () {
7132 function BaseWrapper(element) {
7133 var _this = this;
7134 this.isDisabled = function () {
7135 var validTagsToBeDisabled = [
7136 'BUTTON',
7137 'COMMAND',
7138 'FIELDSET',
7139 'KEYGEN',
7140 'OPTGROUP',
7141 'OPTION',
7142 'SELECT',
7143 'TEXTAREA',
7144 'INPUT'
7145 ];
7146 var hasDisabledAttribute = _this.attributes().disabled !== undefined;
7147 var elementCanBeDisabled = isElement(_this.element) &&
7148 validTagsToBeDisabled.includes(_this.element.tagName);
7149 return hasDisabledAttribute && elementCanBeDisabled;
7150 };
7151 this.wrapperElement = element;
7152 }
7153 Object.defineProperty(BaseWrapper.prototype, "element", {
7154 get: function () {
7155 return this.wrapperElement;
7156 },
7157 enumerable: false,
7158 configurable: true
7159 });
7160 BaseWrapper.prototype.findAllDOMElements = function (selector) {
7161 var elementRootNodes = this.getRootNodes().filter(isElement);
7162 if (elementRootNodes.length === 0)
7163 return [];
7164 var result = __spreadArray([], elementRootNodes.filter(function (node) { return node.matches(selector); }), true);
7165 elementRootNodes.forEach(function (rootNode) {
7166 result.push.apply(result, Array.from(rootNode.querySelectorAll(selector)));
7167 });
7168 return result;
7169 };
7170 BaseWrapper.prototype.find = function (selector) {
7171 if (typeof selector === 'object' && 'ref' in selector) {
7172 var currentComponent = this.getCurrentComponent();
7173 if (!currentComponent) {
7174 return createWrapperError('DOMWrapper');
7175 }
7176 var result = currentComponent.refs[selector.ref];
7177 // When using ref inside v-for, then refs contains array of component instances and nodes
7178 if (Array.isArray(result)) {
7179 result = result.length ? result[0] : undefined;
7180 }
7181 if (result instanceof Node) {
7182 return createDOMWrapper(result);
7183 }
7184 else {
7185 return createWrapperError('DOMWrapper');
7186 }
7187 }
7188 var elements = this.findAll(selector);
7189 if (elements.length > 0) {
7190 return elements[0];
7191 }
7192 return createWrapperError('DOMWrapper');
7193 };
7194 BaseWrapper.prototype.findComponent = function (selector) {
7195 var currentComponent = this.getCurrentComponent();
7196 if (!currentComponent) {
7197 return createWrapperError('VueWrapper');
7198 }
7199 if (typeof selector === 'object' && 'ref' in selector) {
7200 var result_1 = currentComponent.refs[selector.ref];
7201 // When using ref inside v-for, then refs contains array of component instances
7202 if (Array.isArray(result_1)) {
7203 result_1 = result_1.length ? result_1[0] : undefined;
7204 }
7205 if (result_1 && !(result_1 instanceof HTMLElement)) {
7206 return createVueWrapper(null, result_1);
7207 }
7208 else {
7209 return createWrapperError('VueWrapper');
7210 }
7211 }
7212 if (matches(currentComponent.vnode, selector) &&
7213 this.element.contains(currentComponent.vnode.el)) {
7214 return createVueWrapper(null, currentComponent.subTree.component
7215 ? currentComponent.subTree.component.proxy
7216 : currentComponent.proxy);
7217 }
7218 var result = this.findAllComponents(selector)[0];
7219 return result !== null && result !== void 0 ? result : createWrapperError('VueWrapper');
7220 };
7221 BaseWrapper.prototype.findAllComponents = function (selector) {
7222 var currentComponent = this.getCurrentComponent();
7223 if (!currentComponent) {
7224 return [];
7225 }
7226 var results = find(currentComponent.subTree, selector);
7227 return results.map(function (c) {
7228 return c.proxy
7229 ? createVueWrapper(null, c.proxy)
7230 : createDOMWrapper(c.vnode.el);
7231 });
7232 };
7233 BaseWrapper.prototype.html = function (options) {
7234 var stringNodes = this.getRootNodes().map(function (node) { return stringifyNode(node); });
7235 if (options === null || options === void 0 ? void 0 : options.raw)
7236 return stringNodes.join('');
7237 return stringNodes
7238 .map(function (node) {
7239 return beautify.html(node, {
7240 unformatted: ['code', 'pre', 'em', 'strong', 'span'],
7241 indent_inner_html: true,
7242 indent_size: 2,
7243 inline_custom_elements: false
7244 // TODO the cast can be removed when @types/js-beautify will be up-to-date
7245 });
7246 })
7247 .join('\n');
7248 };
7249 BaseWrapper.prototype.classes = function (className) {
7250 var classes = isElement(this.element)
7251 ? Array.from(this.element.classList)
7252 : [];
7253 if (className)
7254 return classes.includes(className);
7255 return classes;
7256 };
7257 BaseWrapper.prototype.attributes = function (key) {
7258 var attributeMap = {};
7259 if (isElement(this.element)) {
7260 var attributes = Array.from(this.element.attributes);
7261 for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) {
7262 var attribute = attributes_1[_i];
7263 attributeMap[attribute.localName] = attribute.value;
7264 }
7265 }
7266 return key ? attributeMap[key] : attributeMap;
7267 };
7268 BaseWrapper.prototype.text = function () {
7269 return this.getRootNodes().map(textContent).join('');
7270 };
7271 BaseWrapper.prototype.exists = function () {
7272 return true;
7273 };
7274 BaseWrapper.prototype.get = function (selector) {
7275 var result = this.find(selector);
7276 if (result.exists()) {
7277 return result;
7278 }
7279 throw new Error("Unable to get ".concat(selector, " within: ").concat(this.html()));
7280 };
7281 BaseWrapper.prototype.getComponent = function (selector) {
7282 var result = this.findComponent(selector);
7283 if (result.exists()) {
7284 return result;
7285 }
7286 var message = 'Unable to get ';
7287 if (typeof selector === 'string') {
7288 message += "component with selector ".concat(selector);
7289 }
7290 else if ('name' in selector) {
7291 message += "component with name ".concat(selector.name);
7292 }
7293 else if ('ref' in selector) {
7294 message += "component with ref ".concat(selector.ref);
7295 }
7296 else {
7297 message += 'specified component';
7298 }
7299 message += " within: ".concat(this.html());
7300 throw new Error(message);
7301 };
7302 BaseWrapper.prototype.isVisible = function () {
7303 return isElement(this.element) && isElementVisible(this.element);
7304 };
7305 BaseWrapper.prototype.trigger = function (eventString, options) {
7306 return __awaiter(this, void 0, void 0, function () {
7307 var event_1;
7308 return __generator(this, function (_a) {
7309 if (options && options['target']) {
7310 throw Error("[vue-test-utils]: you cannot set the target value of an event. See the notes section " +
7311 "of the docs for more details\u2014" +
7312 "https://vue-test-utils.vuejs.org/api/wrapper/trigger.html");
7313 }
7314 if (this.element && !this.isDisabled()) {
7315 event_1 = createDOMEvent(eventString, options);
7316 // see https://github.com/vuejs/test-utils/issues/1854
7317 // fakeTimers provoke an issue as Date.now() always return the same value
7318 // and Vue relies on it to determine if the handler should be invoked
7319 // see https://github.com/vuejs/core/blob/5ee40532a63e0b792e0c1eccf3cf68546a4e23e9/packages/runtime-dom/src/modules/events.ts#L100-L104
7320 // we workaround this issue by manually setting _vts to Date.now() + 1
7321 // thus making sure the event handler is invoked
7322 event_1._vts = Date.now() + 1;
7323 this.element.dispatchEvent(event_1);
7324 }
7325 return [2 /*return*/, Vue.nextTick()];
7326 });
7327 });
7328 };
7329 return BaseWrapper;
7330}());
7331
7332var DOMWrapper = /** @class */ (function (_super) {
7333 __extends(DOMWrapper, _super);
7334 function DOMWrapper(element) {
7335 var _this = this;
7336 if (!element) {
7337 return createWrapperError('DOMWrapper');
7338 }
7339 _this = _super.call(this, element) || this;
7340 // plugins hook
7341 config.plugins.DOMWrapper.extend(_this);
7342 return _this;
7343 }
7344 DOMWrapper.prototype.getRootNodes = function () {
7345 return [this.wrapperElement];
7346 };
7347 DOMWrapper.prototype.getCurrentComponent = function () {
7348 var _a;
7349 var component = this.element.__vueParentComponent;
7350 while (((_a = component === null || component === void 0 ? void 0 : component.parent) === null || _a === void 0 ? void 0 : _a.vnode.el) === this.element) {
7351 component = component.parent;
7352 }
7353 return component;
7354 };
7355 DOMWrapper.prototype.find = function (selector) {
7356 var result = _super.prototype.find.call(this, selector);
7357 if (result.exists() && isRefSelector(selector)) {
7358 return this.element.contains(result.element)
7359 ? result
7360 : createWrapperError('DOMWrapper');
7361 }
7362 return result;
7363 };
7364 DOMWrapper.prototype.findAll = function (selector) {
7365 if (!(this.wrapperElement instanceof Element)) {
7366 return [];
7367 }
7368 return Array.from(this.wrapperElement.querySelectorAll(selector), createDOMWrapper);
7369 };
7370 DOMWrapper.prototype.findAllComponents = function (selector) {
7371 var _this = this;
7372 var results = _super.prototype.findAllComponents.call(this, selector);
7373 return results.filter(function (r) { return _this.element.contains(r.element); });
7374 };
7375 DOMWrapper.prototype.setChecked = function () {
7376 return __awaiter(this, arguments, void 0, function (checked) {
7377 var element, type;
7378 if (checked === void 0) { checked = true; }
7379 return __generator(this, function (_a) {
7380 element = this.element;
7381 type = this.attributes().type;
7382 if (type === 'radio' && !checked) {
7383 throw Error("wrapper.setChecked() cannot be called with parameter false on a '<input type=\"radio\" /> element.");
7384 }
7385 // we do not want to trigger an event if the user
7386 // attempting set the same value twice
7387 // this is because in a browser setting checked = true when it is
7388 // already true is a no-op; no change event is triggered
7389 if (checked === element.checked) {
7390 return [2 /*return*/];
7391 }
7392 element.checked = checked;
7393 this.trigger('input');
7394 return [2 /*return*/, this.trigger('change')];
7395 });
7396 });
7397 };
7398 DOMWrapper.prototype.setValue = function (value) {
7399 var element = this.element;
7400 var tagName = element.tagName;
7401 var type = this.attributes().type;
7402 if (tagName === 'OPTION') {
7403 this.setSelected();
7404 return Promise.resolve();
7405 }
7406 else if (tagName === 'INPUT' && type === 'checkbox') {
7407 return this.setChecked(value);
7408 }
7409 else if (tagName === 'INPUT' && type === 'radio') {
7410 return this.setChecked(value);
7411 }
7412 else if (tagName === 'SELECT') {
7413 if (Array.isArray(value)) {
7414 var selectElement = element;
7415 for (var i = 0; i < selectElement.options.length; i++) {
7416 var option = selectElement.options[i];
7417 option.selected = value.includes(option.value);
7418 }
7419 }
7420 else {
7421 element.value = value;
7422 }
7423 this.trigger('input');
7424 return this.trigger('change');
7425 }
7426 else if (tagName === 'INPUT' || tagName === 'TEXTAREA') {
7427 element.value = value;
7428 this.trigger('input');
7429 // trigger `change` for `v-model.lazy`
7430 return this.trigger('change');
7431 }
7432 else {
7433 throw Error("wrapper.setValue() cannot be called on ".concat(tagName));
7434 }
7435 };
7436 DOMWrapper.prototype.setSelected = function () {
7437 var element = this.element;
7438 if (element.selected) {
7439 return;
7440 }
7441 // todo - review all non-null assertion operators in project
7442 // search globally for `!.` and with regex `!$`
7443 element.selected = true;
7444 var parentElement = element.parentElement;
7445 if (parentElement.tagName === 'OPTGROUP') {
7446 parentElement = parentElement.parentElement;
7447 }
7448 var parentWrapper = new DOMWrapper(parentElement);
7449 parentWrapper.trigger('input');
7450 return parentWrapper.trigger('change');
7451 };
7452 return DOMWrapper;
7453}(BaseWrapper));
7454registerFactory(WrapperType.DOMWrapper, function (element) { return new DOMWrapper(element); });
7455
7456function getRootNodes(vnode) {
7457 if (vnode.shapeFlag & 1 /* ShapeFlags.ELEMENT */) {
7458 return [vnode.el];
7459 }
7460 else if (vnode.shapeFlag & 6 /* ShapeFlags.COMPONENT */) {
7461 var subTree = vnode.component.subTree;
7462 return getRootNodes(subTree);
7463 }
7464 else if (vnode.shapeFlag & 128 /* ShapeFlags.SUSPENSE */) {
7465 return getRootNodes(vnode.suspense.activeBranch);
7466 }
7467 else if (vnode.shapeFlag &
7468 (8 /* ShapeFlags.TEXT_CHILDREN */ | 64 /* ShapeFlags.TELEPORT */)) {
7469 // static node optimization, subTree.children will be static string and will not help us
7470 var result = [vnode.el];
7471 if (vnode.anchor) {
7472 var currentNode = result[0].nextSibling;
7473 while (currentNode && currentNode.previousSibling !== vnode.anchor) {
7474 result.push(currentNode);
7475 currentNode = currentNode.nextSibling;
7476 }
7477 }
7478 return result;
7479 }
7480 else if (vnode.shapeFlag & 16 /* ShapeFlags.ARRAY_CHILDREN */) {
7481 var children = vnode.children.flat();
7482 return children
7483 .flatMap(function (vnode) { return getRootNodes(vnode); })
7484 .filter(isNotNullOrUndefined);
7485 }
7486 // Missing cases which do not need special handling:
7487 // ShapeFlags.SLOTS_CHILDREN comes with ShapeFlags.ELEMENT
7488 // Will hit this default when ShapeFlags is 0
7489 // This is the case for example for unresolved async component without loader
7490 return [];
7491}
7492
7493var events = {};
7494function emitted(vm, eventName) {
7495 var cid = vm.$.uid;
7496 var vmEvents = events[cid] || {};
7497 if (eventName) {
7498 return vmEvents ? vmEvents[eventName] : undefined;
7499 }
7500 return vmEvents;
7501}
7502var attachEmitListener = function () {
7503 var target = getGlobalThis();
7504 // override emit to capture events when devtools is defined
7505 if (target.__VUE_DEVTOOLS_GLOBAL_HOOK__) {
7506 var _emit_1 = target.__VUE_DEVTOOLS_GLOBAL_HOOK__.emit;
7507 target.__VUE_DEVTOOLS_GLOBAL_HOOK__.emit = function (eventType) {
7508 var payload = [];
7509 for (var _i = 1; _i < arguments.length; _i++) {
7510 payload[_i - 1] = arguments[_i];
7511 }
7512 _emit_1.call.apply(_emit_1, __spreadArray([target.__VUE_DEVTOOLS_GLOBAL_HOOK__, eventType], payload, false));
7513 captureDevtoolsVueComponentEmitEvent(eventType, payload);
7514 };
7515 }
7516 else {
7517 // use devtools to capture this "emit"
7518 Vue.setDevtoolsHook(createDevTools(), {});
7519 }
7520};
7521function captureDevtoolsVueComponentEmitEvent(eventType, payload) {
7522 if (eventType === "component:emit" /* DevtoolsHooks.COMPONENT_EMIT */) {
7523 payload[0]; var componentVM = payload[1], event_1 = payload[2], eventArgs = payload[3];
7524 recordEvent(componentVM, event_1, eventArgs);
7525 }
7526}
7527// devtools hook only catches Vue component custom events
7528function createDevTools() {
7529 return {
7530 emit: function (eventType) {
7531 var payload = [];
7532 for (var _i = 1; _i < arguments.length; _i++) {
7533 payload[_i - 1] = arguments[_i];
7534 }
7535 captureDevtoolsVueComponentEmitEvent(eventType, payload);
7536 }
7537 };
7538}
7539var recordEvent = function (vm, event, args) {
7540 // Functional component wrapper creates a parent component
7541 var wrapperVm = vm;
7542 while (typeof (wrapperVm === null || wrapperVm === void 0 ? void 0 : wrapperVm.type) === 'function')
7543 wrapperVm = wrapperVm.parent;
7544 var cid = wrapperVm.uid;
7545 if (!(cid in events)) {
7546 events[cid] = {};
7547 }
7548 if (!(event in events[cid])) {
7549 events[cid][event] = [];
7550 }
7551 // Record the event message sent by the emit
7552 events[cid][event].push(args);
7553};
7554var removeEventHistory = function (vm) {
7555 var cid = vm.$.uid;
7556 delete events[cid];
7557};
7558
7559/**
7560 * Creates a proxy around the VM instance.
7561 * This proxy returns the value from the setupState if there is one, or the one from the VM if not.
7562 * See https://github.com/vuejs/core/issues/7103
7563 */
7564function createVMProxy(vm, setupState) {
7565 return new Proxy(vm, {
7566 get: function (vm, key, receiver) {
7567 if (vm.$.exposed && vm.$.exposeProxy && key in vm.$.exposeProxy) {
7568 // first if the key is exposed
7569 return Reflect.get(vm.$.exposeProxy, key, receiver);
7570 }
7571 else if (key in setupState) {
7572 // second if the key is acccessible from the setupState
7573 return Reflect.get(setupState, key, receiver);
7574 }
7575 else if (key in vm.$.appContext.config.globalProperties) {
7576 // third if the key is a global property
7577 return Reflect.get(vm.$.appContext.config.globalProperties, key, receiver);
7578 }
7579 else {
7580 // vm.$.ctx is the internal context of the vm
7581 // with all variables, methods and props
7582 return vm.$.ctx[key];
7583 }
7584 },
7585 set: function (vm, key, value, receiver) {
7586 if (key in setupState) {
7587 return Reflect.set(setupState, key, value, receiver);
7588 }
7589 else {
7590 return Reflect.set(vm, key, value, receiver);
7591 }
7592 },
7593 has: function (vm, property) {
7594 return Reflect.has(setupState, property) || Reflect.has(vm, property);
7595 },
7596 defineProperty: function (vm, key, attributes) {
7597 if (key in setupState) {
7598 return Reflect.defineProperty(setupState, key, attributes);
7599 }
7600 else {
7601 return Reflect.defineProperty(vm, key, attributes);
7602 }
7603 },
7604 getOwnPropertyDescriptor: function (vm, property) {
7605 if (property in setupState) {
7606 return Reflect.getOwnPropertyDescriptor(setupState, property);
7607 }
7608 else {
7609 return Reflect.getOwnPropertyDescriptor(vm, property);
7610 }
7611 },
7612 deleteProperty: function (vm, property) {
7613 if (property in setupState) {
7614 return Reflect.deleteProperty(setupState, property);
7615 }
7616 else {
7617 return Reflect.deleteProperty(vm, property);
7618 }
7619 }
7620 });
7621}
7622var VueWrapper = /** @class */ (function (_super) {
7623 __extends(VueWrapper, _super);
7624 function VueWrapper(app, vm, setProps) {
7625 var _this = _super.call(this, vm === null || vm === void 0 ? void 0 : vm.$el) || this;
7626 _this.cleanUpCallbacks = [];
7627 _this.__app = app;
7628 // root is null on functional components
7629 _this.rootVM = vm === null || vm === void 0 ? void 0 : vm.$root;
7630 // `vm.$.setupState` is what the template has access to
7631 // so even if the component is closed (as they are by default for `script setup`)
7632 // a test will still be able to do something like
7633 // `expect(wrapper.vm.count).toBe(1)`
7634 // if we return it as `vm`
7635 // This does not work for functional components though (as they have no vm)
7636 // or for components with a setup that returns a render function (as they have an empty proxy)
7637 // in both cases, we return `vm` directly instead
7638 if (hasSetupState(vm)) {
7639 _this.componentVM = createVMProxy(vm, vm.$.setupState);
7640 }
7641 else {
7642 _this.componentVM = vm;
7643 }
7644 _this.__setProps = setProps;
7645 _this.attachNativeEventListener();
7646 config.plugins.VueWrapper.extend(_this);
7647 return _this;
7648 }
7649 Object.defineProperty(VueWrapper.prototype, "hasMultipleRoots", {
7650 get: function () {
7651 // Recursive check subtree for nested root elements
7652 // <template>
7653 // <WithMultipleRoots />
7654 // </template>
7655 var checkTree = function (subTree) {
7656 var _a;
7657 // if the subtree is an array of children, we have multiple root nodes
7658 if (subTree.shapeFlag === 16 /* ShapeFlags.ARRAY_CHILDREN */)
7659 return true;
7660 if (subTree.shapeFlag & 4 /* ShapeFlags.STATEFUL_COMPONENT */ ||
7661 subTree.shapeFlag & 2 /* ShapeFlags.FUNCTIONAL_COMPONENT */) {
7662 // We are rendering other component, check it's tree instead
7663 if ((_a = subTree.component) === null || _a === void 0 ? void 0 : _a.subTree) {
7664 return checkTree(subTree.component.subTree);
7665 }
7666 // Component has multiple children
7667 if (subTree.shapeFlag & 16 /* ShapeFlags.ARRAY_CHILDREN */) {
7668 return true;
7669 }
7670 }
7671 return false;
7672 };
7673 return checkTree(this.vm.$.subTree);
7674 },
7675 enumerable: false,
7676 configurable: true
7677 });
7678 VueWrapper.prototype.getRootNodes = function () {
7679 return getRootNodes(this.vm.$.vnode);
7680 };
7681 Object.defineProperty(VueWrapper.prototype, "parentElement", {
7682 get: function () {
7683 return this.vm.$el.parentElement;
7684 },
7685 enumerable: false,
7686 configurable: true
7687 });
7688 VueWrapper.prototype.getCurrentComponent = function () {
7689 return this.vm.$;
7690 };
7691 VueWrapper.prototype.exists = function () {
7692 return !this.getCurrentComponent().isUnmounted;
7693 };
7694 VueWrapper.prototype.findAll = function (selector) {
7695 return this.findAllDOMElements(selector).map(createDOMWrapper);
7696 };
7697 VueWrapper.prototype.attachNativeEventListener = function () {
7698 var vm = this.vm;
7699 if (!vm)
7700 return;
7701 var emits = vm.$options.emits
7702 ? // if emits is declared as an array
7703 Array.isArray(vm.$options.emits)
7704 ? // use it
7705 vm.$options.emits
7706 : // otherwise it's declared as an object
7707 // and we only need the keys
7708 Object.keys(vm.$options.emits)
7709 : [];
7710 var elementRoots = this.getRootNodes().filter(function (node) { return node instanceof Element; });
7711 if (elementRoots.length !== 1) {
7712 return;
7713 }
7714 var element = elementRoots[0];
7715 var _loop_1 = function (eventName) {
7716 // if a component includes events in 'emits' with the same name as native
7717 // events, the native events with that name should be ignored
7718 // @see https://github.com/vuejs/rfcs/blob/master/active-rfcs/0030-emits-option.md#fallthrough-control
7719 if (emits.includes(eventName))
7720 return "continue";
7721 var eventListener = function () {
7722 var args = [];
7723 for (var _i = 0; _i < arguments.length; _i++) {
7724 args[_i] = arguments[_i];
7725 }
7726 recordEvent(vm.$, eventName, args);
7727 };
7728 element.addEventListener(eventName, eventListener);
7729 this_1.cleanUpCallbacks.push(function () {
7730 element.removeEventListener(eventName, eventListener);
7731 });
7732 };
7733 var this_1 = this;
7734 for (var _i = 0, _a = Object.keys(domEvents); _i < _a.length; _i++) {
7735 var eventName = _a[_i];
7736 _loop_1(eventName);
7737 }
7738 };
7739 Object.defineProperty(VueWrapper.prototype, "element", {
7740 get: function () {
7741 // if the component has multiple root elements, we use the parent's element
7742 return this.hasMultipleRoots ? this.parentElement : this.vm.$el;
7743 },
7744 enumerable: false,
7745 configurable: true
7746 });
7747 Object.defineProperty(VueWrapper.prototype, "vm", {
7748 get: function () {
7749 return this.componentVM;
7750 },
7751 enumerable: false,
7752 configurable: true
7753 });
7754 VueWrapper.prototype.props = function (selector) {
7755 var props = this.componentVM.$props;
7756 return selector ? props[selector] : props;
7757 };
7758 VueWrapper.prototype.emitted = function (eventName) {
7759 return emitted(this.vm, eventName);
7760 };
7761 VueWrapper.prototype.isVisible = function () {
7762 var domWrapper = createDOMWrapper(this.element);
7763 return domWrapper.isVisible();
7764 };
7765 VueWrapper.prototype.setData = function (data) {
7766 mergeDeep(this.componentVM.$data, data);
7767 return Vue.nextTick();
7768 };
7769 VueWrapper.prototype.setProps = function (props) {
7770 // if this VM's parent is not the root or if setProps does not exist, error out
7771 if (this.vm.$parent !== this.rootVM || !this.__setProps) {
7772 throw Error('You can only use setProps on your mounted component');
7773 }
7774 this.__setProps(props);
7775 return Vue.nextTick();
7776 };
7777 VueWrapper.prototype.setValue = function (value, prop) {
7778 var propEvent = prop || 'modelValue';
7779 this.vm.$emit("update:".concat(propEvent), value);
7780 return this.vm.$nextTick();
7781 };
7782 VueWrapper.prototype.unmount = function () {
7783 // preventing dispose of child component
7784 if (!this.__app) {
7785 throw new Error("wrapper.unmount() can only be called by the root wrapper");
7786 }
7787 // Clear emitted events cache for this component instance
7788 removeEventHistory(this.vm);
7789 this.cleanUpCallbacks.forEach(function (cb) { return cb(); });
7790 this.cleanUpCallbacks = [];
7791 this.__app.unmount();
7792 };
7793 return VueWrapper;
7794}(BaseWrapper));
7795registerFactory(WrapperType.VueWrapper, function (app, vm, setProps) { return new VueWrapper(app, vm, setProps); });
7796
7797function processSlot(source, Vue) {
7798 if (source === void 0) { source = ''; }
7799 if (Vue === void 0) { Vue = Vue__namespace; }
7800 var template = source.trim();
7801 var hasWrappingTemplate = template && template.startsWith('<template');
7802 // allow content without `template` tag, for easier testing
7803 if (!hasWrappingTemplate) {
7804 template = "<template #default=\"params\">".concat(template, "</template>");
7805 }
7806 // Vue does not provide an easy way to compile template in "slot" mode
7807 // Since we do not want to rely on compiler internals and specify
7808 // transforms manually we create fake component invocation with the slot we
7809 // need and pick slots param from render function later. Fake component will
7810 // never be instantiated but it requires to be a component so compile
7811 // properly generate invocation. Since we do not want to monkey-patch
7812 // `resolveComponent` function we are just using one of built-in components:
7813 // transition
7814 var code = compilerDom.compile("<transition>".concat(template, "</transition>"), {
7815 mode: 'function',
7816 prefixIdentifiers: true
7817 }).code;
7818 var createRenderFunction = new Function('Vue', code);
7819 var renderFn = createRenderFunction(Vue);
7820 return function (ctx) {
7821 if (ctx === void 0) { ctx = {}; }
7822 var result = renderFn(ctx);
7823 var slotName = Object.keys(result.children)[0];
7824 return result.children[slotName](ctx);
7825 };
7826}
7827
7828var isTeleport = function (type) { return type.__isTeleport; };
7829var isKeepAlive = function (type) { return type.__isKeepAlive; };
7830var isRootComponent = function (rootComponents, type, instance) {
7831 return !!(!instance ||
7832 // Don't stub mounted component on root level
7833 (rootComponents.component === type && !(instance === null || instance === void 0 ? void 0 : instance.parent)) ||
7834 // Don't stub component with compat wrapper
7835 (rootComponents.functional && rootComponents.functional === type));
7836};
7837var createVNodeTransformer = function (_a) {
7838 var rootComponents = _a.rootComponents, transformers = _a.transformers;
7839 var transformationCache = new WeakMap();
7840 return function (args, instance) {
7841 var originalType = args[0], props = args[1], children = args[2], restVNodeArgs = args.slice(3);
7842 if (!isComponent(originalType)) {
7843 return __spreadArray([originalType, props, children], restVNodeArgs, true);
7844 }
7845 var componentType = originalType;
7846 var cachedTransformation = transformationCache.get(originalType);
7847 if (cachedTransformation &&
7848 // Don't use cache for root component, as it could use stubbed recursive component
7849 !isRootComponent(rootComponents, componentType, instance) &&
7850 !isTeleport(originalType) &&
7851 !isKeepAlive(originalType)) {
7852 return __spreadArray([cachedTransformation, props, children], restVNodeArgs, true);
7853 }
7854 var transformedType = transformers.reduce(function (type, transformer) { return transformer(type, instance); }, componentType);
7855 if (originalType !== transformedType) {
7856 transformationCache.set(originalType, transformedType);
7857 registerStub({ source: originalType, stub: transformedType });
7858 // https://github.com/vuejs/test-utils/issues/1829 & https://github.com/vuejs/test-utils/issues/1888
7859 // Teleport/KeepAlive should return child nodes as a function
7860 if (isTeleport(originalType) || isKeepAlive(originalType)) {
7861 return __spreadArray([transformedType, props, function () { return children; }], restVNodeArgs, true);
7862 }
7863 }
7864 return __spreadArray([transformedType, props, children], restVNodeArgs, true);
7865 };
7866};
7867
7868var normalizeStubProps = function (props) {
7869 // props are always normalized to object syntax
7870 var $props = props;
7871 return Object.keys($props).reduce(function (acc, key) {
7872 var _a, _b, _c;
7873 var _d;
7874 if (typeof $props[key] === 'symbol') {
7875 return __assign(__assign({}, acc), (_a = {}, _a[key] = [(_d = $props[key]) === null || _d === void 0 ? void 0 : _d.toString()], _a));
7876 }
7877 if (typeof $props[key] === 'function') {
7878 return __assign(__assign({}, acc), (_b = {}, _b[key] = ['[Function]'], _b));
7879 }
7880 return __assign(__assign({}, acc), (_c = {}, _c[key] = $props[key], _c));
7881 }, {});
7882};
7883var clearAndUpper = function (text) { return text.replace(/-/, '').toUpperCase(); };
7884var kebabToPascalCase = function (tag) {
7885 return tag.replace(/(^\w|-\w)/g, clearAndUpper);
7886};
7887var DEFAULT_STUBS = {
7888 teleport: isTeleport,
7889 'keep-alive': isKeepAlive,
7890 transition: function (type) { return type === Vue.Transition || type === Vue.BaseTransition; },
7891 'transition-group': function (type) { return type === Vue.TransitionGroup; }
7892};
7893var createDefaultStub = function (kebabTag, predicate, type, stubs) {
7894 var pascalTag = kebabToPascalCase(kebabTag);
7895 if (predicate(type) && (pascalTag in stubs || kebabTag in stubs)) {
7896 if (kebabTag in stubs && stubs[kebabTag] === false)
7897 return type;
7898 if (pascalTag in stubs && stubs[pascalTag] === false)
7899 return type;
7900 if (stubs[kebabTag] === true || stubs[pascalTag] === true) {
7901 return createStub({
7902 name: kebabTag,
7903 type: type,
7904 renderStubDefaultSlot: true
7905 });
7906 }
7907 }
7908};
7909var createStub = function (_a) {
7910 var name = _a.name, type = _a.type, renderStubDefaultSlot = _a.renderStubDefaultSlot;
7911 var anonName = 'anonymous-stub';
7912 var tag = name ? "".concat(hyphenate(name), "-stub") : anonName;
7913 var componentOptions = type
7914 ? unwrapLegacyVueExtendComponent(type) || {}
7915 : {};
7916 var stub = Vue.defineComponent({
7917 name: name || anonName,
7918 props: componentOptions.props || {},
7919 // fix #1550 - respect old-style v-model for shallow mounted components with @vue/compat
7920 // @ts-expect-error
7921 model: componentOptions.model,
7922 setup: function (props, _a) {
7923 var slots = _a.slots;
7924 return function () {
7925 // https://github.com/vuejs/test-utils/issues/1076
7926 // Passing a symbol as a static prop is not legal, since Vue will try to do
7927 // something like `el.setAttribute('val', Symbol())` which is not valid and
7928 // causes an error.
7929 // Only a problem when shallow mounting. For this reason we iterate of the
7930 // props that will be passed and stringify any that are symbols.
7931 // Also having function text as attribute is useless and annoying so
7932 // we replace it with "[Function]""
7933 var stubProps = normalizeStubProps(props);
7934 // if renderStubDefaultSlot is true, we render the default slot
7935 if (renderStubDefaultSlot && slots.default) {
7936 // we explicitly call the default slot with an empty object
7937 // so scope slots destructuring works
7938 return Vue.h(tag, stubProps, slots.default({}));
7939 }
7940 return Vue.h(tag, stubProps);
7941 };
7942 }
7943 });
7944 var asyncLoader = type.__asyncLoader;
7945 if (asyncLoader) {
7946 asyncLoader().then(function () {
7947 registerStub({
7948 source: type.__asyncResolved,
7949 stub: stub
7950 });
7951 });
7952 }
7953 return stub;
7954};
7955var resolveComponentStubByName = function (componentName, stubs) {
7956 for (var _i = 0, _a = Object.entries(stubs); _i < _a.length; _i++) {
7957 var _b = _a[_i], stubKey = _b[0], value = _b[1];
7958 if (matchName(componentName, stubKey)) {
7959 return value;
7960 }
7961 }
7962};
7963function createStubComponentsTransformer(_a) {
7964 var rootComponents = _a.rootComponents, _b = _a.stubs, stubs = _b === void 0 ? {} : _b, _c = _a.shallow, shallow = _c === void 0 ? false : _c, _d = _a.renderStubDefaultSlot, renderStubDefaultSlot = _d === void 0 ? false : _d;
7965 return function componentsTransformer(type, instance) {
7966 var _a, _b, _c;
7967 for (var tag in DEFAULT_STUBS) {
7968 var predicate = DEFAULT_STUBS[tag];
7969 var defaultStub = createDefaultStub(tag, predicate, type, stubs);
7970 if (defaultStub)
7971 return defaultStub;
7972 }
7973 // Don't stub root components
7974 if (isRootComponent(rootComponents, type, instance)) {
7975 return type;
7976 }
7977 var registeredName = getComponentRegisteredName(instance, type);
7978 var componentName = getComponentName(instance, type);
7979 var stub = null;
7980 var name = null;
7981 // Prio 1 using the key in locally registered components in the parent
7982 if (registeredName) {
7983 stub = resolveComponentStubByName(registeredName, stubs);
7984 if (stub) {
7985 name = registeredName;
7986 }
7987 }
7988 // Prio 2 using the name attribute in the component
7989 if (!stub && componentName) {
7990 stub = resolveComponentStubByName(componentName, stubs);
7991 if (stub) {
7992 name = componentName;
7993 }
7994 }
7995 // case 2: custom implementation
7996 if (isComponent(stub)) {
7997 var unwrappedStub = unwrapLegacyVueExtendComponent(stub);
7998 var stubFn_1 = isFunctionalComponent(unwrappedStub) ? unwrappedStub : null;
7999 // Edge case: stub is component, we will not render stub but instead will create
8000 // a new "copy" of stub component definition, but we want user still to be able
8001 // to find our component by stub definition, so we register it manually
8002 registerStub({ source: type, stub: stub });
8003 var specializedStubComponent = stubFn_1
8004 ? function () {
8005 var args = [];
8006 for (var _i = 0; _i < arguments.length; _i++) {
8007 args[_i] = arguments[_i];
8008 }
8009 return stubFn_1.apply(void 0, args);
8010 }
8011 : __assign({}, unwrappedStub);
8012 specializedStubComponent.props = unwrappedStub.props;
8013 return specializedStubComponent;
8014 }
8015 if (stub === false) {
8016 // we explicitly opt out of stubbing this component
8017 return type;
8018 }
8019 // we return a stub by matching Vue's `h` function
8020 // where the signature is h(Component, props, slots)
8021 // case 1: default stub
8022 if (stub === true || shallow) {
8023 // Set name when using shallow without stub
8024 var stubName = name || registeredName || componentName;
8025 return ((_c = (_b = (_a = config.plugins).createStubs) === null || _b === void 0 ? void 0 : _b.call(_a, {
8026 name: stubName,
8027 component: type,
8028 registerStub: registerStub
8029 })) !== null && _c !== void 0 ? _c : createStub({
8030 name: stubName,
8031 type: type,
8032 renderStubDefaultSlot: renderStubDefaultSlot
8033 }));
8034 }
8035 return type;
8036 };
8037}
8038
8039var noop = function () { };
8040function createStubDirectivesTransformer(_a) {
8041 var _b = _a.directives, directives = _b === void 0 ? {} : _b;
8042 if (Object.keys(directives).length === 0) {
8043 return function (type) { return type; };
8044 }
8045 return function directivesTransformer(type) {
8046 if (isObjectComponent(type) && type.directives) {
8047 // We want to change component types as rarely as possible
8048 // So first we check if there are any directives we should stub
8049 var directivesToPatch = Object.keys(type.directives).filter(function (key) { return key in directives; });
8050 if (!directivesToPatch.length) {
8051 return type;
8052 }
8053 var replacementDirectives = Object.fromEntries(directivesToPatch.map(function (name) {
8054 var directive = directives[name];
8055 return [name, typeof directive === 'boolean' ? noop : directive];
8056 }));
8057 return __assign(__assign({}, type), { directives: __assign(__assign({}, type.directives), replacementDirectives) });
8058 }
8059 return type;
8060 };
8061}
8062
8063/**
8064 * Implementation details of isDeepRef to avoid circular dependencies.
8065 * It keeps track of visited objects to avoid infinite recursion.
8066 *
8067 * @param r The value to check for a Ref.
8068 * @param visitedObjects a weak map to keep track of visited objects and avoid infinite recursion
8069 * @returns returns true if the value is a Ref, false otherwise
8070 */
8071var deeplyCheckForRef = function (r, visitedObjects) {
8072 if (Vue.isRef(r))
8073 return true;
8074 if (!isObject(r))
8075 return false;
8076 if (visitedObjects.has(r))
8077 return false;
8078 visitedObjects.set(r, true);
8079 return Object.values(r).some(function (val) { return deeplyCheckForRef(val, visitedObjects); });
8080};
8081/**
8082 * Checks if the given value is a DeepRef.
8083 *
8084 * For both arrays and objects, it will recursively check
8085 * if any of their values is a Ref.
8086 *
8087 * @param {DeepRef<T> | unknown} r - The value to check.
8088 * @returns {boolean} Returns true if the value is a DeepRef, false otherwise.
8089 */
8090var isDeepRef = function (r) {
8091 var visitedObjects = new WeakMap();
8092 return deeplyCheckForRef(r, visitedObjects);
8093};
8094
8095var MOUNT_OPTIONS = [
8096 'attachTo',
8097 'attrs',
8098 'data',
8099 'props',
8100 'slots',
8101 'global',
8102 'shallow'
8103];
8104function getInstanceOptions(options) {
8105 if (options.methods) {
8106 console.warn("Passing a `methods` option to mount was deprecated on Vue Test Utils v1, and it won't have any effect on v2. For additional info: https://vue-test-utils.vuejs.org/upgrading-to-v1/#setmethods-and-mountingoptions-methods");
8107 delete options.methods;
8108 }
8109 var resultOptions = __assign({}, options);
8110 for (var _i = 0, _a = Object.keys(options); _i < _a.length; _i++) {
8111 var key = _a[_i];
8112 if (MOUNT_OPTIONS.includes(key)) {
8113 delete resultOptions[key];
8114 }
8115 }
8116 return resultOptions;
8117}
8118// implementation
8119function createInstance(inputComponent, options) {
8120 // normalize the incoming component
8121 var originalComponent = unwrapLegacyVueExtendComponent(inputComponent);
8122 var component;
8123 var instanceOptions = getInstanceOptions(options !== null && options !== void 0 ? options : {});
8124 var rootComponents = {};
8125 if (isFunctionalComponent(originalComponent) ||
8126 isLegacyFunctionalComponent(originalComponent)) {
8127 component = Vue.defineComponent(__assign({ compatConfig: {
8128 MODE: 3,
8129 INSTANCE_LISTENERS: false,
8130 INSTANCE_ATTRS_CLASS_STYLE: false,
8131 COMPONENT_FUNCTIONAL: isLegacyFunctionalComponent(originalComponent)
8132 ? 'suppress-warning'
8133 : false
8134 }, props: originalComponent.props || {}, setup: function (props, _a) {
8135 var attrs = _a.attrs, slots = _a.slots;
8136 return function () {
8137 return Vue.h(originalComponent, __assign(__assign({}, props), attrs), slots);
8138 };
8139 } }, instanceOptions));
8140 rootComponents.functional = originalComponent;
8141 }
8142 else if (isObjectComponent(originalComponent)) {
8143 component = __assign(__assign({}, originalComponent), instanceOptions);
8144 }
8145 else {
8146 component = originalComponent;
8147 }
8148 rootComponents.component = component;
8149 // We've just replaced our component with its copy
8150 // Let's register it as a stub so user can find it
8151 registerStub({ source: originalComponent, stub: component });
8152 function slotToFunction(slot) {
8153 switch (typeof slot) {
8154 case 'function':
8155 return slot;
8156 case 'object':
8157 return function () { return Vue.h(slot); };
8158 case 'string':
8159 return processSlot(slot);
8160 default:
8161 throw Error("Invalid slot received.");
8162 }
8163 }
8164 // handle any slots passed via mounting options
8165 var slots = (options === null || options === void 0 ? void 0 : options.slots) &&
8166 Object.entries(options.slots).reduce(function (acc, _a) {
8167 var name = _a[0], slot = _a[1];
8168 if (Array.isArray(slot)) {
8169 var normalized_1 = slot.map(slotToFunction);
8170 acc[name] = function (args) { return normalized_1.map(function (f) { return f(args); }); };
8171 return acc;
8172 }
8173 acc[name] = slotToFunction(slot);
8174 return acc;
8175 }, {});
8176 // override component data with mounting options data
8177 if (options === null || options === void 0 ? void 0 : options.data) {
8178 var providedData_1 = options.data();
8179 if (isObjectComponent(originalComponent)) {
8180 // component is guaranteed to be the same type as originalComponent
8181 var objectComponent = component;
8182 var originalDataFn_1 = originalComponent.data || (function () { return ({}); });
8183 objectComponent.data = function (vm) { return (__assign(__assign({}, originalDataFn_1.call(vm, vm)), providedData_1)); };
8184 }
8185 else {
8186 throw new Error('data() option is not supported on functional and class components');
8187 }
8188 }
8189 var MOUNT_COMPONENT_REF = 'VTU_COMPONENT';
8190 // we define props as reactive so that way when we update them with `setProps`
8191 // Vue's reactivity system will cause a rerender.
8192 var refs = Vue.shallowReactive({});
8193 var props = Vue.reactive({});
8194 Object.entries(__assign(__assign(__assign(__assign({}, options === null || options === void 0 ? void 0 : options.attrs), options === null || options === void 0 ? void 0 : options.propsData), options === null || options === void 0 ? void 0 : options.props), { ref: MOUNT_COMPONENT_REF })).forEach(function (_a) {
8195 var k = _a[0], v = _a[1];
8196 if (isDeepRef(v)) {
8197 refs[k] = v;
8198 }
8199 else {
8200 props[k] = v;
8201 }
8202 });
8203 var global = mergeGlobalProperties(options === null || options === void 0 ? void 0 : options.global);
8204 if (isObjectComponent(component)) {
8205 component.components = __assign(__assign({}, component.components), global.components);
8206 }
8207 var componentRef = Vue.ref(null);
8208 // create the wrapper component
8209 var Parent = Vue.defineComponent({
8210 name: 'VTU_ROOT',
8211 setup: function () {
8212 var _a;
8213 return _a = {},
8214 _a[MOUNT_COMPONENT_REF] = componentRef,
8215 _a;
8216 },
8217 render: function () {
8218 return Vue.h(component, __assign(__assign({}, props), refs), slots);
8219 }
8220 });
8221 // create the app
8222 var app = Vue.createApp(Parent);
8223 // add tracking for emitted events
8224 // this must be done after `createApp`: https://github.com/vuejs/test-utils/issues/436
8225 attachEmitListener();
8226 // global mocks mixin
8227 if (global === null || global === void 0 ? void 0 : global.mocks) {
8228 var mixin = {
8229 beforeCreate: function () {
8230 // we need to differentiate components that are or not not `script setup`
8231 // otherwise we run into a proxy set error
8232 // due to https://github.com/vuejs/core/commit/f73925d76a76ee259749b8b48cb68895f539a00f#diff-ea4d1ddabb7e22e17e80ada458eef70679af4005df2a1a6b73418fec897603ceR404
8233 // introduced in Vue v3.2.45
8234 // Also ensures not to include option API components in this block
8235 // since they can also have setup state but need to be patched using
8236 // the regular method.
8237 if (isScriptSetup(this)) {
8238 // add the mocks to setupState
8239 for (var _i = 0, _a = Object.entries(global.mocks); _i < _a.length; _i++) {
8240 var _b = _a[_i], k = _b[0], v = _b[1];
8241 // we do this in a try/catch, as some properties might be read-only
8242 try {
8243 this.$.setupState[k] = v;
8244 // eslint-disable-next-line no-empty
8245 }
8246 catch (e) { }
8247 }
8248 this.$.proxy = new Proxy(this.$.proxy, {
8249 get: function (target, key) {
8250 if (key in global.mocks) {
8251 return global.mocks[key];
8252 }
8253 return target[key];
8254 }
8255 });
8256 }
8257 else {
8258 for (var _c = 0, _d = Object.entries(global.mocks); _c < _d.length; _c++) {
8259 var _e = _d[_c], k = _e[0], v = _e[1];
8260 this[k] = v;
8261 }
8262 }
8263 }
8264 };
8265 app.mixin(mixin);
8266 }
8267 // AppConfig
8268 if (global.config) {
8269 for (var _i = 0, _a = Object.entries(global.config); _i < _a.length; _i++) {
8270 var _b = _a[_i], k = _b[0], v = _b[1];
8271 app.config[k] = isObject(app.config[k])
8272 ? Object.assign(app.config[k], v)
8273 : v;
8274 }
8275 }
8276 // provide any values passed via provides mounting option
8277 if (global.provide) {
8278 for (var _c = 0, _d = Reflect.ownKeys(global.provide); _c < _d.length; _c++) {
8279 var key = _d[_c];
8280 // @ts-ignore: https://github.com/microsoft/TypeScript/issues/1863
8281 app.provide(key, global.provide[key]);
8282 }
8283 }
8284 // use and plugins from mounting options
8285 if (global.plugins) {
8286 for (var _e = 0, _f = global.plugins; _e < _f.length; _e++) {
8287 var plugin = _f[_e];
8288 if (Array.isArray(plugin)) {
8289 app.use.apply(app, __spreadArray([plugin[0]], plugin.slice(1), false));
8290 continue;
8291 }
8292 app.use(plugin);
8293 }
8294 }
8295 // use any mixins from mounting options
8296 if (global.mixins) {
8297 for (var _g = 0, _h = global.mixins; _g < _h.length; _g++) {
8298 var mixin = _h[_g];
8299 app.mixin(mixin);
8300 }
8301 }
8302 if (global.components) {
8303 for (var _j = 0, _k = Object.keys(global.components); _j < _k.length; _j++) {
8304 var key = _k[_j];
8305 // avoid registering components that are stubbed twice
8306 if (!(key in global.stubs)) {
8307 app.component(key, global.components[key]);
8308 }
8309 }
8310 }
8311 if (global.directives) {
8312 for (var _l = 0, _m = Object.keys(global.directives); _l < _m.length; _l++) {
8313 var key = _m[_l];
8314 app.directive(key, global.directives[key]);
8315 }
8316 }
8317 // stubs
8318 // even if we are using `mount`, we will still
8319 // stub out Transition and Transition Group by default.
8320 Vue.transformVNodeArgs(createVNodeTransformer({
8321 rootComponents: rootComponents,
8322 transformers: [
8323 createStubComponentsTransformer({
8324 rootComponents: rootComponents,
8325 stubs: getComponentsFromStubs(global.stubs),
8326 shallow: options === null || options === void 0 ? void 0 : options.shallow,
8327 renderStubDefaultSlot: global.renderStubDefaultSlot
8328 }),
8329 createStubDirectivesTransformer({
8330 directives: getDirectivesFromStubs(global.stubs)
8331 })
8332 ]
8333 }));
8334 // users expect stubs to work with globally registered
8335 // components so we register stubs as global components to avoid
8336 // warning about not being able to resolve component
8337 //
8338 // component implementation provided here will never be called
8339 // but we need name to make sure that stubComponents will
8340 // properly stub this later by matching stub name
8341 //
8342 // ref: https://github.com/vuejs/test-utils/issues/249
8343 // ref: https://github.com/vuejs/test-utils/issues/425
8344 if (global === null || global === void 0 ? void 0 : global.stubs) {
8345 for (var _o = 0, _p = Object.keys(getComponentsFromStubs(global.stubs)); _o < _p.length; _o++) {
8346 var name_1 = _p[_o];
8347 if (!app.component(name_1)) {
8348 app.component(name_1, { name: name_1 });
8349 }
8350 }
8351 }
8352 return {
8353 app: app,
8354 props: props,
8355 componentRef: componentRef
8356 };
8357}
8358
8359var isEnabled = false;
8360var wrapperInstances = [];
8361function disableAutoUnmount() {
8362 isEnabled = false;
8363 wrapperInstances.length = 0;
8364}
8365function enableAutoUnmount(hook) {
8366 if (isEnabled) {
8367 throw new Error('enableAutoUnmount cannot be called more than once');
8368 }
8369 isEnabled = true;
8370 hook(function () {
8371 wrapperInstances.forEach(function (wrapper) {
8372 wrapper.unmount();
8373 });
8374 wrapperInstances.length = 0;
8375 });
8376}
8377function trackInstance(wrapper) {
8378 if (!isEnabled)
8379 return;
8380 wrapperInstances.push(wrapper);
8381}
8382
8383// implementation
8384function mount(inputComponent, options) {
8385 var _a = createInstance(inputComponent, options), app = _a.app, props = _a.props, componentRef = _a.componentRef;
8386 var setProps = function (newProps) {
8387 for (var _i = 0, _a = Object.entries(newProps); _i < _a.length; _i++) {
8388 var _b = _a[_i], k = _b[0], v = _b[1];
8389 props[k] = v;
8390 }
8391 return vm.$nextTick();
8392 };
8393 // Workaround for https://github.com/vuejs/core/issues/7020
8394 var originalErrorHandler = app.config.errorHandler;
8395 var errorsOnMount = [];
8396 app.config.errorHandler = function (err, instance, info) {
8397 errorsOnMount.push(err);
8398 return originalErrorHandler === null || originalErrorHandler === void 0 ? void 0 : originalErrorHandler(err, instance, info);
8399 };
8400 // mount the app!
8401 var el = document.createElement('div');
8402 if (options === null || options === void 0 ? void 0 : options.attachTo) {
8403 var to = void 0;
8404 if (typeof options.attachTo === 'string') {
8405 to = document.querySelector(options.attachTo);
8406 if (!to) {
8407 throw new Error("Unable to find the element matching the selector ".concat(options.attachTo, " given as the `attachTo` option"));
8408 }
8409 }
8410 else {
8411 to = options.attachTo;
8412 }
8413 to.appendChild(el);
8414 }
8415 var vm = app.mount(el);
8416 if (errorsOnMount.length) {
8417 // If several errors are thrown during mount, then throw the first one
8418 throw errorsOnMount[0];
8419 }
8420 app.config.errorHandler = originalErrorHandler;
8421 var appRef = componentRef.value;
8422 // we add `hasOwnProperty` so Jest can spy on the proxied vm without throwing
8423 // note that this is not necessary with Jest v27+ or Vitest, but is kept for compatibility with older Jest versions
8424 if (!app.hasOwnProperty) {
8425 appRef.hasOwnProperty = function (property) {
8426 return Reflect.has(appRef, property);
8427 };
8428 }
8429 var wrapper = createVueWrapper(app, appRef, setProps);
8430 trackInstance(wrapper);
8431 return wrapper;
8432}
8433var shallowMount = function (component, options) {
8434 return mount(component, __assign(__assign({}, options), { shallow: true }));
8435};
8436
8437function renderToString(component, options) {
8438 if (options === null || options === void 0 ? void 0 : options.attachTo) {
8439 console.warn('attachTo option is not available for renderToString');
8440 }
8441 var app = createInstance(component, options).app;
8442 return serverRenderer.renderToString(app);
8443}
8444
8445// match return type of router.resolve: RouteLocation & { href: string }
8446var defaultRoute = {
8447 path: '/',
8448 name: undefined,
8449 redirectedFrom: undefined,
8450 params: {},
8451 query: {},
8452 hash: '',
8453 fullPath: '/',
8454 matched: [],
8455 meta: {},
8456 href: '/'
8457};
8458// TODO: Borrow typings from vue-router-next
8459var RouterLinkStub = Vue.defineComponent({
8460 name: 'RouterLinkStub',
8461 compatConfig: { MODE: 3 },
8462 props: {
8463 to: {
8464 type: [String, Object],
8465 required: true
8466 },
8467 custom: {
8468 type: Boolean,
8469 default: false
8470 }
8471 },
8472 render: function () {
8473 var _this = this;
8474 var _a, _b;
8475 var route = Vue.computed(function () { return defaultRoute; });
8476 // mock reasonable return values to mimic vue-router's useLink
8477 var children = (_b = (_a = this.$slots) === null || _a === void 0 ? void 0 : _a.default) === null || _b === void 0 ? void 0 : _b.call(_a, {
8478 route: route,
8479 href: Vue.computed(function () { return route.value.href; }),
8480 isActive: Vue.computed(function () { return false; }),
8481 isExactActive: Vue.computed(function () { return false; }),
8482 navigate: function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
8483 return [2 /*return*/];
8484 }); }); }
8485 });
8486 return this.custom ? children : Vue.h('a', undefined, children);
8487 }
8488});
8489
8490var scheduler = typeof setImmediate === 'function' ? setImmediate : setTimeout;
8491// Credit to: https://github.com/kentor/flush-promises
8492function flushPromises() {
8493 return new Promise(function (resolve) {
8494 scheduler(resolve, 0);
8495 });
8496}
8497
8498exports.BaseWrapper = BaseWrapper;
8499exports.DOMWrapper = DOMWrapper;
8500exports.RouterLinkStub = RouterLinkStub;
8501exports.VueWrapper = VueWrapper;
8502exports.config = config;
8503exports.createWrapperError = createWrapperError;
8504exports.disableAutoUnmount = disableAutoUnmount;
8505exports.enableAutoUnmount = enableAutoUnmount;
8506exports.flushPromises = flushPromises;
8507exports.mount = mount;
8508exports.renderToString = renderToString;
8509exports.shallowMount = shallowMount;