import { type Parser, type ParserOptions, resolveConfigFile } from "prettier"; import type { FormatterOption } from "blade-formatter"; import { Formatter } from "blade-formatter"; import path from "node:path"; import { parsePhpVersion } from "./options"; /** * Parses the given Blade template text using the provided options and returns the formatted result. * @param text The Blade template text to parse and format. * @param parsers An object containing parsers to use for parsing the template. * @param opts The options to use for formatting the template. * @returns An object containing the formatted result, along with metadata about the original text. */ export const parse = async ( text: string, parsers: { [parserName: string]: Parser }, opts: ParserOptions & FormatterOption, ) => { const phpVersion = parsePhpVersion(opts.phpVersion); const formatterOptions: FormatterOption = { indentSize: opts.tabWidth, wrapLineLength: opts.printWidth, wrapAttributes: opts.singleAttributePerLine ? "force-expand-multiline" : opts.bracketSameLine ? "force-aligned" : opts.wrapAttributes, wrapAttributesMinAttrs: opts.wrapAttributesMinAttrs, endWithNewline: opts.endWithNewline, useTabs: opts.useTabs, sortTailwindcssClasses: opts.sortTailwindcssClasses, tailwindcssConfigPath: await resolveTailwindConfigPath( opts.filepath, opts.tailwindcssConfigPath, ), sortHtmlAttributes: opts.sortHtmlAttributes, noMultipleEmptyLines: true, noPhpSyntaxCheck: opts.noPhpSyntaxCheck, noSingleQuote: !opts.singleQuote, noTrailingCommaPhp: phpVersion < 7.2 || !opts.trailingCommaPHP, customHtmlAttributesOrder: opts.customHtmlAttributesOrder, indentInnerHtml: opts.indentInnerHtml, componentPrefix: opts.componentPrefix?.split(","), // @ts-ignore extraLiners: opts.extraLiners.split(","), phpVersion: opts.phpVersion || "auto", }; const result = await new Formatter(formatterOptions).formatContent(text); return { type: "blade-formatter", body: result, end: text.length, source: text, start: 0, }; }; /** * Resolves the path to the Tailwind CSS configuration file, if one is specified. * @param filepath The path to the Blade template file being formatted. * @param optionPath The path to the Tailwind CSS configuration file, as specified in the formatting options. * @returns The resolved path to the Tailwind CSS configuration file, or undefined if no path was specified. */ async function resolveTailwindConfigPath( filepath: string | undefined, optionPath: string | undefined, ): Promise { if (!optionPath) { return; } if (path.isAbsolute(optionPath ?? "")) { return optionPath; } const prettierRcPath = await resolveConfigFile(filepath); return path.resolve(path.dirname(prettierRcPath ?? ""), optionPath ?? ""); }