|
import { parsers as parsers$1 } from 'prettier/plugins/babel'; |
|
import { doc } from 'prettier/standalone'; |
|
import { VERSION, parse } from 'svelte/compiler'; |
|
|
|
|
|
const selfClosingTags = [ |
|
'area', |
|
'base', |
|
'br', |
|
'col', |
|
'embed', |
|
'hr', |
|
'img', |
|
'input', |
|
'link', |
|
'meta', |
|
'param', |
|
'source', |
|
'track', |
|
'wbr', |
|
]; |
|
|
|
const blockElements = [ |
|
'address', |
|
'article', |
|
'aside', |
|
'blockquote', |
|
'details', |
|
'dialog', |
|
'dd', |
|
'div', |
|
'dl', |
|
'dt', |
|
'fieldset', |
|
'figcaption', |
|
'figure', |
|
'footer', |
|
'form', |
|
'h1', |
|
'h2', |
|
'h3', |
|
'h4', |
|
'h5', |
|
'h6', |
|
'header', |
|
'hgroup', |
|
'hr', |
|
'li', |
|
'main', |
|
'nav', |
|
'ol', |
|
'p', |
|
'pre', |
|
'section', |
|
'table', |
|
'ul', |
|
]; |
|
|
|
|
|
|
|
const formattableAttributes = [ |
|
|
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
const stringToBase64 = typeof Buffer !== 'undefined' |
|
? (str) => Buffer.from(str).toString('base64') |
|
: (str) => btoa(new TextEncoder() |
|
.encode(str) |
|
.reduce((acc, byte) => acc + String.fromCharCode(byte), '')); |
|
const base64ToString = typeof Buffer !== 'undefined' |
|
? (str) => Buffer.from(str, 'base64').toString() |
|
: (str) => new TextDecoder().decode(Uint8Array.from(atob(str), (c) => c.charCodeAt(0))); |
|
|
|
const snippedTagContentAttribute = '✂prettier:content✂'; |
|
const scriptRegex = /<!--[^]*?-->|<script((?:\s+[^=>'"\/\s]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"\/\s]+)*\s*)>([^]*?)<\/script>/g; |
|
const styleRegex = /<!--[^]*?-->|<style((?:\s+[^=>'"\/\s]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"\/\s]+)*\s*)>([^]*?)<\/style>/g; |
|
const langTsRegex = /\slang=["']?ts["']?/; |
|
function snipScriptAndStyleTagContent(source) { |
|
let scriptMatchSpans = getMatchIndexes('script'); |
|
let styleMatchSpans = getMatchIndexes('style'); |
|
let isTypescript = false; |
|
const text = snipTagContent(snipTagContent(source, 'script', '{}', styleMatchSpans), 'style', '', scriptMatchSpans); |
|
return { text, isTypescript }; |
|
function getMatchIndexes(tagName) { |
|
const regex = getRegexp(tagName); |
|
const indexes = []; |
|
let match = null; |
|
while ((match = regex.exec(source)) != null) { |
|
if (source.slice(match.index, match.index + 4) !== '<!--') { |
|
indexes.push([match.index, regex.lastIndex]); |
|
} |
|
} |
|
return indexes; |
|
} |
|
function snipTagContent(_source, tagName, placeholder, otherSpans) { |
|
const regex = getRegexp(tagName); |
|
let newScriptMatchSpans = scriptMatchSpans; |
|
let newStyleMatchSpans = styleMatchSpans; |
|
|
|
const newSource = _source.replace(regex, (match, attributes, content, index) => { |
|
if (match.startsWith('<!--') || withinOtherSpan(index)) { |
|
return match; |
|
} |
|
if (langTsRegex.test(attributes)) { |
|
isTypescript = true; |
|
} |
|
const encodedContent = stringToBase64(content); |
|
const newContent = `<${tagName}${attributes} ${snippedTagContentAttribute}="${encodedContent}">${placeholder}</${tagName}>`; |
|
|
|
const lengthDiff = match.length - newContent.length; |
|
newScriptMatchSpans = adjustSpans(scriptMatchSpans, newScriptMatchSpans); |
|
newStyleMatchSpans = adjustSpans(styleMatchSpans, newStyleMatchSpans); |
|
function adjustSpans(oldSpans, newSpans) { |
|
return oldSpans.map((oldSpan, idx) => { |
|
const newSpan = newSpans[idx]; |
|
|
|
|
|
if (oldSpan[0] > index) { |
|
|
|
return [newSpan[0] - lengthDiff, newSpan[1] - lengthDiff]; |
|
} |
|
else if (oldSpan[0] === index) { |
|
|
|
return [newSpan[0], newSpan[1] - lengthDiff]; |
|
} |
|
else { |
|
|
|
return newSpan; |
|
} |
|
}); |
|
} |
|
return newContent; |
|
}); |
|
|
|
scriptMatchSpans = newScriptMatchSpans; |
|
styleMatchSpans = newStyleMatchSpans; |
|
return newSource; |
|
function withinOtherSpan(idx) { |
|
return otherSpans.some((otherSpan) => idx > otherSpan[0] && idx < otherSpan[1]); |
|
} |
|
} |
|
function getRegexp(tagName) { |
|
return tagName === 'script' ? scriptRegex : styleRegex; |
|
} |
|
} |
|
function hasSnippedContent(text) { |
|
return text.includes(snippedTagContentAttribute); |
|
} |
|
const regex = /(<\w+.*?)\s*✂prettier:content✂="(.*?)">.*?(?=<\/)/gi; |
|
function unsnipContent(text) { |
|
return text.replace(regex, (_, start, encodedContent) => { |
|
const content = base64ToString(encodedContent); |
|
return `${start}>${content}`; |
|
}); |
|
} |
|
|
|
function makeChoice(choice) { |
|
return { value: choice, description: choice }; |
|
} |
|
const options = { |
|
svelteSortOrder: { |
|
category: 'Svelte', |
|
type: 'choice', |
|
default: 'options-scripts-markup-styles', |
|
description: 'Sort order for scripts, markup, and styles', |
|
choices: [ |
|
makeChoice('options-scripts-markup-styles'), |
|
makeChoice('options-scripts-styles-markup'), |
|
makeChoice('options-markup-styles-scripts'), |
|
makeChoice('options-markup-scripts-styles'), |
|
makeChoice('options-styles-markup-scripts'), |
|
makeChoice('options-styles-scripts-markup'), |
|
makeChoice('scripts-options-markup-styles'), |
|
makeChoice('scripts-options-styles-markup'), |
|
makeChoice('markup-options-styles-scripts'), |
|
makeChoice('markup-options-scripts-styles'), |
|
makeChoice('styles-options-markup-scripts'), |
|
makeChoice('styles-options-scripts-markup'), |
|
makeChoice('scripts-markup-options-styles'), |
|
makeChoice('scripts-styles-options-markup'), |
|
makeChoice('markup-styles-options-scripts'), |
|
makeChoice('markup-scripts-options-styles'), |
|
makeChoice('styles-markup-options-scripts'), |
|
makeChoice('styles-scripts-options-markup'), |
|
makeChoice('scripts-markup-styles-options'), |
|
makeChoice('scripts-styles-markup-options'), |
|
makeChoice('markup-styles-scripts-options'), |
|
makeChoice('markup-scripts-styles-options'), |
|
makeChoice('styles-markup-scripts-options'), |
|
makeChoice('styles-scripts-markup-options'), |
|
makeChoice('none'), |
|
], |
|
}, |
|
svelteStrictMode: { |
|
category: 'Svelte', |
|
type: 'boolean', |
|
default: false, |
|
description: 'More strict HTML syntax: Quotes in attributes, no self-closing DOM tags', |
|
}, |
|
svelteBracketNewLine: { |
|
category: 'Svelte', |
|
type: 'boolean', |
|
description: 'Put the `>` of a multiline element on a new line', |
|
deprecated: '2.5.0', |
|
}, |
|
svelteAllowShorthand: { |
|
category: 'Svelte', |
|
type: 'boolean', |
|
default: true, |
|
description: 'Option to enable/disable component attribute shorthand if attribute name and expressions are same', |
|
}, |
|
svelteIndentScriptAndStyle: { |
|
category: 'Svelte', |
|
type: 'boolean', |
|
default: true, |
|
description: 'Whether or not to indent the code inside <script> and <style> tags in Svelte files', |
|
}, |
|
}; |
|
const sortOrderSeparator = '-'; |
|
function parseSortOrder(sortOrder = 'options-scripts-markup-styles') { |
|
if (sortOrder === 'none') { |
|
return []; |
|
} |
|
const order = sortOrder.split(sortOrderSeparator); |
|
|
|
if (!order.includes('options')) { |
|
throw new Error('svelteSortOrder is missing option `options`'); |
|
} |
|
return order; |
|
} |
|
function isBracketSameLine(options) { |
|
return options.svelteBracketNewLine != null |
|
? !options.svelteBracketNewLine |
|
: options.bracketSameLine != null |
|
? options.bracketSameLine |
|
: false; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function isASTNode(n) { |
|
return n && n.__isRoot; |
|
} |
|
function isPreTagContent(path) { |
|
const stack = path.stack; |
|
return stack.some((node) => (node.type === 'Element' && node.name.toLowerCase() === 'pre') || |
|
(node.type === 'Attribute' && !formattableAttributes.includes(node.name))); |
|
} |
|
function flatten(arrays) { |
|
return [].concat.apply([], arrays); |
|
} |
|
function findLastIndex(isMatch, items) { |
|
for (let i = items.length - 1; i >= 0; i--) { |
|
if (isMatch(items[i], i)) { |
|
return i; |
|
} |
|
} |
|
return -1; |
|
} |
|
function replaceEndOfLineWith(text, replacement) { |
|
const parts = []; |
|
for (const part of text.split('\n')) { |
|
if (parts.length > 0) { |
|
parts.push(replacement); |
|
} |
|
if (part.endsWith('\r')) { |
|
parts.push(part.slice(0, -1)); |
|
} |
|
else { |
|
parts.push(part); |
|
} |
|
} |
|
return parts; |
|
} |
|
function getAttributeLine(node, options) { |
|
const { hardline, line } = doc.builders; |
|
const hasThisBinding = (node.type === 'InlineComponent' && !!node.expression) || |
|
(node.type === 'Element' && !!node.tag); |
|
const attributes = node.attributes.filter((attribute) => attribute.name !== snippedTagContentAttribute); |
|
return options.singleAttributePerLine && |
|
(attributes.length > 1 || (attributes.length && hasThisBinding)) |
|
? hardline |
|
: line; |
|
} |
|
function printWithPrependedAttributeLine(node, options, print) { |
|
return (path) => path.getNode().name !== snippedTagContentAttribute |
|
? [getAttributeLine(node, options), path.call(print)] |
|
: ''; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
function isHardline(docToCheck) { |
|
return docToCheck === doc.builders.hardline || deepEqual(docToCheck, doc.builders.hardline); |
|
} |
|
|
|
|
|
|
|
function deepEqual(x, y) { |
|
if (x === y) { |
|
return true; |
|
} |
|
else if (typeof x == 'object' && x != null && typeof y == 'object' && y != null) { |
|
if (Object.keys(x).length != Object.keys(y).length) |
|
return false; |
|
for (var prop in x) { |
|
if (y.hasOwnProperty(prop)) { |
|
if (!deepEqual(x[prop], y[prop])) |
|
return false; |
|
} |
|
else { |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
else { |
|
return false; |
|
} |
|
} |
|
function isDocCommand(doc) { |
|
return typeof doc === 'object' && doc !== null; |
|
} |
|
function isLine(docToCheck) { |
|
return (isHardline(docToCheck) || |
|
(isDocCommand(docToCheck) && docToCheck.type === 'line') || |
|
(Array.isArray(docToCheck) && docToCheck.every(isLine))); |
|
} |
|
|
|
|
|
|
|
function isEmptyDoc(doc) { |
|
if (typeof doc === 'string') { |
|
return doc.length === 0; |
|
} |
|
if (isDocCommand(doc) && doc.type === 'line') { |
|
return !doc.keepIfLonely; |
|
} |
|
if (Array.isArray(doc)) { |
|
return doc.length === 0; |
|
} |
|
const { contents } = doc; |
|
if (contents) { |
|
return isEmptyDoc(contents); |
|
} |
|
const { parts } = doc; |
|
if (parts) { |
|
return isEmptyGroup(parts); |
|
} |
|
return false; |
|
} |
|
function isEmptyGroup(group) { |
|
return !group.find((doc) => !isEmptyDoc(doc)); |
|
} |
|
|
|
|
|
|
|
|
|
function trim(docs, isWhitespace) { |
|
trimLeft(docs, isWhitespace); |
|
trimRight(docs, isWhitespace); |
|
return docs; |
|
} |
|
|
|
|
|
|
|
|
|
function trimLeft(group, isWhitespace) { |
|
let firstNonWhitespace = group.findIndex((doc) => !isEmptyDoc(doc) && !isWhitespace(doc)); |
|
if (firstNonWhitespace < 0 && group.length) { |
|
firstNonWhitespace = group.length; |
|
} |
|
if (firstNonWhitespace > 0) { |
|
const removed = group.splice(0, firstNonWhitespace); |
|
if (removed.every(isEmptyDoc)) { |
|
return trimLeft(group, isWhitespace); |
|
} |
|
} |
|
else { |
|
const parts = getParts(group[0]); |
|
if (parts) { |
|
return trimLeft(parts, isWhitespace); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
function trimRight(group, isWhitespace) { |
|
let lastNonWhitespace = group.length |
|
? findLastIndex((doc) => !isEmptyDoc(doc) && !isWhitespace(doc), group) |
|
: 0; |
|
if (lastNonWhitespace < group.length - 1) { |
|
const removed = group.splice(lastNonWhitespace + 1); |
|
if (removed.every(isEmptyDoc)) { |
|
return trimRight(group, isWhitespace); |
|
} |
|
} |
|
else { |
|
const parts = getParts(group[group.length - 1]); |
|
if (parts) { |
|
return trimRight(parts, isWhitespace); |
|
} |
|
} |
|
} |
|
function getParts(doc) { |
|
if (typeof doc === 'object') { |
|
if (Array.isArray(doc)) { |
|
return doc; |
|
} |
|
if (doc.type === 'fill') { |
|
return doc.parts; |
|
} |
|
if (doc.type === 'group') { |
|
return getParts(doc.contents); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
function removeParentheses(doc) { |
|
return trim([doc], (_doc) => _doc === '(' || _doc === ')')[0]; |
|
} |
|
|
|
const unsupportedLanguages = ['coffee', 'coffeescript', 'styl', 'stylus', 'sass']; |
|
function isInlineElement(path, options, node) { |
|
return (node && node.type === 'Element' && !isBlockElement(node, options) && !isPreTagContent(path)); |
|
} |
|
function isBlockElement(node, options) { |
|
return (node && |
|
node.type === 'Element' && |
|
options.htmlWhitespaceSensitivity !== 'strict' && |
|
(options.htmlWhitespaceSensitivity === 'ignore' || |
|
blockElements.includes(node.name))); |
|
} |
|
function isSvelteBlock(node) { |
|
return [ |
|
'IfBlock', |
|
'SnippetBlock', |
|
'AwaitBlock', |
|
'CatchBlock', |
|
'EachBlock', |
|
'ElseBlock', |
|
'KeyBlock', |
|
'PendingBlock', |
|
'ThenBlock', |
|
].includes(node.type); |
|
} |
|
function isNodeWithChildren(node) { |
|
return node.children; |
|
} |
|
function getChildren(node) { |
|
return isNodeWithChildren(node) ? node.children : []; |
|
} |
|
|
|
|
|
|
|
function getSiblings(path) { |
|
let parent = path.getParentNode(); |
|
if (isASTNode(parent)) { |
|
parent = parent.html; |
|
} |
|
return getChildren(parent); |
|
} |
|
|
|
|
|
|
|
function getNextNode(path, node = path.getNode()) { |
|
return getSiblings(path).find((child) => child.start === node.end); |
|
} |
|
|
|
|
|
|
|
function getLeadingComment(path) { |
|
const siblings = getSiblings(path); |
|
let node = path.getNode(); |
|
let prev = siblings.find((child) => child.end === node.start); |
|
while (prev) { |
|
if (prev.type === 'Comment' && |
|
!isIgnoreStartDirective(prev) && |
|
!isIgnoreEndDirective(prev)) { |
|
return prev; |
|
} |
|
else if (isEmptyTextNode(prev)) { |
|
node = prev; |
|
prev = siblings.find((child) => child.end === node.start); |
|
} |
|
else { |
|
return undefined; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
function doesEmbedStartAfterNode(node, path, siblings = getSiblings(path)) { |
|
|
|
|
|
if (!isNodeTopLevelHTML(node, path)) { |
|
return false; |
|
} |
|
const position = node.end; |
|
const root = path.stack[0]; |
|
const embeds = [root.css, root.html, root.instance, root.js, root.module]; |
|
const nextNode = siblings[siblings.indexOf(node) + 1]; |
|
return embeds.find((n) => n && n.start >= position && (!nextNode || n.end <= nextNode.start)); |
|
} |
|
function isNodeTopLevelHTML(node, path) { |
|
const root = path.stack[0]; |
|
return !!root.html && !!root.html.children && root.html.children.includes(node); |
|
} |
|
function isEmptyTextNode(node) { |
|
return !!node && node.type === 'Text' && getUnencodedText(node).trim() === ''; |
|
} |
|
function isIgnoreDirective(node) { |
|
return !!node && node.type === 'Comment' && node.data.trim() === 'prettier-ignore'; |
|
} |
|
function isIgnoreStartDirective(node) { |
|
return !!node && node.type === 'Comment' && node.data.trim() === 'prettier-ignore-start'; |
|
} |
|
function isIgnoreEndDirective(node) { |
|
return !!node && node.type === 'Comment' && node.data.trim() === 'prettier-ignore-end'; |
|
} |
|
function printRaw(node, originalText, stripLeadingAndTrailingNewline = false) { |
|
if (node.children.length === 0) { |
|
return ''; |
|
} |
|
const firstChild = node.children[0]; |
|
const lastChild = node.children[node.children.length - 1]; |
|
let raw = originalText.substring(firstChild.start, lastChild.end); |
|
if (!stripLeadingAndTrailingNewline) { |
|
return raw; |
|
} |
|
if (startsWithLinebreak(raw)) { |
|
raw = raw.substring(raw.indexOf('\n') + 1); |
|
} |
|
if (endsWithLinebreak(raw)) { |
|
raw = raw.substring(0, raw.lastIndexOf('\n')); |
|
if (raw.charAt(raw.length - 1) === '\r') { |
|
raw = raw.substring(0, raw.length - 1); |
|
} |
|
} |
|
return raw; |
|
} |
|
function isTextNode(node) { |
|
return node.type === 'Text'; |
|
} |
|
function getAttributeValue(attributeName, node) { |
|
var _a; |
|
const attributes = ((_a = node.attributes) !== null && _a !== void 0 ? _a : []); |
|
const langAttribute = attributes.find((attribute) => attribute.name === attributeName); |
|
return langAttribute && langAttribute.value; |
|
} |
|
function getAttributeTextValue(attributeName, node) { |
|
const value = getAttributeValue(attributeName, node); |
|
if (value != null && typeof value === 'object') { |
|
const textValue = value.find(isTextNode); |
|
if (textValue) { |
|
return textValue.data; |
|
} |
|
} |
|
return null; |
|
} |
|
function getLangAttribute(node) { |
|
const value = getAttributeTextValue('lang', node) || getAttributeTextValue('type', node); |
|
if (value != null) { |
|
return value.replace(/^text\//, ''); |
|
} |
|
else { |
|
return null; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function isNodeSupportedLanguage(node) { |
|
const lang = getLangAttribute(node); |
|
return !(lang && unsupportedLanguages.includes(lang)); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
function isTypeScript(node) { |
|
const lang = getLangAttribute(node) || ''; |
|
return ['typescript', 'ts'].includes(lang); |
|
} |
|
function isJSON(node) { |
|
const lang = getLangAttribute(node) || ''; |
|
|
|
return lang.endsWith('json') || lang.endsWith('importmap'); |
|
} |
|
function isLess(node) { |
|
const lang = getLangAttribute(node) || ''; |
|
return ['less'].includes(lang); |
|
} |
|
function isScss(node) { |
|
const lang = getLangAttribute(node) || ''; |
|
return ['sass', 'scss'].includes(lang); |
|
} |
|
function isPugTemplate(node) { |
|
return node.type === 'Element' && node.name === 'template' && getLangAttribute(node) === 'pug'; |
|
} |
|
function isLoneMustacheTag(node) { |
|
return node !== true && node.length === 1 && node[0].type === 'MustacheTag'; |
|
} |
|
function isAttributeShorthand(node) { |
|
return node !== true && node.length === 1 && node[0].type === 'AttributeShorthand'; |
|
} |
|
|
|
|
|
|
|
function isOrCanBeConvertedToShorthand(node) { |
|
if (isAttributeShorthand(node.value)) { |
|
return true; |
|
} |
|
if (isLoneMustacheTag(node.value)) { |
|
const expression = node.value[0].expression; |
|
return expression.type === 'Identifier' && expression.name === node.name; |
|
} |
|
return false; |
|
} |
|
function getUnencodedText(node) { |
|
|
|
return node.raw || node.data; |
|
} |
|
function isTextNodeStartingWithLinebreak(node, nrLines = 1) { |
|
return node.type === 'Text' && startsWithLinebreak(getUnencodedText(node), nrLines); |
|
} |
|
function startsWithLinebreak(text, nrLines = 1) { |
|
return new RegExp(`^([\\t\\f\\r ]*\\n){${nrLines}}`).test(text); |
|
} |
|
function isTextNodeEndingWithLinebreak(node, nrLines = 1) { |
|
return node.type === 'Text' && endsWithLinebreak(getUnencodedText(node), nrLines); |
|
} |
|
function endsWithLinebreak(text, nrLines = 1) { |
|
return new RegExp(`(\\n[\\t\\f\\r ]*){${nrLines}}$`).test(text); |
|
} |
|
function isTextNodeStartingWithWhitespace(node) { |
|
return node.type === 'Text' && /^\s/.test(getUnencodedText(node)); |
|
} |
|
function isTextNodeEndingWithWhitespace(node) { |
|
return node.type === 'Text' && /\s$/.test(getUnencodedText(node)); |
|
} |
|
function trimTextNodeRight(node) { |
|
node.raw = node.raw && node.raw.trimRight(); |
|
node.data = node.data && node.data.trimRight(); |
|
} |
|
function trimTextNodeLeft(node) { |
|
node.raw = node.raw && node.raw.trimLeft(); |
|
node.data = node.data && node.data.trimLeft(); |
|
} |
|
|
|
|
|
|
|
|
|
function trimChildren(children, path) { |
|
let firstNonEmptyNode = children.findIndex((n) => !isEmptyTextNode(n) && !doesEmbedStartAfterNode(n, path)); |
|
firstNonEmptyNode = firstNonEmptyNode === -1 ? children.length - 1 : firstNonEmptyNode; |
|
let lastNonEmptyNode = findLastIndex((n, idx) => { |
|
|
|
|
|
return (!isEmptyTextNode(n) && |
|
((idx === children.length - 1 && n.type !== 'Comment') || |
|
!doesEmbedStartAfterNode(n, path))); |
|
}, children); |
|
lastNonEmptyNode = lastNonEmptyNode === -1 ? 0 : lastNonEmptyNode; |
|
for (let i = 0; i <= firstNonEmptyNode; i++) { |
|
const n = children[i]; |
|
if (n.type === 'Text') { |
|
trimTextNodeLeft(n); |
|
} |
|
} |
|
for (let i = children.length - 1; i >= lastNonEmptyNode; i--) { |
|
const n = children[i]; |
|
if (n.type === 'Text') { |
|
trimTextNodeRight(n); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
function shouldHugStart(node, isSupportedLanguage, options) { |
|
if (!isSupportedLanguage) { |
|
return true; |
|
} |
|
if (isBlockElement(node, options)) { |
|
return false; |
|
} |
|
if (!isNodeWithChildren(node)) { |
|
return false; |
|
} |
|
const children = node.children; |
|
if (children.length === 0) { |
|
return true; |
|
} |
|
if (options.htmlWhitespaceSensitivity === 'ignore') { |
|
return false; |
|
} |
|
const firstChild = children[0]; |
|
return !isTextNodeStartingWithWhitespace(firstChild); |
|
} |
|
|
|
|
|
|
|
|
|
function shouldHugEnd(node, isSupportedLanguage, options) { |
|
if (!isSupportedLanguage) { |
|
return true; |
|
} |
|
if (isBlockElement(node, options)) { |
|
return false; |
|
} |
|
if (!isNodeWithChildren(node)) { |
|
return false; |
|
} |
|
const children = node.children; |
|
if (children.length === 0) { |
|
return true; |
|
} |
|
if (options.htmlWhitespaceSensitivity === 'ignore') { |
|
return false; |
|
} |
|
const lastChild = children[children.length - 1]; |
|
return !isTextNodeEndingWithWhitespace(lastChild); |
|
} |
|
|
|
|
|
|
|
function checkWhitespaceAtStartOfSvelteBlock(node, options) { |
|
if (!isSvelteBlock(node) || !isNodeWithChildren(node)) { |
|
return 'none'; |
|
} |
|
const children = node.children; |
|
if (children.length === 0) { |
|
return 'none'; |
|
} |
|
const firstChild = children[0]; |
|
if (isTextNodeStartingWithLinebreak(firstChild)) { |
|
return 'line'; |
|
} |
|
else if (isTextNodeStartingWithWhitespace(firstChild)) { |
|
return 'space'; |
|
} |
|
|
|
|
|
const parentOpeningEnd = options.originalText.lastIndexOf('}', firstChild.start); |
|
if (parentOpeningEnd > 0 && firstChild.start > parentOpeningEnd + 1) { |
|
const textBetween = options.originalText.substring(parentOpeningEnd + 1, firstChild.start); |
|
if (textBetween.trim() === '') { |
|
return startsWithLinebreak(textBetween) ? 'line' : 'space'; |
|
} |
|
} |
|
return 'none'; |
|
} |
|
|
|
|
|
|
|
function checkWhitespaceAtEndOfSvelteBlock(node, options) { |
|
if (!isSvelteBlock(node) || !isNodeWithChildren(node)) { |
|
return 'none'; |
|
} |
|
const children = node.children; |
|
if (children.length === 0) { |
|
return 'none'; |
|
} |
|
const lastChild = children[children.length - 1]; |
|
if (isTextNodeEndingWithLinebreak(lastChild)) { |
|
return 'line'; |
|
} |
|
else if (isTextNodeEndingWithWhitespace(lastChild)) { |
|
return 'space'; |
|
} |
|
|
|
|
|
const parentClosingStart = options.originalText.indexOf('{', lastChild.end); |
|
if (parentClosingStart > 0 && lastChild.end < parentClosingStart) { |
|
const textBetween = options.originalText.substring(lastChild.end, parentClosingStart); |
|
if (textBetween.trim() === '') { |
|
return endsWithLinebreak(textBetween) ? 'line' : 'space'; |
|
} |
|
} |
|
return 'none'; |
|
} |
|
function isInsideQuotedAttribute(path, options) { |
|
const stack = path.stack; |
|
return stack.some((node) => node.type === 'Attribute' && |
|
(!isLoneMustacheTag(node.value) || |
|
(options.svelteStrictMode && !options._svelte_is5Plus))); |
|
} |
|
|
|
|
|
|
|
function canOmitSoftlineBeforeClosingTag(node, path, options) { |
|
return (isBracketSameLine(options) && |
|
(!hugsStartOfNextNode(node, options) || isLastChildWithinParentBlockElement(path, options))); |
|
} |
|
|
|
|
|
|
|
|
|
function hugsStartOfNextNode(node, options) { |
|
if (node.end === options.originalText.length) { |
|
|
|
return false; |
|
} |
|
return !options.originalText.substring(node.end).match(/^\s/); |
|
} |
|
function isLastChildWithinParentBlockElement(path, options) { |
|
const parent = path.getParentNode(); |
|
if (!parent || !isBlockElement(parent, options)) { |
|
return false; |
|
} |
|
const children = getChildren(parent); |
|
const lastChild = children[children.length - 1]; |
|
return lastChild === path.getNode(); |
|
} |
|
function assignCommentsToNodes(ast) { |
|
if (ast.module) { |
|
ast.module.comments = removeAndGetLeadingComments(ast, ast.module); |
|
} |
|
if (ast.instance) { |
|
ast.instance.comments = removeAndGetLeadingComments(ast, ast.instance); |
|
} |
|
if (ast.css) { |
|
ast.css.comments = removeAndGetLeadingComments(ast, ast.css); |
|
} |
|
} |
|
|
|
|
|
|
|
function removeAndGetLeadingComments(ast, current) { |
|
const siblings = getChildren(ast.html); |
|
const comments = []; |
|
const newlines = []; |
|
if (!siblings.length) { |
|
return []; |
|
} |
|
let node = current; |
|
let prev = siblings.find((child) => child.end === node.start); |
|
while (prev) { |
|
if (prev.type === 'Comment' && |
|
!isIgnoreStartDirective(prev) && |
|
!isIgnoreEndDirective(prev)) { |
|
comments.push(prev); |
|
if (comments.length !== newlines.length) { |
|
newlines.push({ type: 'Text', data: '', raw: '', start: -1, end: -1 }); |
|
} |
|
} |
|
else if (isEmptyTextNode(prev)) { |
|
newlines.push(prev); |
|
} |
|
else { |
|
break; |
|
} |
|
node = prev; |
|
prev = siblings.find((child) => child.end === node.start); |
|
} |
|
newlines.length = comments.length; |
|
for (const comment of comments) { |
|
siblings.splice(siblings.indexOf(comment), 1); |
|
} |
|
for (const text of newlines) { |
|
siblings.splice(siblings.indexOf(text), 1); |
|
} |
|
return comments |
|
.map((comment, i) => ({ |
|
comment, |
|
emptyLineAfter: getUnencodedText(newlines[i]).split('\n').length > 2, |
|
})) |
|
.reverse(); |
|
} |
|
|
|
const { join, line, group, indent, dedent, softline, hardline, fill, breakParent, literalline } = doc.builders; |
|
function hasPragma(text) { |
|
return /^\s*<!--\s*@(format|prettier)\W/.test(text); |
|
} |
|
let ignoreNext = false; |
|
let ignoreRange = false; |
|
let svelteOptionsDoc; |
|
function print(path, options, print) { |
|
var _a, _b; |
|
const bracketSameLine = isBracketSameLine(options); |
|
const n = path.getValue(); |
|
if (!n) { |
|
return ''; |
|
} |
|
if (isASTNode(n)) { |
|
return printTopLevelParts(n, options, path, print); |
|
} |
|
const [open, close] = options.svelteStrictMode && !options._svelte_is5Plus ? ['"{', '}"'] : ['{', '}']; |
|
const printJsExpression = () => [open, printJS(path, print, 'expression'), close]; |
|
const node = n; |
|
if ((ignoreNext || (ignoreRange && !isIgnoreEndDirective(node))) && |
|
(node.type !== 'Text' || !isEmptyTextNode(node))) { |
|
if (ignoreNext) { |
|
ignoreNext = false; |
|
} |
|
return flatten(options.originalText |
|
.slice(options.locStart(node), options.locEnd(node)) |
|
.split('\n') |
|
.map((o, i) => (i == 0 ? [o] : [literalline, o]))); |
|
} |
|
switch (node.type) { |
|
case 'Fragment': |
|
const children = node.children; |
|
if (children.length === 0 || children.every(isEmptyTextNode)) { |
|
return ''; |
|
} |
|
if (!isPreTagContent(path)) { |
|
trimChildren(node.children, path); |
|
const output = trim([printChildren(path, print, options)], (n) => isLine(n) || |
|
(typeof n === 'string' && n.trim() === '') || |
|
|
|
|
|
n === breakParent); |
|
if (output.every((doc) => isEmptyDoc(doc))) { |
|
return ''; |
|
} |
|
return group([...output, hardline]); |
|
} |
|
else { |
|
return group(path.map(print, 'children')); |
|
} |
|
case 'Text': |
|
if (!isPreTagContent(path)) { |
|
if (isEmptyTextNode(node)) { |
|
const hasWhiteSpace = getUnencodedText(node).trim().length < getUnencodedText(node).length; |
|
const hasOneOrMoreNewlines = /\n/.test(getUnencodedText(node)); |
|
const hasTwoOrMoreNewlines = /\n\r?\s*\n\r?/.test(getUnencodedText(node)); |
|
if (hasTwoOrMoreNewlines) { |
|
return [hardline, hardline]; |
|
} |
|
if (hasOneOrMoreNewlines) { |
|
return hardline; |
|
} |
|
if (hasWhiteSpace) { |
|
return line; |
|
} |
|
return ''; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
return fill(splitTextToDocs(node)); |
|
} |
|
else { |
|
let rawText = getUnencodedText(node); |
|
const parent = path.getParentNode(); |
|
if (parent.type === 'Attribute') { |
|
|
|
|
|
if (parent.name === 'class' && path.getParentNode(1).type === 'Element') { |
|
|
|
|
|
rawText = rawText.replace(/([^ \t\n])(([ \t]+$)|([ \t]+(\r?\n))|[ \t]+)/g, |
|
|
|
|
|
(match, characterBeforeWhitespace, _, isEndOfString, isEndOfLine, endOfLine) => isEndOfString |
|
? match |
|
: characterBeforeWhitespace + (isEndOfLine ? endOfLine : ' ')); |
|
|
|
|
|
|
|
rawText = rawText.replace(/([^ \t\n])[ \t]+$/, parent.value.indexOf(node) === parent.value.length - 1 ? '$1' : '$1 '); |
|
} |
|
return replaceEndOfLineWith(rawText, literalline); |
|
} |
|
return rawText; |
|
} |
|
case 'Element': |
|
case 'InlineComponent': |
|
case 'Slot': |
|
case 'SlotTemplate': |
|
case 'Window': |
|
case 'Head': |
|
case 'Title': { |
|
const isSupportedLanguage = !(node.name === 'template' && !isNodeSupportedLanguage(node)); |
|
const isEmpty = node.children.every((child) => isEmptyTextNode(child)); |
|
const isDoctypeTag = node.name.toUpperCase() === '!DOCTYPE'; |
|
const didSelfClose = options.originalText[node.end - 2] === '/'; |
|
const isSelfClosingTag = isEmpty && |
|
((((node.type === 'Element' && !options.svelteStrictMode) || |
|
node.type === 'Head' || |
|
node.type === 'InlineComponent' || |
|
node.type === 'Slot' || |
|
node.type === 'SlotTemplate' || |
|
node.type === 'Title') && |
|
didSelfClose) || |
|
node.type === 'Window' || |
|
selfClosingTags.indexOf(node.name) !== -1 || |
|
isDoctypeTag); |
|
|
|
const attributes = path.map(printWithPrependedAttributeLine(node, options, print), 'attributes'); |
|
const attributeLine = getAttributeLine(node, options); |
|
const possibleThisBinding = node.type === 'InlineComponent' && node.expression |
|
? [attributeLine, 'this=', ...printJsExpression()] |
|
: node.type === 'Element' && node.tag |
|
? [ |
|
attributeLine, |
|
'this=', |
|
...(typeof node.tag === 'string' |
|
? [`"${node.tag}"`] |
|
: [open, printJS(path, print, 'tag'), close]), |
|
] |
|
: ''; |
|
if (isSelfClosingTag) { |
|
return group([ |
|
'<', |
|
node.name, |
|
indent(group([ |
|
possibleThisBinding, |
|
...attributes, |
|
bracketSameLine || isDoctypeTag ? '' : dedent(line), |
|
])), |
|
...[bracketSameLine && !isDoctypeTag ? ' ' : '', `${isDoctypeTag ? '' : '/'}>`], |
|
]); |
|
} |
|
const children = node.children; |
|
const firstChild = children[0]; |
|
const lastChild = children[children.length - 1]; |
|
|
|
|
|
let body; |
|
const hugStart = shouldHugStart(node, isSupportedLanguage, options); |
|
const hugEnd = shouldHugEnd(node, isSupportedLanguage, options); |
|
if (isEmpty) { |
|
body = |
|
isInlineElement(path, options, node) && |
|
node.children.length && |
|
isTextNodeStartingWithWhitespace(node.children[0]) && |
|
!isPreTagContent(path) |
|
? () => line |
|
: () => (bracketSameLine ? softline : ''); |
|
} |
|
else if (isPreTagContent(path)) { |
|
body = () => printPre(node, options.originalText, path, print); |
|
} |
|
else if (!isSupportedLanguage) { |
|
body = () => printRaw(node, options.originalText, true); |
|
} |
|
else if (isInlineElement(path, options, node) && !isPreTagContent(path)) { |
|
body = () => printChildren(path, print, options); |
|
} |
|
else { |
|
body = () => printChildren(path, print, options); |
|
} |
|
const openingTag = [ |
|
'<', |
|
node.name, |
|
indent(group([ |
|
possibleThisBinding, |
|
...attributes, |
|
hugStart && !isEmpty |
|
? '' |
|
: !bracketSameLine && !isPreTagContent(path) |
|
? dedent(softline) |
|
: '', |
|
])), |
|
]; |
|
if (!isSupportedLanguage && !isEmpty) { |
|
|
|
|
|
|
|
return group([ |
|
...openingTag, |
|
'>', |
|
group([hardline, body(), hardline]), |
|
`</${node.name}>`, |
|
]); |
|
} |
|
if (hugStart && hugEnd) { |
|
const huggedContent = [softline, group(['>', body(), `</${node.name}`])]; |
|
const omitSoftlineBeforeClosingTag = (isEmpty && !bracketSameLine) || |
|
canOmitSoftlineBeforeClosingTag(node, path, options); |
|
return group([ |
|
...openingTag, |
|
isEmpty ? group(huggedContent) : group(indent(huggedContent)), |
|
omitSoftlineBeforeClosingTag ? '' : softline, |
|
'>', |
|
]); |
|
} |
|
|
|
let noHugSeparatorStart = softline; |
|
let noHugSeparatorEnd = softline; |
|
if (isPreTagContent(path)) { |
|
noHugSeparatorStart = ''; |
|
noHugSeparatorEnd = ''; |
|
} |
|
else { |
|
let didSetEndSeparator = false; |
|
if (!hugStart && firstChild && firstChild.type === 'Text') { |
|
if (isTextNodeStartingWithLinebreak(firstChild) && |
|
firstChild !== lastChild && |
|
(!isInlineElement(path, options, node) || |
|
isTextNodeEndingWithWhitespace(lastChild))) { |
|
noHugSeparatorStart = hardline; |
|
noHugSeparatorEnd = hardline; |
|
didSetEndSeparator = true; |
|
} |
|
else if (isInlineElement(path, options, node)) { |
|
noHugSeparatorStart = line; |
|
} |
|
trimTextNodeLeft(firstChild); |
|
} |
|
if (!hugEnd && lastChild && lastChild.type === 'Text') { |
|
if (isInlineElement(path, options, node) && !didSetEndSeparator) { |
|
noHugSeparatorEnd = line; |
|
} |
|
trimTextNodeRight(lastChild); |
|
} |
|
} |
|
if (hugStart) { |
|
return group([ |
|
...openingTag, |
|
indent([softline, group(['>', body()])]), |
|
noHugSeparatorEnd, |
|
`</${node.name}>`, |
|
]); |
|
} |
|
if (hugEnd) { |
|
return group([ |
|
...openingTag, |
|
'>', |
|
indent([noHugSeparatorStart, group([body(), `</${node.name}`])]), |
|
canOmitSoftlineBeforeClosingTag(node, path, options) ? '' : softline, |
|
'>', |
|
]); |
|
} |
|
if (isEmpty) { |
|
return group([...openingTag, '>', body(), `</${node.name}>`]); |
|
} |
|
return group([ |
|
...openingTag, |
|
'>', |
|
indent([noHugSeparatorStart, body()]), |
|
noHugSeparatorEnd, |
|
`</${node.name}>`, |
|
]); |
|
} |
|
case 'Options': |
|
if (options.svelteSortOrder !== 'none') { |
|
throw new Error('Options tags should have been handled by prepareChildren'); |
|
} |
|
|
|
case 'Body': |
|
case 'Document': |
|
return group([ |
|
'<', |
|
node.name, |
|
indent(group([ |
|
...path.map(printWithPrependedAttributeLine(node, options, print), 'attributes'), |
|
bracketSameLine ? '' : dedent(line), |
|
])), |
|
...[bracketSameLine ? ' ' : '', '/>'], |
|
]); |
|
case 'Document': |
|
return group([ |
|
'<', |
|
node.name, |
|
indent(group([ |
|
...path.map(printWithPrependedAttributeLine(node, options, print), 'attributes'), |
|
bracketSameLine ? '' : dedent(line), |
|
])), |
|
...[bracketSameLine ? ' ' : '', '/>'], |
|
]); |
|
case 'Identifier': |
|
return node.name; |
|
case 'AttributeShorthand': { |
|
return node.expression.name; |
|
} |
|
case 'Attribute': { |
|
if (isOrCanBeConvertedToShorthand(node)) { |
|
if (options.svelteAllowShorthand) { |
|
return ['{', node.name, '}']; |
|
} |
|
else { |
|
return [node.name, `=${open}`, node.name, close]; |
|
} |
|
} |
|
else { |
|
if (node.value === true) { |
|
return [node.name]; |
|
} |
|
const quotes = !isLoneMustacheTag(node.value) || |
|
((_a = (options.svelteStrictMode && !options._svelte_is5Plus)) !== null && _a !== void 0 ? _a : false); |
|
const attrNodeValue = printAttributeNodeValue(path, print, quotes, node); |
|
if (quotes) { |
|
return [node.name, '=', '"', attrNodeValue, '"']; |
|
} |
|
else { |
|
return [node.name, '=', attrNodeValue]; |
|
} |
|
} |
|
} |
|
case 'MustacheTag': |
|
return ['{', printJS(path, print, 'expression'), '}']; |
|
case 'IfBlock': { |
|
const def = [ |
|
'{#if ', |
|
printJS(path, print, 'expression'), |
|
'}', |
|
printSvelteBlockChildren(path, print, options), |
|
]; |
|
if (node.else) { |
|
def.push(path.call(print, 'else')); |
|
} |
|
def.push('{/if}'); |
|
return group([def, breakParent]); |
|
} |
|
case 'ElseBlock': { |
|
|
|
const parent = path.getParentNode(); |
|
if (node.children.length === 1 && |
|
node.children[0].type === 'IfBlock' && |
|
parent.type !== 'EachBlock') { |
|
const ifNode = node.children[0]; |
|
const def = [ |
|
'{:else if ', |
|
path.map((ifPath) => printJS(ifPath, print, 'expression'), 'children')[0], |
|
'}', |
|
path.map((ifPath) => printSvelteBlockChildren(ifPath, print, options), 'children')[0], |
|
]; |
|
if (ifNode.else) { |
|
def.push(path.map((ifPath) => ifPath.call(print, 'else'), 'children')[0]); |
|
} |
|
return def; |
|
} |
|
return ['{:else}', printSvelteBlockChildren(path, print, options)]; |
|
} |
|
case 'EachBlock': { |
|
const def = [ |
|
'{#each ', |
|
printJS(path, print, 'expression'), |
|
' as', |
|
expandNode(node.context, options.originalText), |
|
]; |
|
if (node.index) { |
|
def.push(', ', node.index); |
|
} |
|
if (node.key) { |
|
def.push(' (', printJS(path, print, 'key'), ')'); |
|
} |
|
def.push('}', printSvelteBlockChildren(path, print, options)); |
|
if (node.else) { |
|
def.push(path.call(print, 'else')); |
|
} |
|
def.push('{/each}'); |
|
return group([def, breakParent]); |
|
} |
|
case 'AwaitBlock': { |
|
const hasPendingBlock = node.pending.children.some((n) => !isEmptyTextNode(n)); |
|
const hasThenBlock = node.then.children.some((n) => !isEmptyTextNode(n)); |
|
const hasCatchBlock = node.catch.children.some((n) => !isEmptyTextNode(n)); |
|
let block = []; |
|
if (!hasPendingBlock && hasThenBlock) { |
|
block.push(group([ |
|
'{#await ', |
|
printJS(path, print, 'expression'), |
|
' then', |
|
expandNode(node.value, options.originalText), |
|
'}', |
|
]), path.call(print, 'then')); |
|
} |
|
else if (!hasPendingBlock && hasCatchBlock) { |
|
block.push(group([ |
|
'{#await ', |
|
printJS(path, print, 'expression'), |
|
' catch', |
|
expandNode(node.error, options.originalText), |
|
'}', |
|
]), path.call(print, 'catch')); |
|
} |
|
else { |
|
block.push(group(['{#await ', printJS(path, print, 'expression'), '}'])); |
|
if (hasPendingBlock) { |
|
block.push(path.call(print, 'pending')); |
|
} |
|
if (hasThenBlock) { |
|
block.push(group(['{:then', expandNode(node.value, options.originalText), '}']), path.call(print, 'then')); |
|
} |
|
} |
|
if ((hasPendingBlock || hasThenBlock) && hasCatchBlock) { |
|
block.push(group(['{:catch', expandNode(node.error, options.originalText), '}']), path.call(print, 'catch')); |
|
} |
|
block.push('{/await}'); |
|
return group(block); |
|
} |
|
case 'KeyBlock': { |
|
const def = [ |
|
'{#key ', |
|
printJS(path, print, 'expression'), |
|
'}', |
|
printSvelteBlockChildren(path, print, options), |
|
]; |
|
def.push('{/key}'); |
|
return group([def, breakParent]); |
|
} |
|
case 'ThenBlock': |
|
case 'PendingBlock': |
|
case 'CatchBlock': |
|
return printSvelteBlockChildren(path, print, options); |
|
|
|
case 'SnippetBlock': { |
|
const snippet = ['{#snippet ', printJS(path, print, 'expression')]; |
|
snippet.push('}', printSvelteBlockChildren(path, print, options), '{/snippet}'); |
|
return snippet; |
|
} |
|
case 'EventHandler': |
|
return [ |
|
'on:', |
|
node.name, |
|
node.modifiers && node.modifiers.length ? ['|', join('|', node.modifiers)] : '', |
|
node.expression ? ['=', ...printJsExpression()] : '', |
|
]; |
|
case 'Binding': |
|
return [ |
|
'bind:', |
|
node.name, |
|
node.expression.type === 'Identifier' && |
|
node.expression.name === node.name && |
|
options.svelteAllowShorthand |
|
? '' |
|
: ['=', ...printJsExpression()], |
|
]; |
|
case 'Class': |
|
return [ |
|
'class:', |
|
node.name, |
|
node.expression.type === 'Identifier' && |
|
node.expression.name === node.name && |
|
options.svelteAllowShorthand |
|
? '' |
|
: ['=', ...printJsExpression()], |
|
]; |
|
case 'StyleDirective': |
|
const prefix = [ |
|
'style:', |
|
node.name, |
|
node.modifiers && node.modifiers.length ? ['|', join('|', node.modifiers)] : '', |
|
]; |
|
if (isOrCanBeConvertedToShorthand(node) || node.value === true) { |
|
if (options.svelteAllowShorthand) { |
|
return [...prefix]; |
|
} |
|
else { |
|
return [...prefix, `=${open}`, node.name, close]; |
|
} |
|
} |
|
else { |
|
const quotes = !isLoneMustacheTag(node.value) || |
|
((_b = (options.svelteStrictMode && !options._svelte_is5Plus)) !== null && _b !== void 0 ? _b : false); |
|
const attrNodeValue = printAttributeNodeValue(path, print, quotes, node); |
|
if (quotes) { |
|
return [...prefix, '=', '"', attrNodeValue, '"']; |
|
} |
|
else { |
|
return [...prefix, '=', attrNodeValue]; |
|
} |
|
} |
|
case 'Let': |
|
return [ |
|
'let:', |
|
node.name, |
|
|
|
!node.expression || |
|
(node.expression.type === 'Identifier' && node.expression.name === node.name) |
|
? '' |
|
: ['=', ...printJsExpression()], |
|
]; |
|
case 'DebugTag': |
|
return [ |
|
'{@debug', |
|
node.identifiers.length > 0 |
|
? [' ', join(', ', path.map(print, 'identifiers'))] |
|
: '', |
|
'}', |
|
]; |
|
case 'Ref': |
|
return ['ref:', node.name]; |
|
case 'Comment': { |
|
const nodeAfterComment = getNextNode(path); |
|
if (isIgnoreStartDirective(node) && isNodeTopLevelHTML(node, path)) { |
|
ignoreRange = true; |
|
} |
|
else if (isIgnoreEndDirective(node) && isNodeTopLevelHTML(node, path)) { |
|
ignoreRange = false; |
|
} |
|
else if ( |
|
|
|
|
|
|
|
|
|
|
|
doesEmbedStartAfterNode(node, path) || |
|
(isEmptyTextNode(nodeAfterComment) && |
|
doesEmbedStartAfterNode(nodeAfterComment, path))) { |
|
return ''; |
|
} |
|
else if (isIgnoreDirective(node)) { |
|
ignoreNext = true; |
|
} |
|
return printComment(node); |
|
} |
|
case 'Transition': |
|
const kind = node.intro && node.outro ? 'transition' : node.intro ? 'in' : 'out'; |
|
return [ |
|
kind, |
|
':', |
|
node.name, |
|
node.modifiers && node.modifiers.length ? ['|', join('|', node.modifiers)] : '', |
|
node.expression ? ['=', ...printJsExpression()] : '', |
|
]; |
|
case 'Action': |
|
return ['use:', node.name, node.expression ? ['=', ...printJsExpression()] : '']; |
|
case 'Animation': |
|
return ['animate:', node.name, node.expression ? ['=', ...printJsExpression()] : '']; |
|
case 'RawMustacheTag': |
|
return ['{@html ', printJS(path, print, 'expression'), '}']; |
|
|
|
case 'RenderTag': { |
|
const render = ['{@render ', printJS(path, print, 'expression'), '}']; |
|
return render; |
|
} |
|
case 'Spread': |
|
return ['{...', printJS(path, print, 'expression'), '}']; |
|
case 'ConstTag': |
|
return ['{@const ', printJS(path, print, 'expression'), '}']; |
|
} |
|
console.error(JSON.stringify(node, null, 4)); |
|
throw new Error('unknown node type: ' + node.type); |
|
} |
|
function printTopLevelParts(n, options, path, print) { |
|
if (options.svelteSortOrder === 'none') { |
|
const topLevelPartsByEnd = {}; |
|
if (n.module) { |
|
topLevelPartsByEnd[n.module.end] = n.module; |
|
} |
|
if (n.instance) { |
|
topLevelPartsByEnd[n.instance.end] = n.instance; |
|
} |
|
if (n.css) { |
|
topLevelPartsByEnd[n.css.end] = n.css; |
|
} |
|
const children = getChildren(n.html); |
|
for (let i = 0; i < children.length; i++) { |
|
const node = children[i]; |
|
if (topLevelPartsByEnd[node.start]) { |
|
children.splice(i, 0, topLevelPartsByEnd[node.start]); |
|
delete topLevelPartsByEnd[node.start]; |
|
} |
|
} |
|
const result = path.call(print, 'html'); |
|
if (options.insertPragma && !hasPragma(options.originalText)) { |
|
return [`<!-- @format -->`, hardline, result]; |
|
} |
|
else { |
|
return result; |
|
} |
|
} |
|
const parts = { |
|
options: [], |
|
scripts: [], |
|
markup: [], |
|
styles: [], |
|
}; |
|
|
|
if (n.module) { |
|
parts.scripts.push(path.call(print, 'module')); |
|
} |
|
if (n.instance) { |
|
parts.scripts.push(path.call(print, 'instance')); |
|
} |
|
|
|
if (n.css) { |
|
parts.styles.push(path.call(print, 'css')); |
|
} |
|
|
|
const htmlDoc = path.call(print, 'html'); |
|
if (htmlDoc) { |
|
parts.markup.push(htmlDoc); |
|
} |
|
if (svelteOptionsDoc) { |
|
parts.options.push(svelteOptionsDoc); |
|
} |
|
const docs = flatten(parseSortOrder(options.svelteSortOrder).map((p) => parts[p])); |
|
|
|
ignoreNext = false; |
|
ignoreRange = false; |
|
svelteOptionsDoc = undefined; |
|
|
|
|
|
|
|
|
|
if (options.parentParser === 'markdown') { |
|
const lastDoc = docs[docs.length - 1]; |
|
trimRight([lastDoc], isLine); |
|
} |
|
if (options.insertPragma && !hasPragma(options.originalText)) { |
|
return [`<!-- @format -->`, hardline, group(docs)]; |
|
} |
|
else { |
|
return group([join(hardline, docs)]); |
|
} |
|
} |
|
function printAttributeNodeValue(path, print, quotes, node) { |
|
const valueDocs = path.map((childPath) => childPath.call(print), 'value'); |
|
if (!quotes || !formattableAttributes.includes(node.name)) { |
|
return valueDocs; |
|
} |
|
else { |
|
return indent(group(trim(valueDocs, isLine))); |
|
} |
|
} |
|
function printSvelteBlockChildren(path, print, options) { |
|
const node = path.getValue(); |
|
const children = node.children; |
|
if (!children || children.length === 0) { |
|
return ''; |
|
} |
|
const whitespaceAtStartOfBlock = checkWhitespaceAtStartOfSvelteBlock(node, options); |
|
const whitespaceAtEndOfBlock = checkWhitespaceAtEndOfSvelteBlock(node, options); |
|
const startline = whitespaceAtStartOfBlock === 'none' |
|
? '' |
|
: whitespaceAtEndOfBlock === 'line' || whitespaceAtStartOfBlock === 'line' |
|
? hardline |
|
: line; |
|
const endline = whitespaceAtEndOfBlock === 'none' |
|
? '' |
|
: whitespaceAtEndOfBlock === 'line' || whitespaceAtStartOfBlock === 'line' |
|
? hardline |
|
: line; |
|
const firstChild = children[0]; |
|
const lastChild = children[children.length - 1]; |
|
if (isTextNodeStartingWithWhitespace(firstChild)) { |
|
trimTextNodeLeft(firstChild); |
|
} |
|
if (isTextNodeEndingWithWhitespace(lastChild)) { |
|
trimTextNodeRight(lastChild); |
|
} |
|
return [indent([startline, group(printChildren(path, print, options))]), endline]; |
|
} |
|
function printPre(node, originalText, path, print) { |
|
const result = []; |
|
const length = node.children.length; |
|
for (let i = 0; i < length; i++) { |
|
const child = node.children[i]; |
|
if (child.type === 'Text') { |
|
const lines = originalText.substring(child.start, child.end).split(/\r?\n/); |
|
lines.forEach((line, j) => { |
|
if (j > 0) |
|
result.push(literalline); |
|
result.push(line); |
|
}); |
|
} |
|
else { |
|
result.push(path.call(print, 'children', i)); |
|
} |
|
} |
|
return result; |
|
} |
|
function printChildren(path, print, options) { |
|
if (isPreTagContent(path)) { |
|
return path.map(print, 'children'); |
|
} |
|
const childNodes = prepareChildren(path.getValue().children, path, print, options); |
|
|
|
path.getValue().children = childNodes; |
|
if (childNodes.length === 0) { |
|
return ''; |
|
} |
|
const childDocs = []; |
|
let handleWhitespaceOfPrevTextNode = false; |
|
for (let i = 0; i < childNodes.length; i++) { |
|
const childNode = childNodes[i]; |
|
if (childNode.type === 'Text') { |
|
handleTextChild(i, childNode); |
|
} |
|
else if (isBlockElement(childNode, options)) { |
|
handleBlockChild(i); |
|
} |
|
else if (isInlineElement(path, options, childNode)) { |
|
handleInlineChild(i); |
|
} |
|
else { |
|
childDocs.push(printChild(i)); |
|
handleWhitespaceOfPrevTextNode = false; |
|
} |
|
} |
|
|
|
const forceBreakContent = childNodes.length > 1 && childNodes.some((child) => isBlockElement(child, options)); |
|
if (forceBreakContent) { |
|
childDocs.push(breakParent); |
|
} |
|
return childDocs; |
|
function printChild(idx) { |
|
return path.call(print, 'children', idx); |
|
} |
|
|
|
|
|
|
|
function handleInlineChild(idx) { |
|
if (handleWhitespaceOfPrevTextNode) { |
|
childDocs.push(group([line, printChild(idx)])); |
|
} |
|
else { |
|
childDocs.push(printChild(idx)); |
|
} |
|
handleWhitespaceOfPrevTextNode = false; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
function handleBlockChild(idx) { |
|
const prevChild = childNodes[idx - 1]; |
|
if (prevChild && |
|
!isBlockElement(prevChild, options) && |
|
(prevChild.type !== 'Text' || |
|
handleWhitespaceOfPrevTextNode || |
|
!isTextNodeEndingWithWhitespace(prevChild))) { |
|
childDocs.push(softline); |
|
} |
|
childDocs.push(printChild(idx)); |
|
const nextChild = childNodes[idx + 1]; |
|
if (nextChild && |
|
(nextChild.type !== 'Text' || |
|
|
|
|
|
|
|
((!isEmptyTextNode(nextChild) || |
|
(childNodes[idx + 2] && isInlineElement(path, options, childNodes[idx + 2]))) && |
|
!isTextNodeStartingWithLinebreak(nextChild)))) { |
|
childDocs.push(softline); |
|
} |
|
handleWhitespaceOfPrevTextNode = false; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function handleTextChild(idx, childNode) { |
|
handleWhitespaceOfPrevTextNode = false; |
|
if (idx === 0 || idx === childNodes.length - 1) { |
|
childDocs.push(printChild(idx)); |
|
return; |
|
} |
|
const prevNode = childNodes[idx - 1]; |
|
const nextNode = childNodes[idx + 1]; |
|
if (isTextNodeStartingWithWhitespace(childNode) && |
|
|
|
!isEmptyTextNode(childNode)) { |
|
if (isInlineElement(path, options, prevNode) && |
|
!isTextNodeStartingWithLinebreak(childNode)) { |
|
trimTextNodeLeft(childNode); |
|
const lastChildDoc = childDocs.pop(); |
|
childDocs.push(group([lastChildDoc, line])); |
|
} |
|
if (isBlockElement(prevNode, options) && !isTextNodeStartingWithLinebreak(childNode)) { |
|
trimTextNodeLeft(childNode); |
|
} |
|
} |
|
if (isTextNodeEndingWithWhitespace(childNode)) { |
|
if (isInlineElement(path, options, nextNode) && |
|
!isTextNodeEndingWithLinebreak(childNode)) { |
|
handleWhitespaceOfPrevTextNode = !prevNode || !isBlockElement(prevNode, options); |
|
trimTextNodeRight(childNode); |
|
} |
|
if (isBlockElement(nextNode, options) && !isTextNodeEndingWithLinebreak(childNode, 2)) { |
|
handleWhitespaceOfPrevTextNode = !prevNode || !isBlockElement(prevNode, options); |
|
trimTextNodeRight(childNode); |
|
} |
|
} |
|
childDocs.push(printChild(idx)); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function prepareChildren(children, path, print, options) { |
|
let svelteOptionsComment; |
|
const childrenWithoutOptions = []; |
|
const bracketSameLine = isBracketSameLine(options); |
|
for (let idx = 0; idx < children.length; idx++) { |
|
const currentChild = children[idx]; |
|
if (currentChild.type === 'Text' && getUnencodedText(currentChild) === '') { |
|
continue; |
|
} |
|
if (isEmptyTextNode(currentChild) && doesEmbedStartAfterNode(currentChild, path)) { |
|
continue; |
|
} |
|
if (options.svelteSortOrder !== 'none') { |
|
if (isCommentFollowedByOptions(currentChild, idx)) { |
|
svelteOptionsComment = printComment(currentChild); |
|
const nextChild = children[idx + 1]; |
|
idx += nextChild && isEmptyTextNode(nextChild) ? 1 : 0; |
|
continue; |
|
} |
|
if (currentChild.type === 'Options') { |
|
printSvelteOptions(currentChild, idx, path, print); |
|
continue; |
|
} |
|
} |
|
childrenWithoutOptions.push(currentChild); |
|
} |
|
const mergedChildrenWithoutOptions = []; |
|
for (let idx = 0; idx < childrenWithoutOptions.length; idx++) { |
|
const currentChild = childrenWithoutOptions[idx]; |
|
const nextChild = childrenWithoutOptions[idx + 1]; |
|
if (currentChild.type === 'Text' && nextChild && nextChild.type === 'Text') { |
|
|
|
currentChild.raw += nextChild.raw; |
|
currentChild.data += nextChild.data; |
|
idx++; |
|
} |
|
mergedChildrenWithoutOptions.push(currentChild); |
|
} |
|
return mergedChildrenWithoutOptions; |
|
function printSvelteOptions(node, idx, path, print) { |
|
svelteOptionsDoc = group([ |
|
[ |
|
'<', |
|
node.name, |
|
indent(group([ |
|
...path.map(printWithPrependedAttributeLine(node, options, print), 'children', idx, 'attributes'), |
|
bracketSameLine ? '' : dedent(line), |
|
])), |
|
...[bracketSameLine ? ' ' : '', '/>'], |
|
], |
|
hardline, |
|
]); |
|
if (svelteOptionsComment) { |
|
svelteOptionsDoc = group([svelteOptionsComment, hardline, svelteOptionsDoc]); |
|
} |
|
} |
|
function isCommentFollowedByOptions(node, idx) { |
|
if (node.type !== 'Comment' || isIgnoreEndDirective(node) || isIgnoreStartDirective(node)) { |
|
return false; |
|
} |
|
const nextChild = children[idx + 1]; |
|
if (nextChild) { |
|
if (isEmptyTextNode(nextChild)) { |
|
const afterNext = children[idx + 2]; |
|
return afterNext && afterNext.type === 'Options'; |
|
} |
|
return nextChild.type === 'Options'; |
|
} |
|
return false; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
function splitTextToDocs(node) { |
|
const text = getUnencodedText(node); |
|
const lines = text.split(/[\t\n\f\r ]+/); |
|
let docs = join(line, lines).filter((doc) => doc !== ''); |
|
if (startsWithLinebreak(text)) { |
|
docs[0] = hardline; |
|
} |
|
if (startsWithLinebreak(text, 2)) { |
|
docs = [hardline, ...docs]; |
|
} |
|
if (endsWithLinebreak(text)) { |
|
docs[docs.length - 1] = hardline; |
|
} |
|
if (endsWithLinebreak(text, 2)) { |
|
docs = [...docs, hardline]; |
|
} |
|
return docs; |
|
} |
|
function printJS(path, print, name) { |
|
return path.call(print, name); |
|
} |
|
function expandNode(node, original) { |
|
let str = _expandNode(node); |
|
if (node === null || node === void 0 ? void 0 : node.typeAnnotation) { |
|
str += ': ' + original.slice(node.typeAnnotation.start, node.typeAnnotation.end); |
|
} |
|
return str; |
|
} |
|
function _expandNode(node, parent) { |
|
if (node === null) { |
|
return ''; |
|
} |
|
if (typeof node === 'string') { |
|
|
|
return ' ' + node; |
|
} |
|
switch (node.type) { |
|
case 'ArrayExpression': |
|
case 'ArrayPattern': |
|
return ' [' + node.elements.map(_expandNode).join(',').slice(1) + ']'; |
|
case 'AssignmentPattern': |
|
return _expandNode(node.left) + ' =' + _expandNode(node.right); |
|
case 'Identifier': |
|
return ' ' + node.name; |
|
case 'Literal': |
|
return ' ' + node.raw; |
|
case 'ObjectExpression': |
|
return ' {' + node.properties.map((p) => _expandNode(p, node)).join(',') + ' }'; |
|
case 'ObjectPattern': |
|
return ' {' + node.properties.map(_expandNode).join(',') + ' }'; |
|
case 'Property': |
|
if (node.value.type === 'ObjectPattern' || node.value.type === 'ArrayPattern') { |
|
return ' ' + node.key.name + ':' + _expandNode(node.value); |
|
} |
|
else if ((node.value.type === 'Identifier' && node.key.name !== node.value.name) || |
|
(parent && parent.type === 'ObjectExpression')) { |
|
return _expandNode(node.key) + ':' + _expandNode(node.value); |
|
} |
|
else { |
|
return _expandNode(node.value); |
|
} |
|
case 'RestElement': |
|
return ' ...' + node.argument.name; |
|
} |
|
console.error(JSON.stringify(node, null, 4)); |
|
throw new Error('unknown node type: ' + node.type); |
|
} |
|
function printComment(node) { |
|
let text = node.data; |
|
if (hasSnippedContent(text)) { |
|
text = unsnipContent(text); |
|
} |
|
return group(['<!--', text, '-->']); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function __awaiter(thisArg, _arguments, P, generator) { |
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } |
|
return new (P || (P = Promise))(function (resolve, reject) { |
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } |
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } |
|
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } |
|
step((generator = generator.apply(thisArg, _arguments || [])).next()); |
|
}); |
|
} |
|
|
|
var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { |
|
var e = new Error(message); |
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; |
|
}; |
|
|
|
function getText(node, options, unsnip = false) { |
|
const leadingComments = node.leadingComments; |
|
const text = options.originalText.slice(options.locStart( |
|
|
|
|
|
(leadingComments && leadingComments[0]) || node), options.locEnd(node)); |
|
if (!unsnip || !hasSnippedContent(text)) { |
|
return text; |
|
} |
|
return unsnipContent(text); |
|
} |
|
|
|
const extractAttributesRegex = /<[a-z]+((?:\s+[^=>'"\/]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"\/]+)*\s*)>/im; |
|
const attributeRegex = /([^\s=]+)(?:=(?:(?:("|')([\s\S]*?)\2)|(?:([^>\s]+?)(?:\s|>|$))))?/gim; |
|
function extractAttributes(html) { |
|
const [, attributesString] = html.match(extractAttributesRegex); |
|
const attrs = []; |
|
let match; |
|
while ((match = attributeRegex.exec(attributesString))) { |
|
const [all, name, quotes, valueQuoted, valueUnquoted] = match; |
|
const value = valueQuoted || valueUnquoted; |
|
const attrStart = match.index; |
|
let valueNode; |
|
if (!value) { |
|
valueNode = true; |
|
} |
|
else { |
|
let valueStart = attrStart + name.length; |
|
if (quotes) { |
|
valueStart += 2; |
|
} |
|
valueNode = [ |
|
{ |
|
type: 'Text', |
|
data: value, |
|
start: valueStart, |
|
end: valueStart + value.length, |
|
}, |
|
]; |
|
} |
|
attrs.push({ |
|
type: 'Attribute', |
|
name, |
|
value: valueNode, |
|
start: attrStart, |
|
end: attrStart + all.length, |
|
}); |
|
} |
|
return attrs; |
|
} |
|
|
|
const { builders: { group: group$1, hardline: hardline$1, softline: softline$1, indent: indent$1, dedent: dedent$1, literalline: literalline$1 }, utils: { removeLines }, } = doc; |
|
const leaveAlone = new Set([ |
|
'Script', |
|
'Style', |
|
'Identifier', |
|
'MemberExpression', |
|
'CallExpression', |
|
'ArrowFunctionExpression', |
|
]); |
|
const dontTraverse = new Set(['start', 'end', 'type']); |
|
function getVisitorKeys(node, nonTraversableKeys) { |
|
return Object.keys(node).filter((key) => { |
|
return !nonTraversableKeys.has(key) && !leaveAlone.has(node.type) && !dontTraverse.has(key); |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function embed(path, _options) { |
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l; |
|
const node = path.getNode(); |
|
const options = _options; |
|
if (!options.locStart || !options.locEnd || !options.originalText) { |
|
throw new Error('Missing required options'); |
|
} |
|
if (isASTNode(node)) { |
|
assignCommentsToNodes(node); |
|
if (node.module) { |
|
node.module.type = 'Script'; |
|
node.module.attributes = extractAttributes(getText(node.module, options)); |
|
} |
|
if (node.instance) { |
|
node.instance.type = 'Script'; |
|
node.instance.attributes = extractAttributes(getText(node.instance, options)); |
|
} |
|
if (node.css) { |
|
node.css.type = 'Style'; |
|
node.css.content.type = 'StyleProgram'; |
|
} |
|
return null; |
|
} |
|
|
|
|
|
const parent = path.getParentNode(); |
|
const printJsExpression = () => { |
|
var _a; |
|
return parent.expression |
|
? printJS$1(parent, (_a = (options.svelteStrictMode && !options._svelte_is5Plus)) !== null && _a !== void 0 ? _a : false, false, false, 'expression') |
|
: undefined; |
|
}; |
|
const printSvelteBlockJS = (name) => printJS$1(parent, false, true, false, name); |
|
switch (parent.type) { |
|
case 'IfBlock': |
|
case 'ElseBlock': |
|
case 'AwaitBlock': |
|
case 'KeyBlock': |
|
printSvelteBlockJS('expression'); |
|
break; |
|
case 'EachBlock': |
|
printSvelteBlockJS('expression'); |
|
printSvelteBlockJS('key'); |
|
break; |
|
case 'SnippetBlock': |
|
|
|
if (node === parent.expression) { |
|
parent.expression.end = |
|
options.originalText.indexOf(')', (_e = (_b = (_a = parent.context) === null || _a === void 0 ? void 0 : _a.end) !== null && _b !== void 0 ? _b : (_d = (_c = parent.parameters) === null || _c === void 0 ? void 0 : _c[parent.parameters.length - 1]) === null || _d === void 0 ? void 0 : _d.end) !== null && _e !== void 0 ? _e : parent.expression.end) + 1; |
|
parent.context = null; |
|
parent.parameters = null; |
|
node.isJS = true; |
|
node.asFunction = true; |
|
} |
|
break; |
|
case 'Element': |
|
printJS$1(parent, (_f = (options.svelteStrictMode && !options._svelte_is5Plus)) !== null && _f !== void 0 ? _f : false, false, false, 'tag'); |
|
break; |
|
case 'MustacheTag': |
|
printJS$1(parent, isInsideQuotedAttribute(path, options), false, false, 'expression'); |
|
break; |
|
case 'RawMustacheTag': |
|
printJS$1(parent, false, false, false, 'expression'); |
|
break; |
|
case 'Spread': |
|
printJS$1(parent, false, false, false, 'expression'); |
|
break; |
|
case 'ConstTag': |
|
printJS$1(parent, false, false, true, 'expression'); |
|
break; |
|
case 'RenderTag': |
|
if (node === parent.expression) { |
|
|
|
if ('argument' in parent || 'arguments' in parent) { |
|
parent.expression.end = |
|
options.originalText.indexOf(')', (_l = (_h = (_g = parent.argument) === null || _g === void 0 ? void 0 : _g.end) !== null && _h !== void 0 ? _h : (_k = (_j = parent.arguments) === null || _j === void 0 ? void 0 : _j[parent.arguments.length - 1]) === null || _k === void 0 ? void 0 : _k.end) !== null && _l !== void 0 ? _l : parent.expression.end) + 1; |
|
parent.argument = null; |
|
parent.arguments = null; |
|
} |
|
printJS$1(parent, false, false, false, 'expression'); |
|
} |
|
break; |
|
case 'EventHandler': |
|
case 'Binding': |
|
case 'Class': |
|
case 'Let': |
|
case 'Transition': |
|
case 'Action': |
|
case 'Animation': |
|
case 'InlineComponent': |
|
printJsExpression(); |
|
break; |
|
} |
|
if (node.isJS) { |
|
return (textToDoc) => __awaiter(this, void 0, void 0, function* () { |
|
try { |
|
const embeddedOptions = { |
|
|
|
|
|
parser: options._svelte_ts |
|
? 'svelteTSExpressionParser' |
|
: 'svelteExpressionParser', |
|
singleQuote: node.forceSingleQuote ? true : options.singleQuote, |
|
_svelte_asFunction: node.asFunction, |
|
}; |
|
|
|
|
|
const text = getText(node, options, true); |
|
let docs = yield textToDoc(node.asFunction ? forceIntoFunction(text) : forceIntoExpression(text), embeddedOptions); |
|
if (node.forceSingleLine) { |
|
docs = removeLines(docs); |
|
} |
|
if (node.removeParentheses) { |
|
docs = removeParentheses(docs); |
|
} |
|
if (node.asFunction) { |
|
if (Array.isArray(docs) && typeof docs[0] === 'string') { |
|
docs[0] = docs[0].replace('function ', ''); |
|
docs.splice(-1, 1); |
|
} |
|
else { |
|
throw new Error('Prettier AST changed, asFunction logic needs to change'); |
|
} |
|
} |
|
return docs; |
|
} |
|
catch (e) { |
|
return getText(node, options, true); |
|
} |
|
}); |
|
} |
|
const embedType = (tag, parser, isTopLevel) => { |
|
return (textToDoc, print) => __awaiter(this, void 0, void 0, function* () { |
|
return embedTag(tag, options.originalText, path, (content) => formatBodyContent(content, parser, textToDoc, options), print, isTopLevel, options); |
|
}); |
|
}; |
|
const embedScript = (isTopLevel) => embedType('script', |
|
|
|
|
|
|
|
|
|
isTypeScript(node) ? 'typescript' : isJSON(node) ? 'json' : 'babel-ts', isTopLevel); |
|
const embedStyle = (isTopLevel) => embedType('style', isLess(node) ? 'less' : isScss(node) ? 'scss' : 'css', isTopLevel); |
|
const embedPug = () => embedType('template', 'pug', false); |
|
switch (node.type) { |
|
case 'Script': |
|
return embedScript(true); |
|
case 'Style': |
|
return embedStyle(true); |
|
case 'Element': { |
|
if (node.name === 'script') { |
|
return embedScript(false); |
|
} |
|
else if (node.name === 'style') { |
|
return embedStyle(false); |
|
} |
|
else if (isPugTemplate(node)) { |
|
return embedPug(); |
|
} |
|
} |
|
} |
|
return null; |
|
} |
|
function forceIntoExpression(statement) { |
|
|
|
|
|
return `(${statement}\n)`; |
|
} |
|
function forceIntoFunction(statement) { |
|
return `function ${statement} {}`; |
|
} |
|
function preformattedBody(str) { |
|
if (!str) { |
|
return ''; |
|
} |
|
const firstNewline = /^[\t\f\r ]*\n/; |
|
const lastNewline = /\n[\t\f\r ]*$/; |
|
|
|
|
|
return [literalline$1, str.replace(firstNewline, '').replace(lastNewline, ''), hardline$1]; |
|
} |
|
function getSnippedContent(node) { |
|
const encodedContent = getAttributeTextValue(snippedTagContentAttribute, node); |
|
if (encodedContent) { |
|
return base64ToString(encodedContent); |
|
} |
|
else { |
|
return ''; |
|
} |
|
} |
|
function formatBodyContent(content, parser, textToDoc, options) { |
|
return __awaiter(this, void 0, void 0, function* () { |
|
try { |
|
const body = yield textToDoc(content, { parser }); |
|
if (parser === 'pug' && typeof body === 'string') { |
|
|
|
|
|
const whitespace = options.useTabs |
|
? '\t' |
|
: ' '.repeat(options.pugTabWidth && options.pugTabWidth > 0 |
|
? options.pugTabWidth |
|
: options.tabWidth); |
|
const pugBody = body |
|
.split('\n') |
|
.map((line) => (line ? whitespace + line : line)) |
|
.join('\n'); |
|
return [hardline$1, pugBody]; |
|
} |
|
const indentIfDesired = (doc) => options.svelteIndentScriptAndStyle ? indent$1(doc) : doc; |
|
trimRight([body], isLine); |
|
return [indentIfDesired([hardline$1, body]), hardline$1]; |
|
} |
|
catch (error) { |
|
if (process.env.PRETTIER_DEBUG) { |
|
throw error; |
|
} |
|
|
|
|
|
|
|
|
|
console.error(error); |
|
return preformattedBody(content); |
|
} |
|
}); |
|
} |
|
function embedTag(tag, text, path, formatBodyContent, print, isTopLevel, options) { |
|
var _a; |
|
return __awaiter(this, void 0, void 0, function* () { |
|
const node = path.getNode(); |
|
const content = tag === 'template' ? printRaw(node, text) : getSnippedContent(node); |
|
const previousComments = node.type === 'Script' || node.type === 'Style' |
|
? node.comments |
|
: [getLeadingComment(path)] |
|
.filter(Boolean) |
|
.map((comment) => ({ comment: comment, emptyLineAfter: false })); |
|
const canFormat = isNodeSupportedLanguage(node) && |
|
!isIgnoreDirective((_a = previousComments[previousComments.length - 1]) === null || _a === void 0 ? void 0 : _a.comment) && |
|
(tag !== 'template' || |
|
options.plugins.some((plugin) => typeof plugin !== 'string' && plugin.parsers && plugin.parsers.pug)); |
|
const body = canFormat |
|
? content.trim() !== '' |
|
? yield formatBodyContent(content) |
|
: content === '' |
|
? '' |
|
: hardline$1 |
|
: preformattedBody(content); |
|
const openingTag = group$1([ |
|
'<', |
|
tag, |
|
indent$1(group$1([ |
|
...path.map(printWithPrependedAttributeLine(node, options, print), 'attributes'), |
|
isBracketSameLine(options) ? '' : dedent$1(softline$1), |
|
])), |
|
'>', |
|
]); |
|
let result = group$1([openingTag, body, '</', tag, '>']); |
|
const comments = []; |
|
for (const comment of previousComments) { |
|
comments.push('<!--', comment.comment.data, '-->'); |
|
comments.push(hardline$1); |
|
if (comment.emptyLineAfter) { |
|
comments.push(hardline$1); |
|
} |
|
} |
|
if (isTopLevel && options.svelteSortOrder !== 'none') { |
|
|
|
|
|
|
|
return [...comments, result, hardline$1]; |
|
} |
|
else { |
|
|
|
return isTopLevel && comments.length ? [...comments, result] : result; |
|
} |
|
}); |
|
} |
|
function printJS$1(node, forceSingleQuote, forceSingleLine, removeParentheses, name) { |
|
const part = node[name]; |
|
if (!part || typeof part !== 'object') { |
|
return; |
|
} |
|
part.isJS = true; |
|
part.forceSingleQuote = forceSingleQuote; |
|
part.forceSingleLine = forceSingleLine; |
|
part.removeParentheses = removeParentheses; |
|
} |
|
|
|
const babelParser = parsers$1.babel; |
|
const typescriptParser = parsers$1['babel-ts']; |
|
const isSvelte5Plus = Number(VERSION.split('.')[0]) >= 5; |
|
function locStart(node) { |
|
return node.start; |
|
} |
|
function locEnd(node) { |
|
return node.end; |
|
} |
|
const languages = [ |
|
{ |
|
name: 'svelte', |
|
parsers: ['svelte'], |
|
extensions: ['.svelte'], |
|
vscodeLanguageIds: ['svelte'], |
|
}, |
|
]; |
|
const parsers = { |
|
svelte: { |
|
hasPragma, |
|
parse: (text) => { |
|
try { |
|
return Object.assign(Object.assign({}, parse(text)), { __isRoot: true }); |
|
} |
|
catch (err) { |
|
if (err.start != null && err.end != null) { |
|
|
|
|
|
err.loc = { |
|
start: err.start, |
|
end: err.end, |
|
}; |
|
} |
|
throw err; |
|
} |
|
}, |
|
preprocess: (text, options) => { |
|
const result = snipScriptAndStyleTagContent(text); |
|
text = result.text.trim(); |
|
|
|
|
|
|
|
|
|
|
|
options.originalText = text; |
|
|
|
options._svelte_ts = isSvelte5Plus && result.isTypescript; |
|
options._svelte_is5Plus = isSvelte5Plus; |
|
return text; |
|
}, |
|
locStart, |
|
locEnd, |
|
astFormat: 'svelte-ast', |
|
}, |
|
svelteExpressionParser: Object.assign(Object.assign({}, babelParser), { parse: (text, options) => { |
|
const ast = babelParser.parse(text, options); |
|
let program = ast.program.body[0]; |
|
if (!options._svelte_asFunction) { |
|
program = program.expression; |
|
} |
|
return Object.assign(Object.assign({}, ast), { program }); |
|
} }), |
|
svelteTSExpressionParser: Object.assign(Object.assign({}, typescriptParser), { parse: (text, options) => { |
|
const ast = typescriptParser.parse(text, options); |
|
let program = ast.program.body[0]; |
|
if (!options._svelte_asFunction) { |
|
program = program.expression; |
|
} |
|
return Object.assign(Object.assign({}, ast), { program }); |
|
} }), |
|
}; |
|
const printers = { |
|
'svelte-ast': { |
|
print, |
|
embed, |
|
|
|
getVisitorKeys, |
|
}, |
|
}; |
|
|
|
export { languages, options, parsers, printers }; |
|
|