ab2c33a57d287440663c1263927a34de36c74ec3
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / prettier / doc.js
1 (function (global, factory) {
2   typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3   typeof define === 'function' && define.amd ? define(['exports'], factory) :
4   (global = global || self, factory(global.doc = {}));
5 }(this, (function (exports) { 'use strict';
6
7   /**
8    * @param {Doc[]} parts
9    * @returns Doc
10    */
11
12
13   function concat(parts) {
14     // access the internals of a document directly.
15     // if(parts.length === 1) {
16     //   // If it's a single document, no need to concat it.
17     //   return parts[0];
18     // }
19
20
21     return {
22       type: "concat",
23       parts
24     };
25   }
26   /**
27    * @param {Doc} contents
28    * @returns Doc
29    */
30
31
32   function indent(contents) {
33
34     return {
35       type: "indent",
36       contents
37     };
38   }
39   /**
40    * @param {number} n
41    * @param {Doc} contents
42    * @returns Doc
43    */
44
45
46   function align(n, contents) {
47
48     return {
49       type: "align",
50       contents,
51       n
52     };
53   }
54   /**
55    * @param {Doc} contents
56    * @param {object} [opts] - TBD ???
57    * @returns Doc
58    */
59
60
61   function group(contents, opts) {
62     opts = opts || {};
63
64     return {
65       type: "group",
66       id: opts.id,
67       contents,
68       break: !!opts.shouldBreak,
69       expandedStates: opts.expandedStates
70     };
71   }
72   /**
73    * @param {Doc} contents
74    * @returns Doc
75    */
76
77
78   function dedentToRoot(contents) {
79     return align(-Infinity, contents);
80   }
81   /**
82    * @param {Doc} contents
83    * @returns Doc
84    */
85
86
87   function markAsRoot(contents) {
88     // @ts-ignore - TBD ???:
89     return align({
90       type: "root"
91     }, contents);
92   }
93   /**
94    * @param {Doc} contents
95    * @returns Doc
96    */
97
98
99   function dedent(contents) {
100     return align(-1, contents);
101   }
102   /**
103    * @param {Doc[]} states
104    * @param {object} [opts] - TBD ???
105    * @returns Doc
106    */
107
108
109   function conditionalGroup(states, opts) {
110     return group(states[0], Object.assign({}, opts, {
111       expandedStates: states
112     }));
113   }
114   /**
115    * @param {Doc[]} parts
116    * @returns Doc
117    */
118
119
120   function fill(parts) {
121
122     return {
123       type: "fill",
124       parts
125     };
126   }
127   /**
128    * @param {Doc} [breakContents]
129    * @param {Doc} [flatContents]
130    * @param {object} [opts] - TBD ???
131    * @returns Doc
132    */
133
134
135   function ifBreak(breakContents, flatContents, opts) {
136     opts = opts || {};
137
138     return {
139       type: "if-break",
140       breakContents,
141       flatContents,
142       groupId: opts.groupId
143     };
144   }
145   /**
146    * @param {Doc} contents
147    * @returns Doc
148    */
149
150
151   function lineSuffix(contents) {
152
153     return {
154       type: "line-suffix",
155       contents
156     };
157   }
158
159   const lineSuffixBoundary = {
160     type: "line-suffix-boundary"
161   };
162   const breakParent = {
163     type: "break-parent"
164   };
165   const trim = {
166     type: "trim"
167   };
168   const line = {
169     type: "line"
170   };
171   const softline = {
172     type: "line",
173     soft: true
174   };
175   const hardline = concat([{
176     type: "line",
177     hard: true
178   }, breakParent]);
179   const literalline = concat([{
180     type: "line",
181     hard: true,
182     literal: true
183   }, breakParent]);
184   const cursor = {
185     type: "cursor",
186     placeholder: Symbol("cursor")
187   };
188   /**
189    * @param {Doc} sep
190    * @param {Doc[]} arr
191    * @returns Doc
192    */
193
194   function join(sep, arr) {
195     const res = [];
196
197     for (let i = 0; i < arr.length; i++) {
198       if (i !== 0) {
199         res.push(sep);
200       }
201
202       res.push(arr[i]);
203     }
204
205     return concat(res);
206   }
207   /**
208    * @param {Doc} doc
209    * @param {number} size
210    * @param {number} tabWidth
211    */
212
213
214   function addAlignmentToDoc(doc, size, tabWidth) {
215     let aligned = doc;
216
217     if (size > 0) {
218       // Use indent to add tabs for all the levels of tabs we need
219       for (let i = 0; i < Math.floor(size / tabWidth); ++i) {
220         aligned = indent(aligned);
221       } // Use align for all the spaces that are needed
222
223
224       aligned = align(size % tabWidth, aligned); // size is absolute from 0 and not relative to the current
225       // indentation, so we use -Infinity to reset the indentation to 0
226
227       aligned = align(-Infinity, aligned);
228     }
229
230     return aligned;
231   }
232
233   var docBuilders = {
234     concat,
235     join,
236     line,
237     softline,
238     hardline,
239     literalline,
240     group,
241     conditionalGroup,
242     fill,
243     lineSuffix,
244     lineSuffixBoundary,
245     cursor,
246     breakParent,
247     ifBreak,
248     trim,
249     indent,
250     align,
251     addAlignmentToDoc,
252     markAsRoot,
253     dedentToRoot,
254     dedent
255   };
256
257   var ansiRegex = ({
258     onlyFirst = false
259   } = {}) => {
260     const pattern = ['[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'].join('|');
261     return new RegExp(pattern, onlyFirst ? undefined : 'g');
262   };
263
264   var stripAnsi = string => typeof string === 'string' ? string.replace(ansiRegex(), '') : string;
265
266   /* eslint-disable yoda */
267
268   const isFullwidthCodePoint = codePoint => {
269     if (Number.isNaN(codePoint)) {
270       return false;
271     } // Code points are derived from:
272     // http://www.unix.org/Public/UNIDATA/EastAsianWidth.txt
273
274
275     if (codePoint >= 0x1100 && (codePoint <= 0x115F || // Hangul Jamo
276     codePoint === 0x2329 || // LEFT-POINTING ANGLE BRACKET
277     codePoint === 0x232A || // RIGHT-POINTING ANGLE BRACKET
278     // CJK Radicals Supplement .. Enclosed CJK Letters and Months
279     0x2E80 <= codePoint && codePoint <= 0x3247 && codePoint !== 0x303F || // Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A
280     0x3250 <= codePoint && codePoint <= 0x4DBF || // CJK Unified Ideographs .. Yi Radicals
281     0x4E00 <= codePoint && codePoint <= 0xA4C6 || // Hangul Jamo Extended-A
282     0xA960 <= codePoint && codePoint <= 0xA97C || // Hangul Syllables
283     0xAC00 <= codePoint && codePoint <= 0xD7A3 || // CJK Compatibility Ideographs
284     0xF900 <= codePoint && codePoint <= 0xFAFF || // Vertical Forms
285     0xFE10 <= codePoint && codePoint <= 0xFE19 || // CJK Compatibility Forms .. Small Form Variants
286     0xFE30 <= codePoint && codePoint <= 0xFE6B || // Halfwidth and Fullwidth Forms
287     0xFF01 <= codePoint && codePoint <= 0xFF60 || 0xFFE0 <= codePoint && codePoint <= 0xFFE6 || // Kana Supplement
288     0x1B000 <= codePoint && codePoint <= 0x1B001 || // Enclosed Ideographic Supplement
289     0x1F200 <= codePoint && codePoint <= 0x1F251 || // CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane
290     0x20000 <= codePoint && codePoint <= 0x3FFFD)) {
291       return true;
292     }
293
294     return false;
295   };
296
297   var isFullwidthCodePoint_1 = isFullwidthCodePoint;
298   var default_1 = isFullwidthCodePoint;
299   isFullwidthCodePoint_1.default = default_1;
300
301   var emojiRegex = function emojiRegex() {
302     // https://mths.be/emoji
303     return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F|\uD83D\uDC68(?:\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68\uD83C\uDFFB|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|[\u2695\u2696\u2708]\uFE0F|\uD83D[\uDC66\uDC67]|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708])\uFE0F|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C[\uDFFB-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)\uD83C\uDFFB|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB\uDFFC])|\uD83D\uDC69(?:\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D\uD83D\uDC69)(?:\uD83C[\uDFFB-\uDFFD])|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|(?:(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)\uFE0F|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:(?:\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\u200D[\u2640\u2642])|\uD83C\uDFF4\u200D\u2620)\uFE0F|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF4\uD83C\uDDF2|\uD83C\uDDF6\uD83C\uDDE6|[#\*0-9]\uFE0F\u20E3|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83D\uDC69(?:\uD83C[\uDFFB-\uDFFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270A-\u270D]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC70\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDCAA\uDD74\uDD7A\uDD90\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD36\uDDB5\uDDB6\uDDBB\uDDD2-\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5\uDEEB\uDEEC\uDEF4-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFA\uDFE0-\uDFEB]|\uD83E[\uDD0D-\uDD3A\uDD3C-\uDD45\uDD47-\uDD71\uDD73-\uDD76\uDD7A-\uDDA2\uDDA5-\uDDAA\uDDAE-\uDDCA\uDDCD-\uDDFF\uDE70-\uDE73\uDE78-\uDE7A\uDE80-\uDE82\uDE90-\uDE95])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g;
304   };
305
306   const stringWidth = string => {
307     string = string.replace(emojiRegex(), '  ');
308
309     if (typeof string !== 'string' || string.length === 0) {
310       return 0;
311     }
312
313     string = stripAnsi(string);
314     let width = 0;
315
316     for (let i = 0; i < string.length; i++) {
317       const code = string.codePointAt(i); // Ignore control characters
318
319       if (code <= 0x1F || code >= 0x7F && code <= 0x9F) {
320         continue;
321       } // Ignore combining characters
322
323
324       if (code >= 0x300 && code <= 0x36F) {
325         continue;
326       } // Surrogates
327
328
329       if (code > 0xFFFF) {
330         i++;
331       }
332
333       width += isFullwidthCodePoint_1(code) ? 2 : 1;
334     }
335
336     return width;
337   };
338
339   var stringWidth_1 = stringWidth; // TODO: remove this in the next major version
340
341   var default_1$1 = stringWidth;
342   stringWidth_1.default = default_1$1;
343
344   const matchOperatorsRegex = /[|\\{}()[\]^$+*?.-]/g;
345
346   var escapeStringRegexp = string => {
347     if (typeof string !== 'string') {
348       throw new TypeError('Expected a string');
349     }
350
351     return string.replace(matchOperatorsRegex, '\\$&');
352   };
353
354   var getLast = arr => arr[arr.length - 1];
355
356   const notAsciiRegex = /[^\x20-\x7F]/;
357
358   function getPenultimate(arr) {
359     if (arr.length > 1) {
360       return arr[arr.length - 2];
361     }
362
363     return null;
364   }
365   /**
366    * @typedef {{backwards?: boolean}} SkipOptions
367    */
368
369   /**
370    * @param {string | RegExp} chars
371    * @returns {(text: string, index: number | false, opts?: SkipOptions) => number | false}
372    */
373
374
375   function skip(chars) {
376     return (text, index, opts) => {
377       const backwards = opts && opts.backwards; // Allow `skip` functions to be threaded together without having
378       // to check for failures (did someone say monads?).
379
380       if (index === false) {
381         return false;
382       }
383
384       const {
385         length
386       } = text;
387       let cursor = index;
388
389       while (cursor >= 0 && cursor < length) {
390         const c = text.charAt(cursor);
391
392         if (chars instanceof RegExp) {
393           if (!chars.test(c)) {
394             return cursor;
395           }
396         } else if (!chars.includes(c)) {
397           return cursor;
398         }
399
400         backwards ? cursor-- : cursor++;
401       }
402
403       if (cursor === -1 || cursor === length) {
404         // If we reached the beginning or end of the file, return the
405         // out-of-bounds cursor. It's up to the caller to handle this
406         // correctly. We don't want to indicate `false` though if it
407         // actually skipped valid characters.
408         return cursor;
409       }
410
411       return false;
412     };
413   }
414   /**
415    * @type {(text: string, index: number | false, opts?: SkipOptions) => number | false}
416    */
417
418
419   const skipWhitespace = skip(/\s/);
420   /**
421    * @type {(text: string, index: number | false, opts?: SkipOptions) => number | false}
422    */
423
424   const skipSpaces = skip(" \t");
425   /**
426    * @type {(text: string, index: number | false, opts?: SkipOptions) => number | false}
427    */
428
429   const skipToLineEnd = skip(",; \t");
430   /**
431    * @type {(text: string, index: number | false, opts?: SkipOptions) => number | false}
432    */
433
434   const skipEverythingButNewLine = skip(/[^\r\n]/);
435   /**
436    * @param {string} text
437    * @param {number | false} index
438    * @returns {number | false}
439    */
440
441   function skipInlineComment(text, index) {
442     if (index === false) {
443       return false;
444     }
445
446     if (text.charAt(index) === "/" && text.charAt(index + 1) === "*") {
447       for (let i = index + 2; i < text.length; ++i) {
448         if (text.charAt(i) === "*" && text.charAt(i + 1) === "/") {
449           return i + 2;
450         }
451       }
452     }
453
454     return index;
455   }
456   /**
457    * @param {string} text
458    * @param {number | false} index
459    * @returns {number | false}
460    */
461
462
463   function skipTrailingComment(text, index) {
464     if (index === false) {
465       return false;
466     }
467
468     if (text.charAt(index) === "/" && text.charAt(index + 1) === "/") {
469       return skipEverythingButNewLine(text, index);
470     }
471
472     return index;
473   } // This one doesn't use the above helper function because it wants to
474   // test \r\n in order and `skip` doesn't support ordering and we only
475   // want to skip one newline. It's simple to implement.
476
477   /**
478    * @param {string} text
479    * @param {number | false} index
480    * @param {SkipOptions=} opts
481    * @returns {number | false}
482    */
483
484
485   function skipNewline(text, index, opts) {
486     const backwards = opts && opts.backwards;
487
488     if (index === false) {
489       return false;
490     }
491
492     const atIndex = text.charAt(index);
493
494     if (backwards) {
495       if (text.charAt(index - 1) === "\r" && atIndex === "\n") {
496         return index - 2;
497       }
498
499       if (atIndex === "\n" || atIndex === "\r" || atIndex === "\u2028" || atIndex === "\u2029") {
500         return index - 1;
501       }
502     } else {
503       if (atIndex === "\r" && text.charAt(index + 1) === "\n") {
504         return index + 2;
505       }
506
507       if (atIndex === "\n" || atIndex === "\r" || atIndex === "\u2028" || atIndex === "\u2029") {
508         return index + 1;
509       }
510     }
511
512     return index;
513   }
514   /**
515    * @param {string} text
516    * @param {number} index
517    * @param {SkipOptions=} opts
518    * @returns {boolean}
519    */
520
521
522   function hasNewline(text, index, opts) {
523     opts = opts || {};
524     const idx = skipSpaces(text, opts.backwards ? index - 1 : index, opts);
525     const idx2 = skipNewline(text, idx, opts);
526     return idx !== idx2;
527   }
528   /**
529    * @param {string} text
530    * @param {number} start
531    * @param {number} end
532    * @returns {boolean}
533    */
534
535
536   function hasNewlineInRange(text, start, end) {
537     for (let i = start; i < end; ++i) {
538       if (text.charAt(i) === "\n") {
539         return true;
540       }
541     }
542
543     return false;
544   } // Note: this function doesn't ignore leading comments unlike isNextLineEmpty
545
546   /**
547    * @template N
548    * @param {string} text
549    * @param {N} node
550    * @param {(node: N) => number} locStart
551    */
552
553
554   function isPreviousLineEmpty(text, node, locStart) {
555     /** @type {number | false} */
556     let idx = locStart(node) - 1;
557     idx = skipSpaces(text, idx, {
558       backwards: true
559     });
560     idx = skipNewline(text, idx, {
561       backwards: true
562     });
563     idx = skipSpaces(text, idx, {
564       backwards: true
565     });
566     const idx2 = skipNewline(text, idx, {
567       backwards: true
568     });
569     return idx !== idx2;
570   }
571   /**
572    * @param {string} text
573    * @param {number} index
574    * @returns {boolean}
575    */
576
577
578   function isNextLineEmptyAfterIndex(text, index) {
579     /** @type {number | false} */
580     let oldIdx = null;
581     /** @type {number | false} */
582
583     let idx = index;
584
585     while (idx !== oldIdx) {
586       // We need to skip all the potential trailing inline comments
587       oldIdx = idx;
588       idx = skipToLineEnd(text, idx);
589       idx = skipInlineComment(text, idx);
590       idx = skipSpaces(text, idx);
591     }
592
593     idx = skipTrailingComment(text, idx);
594     idx = skipNewline(text, idx);
595     return idx !== false && hasNewline(text, idx);
596   }
597   /**
598    * @template N
599    * @param {string} text
600    * @param {N} node
601    * @param {(node: N) => number} locEnd
602    * @returns {boolean}
603    */
604
605
606   function isNextLineEmpty(text, node, locEnd) {
607     return isNextLineEmptyAfterIndex(text, locEnd(node));
608   }
609   /**
610    * @param {string} text
611    * @param {number} idx
612    * @returns {number | false}
613    */
614
615
616   function getNextNonSpaceNonCommentCharacterIndexWithStartIndex(text, idx) {
617     /** @type {number | false} */
618     let oldIdx = null;
619     /** @type {number | false} */
620
621     let nextIdx = idx;
622
623     while (nextIdx !== oldIdx) {
624       oldIdx = nextIdx;
625       nextIdx = skipSpaces(text, nextIdx);
626       nextIdx = skipInlineComment(text, nextIdx);
627       nextIdx = skipTrailingComment(text, nextIdx);
628       nextIdx = skipNewline(text, nextIdx);
629     }
630
631     return nextIdx;
632   }
633   /**
634    * @template N
635    * @param {string} text
636    * @param {N} node
637    * @param {(node: N) => number} locEnd
638    * @returns {number | false}
639    */
640
641
642   function getNextNonSpaceNonCommentCharacterIndex(text, node, locEnd) {
643     return getNextNonSpaceNonCommentCharacterIndexWithStartIndex(text, locEnd(node));
644   }
645   /**
646    * @template N
647    * @param {string} text
648    * @param {N} node
649    * @param {(node: N) => number} locEnd
650    * @returns {string}
651    */
652
653
654   function getNextNonSpaceNonCommentCharacter(text, node, locEnd) {
655     return text.charAt( // @ts-ignore => TBD: can return false, should we define a fallback?
656     getNextNonSpaceNonCommentCharacterIndex(text, node, locEnd));
657   }
658   /**
659    * @param {string} text
660    * @param {number} index
661    * @param {SkipOptions=} opts
662    * @returns {boolean}
663    */
664
665
666   function hasSpaces(text, index, opts) {
667     opts = opts || {};
668     const idx = skipSpaces(text, opts.backwards ? index - 1 : index, opts);
669     return idx !== index;
670   }
671   /**
672    * @param {{range?: [number, number], start?: number}} node
673    * @param {number} index
674    */
675
676
677   function setLocStart(node, index) {
678     if (node.range) {
679       node.range[0] = index;
680     } else {
681       node.start = index;
682     }
683   }
684   /**
685    * @param {{range?: [number, number], end?: number}} node
686    * @param {number} index
687    */
688
689
690   function setLocEnd(node, index) {
691     if (node.range) {
692       node.range[1] = index;
693     } else {
694       node.end = index;
695     }
696   }
697
698   const PRECEDENCE = {};
699   [["|>"], ["??"], ["||"], ["&&"], ["|"], ["^"], ["&"], ["==", "===", "!=", "!=="], ["<", ">", "<=", ">=", "in", "instanceof"], [">>", "<<", ">>>"], ["+", "-"], ["*", "/", "%"], ["**"]].forEach((tier, i) => {
700     tier.forEach(op => {
701       PRECEDENCE[op] = i;
702     });
703   });
704
705   function getPrecedence(op) {
706     return PRECEDENCE[op];
707   }
708
709   const equalityOperators = {
710     "==": true,
711     "!=": true,
712     "===": true,
713     "!==": true
714   };
715   const multiplicativeOperators = {
716     "*": true,
717     "/": true,
718     "%": true
719   };
720   const bitshiftOperators = {
721     ">>": true,
722     ">>>": true,
723     "<<": true
724   };
725
726   function shouldFlatten(parentOp, nodeOp) {
727     if (getPrecedence(nodeOp) !== getPrecedence(parentOp)) {
728       return false;
729     } // ** is right-associative
730     // x ** y ** z --> x ** (y ** z)
731
732
733     if (parentOp === "**") {
734       return false;
735     } // x == y == z --> (x == y) == z
736
737
738     if (equalityOperators[parentOp] && equalityOperators[nodeOp]) {
739       return false;
740     } // x * y % z --> (x * y) % z
741
742
743     if (nodeOp === "%" && multiplicativeOperators[parentOp] || parentOp === "%" && multiplicativeOperators[nodeOp]) {
744       return false;
745     } // x * y / z --> (x * y) / z
746     // x / y * z --> (x / y) * z
747
748
749     if (nodeOp !== parentOp && multiplicativeOperators[nodeOp] && multiplicativeOperators[parentOp]) {
750       return false;
751     } // x << y << z --> (x << y) << z
752
753
754     if (bitshiftOperators[parentOp] && bitshiftOperators[nodeOp]) {
755       return false;
756     }
757
758     return true;
759   }
760
761   function isBitwiseOperator(operator) {
762     return !!bitshiftOperators[operator] || operator === "|" || operator === "^" || operator === "&";
763   } // Tests if an expression starts with `{`, or (if forbidFunctionClassAndDoExpr
764   // holds) `function`, `class`, or `do {}`. Will be overzealous if there's
765   // already necessary grouping parentheses.
766
767
768   function startsWithNoLookaheadToken(node, forbidFunctionClassAndDoExpr) {
769     node = getLeftMost(node);
770
771     switch (node.type) {
772       case "FunctionExpression":
773       case "ClassExpression":
774       case "DoExpression":
775         return forbidFunctionClassAndDoExpr;
776
777       case "ObjectExpression":
778         return true;
779
780       case "MemberExpression":
781       case "OptionalMemberExpression":
782         return startsWithNoLookaheadToken(node.object, forbidFunctionClassAndDoExpr);
783
784       case "TaggedTemplateExpression":
785         if (node.tag.type === "FunctionExpression") {
786           // IIFEs are always already parenthesized
787           return false;
788         }
789
790         return startsWithNoLookaheadToken(node.tag, forbidFunctionClassAndDoExpr);
791
792       case "CallExpression":
793       case "OptionalCallExpression":
794         if (node.callee.type === "FunctionExpression") {
795           // IIFEs are always already parenthesized
796           return false;
797         }
798
799         return startsWithNoLookaheadToken(node.callee, forbidFunctionClassAndDoExpr);
800
801       case "ConditionalExpression":
802         return startsWithNoLookaheadToken(node.test, forbidFunctionClassAndDoExpr);
803
804       case "UpdateExpression":
805         return !node.prefix && startsWithNoLookaheadToken(node.argument, forbidFunctionClassAndDoExpr);
806
807       case "BindExpression":
808         return node.object && startsWithNoLookaheadToken(node.object, forbidFunctionClassAndDoExpr);
809
810       case "SequenceExpression":
811         return startsWithNoLookaheadToken(node.expressions[0], forbidFunctionClassAndDoExpr);
812
813       case "TSAsExpression":
814         return startsWithNoLookaheadToken(node.expression, forbidFunctionClassAndDoExpr);
815
816       default:
817         return false;
818     }
819   }
820
821   function getLeftMost(node) {
822     if (node.left) {
823       return getLeftMost(node.left);
824     }
825
826     return node;
827   }
828   /**
829    * @param {string} value
830    * @param {number} tabWidth
831    * @param {number=} startIndex
832    * @returns {number}
833    */
834
835
836   function getAlignmentSize(value, tabWidth, startIndex) {
837     startIndex = startIndex || 0;
838     let size = 0;
839
840     for (let i = startIndex; i < value.length; ++i) {
841       if (value[i] === "\t") {
842         // Tabs behave in a way that they are aligned to the nearest
843         // multiple of tabWidth:
844         // 0 -> 4, 1 -> 4, 2 -> 4, 3 -> 4
845         // 4 -> 8, 5 -> 8, 6 -> 8, 7 -> 8 ...
846         size = size + tabWidth - size % tabWidth;
847       } else {
848         size++;
849       }
850     }
851
852     return size;
853   }
854   /**
855    * @param {string} value
856    * @param {number} tabWidth
857    * @returns {number}
858    */
859
860
861   function getIndentSize(value, tabWidth) {
862     const lastNewlineIndex = value.lastIndexOf("\n");
863
864     if (lastNewlineIndex === -1) {
865       return 0;
866     }
867
868     return getAlignmentSize( // All the leading whitespaces
869     value.slice(lastNewlineIndex + 1).match(/^[ \t]*/)[0], tabWidth);
870   }
871   /**
872    * @typedef {'"' | "'"} Quote
873    */
874
875   /**
876    *
877    * @param {string} raw
878    * @param {Quote} preferredQuote
879    * @returns {Quote}
880    */
881
882
883   function getPreferredQuote(raw, preferredQuote) {
884     // `rawContent` is the string exactly like it appeared in the input source
885     // code, without its enclosing quotes.
886     const rawContent = raw.slice(1, -1);
887     /** @type {{ quote: '"', regex: RegExp }} */
888
889     const double = {
890       quote: '"',
891       regex: /"/g
892     };
893     /** @type {{ quote: "'", regex: RegExp }} */
894
895     const single = {
896       quote: "'",
897       regex: /'/g
898     };
899     const preferred = preferredQuote === "'" ? single : double;
900     const alternate = preferred === single ? double : single;
901     let result = preferred.quote; // If `rawContent` contains at least one of the quote preferred for enclosing
902     // the string, we might want to enclose with the alternate quote instead, to
903     // minimize the number of escaped quotes.
904
905     if (rawContent.includes(preferred.quote) || rawContent.includes(alternate.quote)) {
906       const numPreferredQuotes = (rawContent.match(preferred.regex) || []).length;
907       const numAlternateQuotes = (rawContent.match(alternate.regex) || []).length;
908       result = numPreferredQuotes > numAlternateQuotes ? alternate.quote : preferred.quote;
909     }
910
911     return result;
912   }
913
914   function printString(raw, options, isDirectiveLiteral) {
915     // `rawContent` is the string exactly like it appeared in the input source
916     // code, without its enclosing quotes.
917     const rawContent = raw.slice(1, -1); // Check for the alternate quote, to determine if we're allowed to swap
918     // the quotes on a DirectiveLiteral.
919
920     const canChangeDirectiveQuotes = !rawContent.includes('"') && !rawContent.includes("'");
921     /** @type {Quote} */
922
923     const enclosingQuote = options.parser === "json" ? '"' : options.__isInHtmlAttribute ? "'" : getPreferredQuote(raw, options.singleQuote ? "'" : '"'); // Directives are exact code unit sequences, which means that you can't
924     // change the escape sequences they use.
925     // See https://github.com/prettier/prettier/issues/1555
926     // and https://tc39.github.io/ecma262/#directive-prologue
927
928     if (isDirectiveLiteral) {
929       if (canChangeDirectiveQuotes) {
930         return enclosingQuote + rawContent + enclosingQuote;
931       }
932
933       return raw;
934     } // It might sound unnecessary to use `makeString` even if the string already
935     // is enclosed with `enclosingQuote`, but it isn't. The string could contain
936     // unnecessary escapes (such as in `"\'"`). Always using `makeString` makes
937     // sure that we consistently output the minimum amount of escaped quotes.
938
939
940     return makeString(rawContent, enclosingQuote, !(options.parser === "css" || options.parser === "less" || options.parser === "scss" || options.embeddedInHtml));
941   }
942   /**
943    * @param {string} rawContent
944    * @param {Quote} enclosingQuote
945    * @param {boolean=} unescapeUnnecessaryEscapes
946    * @returns {string}
947    */
948
949
950   function makeString(rawContent, enclosingQuote, unescapeUnnecessaryEscapes) {
951     const otherQuote = enclosingQuote === '"' ? "'" : '"'; // Matches _any_ escape and unescaped quotes (both single and double).
952
953     const regex = /\\([\s\S])|(['"])/g; // Escape and unescape single and double quotes as needed to be able to
954     // enclose `rawContent` with `enclosingQuote`.
955
956     const newContent = rawContent.replace(regex, (match, escaped, quote) => {
957       // If we matched an escape, and the escaped character is a quote of the
958       // other type than we intend to enclose the string with, there's no need for
959       // it to be escaped, so return it _without_ the backslash.
960       if (escaped === otherQuote) {
961         return escaped;
962       } // If we matched an unescaped quote and it is of the _same_ type as we
963       // intend to enclose the string with, it must be escaped, so return it with
964       // a backslash.
965
966
967       if (quote === enclosingQuote) {
968         return "\\" + quote;
969       }
970
971       if (quote) {
972         return quote;
973       } // Unescape any unnecessarily escaped character.
974       // Adapted from https://github.com/eslint/eslint/blob/de0b4ad7bd820ade41b1f606008bea68683dc11a/lib/rules/no-useless-escape.js#L27
975
976
977       return unescapeUnnecessaryEscapes && /^[^\\nrvtbfux\r\n\u2028\u2029"'0-7]$/.test(escaped) ? escaped : "\\" + escaped;
978     });
979     return enclosingQuote + newContent + enclosingQuote;
980   }
981
982   function printNumber(rawNumber) {
983     return rawNumber.toLowerCase() // Remove unnecessary plus and zeroes from scientific notation.
984     .replace(/^([+-]?[\d.]+e)(?:\+|(-))?0*(\d)/, "$1$2$3") // Remove unnecessary scientific notation (1e0).
985     .replace(/^([+-]?[\d.]+)e[+-]?0+$/, "$1") // Make sure numbers always start with a digit.
986     .replace(/^([+-])?\./, "$10.") // Remove extraneous trailing decimal zeroes.
987     .replace(/(\.\d+?)0+(?=e|$)/, "$1") // Remove trailing dot.
988     .replace(/\.(?=e|$)/, "");
989   }
990   /**
991    * @param {string} str
992    * @param {string} target
993    * @returns {number}
994    */
995
996
997   function getMaxContinuousCount(str, target) {
998     const results = str.match(new RegExp("(".concat(escapeStringRegexp(target), ")+"), "g"));
999
1000     if (results === null) {
1001       return 0;
1002     }
1003
1004     return results.reduce((maxCount, result) => Math.max(maxCount, result.length / target.length), 0);
1005   }
1006
1007   function getMinNotPresentContinuousCount(str, target) {
1008     const matches = str.match(new RegExp("(".concat(escapeStringRegexp(target), ")+"), "g"));
1009
1010     if (matches === null) {
1011       return 0;
1012     }
1013
1014     const countPresent = new Map();
1015     let max = 0;
1016
1017     for (const match of matches) {
1018       const count = match.length / target.length;
1019       countPresent.set(count, true);
1020
1021       if (count > max) {
1022         max = count;
1023       }
1024     }
1025
1026     for (let i = 1; i < max; i++) {
1027       if (!countPresent.get(i)) {
1028         return i;
1029       }
1030     }
1031
1032     return max + 1;
1033   }
1034   /**
1035    * @param {string} text
1036    * @returns {number}
1037    */
1038
1039
1040   function getStringWidth(text) {
1041     if (!text) {
1042       return 0;
1043     } // shortcut to avoid needless string `RegExp`s, replacements, and allocations within `string-width`
1044
1045
1046     if (!notAsciiRegex.test(text)) {
1047       return text.length;
1048     }
1049
1050     return stringWidth_1(text);
1051   }
1052
1053   function hasIgnoreComment(path) {
1054     const node = path.getValue();
1055     return hasNodeIgnoreComment(node);
1056   }
1057
1058   function hasNodeIgnoreComment(node) {
1059     return node && (node.comments && node.comments.length > 0 && node.comments.some(comment => isNodeIgnoreComment(comment) && !comment.unignore) || node.prettierIgnore);
1060   }
1061
1062   function isNodeIgnoreComment(comment) {
1063     return comment.value.trim() === "prettier-ignore";
1064   }
1065
1066   function addCommentHelper(node, comment) {
1067     const comments = node.comments || (node.comments = []);
1068     comments.push(comment);
1069     comment.printed = false; // For some reason, TypeScript parses `// x` inside of JSXText as a comment
1070     // We already "print" it via the raw text, we don't need to re-print it as a
1071     // comment
1072
1073     if (node.type === "JSXText") {
1074       comment.printed = true;
1075     }
1076   }
1077
1078   function addLeadingComment(node, comment) {
1079     comment.leading = true;
1080     comment.trailing = false;
1081     addCommentHelper(node, comment);
1082   }
1083
1084   function addDanglingComment(node, comment) {
1085     comment.leading = false;
1086     comment.trailing = false;
1087     addCommentHelper(node, comment);
1088   }
1089
1090   function addTrailingComment(node, comment) {
1091     comment.leading = false;
1092     comment.trailing = true;
1093     addCommentHelper(node, comment);
1094   }
1095
1096   function isWithinParentArrayProperty(path, propertyName) {
1097     const node = path.getValue();
1098     const parent = path.getParentNode();
1099
1100     if (parent == null) {
1101       return false;
1102     }
1103
1104     if (!Array.isArray(parent[propertyName])) {
1105       return false;
1106     }
1107
1108     const key = path.getName();
1109     return parent[propertyName][key] === node;
1110   }
1111
1112   function replaceEndOfLineWith(text, replacement) {
1113     const parts = [];
1114
1115     for (const part of text.split("\n")) {
1116       if (parts.length !== 0) {
1117         parts.push(replacement);
1118       }
1119
1120       parts.push(part);
1121     }
1122
1123     return parts;
1124   }
1125
1126   var util = {
1127     replaceEndOfLineWith,
1128     getStringWidth,
1129     getMaxContinuousCount,
1130     getMinNotPresentContinuousCount,
1131     getPrecedence,
1132     shouldFlatten,
1133     isBitwiseOperator,
1134     getPenultimate,
1135     getLast,
1136     getNextNonSpaceNonCommentCharacterIndexWithStartIndex,
1137     getNextNonSpaceNonCommentCharacterIndex,
1138     getNextNonSpaceNonCommentCharacter,
1139     skip,
1140     skipWhitespace,
1141     skipSpaces,
1142     skipToLineEnd,
1143     skipEverythingButNewLine,
1144     skipInlineComment,
1145     skipTrailingComment,
1146     skipNewline,
1147     isNextLineEmptyAfterIndex,
1148     isNextLineEmpty,
1149     isPreviousLineEmpty,
1150     hasNewline,
1151     hasNewlineInRange,
1152     hasSpaces,
1153     setLocStart,
1154     setLocEnd,
1155     startsWithNoLookaheadToken,
1156     getAlignmentSize,
1157     getIndentSize,
1158     getPreferredQuote,
1159     printString,
1160     printNumber,
1161     hasIgnoreComment,
1162     hasNodeIgnoreComment,
1163     isNodeIgnoreComment,
1164     makeString,
1165     addLeadingComment,
1166     addDanglingComment,
1167     addTrailingComment,
1168     isWithinParentArrayProperty
1169   };
1170
1171   function guessEndOfLine(text) {
1172     const index = text.indexOf("\r");
1173
1174     if (index >= 0) {
1175       return text.charAt(index + 1) === "\n" ? "crlf" : "cr";
1176     }
1177
1178     return "lf";
1179   }
1180
1181   function convertEndOfLineToChars(value) {
1182     switch (value) {
1183       case "cr":
1184         return "\r";
1185
1186       case "crlf":
1187         return "\r\n";
1188
1189       default:
1190         return "\n";
1191     }
1192   }
1193
1194   var endOfLine = {
1195     guessEndOfLine,
1196     convertEndOfLineToChars
1197   };
1198
1199   const {
1200     getStringWidth: getStringWidth$1
1201   } = util;
1202   const {
1203     convertEndOfLineToChars: convertEndOfLineToChars$1
1204   } = endOfLine;
1205   const {
1206     concat: concat$1,
1207     fill: fill$1,
1208     cursor: cursor$1
1209   } = docBuilders;
1210   /** @type {Record<symbol, typeof MODE_BREAK | typeof MODE_FLAT>} */
1211
1212   let groupModeMap;
1213   const MODE_BREAK = 1;
1214   const MODE_FLAT = 2;
1215
1216   function rootIndent() {
1217     return {
1218       value: "",
1219       length: 0,
1220       queue: []
1221     };
1222   }
1223
1224   function makeIndent(ind, options) {
1225     return generateInd(ind, {
1226       type: "indent"
1227     }, options);
1228   }
1229
1230   function makeAlign(ind, n, options) {
1231     return n === -Infinity ? ind.root || rootIndent() : n < 0 ? generateInd(ind, {
1232       type: "dedent"
1233     }, options) : !n ? ind : n.type === "root" ? Object.assign({}, ind, {
1234       root: ind
1235     }) : typeof n === "string" ? generateInd(ind, {
1236       type: "stringAlign",
1237       n
1238     }, options) : generateInd(ind, {
1239       type: "numberAlign",
1240       n
1241     }, options);
1242   }
1243
1244   function generateInd(ind, newPart, options) {
1245     const queue = newPart.type === "dedent" ? ind.queue.slice(0, -1) : ind.queue.concat(newPart);
1246     let value = "";
1247     let length = 0;
1248     let lastTabs = 0;
1249     let lastSpaces = 0;
1250
1251     for (const part of queue) {
1252       switch (part.type) {
1253         case "indent":
1254           flush();
1255
1256           if (options.useTabs) {
1257             addTabs(1);
1258           } else {
1259             addSpaces(options.tabWidth);
1260           }
1261
1262           break;
1263
1264         case "stringAlign":
1265           flush();
1266           value += part.n;
1267           length += part.n.length;
1268           break;
1269
1270         case "numberAlign":
1271           lastTabs += 1;
1272           lastSpaces += part.n;
1273           break;
1274
1275         /* istanbul ignore next */
1276
1277         default:
1278           throw new Error("Unexpected type '".concat(part.type, "'"));
1279       }
1280     }
1281
1282     flushSpaces();
1283     return Object.assign({}, ind, {
1284       value,
1285       length,
1286       queue
1287     });
1288
1289     function addTabs(count) {
1290       value += "\t".repeat(count);
1291       length += options.tabWidth * count;
1292     }
1293
1294     function addSpaces(count) {
1295       value += " ".repeat(count);
1296       length += count;
1297     }
1298
1299     function flush() {
1300       if (options.useTabs) {
1301         flushTabs();
1302       } else {
1303         flushSpaces();
1304       }
1305     }
1306
1307     function flushTabs() {
1308       if (lastTabs > 0) {
1309         addTabs(lastTabs);
1310       }
1311
1312       resetLast();
1313     }
1314
1315     function flushSpaces() {
1316       if (lastSpaces > 0) {
1317         addSpaces(lastSpaces);
1318       }
1319
1320       resetLast();
1321     }
1322
1323     function resetLast() {
1324       lastTabs = 0;
1325       lastSpaces = 0;
1326     }
1327   }
1328
1329   function trim$1(out) {
1330     if (out.length === 0) {
1331       return 0;
1332     }
1333
1334     let trimCount = 0; // Trim whitespace at the end of line
1335
1336     while (out.length > 0 && typeof out[out.length - 1] === "string" && out[out.length - 1].match(/^[ \t]*$/)) {
1337       trimCount += out.pop().length;
1338     }
1339
1340     if (out.length && typeof out[out.length - 1] === "string") {
1341       const trimmed = out[out.length - 1].replace(/[ \t]*$/, "");
1342       trimCount += out[out.length - 1].length - trimmed.length;
1343       out[out.length - 1] = trimmed;
1344     }
1345
1346     return trimCount;
1347   }
1348
1349   function fits(next, restCommands, width, options, mustBeFlat) {
1350     let restIdx = restCommands.length;
1351     const cmds = [next]; // `out` is only used for width counting because `trim` requires to look
1352     // backwards for space characters.
1353
1354     const out = [];
1355
1356     while (width >= 0) {
1357       if (cmds.length === 0) {
1358         if (restIdx === 0) {
1359           return true;
1360         }
1361
1362         cmds.push(restCommands[restIdx - 1]);
1363         restIdx--;
1364         continue;
1365       }
1366
1367       const [ind, mode, doc] = cmds.pop();
1368
1369       if (typeof doc === "string") {
1370         out.push(doc);
1371         width -= getStringWidth$1(doc);
1372       } else {
1373         switch (doc.type) {
1374           case "concat":
1375             for (let i = doc.parts.length - 1; i >= 0; i--) {
1376               cmds.push([ind, mode, doc.parts[i]]);
1377             }
1378
1379             break;
1380
1381           case "indent":
1382             cmds.push([makeIndent(ind, options), mode, doc.contents]);
1383             break;
1384
1385           case "align":
1386             cmds.push([makeAlign(ind, doc.n, options), mode, doc.contents]);
1387             break;
1388
1389           case "trim":
1390             width += trim$1(out);
1391             break;
1392
1393           case "group":
1394             if (mustBeFlat && doc.break) {
1395               return false;
1396             }
1397
1398             cmds.push([ind, doc.break ? MODE_BREAK : mode, doc.contents]);
1399
1400             if (doc.id) {
1401               groupModeMap[doc.id] = cmds[cmds.length - 1][1];
1402             }
1403
1404             break;
1405
1406           case "fill":
1407             for (let i = doc.parts.length - 1; i >= 0; i--) {
1408               cmds.push([ind, mode, doc.parts[i]]);
1409             }
1410
1411             break;
1412
1413           case "if-break":
1414             {
1415               const groupMode = doc.groupId ? groupModeMap[doc.groupId] : mode;
1416
1417               if (groupMode === MODE_BREAK) {
1418                 if (doc.breakContents) {
1419                   cmds.push([ind, mode, doc.breakContents]);
1420                 }
1421               }
1422
1423               if (groupMode === MODE_FLAT) {
1424                 if (doc.flatContents) {
1425                   cmds.push([ind, mode, doc.flatContents]);
1426                 }
1427               }
1428
1429               break;
1430             }
1431
1432           case "line":
1433             switch (mode) {
1434               // fallthrough
1435               case MODE_FLAT:
1436                 if (!doc.hard) {
1437                   if (!doc.soft) {
1438                     out.push(" ");
1439                     width -= 1;
1440                   }
1441
1442                   break;
1443                 }
1444
1445                 return true;
1446
1447               case MODE_BREAK:
1448                 return true;
1449             }
1450
1451             break;
1452         }
1453       }
1454     }
1455
1456     return false;
1457   }
1458
1459   function printDocToString(doc, options) {
1460     groupModeMap = {};
1461     const width = options.printWidth;
1462     const newLine = convertEndOfLineToChars$1(options.endOfLine);
1463     let pos = 0; // cmds is basically a stack. We've turned a recursive call into a
1464     // while loop which is much faster. The while loop below adds new
1465     // cmds to the array instead of recursively calling `print`.
1466
1467     const cmds = [[rootIndent(), MODE_BREAK, doc]];
1468     const out = [];
1469     let shouldRemeasure = false;
1470     let lineSuffix = [];
1471
1472     while (cmds.length !== 0) {
1473       const [ind, mode, doc] = cmds.pop();
1474
1475       if (typeof doc === "string") {
1476         const formatted = newLine !== "\n" && doc.includes("\n") ? doc.replace(/\n/g, newLine) : doc;
1477         out.push(formatted);
1478         pos += getStringWidth$1(formatted);
1479       } else {
1480         switch (doc.type) {
1481           case "cursor":
1482             out.push(cursor$1.placeholder);
1483             break;
1484
1485           case "concat":
1486             for (let i = doc.parts.length - 1; i >= 0; i--) {
1487               cmds.push([ind, mode, doc.parts[i]]);
1488             }
1489
1490             break;
1491
1492           case "indent":
1493             cmds.push([makeIndent(ind, options), mode, doc.contents]);
1494             break;
1495
1496           case "align":
1497             cmds.push([makeAlign(ind, doc.n, options), mode, doc.contents]);
1498             break;
1499
1500           case "trim":
1501             pos -= trim$1(out);
1502             break;
1503
1504           case "group":
1505             switch (mode) {
1506               case MODE_FLAT:
1507                 if (!shouldRemeasure) {
1508                   cmds.push([ind, doc.break ? MODE_BREAK : MODE_FLAT, doc.contents]);
1509                   break;
1510                 }
1511
1512               // fallthrough
1513
1514               case MODE_BREAK:
1515                 {
1516                   shouldRemeasure = false;
1517                   const next = [ind, MODE_FLAT, doc.contents];
1518                   const rem = width - pos;
1519
1520                   if (!doc.break && fits(next, cmds, rem, options)) {
1521                     cmds.push(next);
1522                   } else {
1523                     // Expanded states are a rare case where a document
1524                     // can manually provide multiple representations of
1525                     // itself. It provides an array of documents
1526                     // going from the least expanded (most flattened)
1527                     // representation first to the most expanded. If a
1528                     // group has these, we need to manually go through
1529                     // these states and find the first one that fits.
1530                     if (doc.expandedStates) {
1531                       const mostExpanded = doc.expandedStates[doc.expandedStates.length - 1];
1532
1533                       if (doc.break) {
1534                         cmds.push([ind, MODE_BREAK, mostExpanded]);
1535                         break;
1536                       } else {
1537                         for (let i = 1; i < doc.expandedStates.length + 1; i++) {
1538                           if (i >= doc.expandedStates.length) {
1539                             cmds.push([ind, MODE_BREAK, mostExpanded]);
1540                             break;
1541                           } else {
1542                             const state = doc.expandedStates[i];
1543                             const cmd = [ind, MODE_FLAT, state];
1544
1545                             if (fits(cmd, cmds, rem, options)) {
1546                               cmds.push(cmd);
1547                               break;
1548                             }
1549                           }
1550                         }
1551                       }
1552                     } else {
1553                       cmds.push([ind, MODE_BREAK, doc.contents]);
1554                     }
1555                   }
1556
1557                   break;
1558                 }
1559             }
1560
1561             if (doc.id) {
1562               groupModeMap[doc.id] = cmds[cmds.length - 1][1];
1563             }
1564
1565             break;
1566           // Fills each line with as much code as possible before moving to a new
1567           // line with the same indentation.
1568           //
1569           // Expects doc.parts to be an array of alternating content and
1570           // whitespace. The whitespace contains the linebreaks.
1571           //
1572           // For example:
1573           //   ["I", line, "love", line, "monkeys"]
1574           // or
1575           //   [{ type: group, ... }, softline, { type: group, ... }]
1576           //
1577           // It uses this parts structure to handle three main layout cases:
1578           // * The first two content items fit on the same line without
1579           //   breaking
1580           //   -> output the first content item and the whitespace "flat".
1581           // * Only the first content item fits on the line without breaking
1582           //   -> output the first content item "flat" and the whitespace with
1583           //   "break".
1584           // * Neither content item fits on the line without breaking
1585           //   -> output the first content item and the whitespace with "break".
1586
1587           case "fill":
1588             {
1589               const rem = width - pos;
1590               const {
1591                 parts
1592               } = doc;
1593
1594               if (parts.length === 0) {
1595                 break;
1596               }
1597
1598               const [content, whitespace] = parts;
1599               const contentFlatCmd = [ind, MODE_FLAT, content];
1600               const contentBreakCmd = [ind, MODE_BREAK, content];
1601               const contentFits = fits(contentFlatCmd, [], rem, options, true);
1602
1603               if (parts.length === 1) {
1604                 if (contentFits) {
1605                   cmds.push(contentFlatCmd);
1606                 } else {
1607                   cmds.push(contentBreakCmd);
1608                 }
1609
1610                 break;
1611               }
1612
1613               const whitespaceFlatCmd = [ind, MODE_FLAT, whitespace];
1614               const whitespaceBreakCmd = [ind, MODE_BREAK, whitespace];
1615
1616               if (parts.length === 2) {
1617                 if (contentFits) {
1618                   cmds.push(whitespaceFlatCmd);
1619                   cmds.push(contentFlatCmd);
1620                 } else {
1621                   cmds.push(whitespaceBreakCmd);
1622                   cmds.push(contentBreakCmd);
1623                 }
1624
1625                 break;
1626               } // At this point we've handled the first pair (context, separator)
1627               // and will create a new fill doc for the rest of the content.
1628               // Ideally we wouldn't mutate the array here but copying all the
1629               // elements to a new array would make this algorithm quadratic,
1630               // which is unusable for large arrays (e.g. large texts in JSX).
1631
1632
1633               parts.splice(0, 2);
1634               const remainingCmd = [ind, mode, fill$1(parts)];
1635               const secondContent = parts[0];
1636               const firstAndSecondContentFlatCmd = [ind, MODE_FLAT, concat$1([content, whitespace, secondContent])];
1637               const firstAndSecondContentFits = fits(firstAndSecondContentFlatCmd, [], rem, options, true);
1638
1639               if (firstAndSecondContentFits) {
1640                 cmds.push(remainingCmd);
1641                 cmds.push(whitespaceFlatCmd);
1642                 cmds.push(contentFlatCmd);
1643               } else if (contentFits) {
1644                 cmds.push(remainingCmd);
1645                 cmds.push(whitespaceBreakCmd);
1646                 cmds.push(contentFlatCmd);
1647               } else {
1648                 cmds.push(remainingCmd);
1649                 cmds.push(whitespaceBreakCmd);
1650                 cmds.push(contentBreakCmd);
1651               }
1652
1653               break;
1654             }
1655
1656           case "if-break":
1657             {
1658               const groupMode = doc.groupId ? groupModeMap[doc.groupId] : mode;
1659
1660               if (groupMode === MODE_BREAK) {
1661                 if (doc.breakContents) {
1662                   cmds.push([ind, mode, doc.breakContents]);
1663                 }
1664               }
1665
1666               if (groupMode === MODE_FLAT) {
1667                 if (doc.flatContents) {
1668                   cmds.push([ind, mode, doc.flatContents]);
1669                 }
1670               }
1671
1672               break;
1673             }
1674
1675           case "line-suffix":
1676             lineSuffix.push([ind, mode, doc.contents]);
1677             break;
1678
1679           case "line-suffix-boundary":
1680             if (lineSuffix.length > 0) {
1681               cmds.push([ind, mode, {
1682                 type: "line",
1683                 hard: true
1684               }]);
1685             }
1686
1687             break;
1688
1689           case "line":
1690             switch (mode) {
1691               case MODE_FLAT:
1692                 if (!doc.hard) {
1693                   if (!doc.soft) {
1694                     out.push(" ");
1695                     pos += 1;
1696                   }
1697
1698                   break;
1699                 } else {
1700                   // This line was forced into the output even if we
1701                   // were in flattened mode, so we need to tell the next
1702                   // group that no matter what, it needs to remeasure
1703                   // because the previous measurement didn't accurately
1704                   // capture the entire expression (this is necessary
1705                   // for nested groups)
1706                   shouldRemeasure = true;
1707                 }
1708
1709               // fallthrough
1710
1711               case MODE_BREAK:
1712                 if (lineSuffix.length) {
1713                   cmds.push([ind, mode, doc]);
1714                   cmds.push(...lineSuffix.reverse());
1715                   lineSuffix = [];
1716                   break;
1717                 }
1718
1719                 if (doc.literal) {
1720                   if (ind.root) {
1721                     out.push(newLine, ind.root.value);
1722                     pos = ind.root.length;
1723                   } else {
1724                     out.push(newLine);
1725                     pos = 0;
1726                   }
1727                 } else {
1728                   pos -= trim$1(out);
1729                   out.push(newLine + ind.value);
1730                   pos = ind.length;
1731                 }
1732
1733                 break;
1734             }
1735
1736             break;
1737         }
1738       }
1739     }
1740
1741     const cursorPlaceholderIndex = out.indexOf(cursor$1.placeholder);
1742
1743     if (cursorPlaceholderIndex !== -1) {
1744       const otherCursorPlaceholderIndex = out.indexOf(cursor$1.placeholder, cursorPlaceholderIndex + 1);
1745       const beforeCursor = out.slice(0, cursorPlaceholderIndex).join("");
1746       const aroundCursor = out.slice(cursorPlaceholderIndex + 1, otherCursorPlaceholderIndex).join("");
1747       const afterCursor = out.slice(otherCursorPlaceholderIndex + 1).join("");
1748       return {
1749         formatted: beforeCursor + aroundCursor + afterCursor,
1750         cursorNodeStart: beforeCursor.length,
1751         cursorNodeText: aroundCursor
1752       };
1753     }
1754
1755     return {
1756       formatted: out.join("")
1757     };
1758   }
1759
1760   var docPrinter = {
1761     printDocToString
1762   };
1763
1764   const traverseDocOnExitStackMarker = {};
1765
1766   function traverseDoc(doc, onEnter, onExit, shouldTraverseConditionalGroups) {
1767     const docsStack = [doc];
1768
1769     while (docsStack.length !== 0) {
1770       const doc = docsStack.pop();
1771
1772       if (doc === traverseDocOnExitStackMarker) {
1773         onExit(docsStack.pop());
1774         continue;
1775       }
1776
1777       let shouldRecurse = true;
1778
1779       if (onEnter) {
1780         if (onEnter(doc) === false) {
1781           shouldRecurse = false;
1782         }
1783       }
1784
1785       if (onExit) {
1786         docsStack.push(doc);
1787         docsStack.push(traverseDocOnExitStackMarker);
1788       }
1789
1790       if (shouldRecurse) {
1791         // When there are multiple parts to process,
1792         // the parts need to be pushed onto the stack in reverse order,
1793         // so that they are processed in the original order
1794         // when the stack is popped.
1795         if (doc.type === "concat" || doc.type === "fill") {
1796           for (let ic = doc.parts.length, i = ic - 1; i >= 0; --i) {
1797             docsStack.push(doc.parts[i]);
1798           }
1799         } else if (doc.type === "if-break") {
1800           if (doc.flatContents) {
1801             docsStack.push(doc.flatContents);
1802           }
1803
1804           if (doc.breakContents) {
1805             docsStack.push(doc.breakContents);
1806           }
1807         } else if (doc.type === "group" && doc.expandedStates) {
1808           if (shouldTraverseConditionalGroups) {
1809             for (let ic = doc.expandedStates.length, i = ic - 1; i >= 0; --i) {
1810               docsStack.push(doc.expandedStates[i]);
1811             }
1812           } else {
1813             docsStack.push(doc.contents);
1814           }
1815         } else if (doc.contents) {
1816           docsStack.push(doc.contents);
1817         }
1818       }
1819     }
1820   }
1821
1822   function mapDoc(doc, cb) {
1823     if (doc.type === "concat" || doc.type === "fill") {
1824       const parts = doc.parts.map(part => mapDoc(part, cb));
1825       return cb(Object.assign({}, doc, {
1826         parts
1827       }));
1828     } else if (doc.type === "if-break") {
1829       const breakContents = doc.breakContents && mapDoc(doc.breakContents, cb);
1830       const flatContents = doc.flatContents && mapDoc(doc.flatContents, cb);
1831       return cb(Object.assign({}, doc, {
1832         breakContents,
1833         flatContents
1834       }));
1835     } else if (doc.contents) {
1836       const contents = mapDoc(doc.contents, cb);
1837       return cb(Object.assign({}, doc, {
1838         contents
1839       }));
1840     }
1841
1842     return cb(doc);
1843   }
1844
1845   function findInDoc(doc, fn, defaultValue) {
1846     let result = defaultValue;
1847     let hasStopped = false;
1848
1849     function findInDocOnEnterFn(doc) {
1850       const maybeResult = fn(doc);
1851
1852       if (maybeResult !== undefined) {
1853         hasStopped = true;
1854         result = maybeResult;
1855       }
1856
1857       if (hasStopped) {
1858         return false;
1859       }
1860     }
1861
1862     traverseDoc(doc, findInDocOnEnterFn);
1863     return result;
1864   }
1865
1866   function isEmpty(n) {
1867     return typeof n === "string" && n.length === 0;
1868   }
1869
1870   function isLineNextFn(doc) {
1871     if (typeof doc === "string") {
1872       return false;
1873     }
1874
1875     if (doc.type === "line") {
1876       return true;
1877     }
1878   }
1879
1880   function isLineNext(doc) {
1881     return findInDoc(doc, isLineNextFn, false);
1882   }
1883
1884   function willBreakFn(doc) {
1885     if (doc.type === "group" && doc.break) {
1886       return true;
1887     }
1888
1889     if (doc.type === "line" && doc.hard) {
1890       return true;
1891     }
1892
1893     if (doc.type === "break-parent") {
1894       return true;
1895     }
1896   }
1897
1898   function willBreak(doc) {
1899     return findInDoc(doc, willBreakFn, false);
1900   }
1901
1902   function breakParentGroup(groupStack) {
1903     if (groupStack.length > 0) {
1904       const parentGroup = groupStack[groupStack.length - 1]; // Breaks are not propagated through conditional groups because
1905       // the user is expected to manually handle what breaks.
1906
1907       if (!parentGroup.expandedStates) {
1908         parentGroup.break = true;
1909       }
1910     }
1911
1912     return null;
1913   }
1914
1915   function propagateBreaks(doc) {
1916     const alreadyVisitedSet = new Set();
1917     const groupStack = [];
1918
1919     function propagateBreaksOnEnterFn(doc) {
1920       if (doc.type === "break-parent") {
1921         breakParentGroup(groupStack);
1922       }
1923
1924       if (doc.type === "group") {
1925         groupStack.push(doc);
1926
1927         if (alreadyVisitedSet.has(doc)) {
1928           return false;
1929         }
1930
1931         alreadyVisitedSet.add(doc);
1932       }
1933     }
1934
1935     function propagateBreaksOnExitFn(doc) {
1936       if (doc.type === "group") {
1937         const group = groupStack.pop();
1938
1939         if (group.break) {
1940           breakParentGroup(groupStack);
1941         }
1942       }
1943     }
1944
1945     traverseDoc(doc, propagateBreaksOnEnterFn, propagateBreaksOnExitFn,
1946     /* shouldTraverseConditionalGroups */
1947     true);
1948   }
1949
1950   function removeLinesFn(doc) {
1951     // Force this doc into flat mode by statically converting all
1952     // lines into spaces (or soft lines into nothing). Hard lines
1953     // should still output because there's too great of a chance
1954     // of breaking existing assumptions otherwise.
1955     if (doc.type === "line" && !doc.hard) {
1956       return doc.soft ? "" : " ";
1957     } else if (doc.type === "if-break") {
1958       return doc.flatContents || "";
1959     }
1960
1961     return doc;
1962   }
1963
1964   function removeLines(doc) {
1965     return mapDoc(doc, removeLinesFn);
1966   }
1967
1968   function stripTrailingHardline(doc) {
1969     // HACK remove ending hardline, original PR: #1984
1970     if (doc.type === "concat" && doc.parts.length !== 0) {
1971       const lastPart = doc.parts[doc.parts.length - 1];
1972
1973       if (lastPart.type === "concat") {
1974         if (lastPart.parts.length === 2 && lastPart.parts[0].hard && lastPart.parts[1].type === "break-parent") {
1975           return {
1976             type: "concat",
1977             parts: doc.parts.slice(0, -1)
1978           };
1979         }
1980
1981         return {
1982           type: "concat",
1983           parts: doc.parts.slice(0, -1).concat(stripTrailingHardline(lastPart))
1984         };
1985       }
1986     }
1987
1988     return doc;
1989   }
1990
1991   var docUtils = {
1992     isEmpty,
1993     willBreak,
1994     isLineNext,
1995     traverseDoc,
1996     findInDoc,
1997     mapDoc,
1998     propagateBreaks,
1999     removeLines,
2000     stripTrailingHardline
2001   };
2002
2003   function flattenDoc(doc) {
2004     if (doc.type === "concat") {
2005       const res = [];
2006
2007       for (let i = 0; i < doc.parts.length; ++i) {
2008         const doc2 = doc.parts[i];
2009
2010         if (typeof doc2 !== "string" && doc2.type === "concat") {
2011           res.push(...flattenDoc(doc2).parts);
2012         } else {
2013           const flattened = flattenDoc(doc2);
2014
2015           if (flattened !== "") {
2016             res.push(flattened);
2017           }
2018         }
2019       }
2020
2021       return Object.assign({}, doc, {
2022         parts: res
2023       });
2024     } else if (doc.type === "if-break") {
2025       return Object.assign({}, doc, {
2026         breakContents: doc.breakContents != null ? flattenDoc(doc.breakContents) : null,
2027         flatContents: doc.flatContents != null ? flattenDoc(doc.flatContents) : null
2028       });
2029     } else if (doc.type === "group") {
2030       return Object.assign({}, doc, {
2031         contents: flattenDoc(doc.contents),
2032         expandedStates: doc.expandedStates ? doc.expandedStates.map(flattenDoc) : doc.expandedStates
2033       });
2034     } else if (doc.contents) {
2035       return Object.assign({}, doc, {
2036         contents: flattenDoc(doc.contents)
2037       });
2038     }
2039
2040     return doc;
2041   }
2042
2043   function printDoc(doc) {
2044     if (typeof doc === "string") {
2045       return JSON.stringify(doc);
2046     }
2047
2048     if (doc.type === "line") {
2049       if (doc.literal) {
2050         return "literalline";
2051       }
2052
2053       if (doc.hard) {
2054         return "hardline";
2055       }
2056
2057       if (doc.soft) {
2058         return "softline";
2059       }
2060
2061       return "line";
2062     }
2063
2064     if (doc.type === "break-parent") {
2065       return "breakParent";
2066     }
2067
2068     if (doc.type === "trim") {
2069       return "trim";
2070     }
2071
2072     if (doc.type === "concat") {
2073       return "[" + doc.parts.map(printDoc).join(", ") + "]";
2074     }
2075
2076     if (doc.type === "indent") {
2077       return "indent(" + printDoc(doc.contents) + ")";
2078     }
2079
2080     if (doc.type === "align") {
2081       return doc.n === -Infinity ? "dedentToRoot(" + printDoc(doc.contents) + ")" : doc.n < 0 ? "dedent(" + printDoc(doc.contents) + ")" : doc.n.type === "root" ? "markAsRoot(" + printDoc(doc.contents) + ")" : "align(" + JSON.stringify(doc.n) + ", " + printDoc(doc.contents) + ")";
2082     }
2083
2084     if (doc.type === "if-break") {
2085       return "ifBreak(" + printDoc(doc.breakContents) + (doc.flatContents ? ", " + printDoc(doc.flatContents) : "") + ")";
2086     }
2087
2088     if (doc.type === "group") {
2089       if (doc.expandedStates) {
2090         return "conditionalGroup(" + "[" + doc.expandedStates.map(printDoc).join(",") + "])";
2091       }
2092
2093       return (doc.break ? "wrappedGroup" : "group") + "(" + printDoc(doc.contents) + ")";
2094     }
2095
2096     if (doc.type === "fill") {
2097       return "fill" + "(" + doc.parts.map(printDoc).join(", ") + ")";
2098     }
2099
2100     if (doc.type === "line-suffix") {
2101       return "lineSuffix(" + printDoc(doc.contents) + ")";
2102     }
2103
2104     if (doc.type === "line-suffix-boundary") {
2105       return "lineSuffixBoundary";
2106     }
2107
2108     throw new Error("Unknown doc type " + doc.type);
2109   }
2110
2111   var docDebug = {
2112     printDocToDebug(doc) {
2113       return printDoc(flattenDoc(doc));
2114     }
2115
2116   };
2117
2118   var document = {
2119     builders: docBuilders,
2120     printer: docPrinter,
2121     utils: docUtils,
2122     debug: docDebug
2123   };
2124   var document_1 = document.builders;
2125   var document_2 = document.printer;
2126   var document_3 = document.utils;
2127   var document_4 = document.debug;
2128
2129   exports.builders = document_1;
2130   exports.debug = document_4;
2131   exports.default = document;
2132   exports.printer = document_2;
2133   exports.utils = document_3;
2134
2135   Object.defineProperty(exports, '__esModule', { value: true });
2136
2137 })));