prettier-plugin-astro 0.0.11 → 0.1.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2,44 +2,27 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var parser = require('@astrojs/parser');
5
+ var makeSynchronous = require('make-synchronous');
6
6
  var _doc = require('prettier/doc');
7
7
  var sassFormatter = require('sass-formatter');
8
- var prettier = require('prettier');
9
8
 
10
9
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
11
10
 
11
+ var makeSynchronous__default = /*#__PURE__*/_interopDefaultLegacy(makeSynchronous);
12
12
  var _doc__default = /*#__PURE__*/_interopDefaultLegacy(_doc);
13
13
 
14
- const parse = (text) => parser.parse(text);
15
-
16
- const options = {
17
- astroSortOrder: {
18
- since: '0.0.1',
19
- category: 'Astro',
20
- type: 'choice',
21
- default: 'markup | styles',
22
- description: 'Sort order for markup, scripts, and styles',
23
- choices: [
24
- {
25
- value: 'markup | styles',
26
- description: 'markup | styles',
27
- },
28
- {
29
- value: 'styles | markup',
30
- description: 'styles | markup',
31
- },
32
- ],
33
- },
34
- astroAllowShorthand: {
35
- since: '0.0.10',
36
- category: 'Astro',
37
- type: 'boolean',
38
- default: true,
39
- description: 'Enable/disable attribute shorthand if attribute name and expression are the same',
40
- },
41
- };
42
- const parseSortOrder = (sortOrder) => sortOrder.split(' | ');
14
+ const parseSync = makeSynchronous__default["default"](async (source) => {
15
+ const dynamicImport = new Function('file', 'return import(file)');
16
+ const { parse } = await dynamicImport('@astrojs/compiler');
17
+ try {
18
+ const { ast } = await parse(source);
19
+ return ast;
20
+ }
21
+ catch (e) {
22
+ console.error(e);
23
+ }
24
+ });
25
+ const parse = (text) => parseSync(text);
43
26
 
44
27
  const blockElementsT = [
45
28
  'address',
@@ -75,70 +58,48 @@ const blockElementsT = [
75
58
  'section',
76
59
  'table',
77
60
  'ul',
61
+ 'title',
62
+ 'html',
78
63
  ];
79
64
  const blockElements = [...blockElementsT];
80
65
  const selfClosingTags = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
81
66
 
67
+ const serializeSync = makeSynchronous__default["default"](async (node) => {
68
+ const dynamicImport = new Function('file', 'return import(file)');
69
+ const { serialize } = await dynamicImport('@astrojs/compiler/utils');
70
+ try {
71
+ return await serialize(node);
72
+ }
73
+ catch (e) {
74
+ console.error(e);
75
+ }
76
+ });
77
+ const serialize = (node) => serializeSync(node);
78
+
82
79
  const formattableAttributes = [];
83
- const rootNodeKeys = new Set(['html', 'css', 'module']);
84
- const isASTNode = (node) => typeof node === 'object' && Object.keys(node).filter((key) => rootNodeKeys.has(key)).length === rootNodeKeys.size;
85
80
  const isEmptyTextNode = (node) => {
86
- return !!node && node.type === 'Text' && getUnencodedText(node).trim() === '';
81
+ return !!node && node.type === 'text' && getUnencodedText(node).trim() === '';
87
82
  };
88
83
  const isPreTagContent = (path) => {
89
84
  if (!path || !path.stack || !Array.isArray(path.stack))
90
85
  return false;
91
- return path.stack.some((node) => (node.type === 'Element' && node.name.toLowerCase() === 'pre') || (node.type === 'Attribute' && !formattableAttributes.includes(node.name)));
86
+ return path.stack.some((node) => (node.type === 'element' && node.name.toLowerCase() === 'pre') || (node.type === 'attribute' && !formattableAttributes.includes(node.name)));
92
87
  };
93
- function isLoneMustacheTag(node) {
94
- return node !== true && node.length === 1 && node[0].type === 'MustacheTag';
95
- }
96
- function isAttributeShorthand(node) {
97
- return node !== true && node.length === 1 && node[0].type === 'AttributeShorthand';
98
- }
99
- function isOrCanBeConvertedToShorthand(node, opts) {
100
- if (!opts.astroAllowShorthand)
101
- return false;
102
- if (isAttributeShorthand(node.value)) {
103
- return true;
104
- }
105
- if (isLoneMustacheTag(node.value)) {
106
- const expression = node.value[0].expression;
107
- return expression.codeChunks[0] === node.name;
108
- }
109
- return false;
110
- }
111
88
  function getText(node, opts) {
112
- return opts.originalText.slice(opts.locStart(node), opts.locEnd(node));
89
+ var _a, _b, _c;
90
+ return opts.originalText.slice(((_a = node.position) === null || _a === void 0 ? void 0 : _a.start.offset) + 1, (_c = (_b = node.position) === null || _b === void 0 ? void 0 : _b.end) === null || _c === void 0 ? void 0 : _c.offset);
113
91
  }
114
92
  function getUnencodedText(node) {
115
- return node.raw || node.data;
93
+ return node.value;
116
94
  }
117
- function replaceEndOfLineWith(text, replacement) {
118
- const parts = [];
119
- for (const part of text.split('\n')) {
120
- if (parts.length > 0) {
121
- parts.push(replacement);
122
- }
123
- if (part.endsWith('\r')) {
124
- parts.push(part.slice(0, -1));
125
- }
126
- else {
127
- parts.push(part);
128
- }
129
- }
130
- return parts;
131
- }
132
- function printRaw(node, originalText, stripLeadingAndTrailingNewline = false) {
95
+ function printRaw(node, stripLeadingAndTrailingNewline = false) {
133
96
  if (!isNodeWithChildren(node)) {
134
97
  return '';
135
98
  }
136
99
  if (node.children.length === 0) {
137
100
  return '';
138
101
  }
139
- const firstChild = node.children[0];
140
- const lastChild = node.children[node.children.length - 1];
141
- let raw = originalText.substring(firstChild.start, lastChild.end);
102
+ let raw = node.children.reduce((prev, curr) => prev + serialize(curr), '');
142
103
  if (!stripLeadingAndTrailingNewline) {
143
104
  return raw;
144
105
  }
@@ -157,10 +118,10 @@ function isNodeWithChildren(node) {
157
118
  return node && Array.isArray(node.children);
158
119
  }
159
120
  function isInlineElement(path, opts, node) {
160
- return node && node.type === 'Element' && !isBlockElement(node, opts) && !isPreTagContent(path);
121
+ return node && node.type === 'element' && !isBlockElement(node, opts) && !isPreTagContent(path);
161
122
  }
162
123
  function isBlockElement(node, opts) {
163
- return node && node.type === 'Element' && opts.htmlWhitespaceSensitivity !== 'strict' && (opts.htmlWhitespaceSensitivity === 'ignore' || blockElements.includes(node.name));
124
+ return node && node.type === 'element' && opts.htmlWhitespaceSensitivity !== 'strict' && (opts.htmlWhitespaceSensitivity === 'ignore' || blockElements.includes(node.name));
164
125
  }
165
126
  function isTextNodeStartingWithLinebreak(node, nrLines = 1) {
166
127
  return startsWithLinebreak(getUnencodedText(node), nrLines);
@@ -172,10 +133,10 @@ function endsWithLinebreak(text, nrLines = 1) {
172
133
  return new RegExp(`(\\n[\\t\\f\\r ]*){${nrLines}}$`).test(text);
173
134
  }
174
135
  function isTextNodeStartingWithWhitespace(node) {
175
- return node.type === 'Text' && /^\s/.test(getUnencodedText(node));
136
+ return node.type === 'text' && /^\s/.test(getUnencodedText(node));
176
137
  }
177
138
  function isTextNodeEndingWithWhitespace(node) {
178
- return node.type === 'Text' && /\s$/.test(getUnencodedText(node));
139
+ return node.type === 'text' && /\s$/.test(getUnencodedText(node));
179
140
  }
180
141
  function forceIntoExpression(statement) {
181
142
  return `(${statement}\n)`;
@@ -205,8 +166,7 @@ function shouldHugEnd(node, opts) {
205
166
  if (children.length === 0) {
206
167
  return true;
207
168
  }
208
- const lastChild = children[children.length - 1];
209
- return !isTextNodeEndingWithWhitespace(lastChild);
169
+ return false;
210
170
  }
211
171
  function canOmitSoftlineBeforeClosingTag(path, opts) {
212
172
  return isLastChildWithinParentBlockElement(path, opts);
@@ -224,179 +184,49 @@ function isLastChildWithinParentBlockElement(path, opts) {
224
184
  return lastChild === path.getNode();
225
185
  }
226
186
  function trimTextNodeLeft(node) {
227
- node.raw = node.raw && node.raw.trimLeft();
228
- node.data = node.data && node.data.trimLeft();
187
+ node.value = node.value && node.value.trimStart();
229
188
  }
230
189
  function trimTextNodeRight(node) {
231
- node.raw = node.raw && node.raw.trimRight();
232
- node.data = node.data && node.data.trimRight();
233
- }
234
- function findLastIndex(isMatch, items) {
235
- for (let i = items.length - 1; i >= 0; i--) {
236
- if (isMatch(items[i], i)) {
237
- return i;
238
- }
239
- }
240
- return -1;
241
- }
242
- function trimChildren(children) {
243
- let firstNonEmptyNode = children.findIndex((n) => !isEmptyTextNode(n));
244
- firstNonEmptyNode = firstNonEmptyNode === -1 ? children.length - 1 : firstNonEmptyNode;
245
- let lastNonEmptyNode = findLastIndex((n, idx) => {
246
- return !isEmptyTextNode(n);
247
- }, children);
248
- lastNonEmptyNode = lastNonEmptyNode === -1 ? 0 : lastNonEmptyNode;
249
- for (let i = 0; i <= firstNonEmptyNode; i++) {
250
- const n = children[i];
251
- if (isTextNode(n)) {
252
- trimTextNodeLeft(n);
253
- }
254
- }
255
- for (let i = children.length - 1; i >= lastNonEmptyNode; i--) {
256
- const n = children[i];
257
- if (isTextNode(n)) {
258
- trimTextNodeRight(n);
259
- }
260
- }
261
- }
262
- function isHardline(docToCheck) {
263
- return docToCheck === prettier.doc.builders.hardline || deepEqual(docToCheck, prettier.doc.builders.hardline);
264
- }
265
- function deepEqual(x, y) {
266
- if (x === y) {
267
- return true;
268
- }
269
- else if (typeof x == 'object' && x != null && typeof y == 'object' && y != null) {
270
- if (Object.keys(x).length != Object.keys(y).length)
271
- return false;
272
- for (var prop in x) {
273
- if (Object.prototype.hasOwnProperty.call(y, prop)) {
274
- if (!deepEqual(x[prop], y[prop]))
275
- return false;
190
+ node.value = node.value && node.value.trimEnd();
191
+ }
192
+ function manualDedent(input) {
193
+ let result = '';
194
+ for (var i = 0; i < input.length; i++) {
195
+ result += input[i]
196
+ .replace(/\\\n[ \t]*/g, '')
197
+ .replace(/\\`/g, '`');
198
+ if (i < (arguments.length <= 1 ? 0 : arguments.length - 1)) {
199
+ result += arguments.length <= i + 1 ? undefined : arguments[i + 1];
200
+ }
201
+ }
202
+ const lines = result.split('\n');
203
+ let mindent = null;
204
+ lines.forEach(function (l) {
205
+ var m = l.match(/^(\s+)\S+/);
206
+ if (m) {
207
+ var indent = m[1].length;
208
+ if (!mindent) {
209
+ mindent = indent;
276
210
  }
277
211
  else {
278
- return false;
279
- }
280
- }
281
- return true;
282
- }
283
- else {
284
- return false;
285
- }
286
- }
287
- function isLine(docToCheck) {
288
- return (isHardline(docToCheck) ||
289
- (typeof docToCheck === 'object' && isDocCommand(docToCheck) && docToCheck.type === 'line') ||
290
- (typeof docToCheck === 'object' && isDocCommand(docToCheck) && docToCheck.type === 'concat' && docToCheck.parts.every(isLine)));
291
- }
292
- function isEmptyDoc(doc) {
293
- if (typeof doc === 'string') {
294
- return doc.length === 0;
295
- }
296
- if (Array.isArray(doc)) {
297
- return doc.length === 0;
298
- }
299
- return false;
300
- }
301
- function trim(docs, isWhitespace) {
302
- trimLeft(docs, isWhitespace);
303
- trimRight(docs, isWhitespace);
304
- return docs;
305
- }
306
- function trimLeft(group, isWhitespace) {
307
- let firstNonWhitespace = group.findIndex((doc) => !isEmptyDoc(doc) && !isWhitespace(doc));
308
- if (firstNonWhitespace < 0 && group.length) {
309
- firstNonWhitespace = group.length;
310
- }
311
- if (firstNonWhitespace > 0) {
312
- const removed = group.splice(0, firstNonWhitespace);
313
- if (removed.every(isEmptyDoc)) {
314
- return trimLeft(group, isWhitespace);
315
- }
316
- }
317
- else {
318
- const parts = getParts(group[0]);
319
- if (parts) {
320
- return trimLeft(parts, isWhitespace);
321
- }
322
- }
323
- }
324
- function trimRight(group, isWhitespace) {
325
- let lastNonWhitespace = group.length ? findLastIndex((doc) => !isEmptyDoc(doc) && !isWhitespace(doc), group) : 0;
326
- if (lastNonWhitespace < group.length - 1) {
327
- const removed = group.splice(lastNonWhitespace + 1);
328
- if (removed.every(isEmptyDoc)) {
329
- return trimRight(group, isWhitespace);
330
- }
331
- }
332
- else {
333
- const parts = getParts(group[group.length - 1]);
334
- if (parts) {
335
- return trimRight(parts, isWhitespace);
336
- }
337
- }
338
- }
339
- function getParts(doc) {
340
- if (typeof doc === 'object') {
341
- if (Array.isArray(doc)) {
342
- return doc;
343
- }
344
- if (doc.type === 'fill' || doc.type === 'concat') {
345
- return doc.parts;
346
- }
347
- if (doc.type === 'group') {
348
- return getParts(doc.contents);
349
- }
350
- }
351
- }
352
- function attachCommentsHTML(node) {
353
- if (!isNodeWithChildren(node) || !node.children.some(({ type }) => type === 'Comment'))
354
- return;
355
- const nodesToRemove = [];
356
- for (let n = 0; n < node.children.length - 1; n++) {
357
- if (!node.children[n])
358
- continue;
359
- if (node.children[n].type === 'Comment') {
360
- let next = n + 1;
361
- while (isEmptyTextNode(node.children[next])) {
362
- nodesToRemove.push(next);
363
- next++;
212
+ mindent = Math.min(mindent, indent);
364
213
  }
365
- prettier.util.addLeadingComment(node.children[next], node.children[n]);
366
214
  }
367
- }
368
- nodesToRemove.reverse();
369
- nodesToRemove.forEach((index) => {
370
- node.children.splice(index, 1);
371
215
  });
372
- }
373
- function dedent$1(input) {
374
- let minTabSize = Infinity;
375
- let result = input;
376
- result = result.replace(/\r\n/g, '\n');
377
- let char = '';
378
- for (const line of result.split('\n')) {
379
- if (!line)
380
- continue;
381
- if (line[0] && /^[^\s]/.test(line[0])) {
382
- minTabSize = 0;
383
- break;
384
- }
385
- const match = line.match(/^(\s+)\S+/);
386
- if (match) {
387
- if (match[1] && !char)
388
- char = match[1][0];
389
- if (match[1].length < minTabSize)
390
- minTabSize = match[1].length;
391
- }
392
- }
393
- if (minTabSize > 0 && Number.isFinite(minTabSize)) {
394
- result = result.replace(new RegExp(`^${new Array(minTabSize + 1).join(char)}`, 'gm'), '');
216
+ if (mindent !== null) {
217
+ (function () {
218
+ var m = mindent;
219
+ result = lines
220
+ .map(function (l) {
221
+ return l[0] === ' ' ? l.slice(m) : l;
222
+ })
223
+ .join('\n');
224
+ })();
395
225
  }
396
226
  return {
397
- tabSize: minTabSize === Infinity ? 0 : minTabSize,
398
- char,
399
- result,
227
+ result: result
228
+ .trim()
229
+ .replace(/\\n/g, '\n'),
400
230
  };
401
231
  }
402
232
  function getMarkdownName(script) {
@@ -423,119 +253,27 @@ function getMarkdownName(script) {
423
253
  return new Set(['Markdown']);
424
254
  }
425
255
  function isTextNode(node) {
426
- return node.type === 'Text';
427
- }
428
- function isDocCommand(doc) {
429
- if (typeof doc === 'string')
430
- return false;
431
- if (Array.isArray(doc))
432
- return false;
433
- return true;
434
- }
435
- function isInsideQuotedAttribute(path) {
436
- const stack = path.stack;
437
- return stack.some((node) => node.type === 'Attribute' && !isLoneMustacheTag(node.value));
256
+ return node.type === 'text';
438
257
  }
439
258
 
440
259
  const { builders: { breakParent, dedent, fill, group, hardline, indent, join, line, literalline, softline }, utils: { removeLines, stripTrailingHardline }, } = _doc__default["default"];
441
- function printTopLevelParts(node, path, opts, print) {
442
- let docs = [];
443
- const normalize = (doc) => [stripTrailingHardline(doc), hardline];
444
- if (node.module) {
445
- const subDoc = normalize(path.call(print, 'module'));
446
- docs.push(subDoc);
447
- }
448
- for (const section of parseSortOrder(opts.astroSortOrder)) {
449
- switch (section) {
450
- case 'markup': {
451
- const subDoc = path.call(print, 'html');
452
- if (!isEmptyDoc(subDoc))
453
- docs.push(normalize(subDoc));
454
- break;
455
- }
456
- case 'styles': {
457
- const subDoc = path.call(print, 'css');
458
- if (!isEmptyDoc(subDoc))
459
- docs.push(normalize(subDoc));
460
- break;
461
- }
462
- }
463
- }
464
- return join(softline, docs);
465
- }
466
- function printAttributeNodeValue(path, print, quotes, node) {
467
- const valueDocs = path.map((childPath) => childPath.call(print), 'value');
468
- if (!quotes || !formattableAttributes.includes(node.name)) {
469
- return valueDocs;
470
- }
471
- else {
472
- return indent(group(trim(valueDocs, isLine)));
473
- }
474
- }
475
- function printJS(path, print, name, { forceSingleQuote, forceSingleLine }) {
476
- path.getValue()[name].isJS = true;
477
- path.getValue()[name].forceSingleQuote = forceSingleQuote;
478
- path.getValue()[name].forceSingleLine = forceSingleLine;
479
- return path.call(print, name);
480
- }
481
260
  function printComment(commentPath, options) {
482
261
  return commentPath;
483
262
  }
484
263
  function print(path, opts, print) {
485
- var _a, _b;
486
264
  const node = path.getValue();
487
- const isMarkdownSubDoc = opts.parentParser === 'markdown';
488
265
  if (!node) {
489
266
  return '';
490
267
  }
491
268
  if (typeof node === 'string') {
492
269
  return node;
493
270
  }
494
- if (Array.isArray(node)) {
495
- return path.map((childPath) => childPath.call(print));
496
- }
497
- if (isASTNode(node)) {
498
- return printTopLevelParts(node, path, opts, print);
499
- }
500
- if (!isPreTagContent(path) && !isMarkdownSubDoc) {
501
- attachCommentsHTML(node);
502
- }
503
271
  switch (node.type) {
504
- case 'Fragment': {
505
- const text = getText(node, opts);
506
- if (text.length === 0) {
507
- return '';
508
- }
509
- if (!isNodeWithChildren(node) || node.children.every(isEmptyTextNode))
510
- return '';
511
- const hasInlineComponent = node.children.filter((x) => x.type === 'InlineComponent').length > 0;
512
- if (text.indexOf('{') === -1 && !hasInlineComponent) {
513
- node.__isRawHTML = true;
514
- node.content = text;
515
- return path.call(print);
516
- }
517
- if (!isPreTagContent(path)) {
518
- trimChildren(node.children);
519
- const output = trim([path.map(print, 'children')], (n) => isLine(n) ||
520
- (typeof n === 'string' && n.trim() === '') ||
521
- n === breakParent);
522
- if (output.every((doc) => isEmptyDoc(doc))) {
523
- return '';
524
- }
525
- return group([...output, hardline]);
526
- }
527
- else {
528
- return group(path.map(print, 'children'));
529
- }
272
+ case 'root': {
273
+ return [stripTrailingHardline(path.map(print, 'children')), hardline];
530
274
  }
531
- case 'Text': {
275
+ case 'text': {
532
276
  const rawText = getUnencodedText(node);
533
- if (isPreTagContent(path)) {
534
- if (((_a = path.getParentNode()) === null || _a === void 0 ? void 0 : _a.type) === 'Attribute') {
535
- return replaceEndOfLineWith(rawText, literalline);
536
- }
537
- return rawText;
538
- }
539
277
  if (isEmptyTextNode(node)) {
540
278
  const hasWhiteSpace = rawText.trim().length < getUnencodedText(node).length;
541
279
  const hasOneOrMoreNewlines = /\n/.test(getUnencodedText(node));
@@ -553,37 +291,20 @@ function print(path, opts, print) {
553
291
  }
554
292
  return fill(splitTextToDocs(node));
555
293
  }
556
- case 'Element':
557
- case 'InlineComponent':
558
- case 'Slot': {
559
- const isEmpty = (_b = node.children) === null || _b === void 0 ? void 0 : _b.every((child) => isEmptyTextNode(child));
560
- const isSelfClosingTag = isEmpty && (node.type !== 'Element' || selfClosingTags.indexOf(node.name) !== -1);
561
- const attributes = path.map(print, 'attributes');
562
- if (isSelfClosingTag) {
563
- return group(['<', node.name, indent(group(attributes)), line, `/>`]);
294
+ case 'component':
295
+ case 'fragment':
296
+ case 'element': {
297
+ let isEmpty;
298
+ if (!node.children) {
299
+ isEmpty = true;
564
300
  }
565
- try {
566
- if (node.name.toLowerCase() === '!doctype') {
567
- const attributesWithLowercaseHTML = attributes.map((attribute) => {
568
- if (typeof attribute === 'string')
569
- return attribute;
570
- if (isDocCommand(attribute))
571
- return attribute;
572
- attribute = attribute.map((attrValue) => {
573
- if (typeof attrValue !== 'string')
574
- return attrValue;
575
- if (attrValue.toLowerCase() === 'html') {
576
- attrValue = attrValue.toLowerCase();
577
- }
578
- return attrValue;
579
- });
580
- return attribute;
581
- });
582
- return group(['<', node.name.toUpperCase(), ...attributesWithLowercaseHTML, `>`]);
583
- }
301
+ else {
302
+ isEmpty = node.children.every((child) => isEmptyTextNode(child));
584
303
  }
585
- catch (e) {
586
- console.warn(`error ${e} in the doctype printing`);
304
+ const isSelfClosingTag = isEmpty && (node.type !== 'element' || selfClosingTags.indexOf(node.name) !== -1);
305
+ const attributes = node.attributes ? path.map(print, 'attributes') : [];
306
+ if (isSelfClosingTag) {
307
+ return group(['<', node.name, indent(group(attributes)), line, `/>`]);
587
308
  }
588
309
  if (node.children) {
589
310
  const children = node.children;
@@ -602,7 +323,7 @@ function print(path, opts, print) {
602
323
  () => softline;
603
324
  }
604
325
  else if (isPreTagContent(path)) {
605
- body = () => printRaw(node, opts.originalText);
326
+ body = () => printRaw(node);
606
327
  }
607
328
  else if (isInlineElement(path, opts, node) && !isPreTagContent(path)) {
608
329
  body = () => path.map(print, 'children');
@@ -635,7 +356,7 @@ function print(path, opts, print) {
635
356
  }
636
357
  if (!hugEnd && lastChild && isTextNode(lastChild)) {
637
358
  if (isInlineElement(path, opts, node) && !didSetEndSeparator) {
638
- noHugSeparatorEnd = line;
359
+ noHugSeparatorEnd = softline;
639
360
  }
640
361
  trimTextNodeRight(lastChild);
641
362
  }
@@ -651,57 +372,35 @@ function print(path, opts, print) {
651
372
  }
652
373
  return group([...openingTag, '>', indent([noHugSeparatorStart, body()]), noHugSeparatorEnd, `</${node.name}>`]);
653
374
  }
375
+ return '';
376
+ }
377
+ case 'attribute': {
378
+ const name = node.name.trim();
379
+ const quote = opts.singleQuote ? "'" : '"';
380
+ switch (node.kind) {
381
+ case 'empty':
382
+ return [line, name];
383
+ case 'expression':
384
+ return '';
385
+ case 'quoted':
386
+ return [line, name, '=', quote, node.value, quote];
387
+ case 'shorthand':
388
+ return [line, '{', name, '}'];
389
+ case 'spread':
390
+ return [line, '{...', name, '}'];
391
+ case 'template-literal':
392
+ return [line, name, '=', '`', node.value, '`'];
393
+ }
394
+ return '';
654
395
  }
655
- case 'AttributeShorthand': {
656
- return node.expression.name;
396
+ case 'directive': {
397
+ return [line, node.name];
657
398
  }
658
- case 'Attribute': {
659
- if (isOrCanBeConvertedToShorthand(node, opts)) {
660
- return [line, '{', node.name, '}'];
661
- }
662
- else {
663
- if (node.value === true) {
664
- return [line, node.name];
665
- }
666
- const quotes = !isLoneMustacheTag(node.value);
667
- const attrNodeValue = printAttributeNodeValue(path, print, quotes, node);
668
- if (quotes) {
669
- return [line, node.name, '=', '"', attrNodeValue, '"'];
670
- }
671
- else {
672
- return [line, node.name, '=', attrNodeValue];
673
- }
674
- }
399
+ case 'doctype': {
400
+ return ['<!DOCTYPE html>', hardline];
675
401
  }
676
- case 'Expression':
677
- return [];
678
- case 'MustacheTag':
679
- return [
680
- '{',
681
- printJS(path, print, 'expression', {
682
- forceSingleLine: isInsideQuotedAttribute(path),
683
- forceSingleQuote: opts.jsxSingleQuote,
684
- }),
685
- '}',
686
- ];
687
- case 'Spread':
688
- return [
689
- line,
690
- '{...',
691
- printJS(path, print, 'expression', {
692
- forceSingleQuote: true,
693
- forceSingleLine: false,
694
- }),
695
- '}',
696
- ];
697
- case 'Comment':
402
+ case 'comment':
698
403
  return ['<!--', getUnencodedText(node), '-->'];
699
- case 'CodeSpan':
700
- return getUnencodedText(node);
701
- case 'CodeFence': {
702
- console.debug(node);
703
- return [node.metadata, hardline, node.data, hardline, '```', hardline];
704
- }
705
404
  default: {
706
405
  throw new Error(`Unhandled node type "${node.type}"!`);
707
406
  }
@@ -726,7 +425,7 @@ function splitTextToDocs(node) {
726
425
  return docs;
727
426
  }
728
427
  function expressionParser(text, parsers, opts) {
729
- const ast = parsers.babel(text, parsers, opts);
428
+ const ast = parsers.babel(text, opts);
730
429
  return { ...ast, program: ast.program.body[0].expression };
731
430
  }
732
431
  let markdownComponentName = new Set();
@@ -736,47 +435,52 @@ function embed(path, print, textToDoc, opts) {
736
435
  const node = path.getValue();
737
436
  if (!node)
738
437
  return null;
739
- if (node.isJS) {
740
- try {
741
- const embeddedopts = {
742
- parser: expressionParser,
743
- };
744
- if (node.forceSingleQuote) {
745
- embeddedopts.singleQuote = true;
746
- }
747
- const docs = textToDoc(forceIntoExpression(getText(node, opts)), embeddedopts);
748
- return node.forceSingleLine ? removeLines(docs) : docs;
749
- }
750
- catch (e) {
751
- return getText(node, opts);
752
- }
753
- }
754
- if (node.type === 'Script' && node.context === 'setup') {
755
- markdownComponentName = getMarkdownName(node.content);
756
- return group(['---', hardline, textToDoc(node.content, { ...opts, parser: 'typescript' }), '---', hardline]);
757
- }
758
- if (isTextNode(node)) {
759
- const parent = path.getParentNode();
760
- if (parent && parent.type === 'Element' && parent.name === 'script') {
761
- const formatttedScript = textToDoc(node.data, { ...opts, parser: 'typescript' });
762
- return stripTrailingHardline(formatttedScript);
763
- }
764
- }
765
- if (node.type === 'Style' || (node.type === 'Element' && node.name === 'style')) {
766
- let styleTagContent = '';
767
- if (node.type === 'Style') {
768
- styleTagContent = node.content.styles;
769
- }
770
- else if (node.children) {
771
- const children = node.children[0];
772
- styleTagContent = getUnencodedText(children);
438
+ if (node.type === 'expression') {
439
+ const textContent = getText(node, opts);
440
+ let content;
441
+ if (node.children.length === 1) {
442
+ content = textContent;
773
443
  }
444
+ else {
445
+ content = textToDoc(textContent, { ...opts, parser: 'babel-ts', semi: false });
446
+ content = stripTrailingHardline(content);
447
+ }
448
+ return [
449
+ '{',
450
+ content,
451
+ '}',
452
+ ];
453
+ }
454
+ if (node.type === 'attribute' && node.kind === 'expression') {
455
+ const value = node.value.trim();
456
+ const name = node.name.trim();
457
+ let attrNodeValue = textToDoc(forceIntoExpression(value), { ...opts, parser: expressionParser, semi: false });
458
+ attrNodeValue = stripTrailingHardline(attrNodeValue);
459
+ if (name === value && opts.astroAllowShorthand) {
460
+ return [line, '{', attrNodeValue, '}'];
461
+ }
462
+ return [line, name, '=', '{', attrNodeValue, '}'];
463
+ }
464
+ if (node.type === 'frontmatter') {
465
+ markdownComponentName = getMarkdownName(node.value);
466
+ return [group(['---', hardline, textToDoc(node.value, { ...opts, parser: 'typescript' }), '---', hardline]), hardline];
467
+ }
468
+ if (node.type === 'element' && node.name === 'script') {
469
+ const scriptContent = node.children[0].value;
470
+ let formatttedScript = textToDoc(scriptContent, { ...opts, parser: 'typescript' });
471
+ formatttedScript = stripTrailingHardline(formatttedScript);
472
+ const attributes = node.attributes ? path.map(print, 'attributes') : [];
473
+ const openingTag = group(['<script', indent(group(attributes)), softline, '>']);
474
+ return [openingTag, indent([hardline, formatttedScript]), hardline, '</script>'];
475
+ }
476
+ if (node.type === 'element' && node.name === 'style') {
477
+ let styleTagContent = node.children[0].value.trim();
774
478
  const supportedStyleLangValues = ['css', 'scss', 'sass'];
775
479
  let parserLang = 'css';
776
- if ('attributes' in node) {
480
+ if (node.attributes) {
777
481
  const langAttribute = node.attributes.filter((x) => x.name === 'lang');
778
482
  if (langAttribute.length) {
779
- const styleLang = langAttribute[0].value[0].raw.toLowerCase();
483
+ const styleLang = langAttribute[0].value.toLowerCase();
780
484
  if (supportedStyleLangValues.includes(styleLang))
781
485
  parserLang = styleLang;
782
486
  }
@@ -786,8 +490,10 @@ function embed(path, print, textToDoc, opts) {
786
490
  case 'scss': {
787
491
  let formattedStyles = textToDoc(styleTagContent, { ...opts, parser: parserLang });
788
492
  formattedStyles = stripTrailingHardline(formattedStyles);
789
- const attributes = path.map(print, 'attributes');
790
- const openingTag = group(['<style', indent(group(attributes)), softline, '>']);
493
+ const attributes = node.attributes ? path.map(print, 'attributes') : [];
494
+ const directives = node.directives ? path.map(print, 'directives') : [];
495
+ const attrAndDirectives = directives.concat(attributes);
496
+ const openingTag = group(['<style', indent(group(attrAndDirectives)), softline, '>']);
791
497
  return [openingTag, indent([hardline, formattedStyles]), hardline, '</style>'];
792
498
  }
793
499
  case 'sass': {
@@ -797,17 +503,17 @@ function embed(path, print, textToDoc, opts) {
797
503
  insertSpaces: !opts.useTabs,
798
504
  lineEnding,
799
505
  };
800
- const { result: raw } = dedent$1(styleTagContent);
506
+ const { result: raw } = manualDedent(styleTagContent);
801
507
  let formattedSassIndented = sassFormatter.SassFormatter.Format(raw, sassOptions).trim();
802
508
  const formattedSass = join(hardline, formattedSassIndented.split('\n'));
803
- const attributes = path.map(print, 'attributes');
509
+ const attributes = node.attributes ? path.map(print, 'attributes') : [];
804
510
  const openingTag = group(['<style', indent(group(attributes)), softline, '>']);
805
511
  return [openingTag, indent(group([hardline, formattedSass])), hardline, '</style>'];
806
512
  }
807
513
  }
808
514
  }
809
- if (node.type === 'InlineComponent' && markdownComponentName.has(node.name)) {
810
- let content = printRaw(node, opts.originalText);
515
+ if (node.type === 'component' && markdownComponentName.has(node.name)) {
516
+ let content = printRaw(node);
811
517
  content = content.replace(/\r\n/g, '\n');
812
518
  const contentArr = content.split('\n').map((s) => s.trimStart());
813
519
  content = contentArr.join('\n');
@@ -817,17 +523,10 @@ function embed(path, print, textToDoc, opts) {
817
523
  const openingTag = group([`<${node.name}`, indent(group(attributes)), softline, '>']);
818
524
  return [openingTag, indent(group([hardline, formatttedMarkdown])), hardline, `</${node.name}>`];
819
525
  }
820
- if (node.__isRawHTML) {
821
- return textToDoc(node.content, { ...opts, parser: 'html' });
822
- }
823
526
  return null;
824
527
  }
825
528
  function hasPrettierIgnore(path) {
826
- const node = path.getNode();
827
- if (!node || !Array.isArray(node.comments))
828
- return false;
829
- const hasIgnore = node.comments.some((comment) => comment.data.includes('prettier-ignore') && !comment.data.includes('prettier-ignore-start') && !comment.data.includes('prettier-ignore-end'));
830
- return hasIgnore;
529
+ return false;
831
530
  }
832
531
  const printer = {
833
532
  print,
@@ -836,6 +535,33 @@ const printer = {
836
535
  hasPrettierIgnore,
837
536
  };
838
537
 
538
+ const options = {
539
+ astroSortOrder: {
540
+ since: '0.0.1',
541
+ category: 'Astro',
542
+ type: 'choice',
543
+ default: 'markup | styles',
544
+ description: 'Sort order for markup, scripts, and styles',
545
+ choices: [
546
+ {
547
+ value: 'markup | styles',
548
+ description: 'markup | styles',
549
+ },
550
+ {
551
+ value: 'styles | markup',
552
+ description: 'styles | markup',
553
+ },
554
+ ],
555
+ },
556
+ astroAllowShorthand: {
557
+ since: '0.0.10',
558
+ category: 'Astro',
559
+ type: 'boolean',
560
+ default: true,
561
+ description: 'Enable/disable attribute shorthand if attribute name and expression are the same',
562
+ },
563
+ };
564
+
839
565
  const languages = [
840
566
  {
841
567
  name: 'astro',