Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/chubby-donkeys-remain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"stylelint": patch
---

Support `customSyntax` with function export
2 changes: 1 addition & 1 deletion docs/user-guide/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ This option should be a string that resolves to a JS module that exports a [Post

If you want to lint two or more different languages, you can combine `customSyntax` with the [`overrides`](./configure.md#overrides) configuration property.

Using the Node.js API, the `customSyntax` option can also accept a [Syntax object](https://postcss.org/docs/how-to-write-custom-syntax#syntax). Stylelint treats the `parse` property as a required value. Also, Stylelint supports syntax modules written in ESM.
Using the Node.js API, the `customSyntax` option can also accept a [Syntax object](https://postcss.org/docs/how-to-write-custom-syntax#syntax) or a function with those properties. Stylelint treats the `parse` property as a required value. Also, Stylelint supports syntax modules written in ESM.

> [!NOTE]
> Stylelint can provide no guarantee that core rules work with custom syntaxes.
Expand Down
13 changes: 13 additions & 0 deletions lib/__tests__/standalone-syntax.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,19 @@ it('standalone with custom syntax as npm package', async () => {
expect(results[0].warnings[0]).toMatchObject({ line: 2, column: 3, rule: 'block-no-empty' });
});

it('standalone with custom syntax as npm package and function export', async () => {
const { results } = await standalone({
config: config(),
customSyntax: (await import('postcss-html')).default,
code: '<style>foo {}</style>',
formatter: stringFormatter,
});

expect(results).toHaveLength(1);
expect(results[0].warnings).toHaveLength(1);
expect(results[0].warnings[0]).toMatchObject({ line: 1, column: 12, rule: 'block-no-empty' });
});

it('rejects on unknown custom syntax option', async () => {
await expect(
standalone({
Expand Down
4 changes: 2 additions & 2 deletions lib/getPostcssResult.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ async function getCustomSyntax(customSyntax, basedir) {
return resolved;
}

if (typeof customSyntax === 'object') {
if (typeof customSyntax === 'object' || typeof customSyntax === 'function') {
if (typeof customSyntax.parse === 'function') {
return { ...customSyntax };
}
Expand All @@ -114,7 +114,7 @@ async function getCustomSyntax(customSyntax, basedir) {
);
}

throw new Error('Custom syntax must be a string or a Syntax object');
throw new Error('Custom syntax must be a string, Syntax object or Syntax function');
}

/**
Expand Down