UNPKG

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