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 = /|`}
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 `