Skip to content

Commit 471e568

Browse files
authored
fix: allow additional properties in CSSLanguageOptions (#538)
* fix: allow additional properties in `CSSLanguageOptions` * wip * wip
1 parent 0658aa0 commit 471e568

4 files changed

Lines changed: 109 additions & 18 deletions

File tree

‎src/languages/css-language.js‎

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,11 @@ import { visitorKeys } from "./css-visitor-keys.js";
2525
/**
2626
* @import { CssNodePlain, Comment, Lexer, StyleSheetPlain, SyntaxConfig } from "@eslint/css-tree"
2727
* @import { Language, OkParseResult, ParseResult, File, FileError } from "@eslint/core";
28+
* @import { CSSLanguageOptions } from "../types.js";
2829
*/
2930

3031
/** @typedef {OkParseResult<StyleSheetPlain> & { comments: Comment[], lexer: Lexer }} CSSOkParseResult */
3132
/** @typedef {ParseResult<StyleSheetPlain>} CSSParseResult */
32-
/**
33-
* DefaultSyntaxConfig type representing the structure returned by `@eslint/css-tree/definition-syntax-data`.
34-
* This type is defined inline because it's not exported from the main `@eslint/css-tree` package.
35-
* @typedef {Pick<SyntaxConfig, "atrules" | "types" | "properties">} DefaultSyntaxConfig
36-
*/
37-
/**
38-
* @typedef {(defaultSyntax: DefaultSyntaxConfig) => Partial<SyntaxConfig>} SyntaxExtensionCallback
39-
*/
40-
/**
41-
* @typedef {Object} CSSLanguageOptions
42-
* @property {boolean} [tolerant] Whether to be tolerant of recoverable parsing errors.
43-
* @property {Partial<SyntaxConfig> | SyntaxExtensionCallback} [customSyntax] Custom syntax to use for parsing.
44-
*/
4533

4634
//-----------------------------------------------------------------------------
4735
// Helpers

‎src/languages/css-source-code.js‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ import { visitorKeys } from "./css-visitor-keys.js";
2222
/**
2323
* @import { CssNode, CssNodePlain, CssLocationRange, Comment, Lexer, StyleSheetPlain } from "@eslint/css-tree"
2424
* @import { SourceRange, FileProblem, DirectiveType, RulesConfig } from "@eslint/core"
25-
* @import { CSSSyntaxElement } from "../types.js"
26-
* @import { CSSLanguageOptions } from "./css-language.js"
25+
* @import { CSSLanguageOptions, CSSSyntaxElement } from "../types.js"
2726
*/
2827

2928
//-----------------------------------------------------------------------------

‎src/types.ts‎

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,52 @@
77
// Imports
88
//------------------------------------------------------------------------------
99

10-
import type { RuleVisitor } from "@eslint/core";
11-
import type { CssNodePlain, StyleSheetPlain } from "@eslint/css-tree";
10+
import type { LanguageOptions, RuleVisitor } from "@eslint/core";
11+
import type { DefaultSyntaxConfig as CSSTreeDefaultSyntaxConfig } from "@eslint/css-tree/definition-syntax-data";
12+
import type {
13+
CssNodePlain,
14+
StyleSheetPlain,
15+
SyntaxConfig,
16+
} from "@eslint/css-tree";
1217
import type {
1318
CustomRuleDefinitionType,
1419
CustomRuleTypeDefinitions,
1520
CustomRuleVisitorWithExit,
1621
} from "@eslint/plugin-kit";
17-
import type { CSSLanguageOptions, CSSSourceCode } from "./index.js";
22+
import type { CSSSourceCode } from "./index.js";
1823

1924
//------------------------------------------------------------------------------
2025
// Types
2126
//------------------------------------------------------------------------------
2227

28+
/**
29+
* Default syntax configuration representing the structure returned by `@eslint/css-tree/definition-syntax-data`.
30+
*/
31+
export type DefaultSyntaxConfig = CSSTreeDefaultSyntaxConfig;
32+
33+
/**
34+
* A callback used to extend the default CSS syntax configuration.
35+
*/
36+
export type SyntaxExtensionCallback = (
37+
defaultSyntax: DefaultSyntaxConfig,
38+
) => Partial<SyntaxConfig>;
39+
40+
/**
41+
* Language options provided for CSS files.
42+
*/
43+
export interface CSSLanguageOptions extends LanguageOptions {
44+
/**
45+
* Whether to be tolerant of recoverable parsing errors.
46+
* @default false
47+
*/
48+
tolerant?: boolean;
49+
50+
/**
51+
* Custom syntax to use for parsing.
52+
*/
53+
customSyntax?: Partial<SyntaxConfig> | SyntaxExtensionCallback;
54+
}
55+
2356
/**
2457
* A CSS syntax element, including nodes and comments.
2558
*/

‎tests/types/types.test.ts‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import css from "@eslint/css";
22
import type {
3+
CSSLanguageOptions,
34
CSSRuleDefinition,
45
CSSRuleVisitor,
56
CSSSourceCode,
7+
DefaultSyntaxConfig,
8+
SyntaxExtensionCallback,
69
} from "@eslint/css";
710
import type { Plugin, SourceLocation, SourceRange } from "@eslint/core";
811
import type { ESLint } from "eslint";
@@ -76,6 +79,74 @@ css.rules[ruleName] satisfies CSSRuleDefinition;
7679
// Check that `plugins` in the recommended config is defined:
7780
css.configs.recommended.plugins satisfies object;
7881

82+
const validLanguageOptions1: CSSLanguageOptions = {};
83+
const validLanguageOptions2: CSSLanguageOptions = {
84+
tolerant: true,
85+
};
86+
const validLanguageOptions3: CSSLanguageOptions = {
87+
tolerant: false,
88+
};
89+
const validLanguageOptions4: CSSLanguageOptions = {
90+
customSyntax: {
91+
atrules: {},
92+
properties: {},
93+
types: {},
94+
},
95+
};
96+
const validLanguageOptions5: CSSLanguageOptions = {
97+
customSyntax: defaultSyntax => {
98+
defaultSyntax satisfies DefaultSyntaxConfig;
99+
100+
return {
101+
properties: {
102+
foo: "<ident>",
103+
},
104+
};
105+
},
106+
};
107+
const validLanguageOptions6: CSSLanguageOptions = {
108+
tolerant: true,
109+
unknownOption: "unknown",
110+
};
111+
112+
const invalidLanguageOptions1: CSSLanguageOptions = {
113+
// @ts-expect-error -- Invalid value for `tolerant`
114+
tolerant: "true",
115+
};
116+
const invalidLanguageOptions2: CSSLanguageOptions = {
117+
// @ts-expect-error -- Invalid value for `customSyntax`
118+
customSyntax: "invalid",
119+
};
120+
121+
const defaultSyntaxConfig: DefaultSyntaxConfig = {
122+
atrules: {},
123+
types: {},
124+
properties: {},
125+
};
126+
127+
// @ts-expect-error -- Default syntax configuration requires `properties`.
128+
const invalidDefaultSyntaxConfig: DefaultSyntaxConfig = {
129+
atrules: {},
130+
types: {},
131+
};
132+
133+
const syntaxExtensionCallback: SyntaxExtensionCallback = defaultSyntax => {
134+
defaultSyntax satisfies DefaultSyntaxConfig;
135+
136+
return {
137+
properties: {
138+
foo: "<ident>",
139+
},
140+
};
141+
};
142+
143+
const invalidSyntaxExtensionCallback: SyntaxExtensionCallback = () => ({
144+
properties: {
145+
// @ts-expect-error -- CSS property syntax definitions must be strings.
146+
foo: 1,
147+
},
148+
});
149+
79150
{
80151
type RecommendedRuleName = keyof typeof css.configs.recommended.rules;
81152
type RuleName = `css/${keyof typeof css.rules}`;

0 commit comments

Comments
 (0)