diff --git a/.changeset/long-cats-laugh.md b/.changeset/long-cats-laugh.md new file mode 100644 index 0000000..93d39c9 --- /dev/null +++ b/.changeset/long-cats-laugh.md @@ -0,0 +1,5 @@ +--- +'prettier-plugin-astro': patch +--- + +Correctly pass options to embedded parsers diff --git a/src/printer/embed.ts b/src/printer/embed.ts index 0ae5c56..75572eb 100644 --- a/src/printer/embed.ts +++ b/src/printer/embed.ts @@ -219,7 +219,11 @@ function forceIntoExpression(statement: string) { } function expressionParser(text: string, parsers: BuiltInParsers, options: ParserOptions) { - const ast = parsers['babel-ts'](text, options); + // @ts-ignore + // The type `RequiredOptions['parser]` is wrong. It uses `BuiltInParsers` as the type for the 2nd argument. + // However, the parsers produced by `getParsers()` include ALL registered parsers, not just the built-in ones. + // And the type of the built-in parsers and custom parsers all take (text[, parsers[, options]]) as arguments. + const ast = parsers['babel-ts'](text, parsers, options); return { ...ast, diff --git a/test/fixtures/other/embedded-expr-options/custom-plugin.js b/test/fixtures/other/embedded-expr-options/custom-plugin.js new file mode 100644 index 0000000..20f89e8 --- /dev/null +++ b/test/fixtures/other/embedded-expr-options/custom-plugin.js @@ -0,0 +1,59 @@ +let prettierParserBabel = require('prettier/parser-babel'); + +module.exports.options = { + customPluginClass: { + since: '1.0.0', + category: 'foo', + type: 'string', + default: 'my-default-class', + description: 'Replace all classes with this one.', + }, +}; + +let original = prettierParserBabel.parsers['babel-ts']; + +/** @type {Record>} */ +module.exports.parsers = { + 'babel-ts': { + parse(text, parsers, options) { + let ast = original.parse(text, parsers, options); + + let nodes = [ast.program]; + while (nodes.length) { + let node = nodes.shift(); + switch (node.type) { + case 'Program': + nodes.push(...node.body); + break; + case 'ExpressionStatement': + nodes.push(node.expression); + break; + case 'JSXExpressionContainer': + nodes.push(node.expression); + break; + case 'JSXFragment': + nodes.push(...node.children); + break; + case 'JSXElement': + nodes.push(node.openingElement); + nodes.push(...node.children); + break; + case 'JSXOpeningElement': + nodes.push(...node.attributes); + break; + case 'JSXAttribute': + if (node.name && node.name.type === 'JSXIdentifier' && node.name.name === 'class') { + node.value.value = `${options.customPluginClass}`; + node.value.extra = { + rawValue: node.value.value, + raw: `"${node.value.value}"`, + }; + } + break; + } + } + + return ast; + }, + }, +}; diff --git a/test/fixtures/other/embedded-expr-options/input.astro b/test/fixtures/other/embedded-expr-options/input.astro new file mode 100644 index 0000000..54046ba --- /dev/null +++ b/test/fixtures/other/embedded-expr-options/input.astro @@ -0,0 +1,5 @@ +
+ { +
+ } +
diff --git a/test/fixtures/other/embedded-expr-options/options.js b/test/fixtures/other/embedded-expr-options/options.js new file mode 100644 index 0000000..21b4732 --- /dev/null +++ b/test/fixtures/other/embedded-expr-options/options.js @@ -0,0 +1,4 @@ +module.exports = { + plugins: [require.resolve('../../../../'), require.resolve('./custom-plugin.js')], + customPluginClass: 'my-custom-class', +}; diff --git a/test/fixtures/other/embedded-expr-options/output.astro b/test/fixtures/other/embedded-expr-options/output.astro new file mode 100644 index 0000000..3dfc2d7 --- /dev/null +++ b/test/fixtures/other/embedded-expr-options/output.astro @@ -0,0 +1,3 @@ +
+ {(
)} +
diff --git a/test/test-utils.ts b/test/test-utils.ts index fc4b23f..edf534c 100644 --- a/test/test-utils.ts +++ b/test/test-utils.ts @@ -55,6 +55,10 @@ function getFiles(file: any, path: string, isMarkdown = false) { } function getOptions(files: any, path: string) { + if (files[`/test/fixtures/${path}/options.js`] !== undefined) { + return files[`/test/fixtures/${path}/options.js`].default; + } + let opts: object; try { opts = JSON.parse(files[`/test/fixtures/${path}/options.json`]); diff --git a/test/tests/other.test.ts b/test/tests/other.test.ts index 1abec12..68e0eed 100644 --- a/test/tests/other.test.ts +++ b/test/tests/other.test.ts @@ -1,13 +1,23 @@ import { test } from '../test-utils'; -const files = import.meta.glob('/test/fixtures/other/*/*', { - eager: true, - as: 'raw', -}); +const files = { + ...import.meta.glob('/test/fixtures/other/*/*', { + eager: true, + as: 'raw', + }), + ...import.meta.glob('/test/fixtures/other/*/*.js', { + eager: true, + }), +}; test('Can format an Astro file with frontmatter', files, 'other/frontmatter'); test('Can format an Astro file with embedded JSX expressions', files, 'other/embedded-expr'); +test( + 'Options are passed to other Prettier Plugins when parsing embedded JSX expressions', + files, + 'other/embedded-expr-options' +); test( 'Can format an Astro file with a `` + embedded JSX expressions',