'use strict'; var node_module = require('node:module'); var synckit = require('synckit'); var _doc = require('prettier/doc'); var node_buffer = require('node:buffer'); var sassFormatter = require('sass-formatter'); const options = { astroAllowShorthand: { since: '0.0.10', category: 'Astro', type: 'boolean', default: false, description: 'Enable/disable attribute shorthand if attribute name and expression are the same', }, }; const selfClosingTags = [ 'area', 'base', 'basefont', 'bgsound', 'br', 'col', 'command', 'embed', 'frame', 'hr', 'image', 'img', 'input', 'isindex', 'keygen', 'link', 'menuitem', 'meta', 'nextid', 'param', 'slot', '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', 'title', 'html', ]; const formattableAttributes = []; const req$1 = node_module.createRequire((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('index.js', document.baseURI).href))); let workerPath$1; try { workerPath$1 = req$1.resolve('../workers/serialize-worker.js'); } catch (e) { workerPath$1 = req$1.resolve('prettier-plugin-astro/workers/serialize-worker.js'); } const serialize = synckit.createSyncFn(req$1.resolve(workerPath$1)); const openingBracketReplace = '_Pé'; const closingBracketReplace = 'èP_'; const atSignReplace = 'ΩP_'; const dotReplace = 'ωP_'; function isInlineElement(path, opts, node) { return node && node.type === 'element' && !isBlockElement(node, opts) && !isPreTagContent(path); } function isBlockElement(node, opts) { return ((node && node.type === 'element' && opts.htmlWhitespaceSensitivity !== 'strict' && (opts.htmlWhitespaceSensitivity === 'ignore' || blockElements.includes(node.name))) || node.type === 'component' || node.type === 'fragment'); } function isIgnoreDirective(node) { return node.type === 'comment' && node.value.trim() === 'prettier-ignore'; } function printRaw(node, stripLeadingAndTrailingNewline = false) { if (!isNodeWithChildren(node)) { return ''; } if (node.children.length === 0) { return ''; } let raw = node.children.reduce((prev, curr) => prev + serialize(curr), ''); 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 isNodeWithChildren(node) { return node && 'children' in node && Array.isArray(node.children); } const isEmptyTextNode = (node) => { return !!node && node.type === 'text' && getUnencodedText(node).trim() === ''; }; function getUnencodedText(node) { return node.value; } function isTextNodeStartingWithLinebreak(node, nrLines = 1) { return startsWithLinebreak(getUnencodedText(node), nrLines); } function startsWithLinebreak(text, nrLines = 1) { return new RegExp(`^([\\t\\f\\r ]*\\n){${nrLines}}`).test(text); } function endsWithLinebreak(text, nrLines = 1) { return new RegExp(`(\\n[\\t\\f\\r ]*){${nrLines}}$`).test(text); } function isTextNodeStartingWithWhitespace(node) { return isTextNode(node) && /^\s/.test(getUnencodedText(node)); } function endsWithWhitespace(text) { return /\s$/.test(text); } function isTextNodeEndingWithWhitespace(node) { return isTextNode(node) && endsWithWhitespace(getUnencodedText(node)); } function hasSetDirectives(node) { const attributes = Array.from(node.attributes, (attr) => attr.name); return attributes.some((attr) => ['set:html', 'set:text'].includes(attr)); } function shouldHugStart(node, opts) { if (isBlockElement(node, opts)) { return false; } if (node.type === 'fragment') { return false; } if (!isNodeWithChildren(node)) { return false; } const children = node.children; if (children.length === 0) { return true; } const firstChild = children[0]; return !isTextNodeStartingWithWhitespace(firstChild); } function shouldHugEnd(node, opts) { if (isBlockElement(node, opts)) { return false; } if (!isNodeWithChildren(node)) { return false; } const children = node.children; if (children.length === 0) { return true; } const lastChild = children[children.length - 1]; if (isExpressionNode(lastChild)) return true; if (isTagLikeNode(lastChild)) return true; return !isTextNodeEndingWithWhitespace(lastChild); } function canOmitSoftlineBeforeClosingTag(path, opts) { return isLastChildWithinParentBlockElement(path, opts); } function getChildren(node) { return isNodeWithChildren(node) ? node.children : []; } function isLastChildWithinParentBlockElement(path, opts) { const parent = path.getParentNode(); if (!parent || !isBlockElement(parent, opts)) { return false; } const children = getChildren(parent); const lastChild = children[children.length - 1]; return lastChild === path.getNode(); } function trimTextNodeLeft(node) { node.value = node.value && node.value.trimStart(); } function trimTextNodeRight(node) { node.value = node.value && node.value.trimEnd(); } function printClassNames(value) { return value.trim().split(/\s+/).join(' '); } function manualDedent(input) { let minTabSize = Infinity; let result = input; result = result.replace(/\r\n/g, '\n'); let char = ''; for (const line of result.split('\n')) { if (!line) continue; if (line[0] && /^[^\s]/.test(line[0])) { minTabSize = 0; break; } const match = line.match(/^(\s+)\S+/); if (match) { if (match[1] && !char) char = match[1][0]; if (match[1].length < minTabSize) minTabSize = match[1].length; } } if (minTabSize > 0 && Number.isFinite(minTabSize)) { result = result.replace(new RegExp(`^${new Array(minTabSize + 1).join(char)}`, 'gm'), ''); } return { tabSize: minTabSize === Infinity ? 0 : minTabSize, char, result, }; } function isTextNode(node) { return node.type === 'text'; } function isExpressionNode(node) { return node.type === 'expression'; } function isTagLikeNode(node) { return (node.type === 'element' || node.type === 'component' || node.type === 'custom-element' || node.type === 'fragment'); } function getSiblings(path) { const parent = path.getParentNode(); if (!parent) return []; return getChildren(parent); } function getNextNode(path) { var _a, _b, _c, _d; const node = path.getNode(); if (node) { const siblings = getSiblings(path); if (((_a = node.position) === null || _a === void 0 ? void 0 : _a.start) === ((_b = siblings[siblings.length - 1].position) === null || _b === void 0 ? void 0 : _b.start)) return null; for (let i = 0; i < siblings.length; i++) { const sibling = siblings[i]; if (((_c = sibling.position) === null || _c === void 0 ? void 0 : _c.start) === ((_d = node.position) === null || _d === void 0 ? void 0 : _d.start) && i !== siblings.length - 1) { return siblings[i + 1]; } } } return null; } const isPreTagContent = (path) => { if (!path || !path.stack || !Array.isArray(path.stack)) return false; return path.stack.some((node) => (node.type === 'element' && node.name.toLowerCase() === 'pre') || (node.type === 'attribute' && !formattableAttributes.includes(node.name))); }; function getPreferredQuote(rawContent, preferredQuote) { const double = { quote: '"', regex: /"/g, escaped: '"' }; const single = { quote: "'", regex: /'/g, escaped: ''' }; const preferred = preferredQuote === "'" ? single : double; const alternate = preferred === single ? double : single; let result = preferred; if (rawContent.includes(preferred.quote) || rawContent.includes(alternate.quote)) { const numPreferredQuotes = (rawContent.match(preferred.regex) || []).length; const numAlternateQuotes = (rawContent.match(alternate.regex) || []).length; result = numPreferredQuotes > numAlternateQuotes ? alternate : preferred; } return result; } function inferParserByTypeAttribute(type) { if (!type) { return 'babel-ts'; } switch (type) { case 'module': case 'text/javascript': case 'text/babel': case 'application/javascript': return 'babel'; case 'application/x-typescript': return 'babel-ts'; case 'text/markdown': return 'markdown'; case 'text/html': return 'html'; case 'text/x-handlebars-template': return 'glimmer'; default: if (type.endsWith('json') || type.endsWith('importmap') || type === 'speculationrules') { return 'json'; } return 'babel-ts'; } } const { builders: { breakParent, dedent, fill, group: group$1, indent: indent$1, join: join$1, line: line$1, softline: softline$1, hardline: hardline$1, literalline, }, utils: { stripTrailingHardline: stripTrailingHardline$1 }, } = _doc; let ignoreNext = false; function print(path, opts, print) { const node = path.getValue(); if (!node) { return ''; } if (ignoreNext && !isEmptyTextNode(node)) { ignoreNext = false; return [ opts.originalText .slice(opts.locStart(node), opts.locEnd(node)) .split('\n') .map((lineContent, i) => (i == 0 ? [lineContent] : [literalline, lineContent])) .flat(), ]; } if (typeof node === 'string') { return node; } switch (node.type) { case 'root': { return [stripTrailingHardline$1(path.map(print, 'children')), hardline$1]; } case 'text': { const rawText = getUnencodedText(node); if (isEmptyTextNode(node)) { const hasWhiteSpace = rawText.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$1, hardline$1]; } if (hasOneOrMoreNewlines) { return hardline$1; } if (hasWhiteSpace) { return line$1; } return ''; } return fill(splitTextToDocs(node)); } case 'component': case 'fragment': case 'custom-element': case 'element': { let isEmpty; if (!node.children) { isEmpty = true; } else { isEmpty = node.children.every((child) => isEmptyTextNode(child)); } const isSelfClosingTag = isEmpty && (node.type === 'component' || selfClosingTags.includes(node.name) || hasSetDirectives(node)); const isSingleLinePerAttribute = opts.singleAttributePerLine && node.attributes.length > 1; const attributeLine = isSingleLinePerAttribute ? breakParent : ''; const attributes = join$1(attributeLine, path.map(print, 'attributes')); if (isSelfClosingTag) { return group$1(['<', node.name, indent$1(attributes), line$1, `/>`]); } if (node.children) { const children = node.children; const firstChild = children[0]; const lastChild = children[children.length - 1]; let noHugSeparatorStart = softline$1; let noHugSeparatorEnd = softline$1; const hugStart = shouldHugStart(node, opts); const hugEnd = shouldHugEnd(node, opts); let body; if (isEmpty) { body = isInlineElement(path, opts, node) && node.children.length && isTextNodeStartingWithWhitespace(node.children[0]) && !isPreTagContent(path) ? () => line$1 : () => softline$1; } else if (isPreTagContent(path)) { body = () => printRaw(node); } else if (isInlineElement(path, opts, node) && !isPreTagContent(path)) { body = () => path.map(print, 'children'); } else { body = () => path.map(print, 'children'); } const openingTag = [ '<', node.name, indent$1(group$1([ attributes, hugStart ? '' : !isPreTagContent(path) && !opts.bracketSameLine ? dedent(softline$1) : '', ])), ]; if (hugStart && hugEnd) { const huggedContent = [ isSingleLinePerAttribute ? hardline$1 : softline$1, group$1(['>', body(), `', ]); } if (isPreTagContent(path)) { noHugSeparatorStart = ''; noHugSeparatorEnd = ''; } else { let didSetEndSeparator = false; if (!hugStart && firstChild && isTextNode(firstChild)) { if (isTextNodeStartingWithLinebreak(firstChild) && firstChild !== lastChild && (!isInlineElement(path, opts, node) || isTextNodeEndingWithWhitespace(lastChild))) { noHugSeparatorStart = hardline$1; noHugSeparatorEnd = hardline$1; didSetEndSeparator = true; } else if (isInlineElement(path, opts, node)) { noHugSeparatorStart = line$1; } trimTextNodeLeft(firstChild); } if (!hugEnd && lastChild && isTextNode(lastChild)) { if (isInlineElement(path, opts, node) && !didSetEndSeparator) { noHugSeparatorEnd = softline$1; } trimTextNodeRight(lastChild); } } if (hugStart) { return group$1([ ...openingTag, indent$1([softline$1, group$1(['>', body()])]), noHugSeparatorEnd, ``, ]); } if (hugEnd) { return group$1([ ...openingTag, '>', indent$1([noHugSeparatorStart, group$1([body(), `', ]); } if (isEmpty) { return group$1([...openingTag, '>', body(), ``]); } return group$1([ ...openingTag, '>', indent$1([noHugSeparatorStart, body()]), noHugSeparatorEnd, ``, ]); } return ''; } case 'attribute': { const name = node.name.trim(); switch (node.kind) { case 'empty': return [line$1, name]; case 'expression': return ''; case 'quoted': let value = node.value; if (node.name === 'class') { value = printClassNames(value); } const unescapedValue = value.replace(/'/g, "'").replace(/"/g, '"'); const { escaped, quote, regex } = getPreferredQuote(unescapedValue, opts.jsxSingleQuote ? "'" : '"'); const result = unescapedValue.replace(regex, escaped); return [line$1, name, '=', quote, result, quote]; case 'shorthand': return [line$1, '{', name, '}']; case 'spread': return [line$1, '{...', name, '}']; case 'template-literal': return [line$1, name, '=', '`', node.value, '`']; } return ''; } case 'doctype': { return ['', hardline$1]; } case 'comment': if (isIgnoreDirective(node)) { ignoreNext = true; } const nextNode = getNextNode(path); let trailingLine = ''; if (nextNode && isTagLikeNode(nextNode)) { trailingLine = hardline$1; } return ['', trailingLine]; default: { throw new Error(`Unhandled node type "${node.type}"!`); } } } function splitTextToDocs(node) { const text = getUnencodedText(node); const textLines = text.split(/[\t\n\f\r ]+/); let docs = join$1(line$1, textLines).parts.filter((s) => s !== ''); if (startsWithLinebreak(text)) { docs[0] = hardline$1; } if (startsWithLinebreak(text, 2)) { docs = [hardline$1, ...docs]; } if (endsWithLinebreak(text)) { docs[docs.length - 1] = hardline$1; } if (endsWithLinebreak(text, 2)) { docs = [...docs, hardline$1]; } return docs; } const { builders: { group, indent, join, line, softline, hardline, lineSuffixBoundary }, utils: { stripTrailingHardline, mapDoc }, } = _doc; const supportedStyleLangValues = ['css', 'scss', 'sass', 'less']; function embed(path, print, textToDoc, opts) { var _a; const node = path.getValue(); if (!node) return null; if (node.type === 'expression') { const jsxNode = makeNodeJSXCompatible(node); const textContent = printRaw(jsxNode); let content; content = wrapParserTryCatch(textToDoc, textContent, { ...opts, parser: expressionParser, }); content = stripTrailingHardline(content); const strings = []; mapDoc(content, (doc) => { if (typeof doc === 'string') { strings.push(doc); } }); if (strings.every((value) => value.startsWith('//'))) { return group(['{', content, softline, lineSuffixBoundary, '}']); } const astroDoc = mapDoc(content, (doc) => { if (typeof doc === 'string') { doc = doc.replace(openingBracketReplace, '{'); doc = doc.replace(closingBracketReplace, '}'); doc = doc.replace(atSignReplace, '@'); doc = doc.replace(dotReplace, '.'); } return doc; }); return group(['{', indent([softline, astroDoc]), softline, lineSuffixBoundary, '}']); } if (node.type === 'attribute' && node.kind === 'expression') { const value = node.value.trim(); const name = node.name.trim(); const attrNodeValue = wrapParserTryCatch(textToDoc, value, { ...opts, parser: expressionParser, }); if (name === value && opts.astroAllowShorthand) { return [line, '{', attrNodeValue, '}']; } return [line, name, '=', '{', attrNodeValue, '}']; } if (node.type === 'attribute' && node.kind === 'spread') { const spreadContent = wrapParserTryCatch(textToDoc, node.name, { ...opts, parser: expressionParser, }); return [line, '{...', spreadContent, '}']; } if (node.type === 'frontmatter') { const frontmatterContent = wrapParserTryCatch(textToDoc, node.value, { ...opts, parser: 'babel-ts', }); return [group(['---', hardline, frontmatterContent, '---', hardline]), hardline]; } if (node.type === 'element' && node.name === 'script' && node.children.length) { const typeAttribute = (_a = node.attributes.find((attr) => attr.name === 'type')) === null || _a === void 0 ? void 0 : _a.value; let parser = 'babel-ts'; if (typeAttribute) { parser = inferParserByTypeAttribute(typeAttribute); } const scriptContent = printRaw(node); let formattedScript = wrapParserTryCatch(textToDoc, scriptContent, { ...opts, parser: parser, }); formattedScript = stripTrailingHardline(formattedScript); const isEmpty = /^\s*$/.test(scriptContent); const attributes = path.map(print, 'attributes'); const openingTag = group(['']); return [ openingTag, indent([isEmpty ? '' : hardline, formattedScript]), isEmpty ? '' : hardline, '', ]; } if (node.type === 'element' && node.name === 'style') { const content = printRaw(node); let parserLang = 'css'; if (node.attributes) { const langAttribute = node.attributes.filter((x) => x.name === 'lang'); if (langAttribute.length) { const styleLang = langAttribute[0].value.toLowerCase(); parserLang = supportedStyleLangValues.includes(styleLang) ? styleLang : undefined; } } return embedStyle(parserLang, content, path, print, textToDoc, opts); } return null; } function wrapParserTryCatch(cb, text, options) { try { return cb(text, options); } catch (e) { process.env.PRETTIER_DEBUG = 'true'; throw e; } } function expressionParser(text, parsers, options) { const expressionContent = `<>{${text}\n}`; const ast = parsers['babel-ts'](expressionContent, parsers, options); return { ...ast, program: ast.program.body[0].expression.children[0].expression, }; } function makeNodeJSXCompatible(node) { const newNode = { ...node }; const childBundle = []; let childBundleIndex = 0; if (isNodeWithChildren(newNode)) { newNode.children = newNode.children.reduce((result, child, index) => { const previousChildren = newNode.children[index - 1]; const nextChildren = newNode.children[index + 1]; if (isTagLikeNode(child)) { child.attributes = child.attributes.map(makeAttributeJSXCompatible); if (!childBundle[childBundleIndex]) { childBundle[childBundleIndex] = []; } if (isNodeWithChildren(child)) { child = makeNodeJSXCompatible(child); } if ((!previousChildren || isTextNode(previousChildren)) && nextChildren && isTagLikeNode(nextChildren)) { childBundle[childBundleIndex].push(child); return result; } if ((!nextChildren || isTextNode(nextChildren)) && childBundle[childBundleIndex].length > 0) { childBundle[childBundleIndex].push(child); const parentNode = { type: 'fragment', name: '', attributes: [], children: childBundle[childBundleIndex], }; childBundleIndex += 1; result.push(parentNode); return result; } } else { childBundleIndex += 1; } result.push(child); return result; }, []); } return newNode; function makeAttributeJSXCompatible(attr) { if (attr.kind === 'shorthand') { attr.kind = 'empty'; attr.name = openingBracketReplace + attr.name + closingBracketReplace; } if (attr.name.includes('@')) { attr.name = attr.name.replace('@', atSignReplace); } if (attr.name.includes('.')) { attr.name = attr.name.replace('.', dotReplace); } return attr; } } function embedStyle(lang, content, path, print, textToDoc, options) { const isEmpty = /^\s*$/.test(content); switch (lang) { case 'less': case 'css': case 'scss': { let formattedStyles = wrapParserTryCatch(textToDoc, content, { ...options, parser: lang }); formattedStyles = stripTrailingHardline(formattedStyles); const attributes = path.map(print, 'attributes'); const openingTag = group(['']); return [ openingTag, indent([isEmpty ? '' : hardline, formattedStyles]), isEmpty ? '' : hardline, '', ]; } case 'sass': { const lineEnding = options.endOfLine.toUpperCase() === 'CRLF' ? 'CRLF' : 'LF'; const sassOptions = { tabSize: options.tabWidth, insertSpaces: !options.useTabs, lineEnding, }; const { result: raw } = manualDedent(content); const formattedSassIndented = sassFormatter.SassFormatter.Format(raw, sassOptions).trim(); const formattedSass = join(hardline, formattedSassIndented.split('\n')); const attributes = path.map(print, 'attributes'); const openingTag = group(['']); return [ openingTag, indent([isEmpty ? '' : hardline, formattedSass]), isEmpty ? '' : hardline, '', ]; } case undefined: { const node = path.getNode(); if (node) { return node_buffer.Buffer.from(options.originalText) .subarray(options.locStart(node), options.locEnd(node)) .toString(); } return null; } } } const req = node_module.createRequire((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('index.js', document.baseURI).href))); let workerPath; try { workerPath = req.resolve('../workers/parse-worker.js'); } catch (e) { workerPath = req.resolve('prettier-plugin-astro/workers/parse-worker.js'); } const parse = synckit.createSyncFn(req.resolve(workerPath)); const languages = [ { name: 'astro', parsers: ['astro'], extensions: ['.astro'], vscodeLanguageIds: ['astro'], }, ]; const parsers = { astro: { parse: (source) => parse(source), astFormat: 'astro', locStart: (node) => node.position.start.offset, locEnd: (node) => node.position.end.offset, }, }; const printers = { astro: { print, embed, }, }; const defaultOptions = { tabWidth: 2, }; exports.defaultOptions = defaultOptions; exports.languages = languages; exports.options = options; exports.parsers = parsers; exports.printers = printers; //# sourceMappingURL=index.js.map