import { parsers as parsers$1 } from 'prettier/plugins/babel'; import { doc } from 'prettier/standalone'; import { VERSION, parse } from 'svelte/compiler'; // @see http://xahlee.info/js/html5_non-closing_tag.html const selfClosingTags = [ 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr', ]; // https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements#Elements 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', ]; /** * HTML attributes that we may safely reformat (trim whitespace, add or remove newlines) */ const formattableAttributes = [ // None at the moment // Prettier HTML does not format attributes at all // and to be consistent we leave this array empty for now ]; // Base64 string encoding and decoding module. // Uses Buffer for Node.js and btoa/atob for browser environments. // We use TextEncoder/TextDecoder for browser environments because // they can handle non-ASCII characters, unlike btoa/atob. 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 = /|'"\/\s]+=(?:"[^"]*"|'[^']*'|[^>\s]+)|\s+[^=>'"\/\s]+)*\s*)>([^]*?)<\/script>/g; const styleRegex = /|'"\/\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) !== '`, hardline, result]; } else { return result; } } const parts = { options: [], scripts: [], markup: [], styles: [], }; // scripts if (n.module) { parts.scripts.push(path.call(print, 'module')); } if (n.instance) { parts.scripts.push(path.call(print, 'instance')); } // styles if (n.css) { parts.styles.push(path.call(print, 'css')); } // markup 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])); // Need to reset these because they are global and could affect the next formatting run ignoreNext = false; ignoreRange = false; svelteOptionsDoc = undefined; // If this is invoked as an embed of markdown, remove the last hardline. // The markdown parser tries this, too, but fails because it does not // recurse into concats. Doing this will prevent an empty line // at the end of the embedded code block. if (options.parentParser === 'markdown') { const lastDoc = docs[docs.length - 1]; trimRight([lastDoc], isLine); } if (options.insertPragma && !hasPragma(options.originalText)) { return [``, 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); // modify original array because it's accessed later through map(print, 'children', idx) 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; } } // If there's at least one block element and more than one node, break content 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); } /** * Print inline child. Hug whitespace of previous text child if there was one. */ function handleInlineChild(idx) { if (handleWhitespaceOfPrevTextNode) { childDocs.push(group([line, printChild(idx)])); } else { childDocs.push(printChild(idx)); } handleWhitespaceOfPrevTextNode = false; } /** * Print block element. Add softlines around it if needed * so it breaks into a separate line if children are broken up. * Don't add lines at the start/end if it's the first/last child because this * kind of whitespace handling is done in the parent already. */ 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' || // Only handle text which starts with a whitespace and has text afterwards, // or is empty but followed by an inline element. The latter is done // so that if the children break, the inline element afterwards is in a separate line. ((!isEmptyTextNode(nextChild) || (childNodes[idx + 2] && isInlineElement(path, options, childNodes[idx + 2]))) && !isTextNodeStartingWithLinebreak(nextChild)))) { childDocs.push(softline); } handleWhitespaceOfPrevTextNode = false; } /** * Print text child. First/last child white space handling * is done in parent already. By definition of the Svelte AST, * a text node always is inbetween other tags. Add hardlines * if the users wants to have them inbetween. * If the text is trimmed right, toggle flag telling * subsequent (inline)block element to alter its printing logic * to check if they need to hug or print lines themselves. */ 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) && // If node is empty, go straight through to checking the right end !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)); } } /** * `svelte:options` is part of the html part but needs to be snipped out and handled * separately to reorder it as configured. The comment above it should be moved with it. * Do that here. */ 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') { // A tag was snipped out (f.e. svelte:options). Join 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; } } /** * Split the text into words separated by whitespace. Replace the whitespaces by lines, * collapsing multiple whitespaces into a single line. * * If the text starts or ends with multiple newlines, two of those should be kept. */ 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') { // pre-v3.20 AST 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(['']); } /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ 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( // if there are comments before the node they are not included // in the `start` of the node itself (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); }); } // Embed works like this in Prettier v3: // - do depth first traversal of all node properties // - deepest property is calling embed first // - if embed returns a function, it will be called after the traversal in a second pass, in the same order (deepest first) // For performance reasons we try to only return functions when we're sure we need to transform something. 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; } // embed does depth first traversal with deepest node called first, therefore we need to // check the parent to see if we are inside an expression that should be embedded. 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': // We merge the two parts into one expression, which future-proofs this for template TS support 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) { // TODO: remove this if block at some point, snippet API changed in .next-.. 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 = { // Prettier only allows string references as parsers from v3 onwards, // so we need to have another public parser and defer to that parser: options._svelte_ts ? 'svelteTSExpressionParser' : 'svelteExpressionParser', singleQuote: node.forceSingleQuote ? true : options.singleQuote, _svelte_asFunction: node.asFunction, }; // If we have snipped content, it was done wrongly and we need to unsnip it. // This happens for example for {@html ``} 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', // Use babel-ts as fallback because the absence does not mean the content is not TS, // the user could have set the default language. babel-ts will format things a little // bit different though, especially preserving parentheses around dot notation which // fixes https://github.com/sveltejs/prettier-plugin-svelte/issues/218 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) { // note the trailing newline: if the statement ends in a // comment, // we can't add the closing bracket right afterwards 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 ]*$/; // If we do not start with a new line prettier might try to break the opening tag // to keep it together with the string. Use a literal line to skip indentation. 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') { // Pug returns no docs but a final string. // Therefore prepend the line offsets 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; } // We will wind up here if there is a syntax error in the embedded code. If we throw an error, // prettier will try to print the node with the printer. That will fail with a hard-to-interpret // error message (e.g. "Unsupported node type", referring to `