diff --git a/.changeset/tame-boxes-shop.md b/.changeset/tame-boxes-shop.md new file mode 100644 index 00000000..78d79492 --- /dev/null +++ b/.changeset/tame-boxes-shop.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-jsonc": minor +--- + +refactor: hourcekeeping, bump all (dev) deps, stricter rule `options` typings diff --git a/docs/.vitepress/theme/components/components/EslintPluginEditor.vue b/docs/.vitepress/theme/components/components/EslintPluginEditor.vue index 8fbbde84..41743821 100644 --- a/docs/.vitepress/theme/components/components/EslintPluginEditor.vue +++ b/docs/.vitepress/theme/components/components/EslintPluginEditor.vue @@ -24,9 +24,6 @@ import { rules } from "../../../../../lib/utils/rules"; export default { name: "EslintPluginEditor", components: { EslintEditor }, - model: { - prop: "code", - }, props: { code: { type: String, diff --git a/eslint.config.mjs b/eslint.config.mjs index b7052572..bc0f2ae9 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,4 +1,5 @@ import myPlugin from "@ota-meshi/eslint-plugin"; +import globals from "globals"; export default [ { @@ -145,6 +146,7 @@ export default [ files: ["docs/.vitepress/**/*.{js,mjs,ts,mts,vue}"], languageOptions: { sourceType: "module", + globals: globals.browser, }, rules: { "eslint-plugin/require-meta-docs-description": "off", diff --git a/lib/rules/array-bracket-newline.ts b/lib/rules/array-bracket-newline.ts index b85749b0..38be2861 100644 --- a/lib/rules/array-bracket-newline.ts +++ b/lib/rules/array-bracket-newline.ts @@ -5,13 +5,10 @@ import { createRule } from "../utils"; import { isTokenOnSameLine } from "../utils/eslint-ast-utils"; import type { Token } from "../types"; import { isCommentToken } from "@eslint-community/eslint-utils"; -type Schema0 = +export type RuleOptions = | ("always" | "never" | "consistent") - | { - multiline?: boolean; - minItems?: number | null; - }; -export default createRule("array-bracket-newline", { + | { multiline?: boolean; minItems?: number | null }; +export default createRule<[RuleOptions]>("array-bracket-newline", { meta: { docs: { description: @@ -66,7 +63,7 @@ export default createRule("array-bracket-newline", { * @param option An option value to parse. * @returns Normalized option object. */ - function normalizeOptionValue(option: Schema0) { + function normalizeOptionValue(option: RuleOptions) { let consistent = false; let multiline = false; let minItems = 0; @@ -100,7 +97,7 @@ export default createRule("array-bracket-newline", { * @param options An option value to parse. * @returns Normalized option object. */ - function normalizeOptions(options: Schema0) { + function normalizeOptions(options: RuleOptions) { const value = normalizeOptionValue(options); return { JSONArrayExpression: value, JSONArrayPattern: value }; diff --git a/lib/rules/array-bracket-spacing.ts b/lib/rules/array-bracket-spacing.ts index 27340531..76f5c984 100644 --- a/lib/rules/array-bracket-spacing.ts +++ b/lib/rules/array-bracket-spacing.ts @@ -5,235 +5,245 @@ import { createRule } from "../utils"; import { isTokenOnSameLine } from "../utils/eslint-ast-utils"; import type { Token } from "../types"; -export default createRule("array-bracket-spacing", { - meta: { - docs: { - description: "disallow or enforce spaces inside of brackets", - recommended: null, - extensionRule: true, - layout: true, - }, - type: "layout", +export interface RuleOptions { + singleValue?: boolean; + objectsInArrays?: boolean; + arraysInArrays?: boolean; +} + +export default createRule<["always" | "never", RuleOptions]>( + "array-bracket-spacing", + { + meta: { + docs: { + description: "disallow or enforce spaces inside of brackets", + recommended: null, + extensionRule: true, + layout: true, + }, + type: "layout", - fixable: "whitespace", + fixable: "whitespace", - schema: [ - { - type: "string", - enum: ["always", "never"], - }, - { - type: "object", - properties: { - singleValue: { - type: "boolean", - }, - objectsInArrays: { - type: "boolean", - }, - arraysInArrays: { - type: "boolean", + schema: [ + { + type: "string", + enum: ["always", "never"], + }, + { + type: "object", + properties: { + singleValue: { + type: "boolean", + }, + objectsInArrays: { + type: "boolean", + }, + arraysInArrays: { + type: "boolean", + }, }, + additionalProperties: false, }, - additionalProperties: false, + ], + + messages: { + unexpectedSpaceAfter: + "There should be no space after '{{tokenValue}}'.", + unexpectedSpaceBefore: + "There should be no space before '{{tokenValue}}'.", + missingSpaceAfter: "A space is required after '{{tokenValue}}'.", + missingSpaceBefore: "A space is required before '{{tokenValue}}'.", }, - ], - - messages: { - unexpectedSpaceAfter: "There should be no space after '{{tokenValue}}'.", - unexpectedSpaceBefore: - "There should be no space before '{{tokenValue}}'.", - missingSpaceAfter: "A space is required after '{{tokenValue}}'.", - missingSpaceBefore: "A space is required before '{{tokenValue}}'.", }, - }, - create(context) { - const sourceCode = context.sourceCode; - if (!sourceCode.parserServices.isJSON) { - return {}; - } - const spaced = context.options[0] === "always"; - interface Schema1 { - singleValue?: boolean; - objectsInArrays?: boolean; - arraysInArrays?: boolean; - } - - /** - * Determines whether an option is set, relative to the spacing option. - * If spaced is "always", then check whether option is set to false. - * If spaced is "never", then check whether option is set to true. - * @param option The option to exclude. - * @returns Whether or not the property is excluded. - */ - function isOptionSet(option: keyof NonNullable) { - return context.options[1] - ? context.options[1][option] === !spaced - : false; - } - - const options = { - spaced, - singleElementException: isOptionSet("singleValue"), - objectsInArraysException: isOptionSet("objectsInArrays"), - arraysInArraysException: isOptionSet("arraysInArrays"), - isOpeningBracketMustBeSpaced(node: AST.JSONArrayExpression) { - if (options.singleElementException && node.elements.length === 1) { - return !options.spaced; - } - const firstElement = node.elements[0]; - return firstElement && - ((options.objectsInArraysException && isObjectType(firstElement)) || - (options.arraysInArraysException && isArrayType(firstElement))) - ? !options.spaced - : options.spaced; - }, - isClosingBracketMustBeSpaced(node: AST.JSONArrayExpression) { - if (options.singleElementException && node.elements.length === 1) { - return !options.spaced; - } - const lastElement = node.elements[node.elements.length - 1]; - return lastElement && - ((options.objectsInArraysException && isObjectType(lastElement)) || - (options.arraysInArraysException && isArrayType(lastElement))) - ? !options.spaced - : options.spaced; - }, - }; - - /** - * Reports that there shouldn't be a space after the first token - * @param node The node to report in the event of an error. - * @param token The token to use for the report. - */ - function reportNoBeginningSpace(node: AST.JSONNode, token: Token) { - const nextToken = sourceCode.getTokenAfter(token)!; - - context.report({ - node: node as any, - loc: { start: token.loc.end, end: nextToken.loc.start }, - messageId: "unexpectedSpaceAfter", - data: { - tokenValue: token.value, - }, - fix(fixer) { - return fixer.removeRange([token.range[1], nextToken.range[0]]); - }, - }); - } - - /** - * Reports that there shouldn't be a space before the last token - * @param node The node to report in the event of an error. - * @param token The token to use for the report. - */ - function reportNoEndingSpace(node: AST.JSONNode, token: Token) { - const previousToken = sourceCode.getTokenBefore(token)!; - - context.report({ - node: node as any, - loc: { start: previousToken.loc.end, end: token.loc.start }, - messageId: "unexpectedSpaceBefore", - data: { - tokenValue: token.value, - }, - fix(fixer) { - return fixer.removeRange([previousToken.range[1], token.range[0]]); - }, - }); - } - - /** - * Reports that there should be a space after the first token - * @param node The node to report in the event of an error. - * @param token The token to use for the report. - */ - function reportRequiredBeginningSpace(node: AST.JSONNode, token: Token) { - context.report({ - node: node as any, - loc: token.loc, - messageId: "missingSpaceAfter", - data: { - tokenValue: token.value, - }, - fix(fixer) { - return fixer.insertTextAfter(token, " "); - }, - }); - } - - /** - * Reports that there should be a space before the last token - * @param node The node to report in the event of an error. - * @param token The token to use for the report. - */ - function reportRequiredEndingSpace(node: AST.JSONNode, token: Token) { - context.report({ - node: node as any, - loc: token.loc, - messageId: "missingSpaceBefore", - data: { - tokenValue: token.value, + create(context) { + const sourceCode = context.sourceCode; + if (!sourceCode.parserServices.isJSON) { + return {}; + } + const spaced = context.options[0] === "always"; + interface Schema1 { + singleValue?: boolean; + objectsInArrays?: boolean; + arraysInArrays?: boolean; + } + + /** + * Determines whether an option is set, relative to the spacing option. + * If spaced is "always", then check whether option is set to false. + * If spaced is "never", then check whether option is set to true. + * @param option The option to exclude. + * @returns Whether or not the property is excluded. + */ + function isOptionSet(option: keyof NonNullable) { + return context.options[1] + ? context.options[1][option] === !spaced + : false; + } + + const options = { + spaced, + singleElementException: isOptionSet("singleValue"), + objectsInArraysException: isOptionSet("objectsInArrays"), + arraysInArraysException: isOptionSet("arraysInArrays"), + isOpeningBracketMustBeSpaced(node: AST.JSONArrayExpression) { + if (options.singleElementException && node.elements.length === 1) { + return !options.spaced; + } + const firstElement = node.elements[0]; + return firstElement && + ((options.objectsInArraysException && isObjectType(firstElement)) || + (options.arraysInArraysException && isArrayType(firstElement))) + ? !options.spaced + : options.spaced; }, - fix(fixer) { - return fixer.insertTextBefore(token, " "); + isClosingBracketMustBeSpaced(node: AST.JSONArrayExpression) { + if (options.singleElementException && node.elements.length === 1) { + return !options.spaced; + } + const lastElement = node.elements[node.elements.length - 1]; + return lastElement && + ((options.objectsInArraysException && isObjectType(lastElement)) || + (options.arraysInArraysException && isArrayType(lastElement))) + ? !options.spaced + : options.spaced; }, - }); - } - - /** - * Determines if a node is an object type - * @param node The node to check. - * @returns Whether or not the node is an object type. - */ - function isObjectType(node: AST.JSONNode) { - return node && node.type === "JSONObjectExpression"; - } - - /** - * Determines if a node is an array type - * @param node The node to check. - * @returns Whether or not the node is an array type. - */ - function isArrayType(node: AST.JSONNode) { - return node && node.type === "JSONArrayExpression"; - } - - /** - * Validates the spacing around array brackets - * @param node The node we're checking for spacing - */ - function validateArraySpacing(node: AST.JSONArrayExpression) { - if (options.spaced && node.elements.length === 0) return; - - const first = sourceCode.getFirstToken(node as any)!; - const second = sourceCode.getFirstToken(node as any, 1)!; - const last = sourceCode.getLastToken(node as any)!; - const penultimate = sourceCode.getTokenBefore(last)!; - - if (isTokenOnSameLine(first, second)) { - if (options.isOpeningBracketMustBeSpaced(node)) { - if (!sourceCode.isSpaceBetween(first, second)) - reportRequiredBeginningSpace(node, first); - } else { - if (sourceCode.isSpaceBetween(first, second)) - reportNoBeginningSpace(node, first); - } + }; + + /** + * Reports that there shouldn't be a space after the first token + * @param node The node to report in the event of an error. + * @param token The token to use for the report. + */ + function reportNoBeginningSpace(node: AST.JSONNode, token: Token) { + const nextToken = sourceCode.getTokenAfter(token)!; + + context.report({ + node: node as any, + loc: { start: token.loc.end, end: nextToken.loc.start }, + messageId: "unexpectedSpaceAfter", + data: { + tokenValue: token.value, + }, + fix(fixer) { + return fixer.removeRange([token.range[1], nextToken.range[0]]); + }, + }); + } + + /** + * Reports that there shouldn't be a space before the last token + * @param node The node to report in the event of an error. + * @param token The token to use for the report. + */ + function reportNoEndingSpace(node: AST.JSONNode, token: Token) { + const previousToken = sourceCode.getTokenBefore(token)!; + + context.report({ + node: node as any, + loc: { start: previousToken.loc.end, end: token.loc.start }, + messageId: "unexpectedSpaceBefore", + data: { + tokenValue: token.value, + }, + fix(fixer) { + return fixer.removeRange([previousToken.range[1], token.range[0]]); + }, + }); + } + + /** + * Reports that there should be a space after the first token + * @param node The node to report in the event of an error. + * @param token The token to use for the report. + */ + function reportRequiredBeginningSpace(node: AST.JSONNode, token: Token) { + context.report({ + node: node as any, + loc: token.loc, + messageId: "missingSpaceAfter", + data: { + tokenValue: token.value, + }, + fix(fixer) { + return fixer.insertTextAfter(token, " "); + }, + }); } - if (first !== penultimate && isTokenOnSameLine(penultimate, last)) { - if (options.isClosingBracketMustBeSpaced(node)) { - if (!sourceCode.isSpaceBetween(penultimate, last)) - reportRequiredEndingSpace(node, last); - } else { - if (sourceCode.isSpaceBetween(penultimate, last)) - reportNoEndingSpace(node, last); + /** + * Reports that there should be a space before the last token + * @param node The node to report in the event of an error. + * @param token The token to use for the report. + */ + function reportRequiredEndingSpace(node: AST.JSONNode, token: Token) { + context.report({ + node: node as any, + loc: token.loc, + messageId: "missingSpaceBefore", + data: { + tokenValue: token.value, + }, + fix(fixer) { + return fixer.insertTextBefore(token, " "); + }, + }); + } + + /** + * Determines if a node is an object type + * @param node The node to check. + * @returns Whether or not the node is an object type. + */ + function isObjectType(node: AST.JSONNode) { + return node && node.type === "JSONObjectExpression"; + } + + /** + * Determines if a node is an array type + * @param node The node to check. + * @returns Whether or not the node is an array type. + */ + function isArrayType(node: AST.JSONNode) { + return node && node.type === "JSONArrayExpression"; + } + + /** + * Validates the spacing around array brackets + * @param node The node we're checking for spacing + */ + function validateArraySpacing(node: AST.JSONArrayExpression) { + if (options.spaced && node.elements.length === 0) return; + + const first = sourceCode.getFirstToken(node as any)!; + const second = sourceCode.getFirstToken(node as any, 1)!; + const last = sourceCode.getLastToken(node as any)!; + const penultimate = sourceCode.getTokenBefore(last)!; + + if (isTokenOnSameLine(first, second)) { + if (options.isOpeningBracketMustBeSpaced(node)) { + if (!sourceCode.isSpaceBetween(first, second)) + reportRequiredBeginningSpace(node, first); + } else { + if (sourceCode.isSpaceBetween(first, second)) + reportNoBeginningSpace(node, first); + } + } + + if (first !== penultimate && isTokenOnSameLine(penultimate, last)) { + if (options.isClosingBracketMustBeSpaced(node)) { + if (!sourceCode.isSpaceBetween(penultimate, last)) + reportRequiredEndingSpace(node, last); + } else { + if (sourceCode.isSpaceBetween(penultimate, last)) + reportNoEndingSpace(node, last); + } } } - } - return { - JSONArrayExpression: validateArraySpacing, - }; + return { + JSONArrayExpression: validateArraySpacing, + }; + }, }, -}); +); diff --git a/lib/rules/array-element-newline.ts b/lib/rules/array-element-newline.ts index 17147b3c..3006d837 100644 --- a/lib/rules/array-element-newline.ts +++ b/lib/rules/array-element-newline.ts @@ -12,7 +12,7 @@ type BasicConfig = multiline?: boolean; minItems?: number | null; }; -export default createRule("array-element-newline", { +export default createRule<[BasicConfig]>("array-element-newline", { meta: { docs: { description: "enforce line breaks between array elements", diff --git a/lib/rules/comma-dangle.ts b/lib/rules/comma-dangle.ts index ab8d9f89..9da271bb 100644 --- a/lib/rules/comma-dangle.ts +++ b/lib/rules/comma-dangle.ts @@ -13,13 +13,30 @@ const DEFAULT_OPTIONS = Object.freeze({ const closeBraces = ["}", "]", ")", ">"]; +export type RuleValueOption = + | "always-multiline" + | "always" + | "never" + | "only-multiline"; +export type RuleValueWithIgnoreOption = RuleValueOption | "ignore"; + +export interface RuleOptions { + arrays?: RuleValueWithIgnoreOption; + objects?: RuleValueWithIgnoreOption; + imports?: RuleValueWithIgnoreOption; + exports?: RuleValueWithIgnoreOption; + functions?: RuleValueWithIgnoreOption; +} + /** * Normalize option value. * @param optionValue The 1st option value to normalize. * @param ecmaVersion The normalized ECMAScript version. * @returns The normalized option value. */ -function normalizeOptions(optionValue: any) { +function normalizeOptions( + optionValue: RuleValueWithIgnoreOption | RuleOptions, +) { if (typeof optionValue === "string") { return { arrays: optionValue, @@ -36,7 +53,7 @@ function normalizeOptions(optionValue: any) { return DEFAULT_OPTIONS; } -export default createRule("comma-dangle", { +export default createRule<[RuleValueOption | RuleOptions]>("comma-dangle", { meta: { docs: { description: "require or disallow trailing commas", diff --git a/lib/rules/comma-style.ts b/lib/rules/comma-style.ts index 3561bb5f..b817540e 100644 --- a/lib/rules/comma-style.ts +++ b/lib/rules/comma-style.ts @@ -13,7 +13,11 @@ import { import type { Comment, Token } from "../types"; import type { Rule } from "eslint"; -export default createRule("comma-style", { +export interface RuleOptions { + exceptions?: Record; +} + +export default createRule<["first" | "last", RuleOptions]>("comma-style", { meta: { docs: { description: "enforce consistent comma style", @@ -71,7 +75,7 @@ export default createRule("comma-style", { (key.startsWith("JSON") ? key : `JSON${key}`) as keyof typeof exceptions - ] = value as boolean; + ] = value; } } diff --git a/lib/rules/indent.ts b/lib/rules/indent.ts index ae4c600c..bc8aa86d 100644 --- a/lib/rules/indent.ts +++ b/lib/rules/indent.ts @@ -448,7 +448,44 @@ const ELEMENT_LIST_SCHEMA: JSONSchema4 = { }, ], }; -export default createRule("indent", { + +export type ElementList = number | "first" | "off"; + +export interface RuleOptions { + SwitchCase?: number; + VariableDeclarator?: + | ElementList + | { + var?: ElementList; + let?: ElementList; + const?: ElementList; + }; + outerIIFEBody?: number | "off"; + MemberExpression?: number | "off"; + FunctionDeclaration?: { + parameters?: ElementList; + body?: number; + }; + FunctionExpression?: { + parameters?: ElementList; + body?: number; + }; + StaticBlock?: { + body?: number; + }; + CallExpression?: { + arguments?: ElementList; + }; + ArrayExpression?: ElementList; + ObjectExpression?: ElementList; + ImportDeclaration?: ElementList; + flatTernaryExpressions?: boolean; + offsetTernaryExpressions?: boolean; + ignoredNodes?: string[]; + ignoreComments?: boolean; +} + +export default createRule<["tab" | number, RuleOptions]>("indent", { meta: { docs: { description: "enforce consistent indentation", @@ -632,7 +669,7 @@ export default createRule("indent", { ignoredNodes: [], ignoreComments: false, offsetTernaryExpressions: false, - }; + } satisfies RuleOptions; if (context.options.length) { if (context.options[0] === "tab") { diff --git a/lib/rules/key-name-casing.ts b/lib/rules/key-name-casing.ts index 685ba4d1..f73d2a1f 100644 --- a/lib/rules/key-name-casing.ts +++ b/lib/rules/key-name-casing.ts @@ -2,13 +2,13 @@ import { createRule } from "../utils"; import type { CasingKind } from "../utils/casing"; import { getChecker, allowedCaseOptions } from "../utils/casing"; -type Option = { +export type RuleOptions = { [key in CasingKind]?: boolean; } & { ignores?: string[]; }; -export default createRule("key-name-casing", { +export default createRule<[RuleOptions]>("key-name-casing", { meta: { docs: { description: "enforce naming convention to property key names", @@ -63,7 +63,7 @@ export default createRule("key-name-casing", { if (!sourceCode.parserServices.isJSON) { return {}; } - const option: Option = { ...context.options[0] }; + const option = { ...context.options[0] }; if (option.camelCase !== false) { option.camelCase = true; } diff --git a/lib/rules/object-curly-newline.ts b/lib/rules/object-curly-newline.ts index d86e105b..52f20c02 100644 --- a/lib/rules/object-curly-newline.ts +++ b/lib/rules/object-curly-newline.ts @@ -269,7 +269,7 @@ export default createRule("object-curly-newline", { fix(fixer) { if (hasCommentsFirstToken) return null; - return fixer.removeRange([openBrace.range[1], first.range![0]]); + return fixer.removeRange([openBrace.range[1], first.range[0]]); }, }); } @@ -286,7 +286,7 @@ export default createRule("object-curly-newline", { fix(fixer) { if (hasCommentsLastToken) return null; - return fixer.removeRange([last.range![1], closeBrace.range[0]]); + return fixer.removeRange([last.range[1], closeBrace.range[0]]); }, }); } diff --git a/lib/rules/object-curly-spacing.ts b/lib/rules/object-curly-spacing.ts index 303ec28c..6d34b447 100644 --- a/lib/rules/object-curly-spacing.ts +++ b/lib/rules/object-curly-spacing.ts @@ -9,260 +9,278 @@ import { isClosingBracketToken, } from "@eslint-community/eslint-utils"; -export default createRule("object-curly-spacing", { - meta: { - docs: { - description: "enforce consistent spacing inside braces", - recommended: null, - extensionRule: true, - layout: true, - }, - type: "layout", - - fixable: "whitespace", +export interface RuleOptions { + arraysInObjects?: boolean; + objectsInObjects?: boolean; +} - schema: [ - { - type: "string", - enum: ["always", "never"], +export default createRule<["always" | "never", RuleOptions]>( + "object-curly-spacing", + { + meta: { + docs: { + description: "enforce consistent spacing inside braces", + recommended: null, + extensionRule: true, + layout: true, }, - { - type: "object", - properties: { - arraysInObjects: { - type: "boolean", - }, - objectsInObjects: { - type: "boolean", + type: "layout", + + fixable: "whitespace", + + schema: [ + { + type: "string", + enum: ["always", "never"], + }, + { + type: "object", + properties: { + arraysInObjects: { + type: "boolean", + }, + objectsInObjects: { + type: "boolean", + }, }, + additionalProperties: false, }, - additionalProperties: false, - }, - ], + ], - messages: { - requireSpaceBefore: "A space is required before '{{token}}'.", - requireSpaceAfter: "A space is required after '{{token}}'.", - unexpectedSpaceBefore: "There should be no space before '{{token}}'.", - unexpectedSpaceAfter: "There should be no space after '{{token}}'.", + messages: { + requireSpaceBefore: "A space is required before '{{token}}'.", + requireSpaceAfter: "A space is required after '{{token}}'.", + unexpectedSpaceBefore: "There should be no space before '{{token}}'.", + unexpectedSpaceAfter: "There should be no space after '{{token}}'.", + }, }, - }, - create(context) { - const sourceCode = context.sourceCode; - if (!sourceCode.parserServices.isJSON) { - return {}; - } - const spaced = context.options[0] === "always"; + create(context) { + const sourceCode = context.sourceCode; + if (!sourceCode.parserServices.isJSON) { + return {}; + } + const spaced = context.options[0] === "always"; - /** - * Determines whether an option is set, relative to the spacing option. - * If spaced is "always", then check whether option is set to false. - * If spaced is "never", then check whether option is set to true. - * @param option The option to exclude. - * @returns Whether or not the property is excluded. - */ - function isOptionSet( - option: "arraysInObjects" | "objectsInObjects", - ): boolean { - return context.options[1] - ? context.options[1][option] === !spaced - : false; - } + /** + * Determines whether an option is set, relative to the spacing option. + * If spaced is "always", then check whether option is set to false. + * If spaced is "never", then check whether option is set to true. + * @param option The option to exclude. + * @returns Whether or not the property is excluded. + */ + function isOptionSet( + option: "arraysInObjects" | "objectsInObjects", + ): boolean { + return context.options[1] + ? context.options[1][option] === !spaced + : false; + } - const options = { - spaced, - arraysInObjectsException: isOptionSet("arraysInObjects"), - objectsInObjectsException: isOptionSet("objectsInObjects"), - isOpeningCurlyBraceMustBeSpaced(_second: Token | Comment) { - return options.spaced; - }, - isClosingCurlyBraceMustBeSpaced(penultimate: Token | Comment) { - const targetPenultimateType = - options.arraysInObjectsException && isClosingBracketToken(penultimate) - ? "JSONArrayExpression" - : options.objectsInObjectsException && - isClosingBraceToken(penultimate) - ? "JSONObjectExpression" - : null; - const node = sourceCode.getNodeByRangeIndex( - penultimate.range![0], - ) as AST.JSONNode | null; + const options = { + spaced, + arraysInObjectsException: isOptionSet("arraysInObjects"), + objectsInObjectsException: isOptionSet("objectsInObjects"), + isOpeningCurlyBraceMustBeSpaced(_second: Token | Comment) { + return options.spaced; + }, + isClosingCurlyBraceMustBeSpaced(penultimate: Token | Comment) { + const targetPenultimateType = + options.arraysInObjectsException && + isClosingBracketToken(penultimate) + ? "JSONArrayExpression" + : options.objectsInObjectsException && + isClosingBraceToken(penultimate) + ? "JSONObjectExpression" + : null; + const node = sourceCode.getNodeByRangeIndex( + penultimate.range![0], + ) as AST.JSONNode | null; - return targetPenultimateType && node?.type === targetPenultimateType - ? !options.spaced - : options.spaced; - }, - }; + return targetPenultimateType && node?.type === targetPenultimateType + ? !options.spaced + : options.spaced; + }, + }; - /** - * Reports that there shouldn't be a space after the first token - * @param node The node to report in the event of an error. - * @param token The token to use for the report. - */ - function reportNoBeginningSpace( - node: AST.JSONObjectExpression, - token: Token, - ) { - const nextToken = sourceCode.getTokenAfter(token, { - includeComments: true, - })!; + /** + * Reports that there shouldn't be a space after the first token + * @param node The node to report in the event of an error. + * @param token The token to use for the report. + */ + function reportNoBeginningSpace( + node: AST.JSONObjectExpression, + token: Token, + ) { + const nextToken = sourceCode.getTokenAfter(token, { + includeComments: true, + })!; - context.report({ - node: node as any, - loc: { start: token.loc.end, end: nextToken.loc!.start }, - messageId: "unexpectedSpaceAfter", - data: { - token: token.value, - }, - fix(fixer) { - return fixer.removeRange([token.range[1], nextToken.range![0]]); - }, - }); - } + context.report({ + node: node as any, + loc: { start: token.loc.end, end: nextToken.loc!.start }, + messageId: "unexpectedSpaceAfter", + data: { + token: token.value, + }, + fix(fixer) { + return fixer.removeRange([token.range[1], nextToken.range![0]]); + }, + }); + } - /** - * Reports that there shouldn't be a space before the last token - * @param node The node to report in the event of an error. - * @param token The token to use for the report. - */ - function reportNoEndingSpace(node: AST.JSONObjectExpression, token: Token) { - const previousToken = sourceCode.getTokenBefore(token, { - includeComments: true, - })!; + /** + * Reports that there shouldn't be a space before the last token + * @param node The node to report in the event of an error. + * @param token The token to use for the report. + */ + function reportNoEndingSpace( + node: AST.JSONObjectExpression, + token: Token, + ) { + const previousToken = sourceCode.getTokenBefore(token, { + includeComments: true, + })!; - context.report({ - node: node as any, - loc: { start: previousToken.loc!.end, end: token.loc.start }, - messageId: "unexpectedSpaceBefore", - data: { - token: token.value, - }, - fix(fixer) { - return fixer.removeRange([previousToken.range![1], token.range[0]]); - }, - }); - } + context.report({ + node: node as any, + loc: { start: previousToken.loc!.end, end: token.loc.start }, + messageId: "unexpectedSpaceBefore", + data: { + token: token.value, + }, + fix(fixer) { + return fixer.removeRange([previousToken.range![1], token.range[0]]); + }, + }); + } - /** - * Reports that there should be a space after the first token - * @param node The node to report in the event of an error. - * @param token The token to use for the report. - */ - function reportRequiredBeginningSpace( - node: AST.JSONObjectExpression, - token: Token, - ) { - context.report({ - node: node as any, - loc: token.loc, - messageId: "requireSpaceAfter", - data: { - token: token.value, - }, - fix(fixer) { - return fixer.insertTextAfter(token, " "); - }, - }); - } + /** + * Reports that there should be a space after the first token + * @param node The node to report in the event of an error. + * @param token The token to use for the report. + */ + function reportRequiredBeginningSpace( + node: AST.JSONObjectExpression, + token: Token, + ) { + context.report({ + node: node as any, + loc: token.loc, + messageId: "requireSpaceAfter", + data: { + token: token.value, + }, + fix(fixer) { + return fixer.insertTextAfter(token, " "); + }, + }); + } - /** - * Reports that there should be a space before the last token - * @param node The node to report in the event of an error. - * @param token The token to use for the report. - */ - function reportRequiredEndingSpace( - node: AST.JSONObjectExpression, - token: Token, - ) { - context.report({ - node: node as any, - loc: token.loc, - messageId: "requireSpaceBefore", - data: { - token: token.value, - }, - fix(fixer) { - return fixer.insertTextBefore(token, " "); - }, - }); - } + /** + * Reports that there should be a space before the last token + * @param node The node to report in the event of an error. + * @param token The token to use for the report. + */ + function reportRequiredEndingSpace( + node: AST.JSONObjectExpression, + token: Token, + ) { + context.report({ + node: node as any, + loc: token.loc, + messageId: "requireSpaceBefore", + data: { + token: token.value, + }, + fix(fixer) { + return fixer.insertTextBefore(token, " "); + }, + }); + } - /** - * Determines if spacing in curly braces is valid. - * @param node The AST node to check. - * @param first The first token to check (should be the opening brace) - * @param second The second token to check (should be first after the opening brace) - * @param penultimate The penultimate token to check (should be last before closing brace) - * @param last The last token to check (should be closing brace) - */ - function validateBraceSpacing( - node: AST.JSONObjectExpression, - first: Token, - second: Token | Comment, - penultimate: Token | Comment, - last: Token, - ) { - if (isTokenOnSameLine(first, second)) { - const firstSpaced = sourceCode.isSpaceBetween(first, second as any); + /** + * Determines if spacing in curly braces is valid. + * @param node The AST node to check. + * @param first The first token to check (should be the opening brace) + * @param second The second token to check (should be first after the opening brace) + * @param penultimate The penultimate token to check (should be last before closing brace) + * @param last The last token to check (should be closing brace) + */ + function validateBraceSpacing( + node: AST.JSONObjectExpression, + first: Token, + second: Token | Comment, + penultimate: Token | Comment, + last: Token, + ) { + if (isTokenOnSameLine(first, second)) { + const firstSpaced = sourceCode.isSpaceBetween(first, second as any); - if (options.isOpeningCurlyBraceMustBeSpaced(second)) { - if (!firstSpaced) reportRequiredBeginningSpace(node, first); - } else { - if (firstSpaced && second.type !== "Line") { - reportNoBeginningSpace(node, first); + if (options.isOpeningCurlyBraceMustBeSpaced(second)) { + if (!firstSpaced) reportRequiredBeginningSpace(node, first); + } else { + if (firstSpaced && second.type !== "Line") { + reportNoBeginningSpace(node, first); + } } } - } - if (isTokenOnSameLine(penultimate, last)) { - const lastSpaced = sourceCode.isSpaceBetween(penultimate as any, last); + if (isTokenOnSameLine(penultimate, last)) { + const lastSpaced = sourceCode.isSpaceBetween( + penultimate as any, + last, + ); - if (options.isClosingCurlyBraceMustBeSpaced(penultimate)) { - if (!lastSpaced) reportRequiredEndingSpace(node, last); - } else { - if (lastSpaced) reportNoEndingSpace(node, last); + if (options.isClosingCurlyBraceMustBeSpaced(penultimate)) { + if (!lastSpaced) reportRequiredEndingSpace(node, last); + } else { + if (lastSpaced) reportNoEndingSpace(node, last); + } } } - } - /** - * Gets '}' token of an object node. - * - * Because the last token of object patterns might be a type annotation, - * this traverses tokens preceded by the last property, then returns the - * first '}' token. - * @param node The node to get. This node is an - * ObjectExpression or an ObjectPattern. And this node has one or - * more properties. - * @returns '}' token. - */ - function getClosingBraceOfObject(node: AST.JSONObjectExpression) { - const lastProperty = node.properties[node.properties.length - 1]; + /** + * Gets '}' token of an object node. + * + * Because the last token of object patterns might be a type annotation, + * this traverses tokens preceded by the last property, then returns the + * first '}' token. + * @param node The node to get. This node is an + * ObjectExpression or an ObjectPattern. And this node has one or + * more properties. + * @returns '}' token. + */ + function getClosingBraceOfObject(node: AST.JSONObjectExpression) { + const lastProperty = node.properties[node.properties.length - 1]; - return sourceCode.getTokenAfter(lastProperty as any, isClosingBraceToken); - } + return sourceCode.getTokenAfter( + lastProperty as any, + isClosingBraceToken, + ); + } - /** - * Reports a given object node if spacing in curly braces is invalid. - * @param node An ObjectExpression or ObjectPattern node to check. - */ - function checkForObject(node: AST.JSONObjectExpression) { - if (node.properties.length === 0) return; + /** + * Reports a given object node if spacing in curly braces is invalid. + * @param node An ObjectExpression or ObjectPattern node to check. + */ + function checkForObject(node: AST.JSONObjectExpression) { + if (node.properties.length === 0) return; - const first = sourceCode.getFirstToken(node as any)!; - const last = getClosingBraceOfObject(node)!; - const second = sourceCode.getTokenAfter(first, { - includeComments: true, - })!; - const penultimate = sourceCode.getTokenBefore(last, { - includeComments: true, - })!; + const first = sourceCode.getFirstToken(node as any)!; + const last = getClosingBraceOfObject(node)!; + const second = sourceCode.getTokenAfter(first, { + includeComments: true, + })!; + const penultimate = sourceCode.getTokenBefore(last, { + includeComments: true, + })!; - validateBraceSpacing(node, first, second, penultimate, last); - } + validateBraceSpacing(node, first, second, penultimate, last); + } - return { - JSONObjectExpression: checkForObject, - }; + return { + JSONObjectExpression: checkForObject, + }; + }, }, -}); +); diff --git a/lib/rules/object-property-newline.ts b/lib/rules/object-property-newline.ts index fa594fd1..aff86f53 100644 --- a/lib/rules/object-property-newline.ts +++ b/lib/rules/object-property-newline.ts @@ -2,7 +2,15 @@ // MIT License. Copyright OpenJS Foundation and other contributors, import { createRule } from "../utils"; -export default createRule("object-property-newline", { +export interface RuleOptions { + allowAllPropertiesOnSameLine?: boolean; + /** + * @deprecated + */ + allowMultiplePropertiesPerLine?: boolean; +} + +export default createRule<[RuleOptions]>("object-property-newline", { meta: { docs: { description: "enforce placing object properties on separate lines", diff --git a/lib/rules/quote-props.ts b/lib/rules/quote-props.ts index d3856aac..e3f68641 100644 --- a/lib/rules/quote-props.ts +++ b/lib/rules/quote-props.ts @@ -7,7 +7,19 @@ import { tokenize } from "espree"; import { keywords } from "../utils/eslint-keywords"; import { isNumericLiteral } from "../utils/eslint-ast-utils"; -export default createRule("quote-props", { +export type RulePresetOption = + | "always" + | "as-needed" + | "consistent" + | "consistent-as-needed"; + +export interface RuleOptions { + keywords?: boolean; + unnecessary?: boolean; + numbers?: boolean; +} + +export default createRule<[RulePresetOption?, RuleOptions?]>("quote-props", { meta: { docs: { description: "require quotes around object literal property names", @@ -89,12 +101,7 @@ export default createRule("quote-props", { if (!sourceCode.parserServices.isJSON) { return {}; } - const MODE = - (context.options[0] as - | "always" - | "as-needed" - | "consistent" - | "consistent-as-needed") || "always"; + const MODE = context.options[0] || "always"; const KEYWORDS = (context.options[1] && context.options[1].keywords)!; const CHECK_UNNECESSARY = !context.options[1] || context.options[1].unnecessary !== false; diff --git a/lib/rules/quotes.ts b/lib/rules/quotes.ts index 70597af5..79fb51e9 100644 --- a/lib/rules/quotes.ts +++ b/lib/rules/quotes.ts @@ -70,7 +70,14 @@ const UNESCAPED_LINEBREAK_PATTERN = new RegExp( const AVOID_ESCAPE = "avoid-escape"; -export default createRule("quotes", { +export interface RuleOptions { + avoidEscape?: boolean; + allowTemplateLiterals?: boolean; +} + +export default createRule< + ["single" | "double" | "backtick", "avoid-escape" | RuleOptions] +>("quotes", { meta: { docs: { description: "enforce use of double or single quotes", @@ -115,8 +122,8 @@ export default createRule("quotes", { if (!sourceCode.parserServices.isJSON) { return {}; } - let quoteOption = context.options[0] as "double" | "single"; - if ((quoteOption as string) === "backtick") { + let quoteOption = context.options[0]; + if (quoteOption === "backtick") { quoteOption = "double"; } const settings = QUOTE_SETTINGS[quoteOption || "double"]; diff --git a/lib/rules/sort-array-values.ts b/lib/rules/sort-array-values.ts index c31b9277..6145ba35 100644 --- a/lib/rules/sort-array-values.ts +++ b/lib/rules/sort-array-values.ts @@ -321,7 +321,7 @@ const ORDER_OBJECT_SCHEMA = { // Rule Definition //------------------------------------------------------------------------------ -export default createRule("sort-array-values", { +export default createRule("sort-array-values", { meta: { docs: { description: "require array values to be sorted", diff --git a/lib/rules/sort-keys.ts b/lib/rules/sort-keys.ts index 6fe5119e..44b63744 100644 --- a/lib/rules/sort-keys.ts +++ b/lib/rules/sort-keys.ts @@ -311,7 +311,7 @@ const ORDER_OBJECT_SCHEMA = { // Rule Definition //------------------------------------------------------------------------------ -export default createRule("sort-keys", { +export default createRule("sort-keys", { meta: { docs: { description: "require object keys to be sorted", diff --git a/lib/rules/space-unary-ops.ts b/lib/rules/space-unary-ops.ts index ac6cfa8a..5079eabf 100644 --- a/lib/rules/space-unary-ops.ts +++ b/lib/rules/space-unary-ops.ts @@ -5,7 +5,13 @@ import { createRule } from "../utils"; import type { Token } from "../types"; import { canTokensBeAdjacent } from "../utils/eslint-ast-utils"; -export default createRule("space-unary-ops", { +export interface RuleOptions { + words?: boolean; + nonwords?: boolean; + overrides?: Record; +} + +export default createRule<[RuleOptions]>("space-unary-ops", { meta: { docs: { description: "disallow spaces after unary operators", diff --git a/lib/rules/vue-custom-block/no-parsing-error.ts b/lib/rules/vue-custom-block/no-parsing-error.ts index a1522fd2..4606e104 100644 --- a/lib/rules/vue-custom-block/no-parsing-error.ts +++ b/lib/rules/vue-custom-block/no-parsing-error.ts @@ -1,5 +1,5 @@ import type { AST } from "jsonc-eslint-parser"; -import type { VAttribute, VElement } from "vue-eslint-parser/ast"; +import type { AST as VueAST } from "vue-eslint-parser"; import { createRule } from "../../utils"; import type { RuleListener } from "../../types"; import * as jsoncESLintParser from "jsonc-eslint-parser"; @@ -33,7 +33,8 @@ export default createRule("vue-custom-block/no-parsing-error", { const parseCustomBlockElement: | ((parser: any, options: any) => any) | undefined = parserServices.parseCustomBlockElement; - const customBlockElement: VElement | undefined = parserServices.customBlock; + const customBlockElement: VueAST.VElement | undefined = + parserServices.customBlock; if (customBlockElement && parseCustomBlockElement) { let lang = getLang(customBlockElement); @@ -80,10 +81,11 @@ function errorReportVisitor( /** * Get lang from given custom block */ -function getLang(customBlock: VElement) { +function getLang(customBlock: VueAST.VElement) { return ( customBlock.startTag.attributes.find( - (attr): attr is VAttribute => !attr.directive && attr.key.name === "lang", + (attr): attr is VueAST.VAttribute => + !attr.directive && attr.key.name === "lang", )?.value?.value || null ); } diff --git a/lib/types.ts b/lib/types.ts index b43a1491..c07da4dc 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -28,10 +28,10 @@ export type BaseRuleListener = MomoaRuleListener & BuiltInRuleListeners & BuiltInRuleListenerExits; -export interface RuleModule { +export interface RuleModule { meta: RuleMetaData; - jsoncDefineRule: PartialRuleModule; - create(context: Rule.RuleContext): RuleListener; + jsoncDefineRule: PartialRuleModule; + create(context: Rule.RuleContext & { options: RuleOptions }): RuleListener; } export interface RuleMetaData { @@ -60,10 +60,10 @@ export interface RuleMetaData { type: "problem" | "suggestion" | "layout"; } -export interface PartialRuleModule { +export interface PartialRuleModule { meta: PartialRuleMetaData; create: ( - context: Rule.RuleContext, + context: Rule.RuleContext & { options: RuleOptions }, params: { customBlock: boolean }, ) => BaseRuleListener; } diff --git a/lib/utils/get-auto-jsonc-rules-config/calculate-config-for-file.ts b/lib/utils/get-auto-jsonc-rules-config/calculate-config-for-file.ts index c0669e9a..a46031b7 100644 --- a/lib/utils/get-auto-jsonc-rules-config/calculate-config-for-file.ts +++ b/lib/utils/get-auto-jsonc-rules-config/calculate-config-for-file.ts @@ -1,5 +1,4 @@ import type { Linter } from "eslint"; -// @ts-expect-error -- ignore import { createSyncFn } from "synckit"; const getSync = createSyncFn(require.resolve("./worker")); diff --git a/lib/utils/get-auto-jsonc-rules-config/worker.ts b/lib/utils/get-auto-jsonc-rules-config/worker.ts index c9305b6e..a509464e 100644 --- a/lib/utils/get-auto-jsonc-rules-config/worker.ts +++ b/lib/utils/get-auto-jsonc-rules-config/worker.ts @@ -1,4 +1,3 @@ -// @ts-expect-error -- ignore import { runAsWorker } from "synckit"; import { getESLint } from "eslint-compat-utils/eslint"; const ESLint = getESLint(); diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 47cfa979..7c59860b 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -12,10 +12,10 @@ import { toCompatCreate } from "eslint-json-compat-utils"; * @param ruleName ruleName * @param rule rule module */ -export function createRule( +export function createRule( ruleName: string, - rule: PartialRuleModule, -): RuleModule { + rule: PartialRuleModule, +): RuleModule { return { meta: { ...rule.meta, @@ -27,7 +27,7 @@ export function createRule( }, }, jsoncDefineRule: rule, - create(baseContext: Rule.RuleContext) { + create(baseContext: Rule.RuleContext & { options: RuleOptions }) { const context = getCompatContext(baseContext); const create = toCompatCreate(rule.create); const sourceCode = context.sourceCode; @@ -46,7 +46,7 @@ export function createRule( } return block.name === "i18n"; }, - create(blockContext: Rule.RuleContext) { + create(blockContext: Rule.RuleContext & { options: RuleOptions }) { return create(blockContext, { customBlock: true, }); @@ -64,14 +64,12 @@ export function createRule( /** * Get the compatible context from the given context. */ -function getCompatContext(context: Rule.RuleContext): Rule.RuleContext { +function getCompatContext(context: T): T { if (context.sourceCode) { return context; } return { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment -- special - // @ts-expect-error __proto__: context, get sourceCode() { return getSourceCode(context); @@ -82,7 +80,7 @@ function getCompatContext(context: Rule.RuleContext): Rule.RuleContext { get cwd() { return getCwd(context); }, - }; + } as unknown as T; } /** diff --git a/package.json b/package.json index b684f3ff..9c3649de 100644 --- a/package.json +++ b/package.json @@ -66,69 +66,68 @@ }, "homepage": "https://ota-meshi.github.io/eslint-plugin-jsonc/", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "eslint-compat-utils": "^0.6.0", + "@eslint-community/eslint-utils": "^4.5.1", + "eslint-compat-utils": "^0.6.4", "eslint-json-compat-utils": "^0.2.1", - "espree": "^9.6.1", + "espree": "^9.6.1 || ^10.3.0", "graphemer": "^1.4.0", - "jsonc-eslint-parser": "^2.0.4", + "jsonc-eslint-parser": "^2.4.0", "natural-compare": "^1.4.0", - "synckit": "^0.6.0" + "synckit": "^0.6.2 || ^0.7.3 || ^0.10.3" }, "peerDependencies": { "eslint": ">=6.0.0" }, "devDependencies": { - "@babel/eslint-parser": "^7.11.0", - "@changesets/changelog-github": "^0.5.0", - "@changesets/cli": "^2.24.2", - "@eslint-community/eslint-plugin-eslint-comments": "^4.3.0", - "@eslint/json": "^0.10.0", - "@ota-meshi/eslint-plugin": "^0.17.4", - "@ota-meshi/site-kit-eslint-editor-vue": "^0.2.0", - "@types/eslint": "^9.0.0", - "@types/eslint-scope": "^3.7.0", - "@types/eslint-visitor-keys": "^1.0.0", - "@types/mocha": "^10.0.0", - "@types/natural-compare": "^1.4.0", - "@types/node": "^22.0.0", - "@types/semver": "^7.3.1", - "@typescript-eslint/eslint-plugin": "^8.5.0", - "@typescript-eslint/parser": "^8.5.0", + "@babel/eslint-parser": "^7.27.0", + "@changesets/changelog-github": "^0.5.1", + "@changesets/cli": "^2.28.1", + "@eslint-community/eslint-plugin-eslint-comments": "^4.4.1", + "@eslint/json": "^0.11.0", + "@ota-meshi/eslint-plugin": "^0.17.6", + "@ota-meshi/site-kit-eslint-editor-vue": "^0.2.4", + "@types/eslint-scope": "^3.7.7", + "@types/mocha": "^10.0.10", + "@types/natural-compare": "^1.4.3", + "@types/node": "^22.13.13", + "@types/semver": "^7.5.8", + "@typescript-eslint/eslint-plugin": "^8.28.0", + "@typescript-eslint/parser": "^8.28.0", "dts-bundle": "^0.7.3", "env-cmd": "^10.1.0", - "esbuild": "^0.24.0", - "eslint": "^9.15.0", - "eslint-config-prettier": "^10.0.0", - "eslint-plugin-eslint-plugin": "^6.1.0", + "esbuild": "^0.25.1", + "eslint": "^9.23.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-eslint-plugin": "^6.4.0", "eslint-plugin-eslint-rule-tester": "^0.6.0", - "eslint-plugin-jsdoc": "^50.0.0", - "eslint-plugin-json-schema-validator": "^5.1.1", - "eslint-plugin-jsonc": "^2.16.0", - "eslint-plugin-markdown": "^5.0.0", - "eslint-plugin-n": "^17.9.0", + "eslint-plugin-jsdoc": "^50.6.9", + "eslint-plugin-json-schema-validator": "^5.3.1", + "eslint-plugin-jsonc": "^2.19.1", + "eslint-plugin-markdown": "^5.1.0", + "eslint-plugin-n": "^17.16.2", "eslint-plugin-node-dependencies": "^0.12.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-regexp": "^2.6.0", - "eslint-plugin-vue": "^9.26.0", - "eslint-plugin-yml": "^1.14.0", + "eslint-plugin-prettier": "^5.2.4", + "eslint-plugin-regexp": "^2.7.0", + "eslint-plugin-vue": "^10.0.0", + "eslint-plugin-yml": "^1.17.0", "events": "^3.3.0", - "mocha": "^11.0.0", - "nyc": "^17.0.0", + "globals": "^16.0.0", + "mocha": "^11.1.0", + "nyc": "^17.1.0", "pako": "^2.1.0", - "prettier": "^3.0.0", - "semver": "^7.3.2", - "stylelint": "^16.0.0", - "stylelint-config-recommended-vue": "^1.0.0", + "prettier": "^3.5.3", + "semver": "^7.7.1", + "stylelint": "^16.16.0", + "stylelint-config-recommended-vue": "^1.6.0", "stylelint-config-standard": "^37.0.0", "stylelint-config-standard-vue": "^1.0.0", "stylelint-stylus": "^1.0.0", - "ts-node": "^10.0.0", - "typescript": "~5.0.0", - "typescript-eslint": "^8.5.0", - "vite-plugin-eslint4b": "^0.5.0", - "vitepress": "^1.2.3", - "vue-eslint-parser": "^9.0.0" + "ts-node": "^10.9.2", + "typescript": "^5.8.2", + "typescript-eslint": "^8.28.0", + "vite-plugin-eslint4b": "^0.5.1", + "vitepress": "^1.6.3", + "vue-eslint-parser": "^10.1.1" }, "publishConfig": { "access": "public" diff --git a/tests/lib/rules/array-bracket-newline.ts b/tests/lib/rules/array-bracket-newline.ts index 25152452..42c8f663 100644 --- a/tests/lib/rules/array-bracket-newline.ts +++ b/tests/lib/rules/array-bracket-newline.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("array-bracket-newline", rule as any, { +tester.run("array-bracket-newline", rule, { valid: ["[]", "[\n1,\n2\n]"], invalid: [ { diff --git a/tests/lib/rules/array-bracket-spacing.ts b/tests/lib/rules/array-bracket-spacing.ts index 5d1e2307..fbc8f7f0 100644 --- a/tests/lib/rules/array-bracket-spacing.ts +++ b/tests/lib/rules/array-bracket-spacing.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("array-bracket-spacing", rule as any, { +tester.run("array-bracket-spacing", rule, { valid: [ '["element"]', { code: "[ 1 ]", options: ["always"] }, diff --git a/tests/lib/rules/array-element-newline.ts b/tests/lib/rules/array-element-newline.ts index ef772716..d991af1e 100644 --- a/tests/lib/rules/array-element-newline.ts +++ b/tests/lib/rules/array-element-newline.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("array-element-newline", rule as any, { +tester.run("array-element-newline", rule, { valid: [ `[1, 2, diff --git a/tests/lib/rules/comma-dangle.ts b/tests/lib/rules/comma-dangle.ts index 4d7630ef..21699f92 100644 --- a/tests/lib/rules/comma-dangle.ts +++ b/tests/lib/rules/comma-dangle.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("comma-dangle", rule as any, { +tester.run("comma-dangle", rule, { valid: ['{"key": "value"}'], invalid: [ { diff --git a/tests/lib/rules/comma-style.ts b/tests/lib/rules/comma-style.ts index de7be745..c05b3529 100644 --- a/tests/lib/rules/comma-style.ts +++ b/tests/lib/rules/comma-style.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("comma-style", rule as any, { +tester.run("comma-style", rule, { valid: [ `{ "GOOD": ["apples", diff --git a/tests/lib/rules/indent.ts b/tests/lib/rules/indent.ts index e8280657..810c593c 100644 --- a/tests/lib/rules/indent.ts +++ b/tests/lib/rules/indent.ts @@ -119,7 +119,7 @@ const tester = new RuleTester({ tester.run( "indent", - rule as any, + rule, loadPatterns( [ { diff --git a/tests/lib/rules/key-name-casing.ts b/tests/lib/rules/key-name-casing.ts index e0a81c3d..614150a3 100644 --- a/tests/lib/rules/key-name-casing.ts +++ b/tests/lib/rules/key-name-casing.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("key-name-casing", rule as any, { +tester.run("key-name-casing", rule, { valid: [ '{"key": "value"}', '{"camelCase": "value"}', diff --git a/tests/lib/rules/key-spacing.ts b/tests/lib/rules/key-spacing.ts index d7154462..3956300e 100644 --- a/tests/lib/rules/key-spacing.ts +++ b/tests/lib/rules/key-spacing.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("key-spacing", rule as any, { +tester.run("key-spacing", rule, { valid: ['{"key": "value"}'], invalid: [ { diff --git a/tests/lib/rules/no-bigint-literals.ts b/tests/lib/rules/no-bigint-literals.ts index f258d105..c83f6284 100644 --- a/tests/lib/rules/no-bigint-literals.ts +++ b/tests/lib/rules/no-bigint-literals.ts @@ -11,7 +11,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-bigint-literals", rule as any, { +tester.run("no-bigint-literals", rule, { valid: ['{"key": "value"}', '"string"', '["element"]'], invalid: [ { diff --git a/tests/lib/rules/no-binary-expression.ts b/tests/lib/rules/no-binary-expression.ts index e8c2510e..418aa7eb 100644 --- a/tests/lib/rules/no-binary-expression.ts +++ b/tests/lib/rules/no-binary-expression.ts @@ -10,7 +10,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-binary-expression", rule as any, { +tester.run("no-binary-expression", rule, { valid: ['{"42": 42}', "42", "[42]"], invalid: [ { diff --git a/tests/lib/rules/no-binary-numeric-literals.ts b/tests/lib/rules/no-binary-numeric-literals.ts index f4240edf..47b22694 100644 --- a/tests/lib/rules/no-binary-numeric-literals.ts +++ b/tests/lib/rules/no-binary-numeric-literals.ts @@ -10,7 +10,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-binary-numeric-literals", rule as any, { +tester.run("no-binary-numeric-literals", rule, { valid: ["0", "1010"], invalid: [ { diff --git a/tests/lib/rules/no-comments.ts b/tests/lib/rules/no-comments.ts index 6e8f332e..ea672fae 100644 --- a/tests/lib/rules/no-comments.ts +++ b/tests/lib/rules/no-comments.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("no-comments", rule as any, { +tester.run("no-comments", rule, { valid: ['{"key": "value"}', '"string"', '["element"]'], invalid: [ { diff --git a/tests/lib/rules/no-dupe-keys.ts b/tests/lib/rules/no-dupe-keys.ts index 14865adc..75c9e183 100644 --- a/tests/lib/rules/no-dupe-keys.ts +++ b/tests/lib/rules/no-dupe-keys.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("no-dupe-keys", rule as any, { +tester.run("no-dupe-keys", rule, { valid: ['{"key": "value"}', '{"key": "value", "key2": "value"}'], invalid: [ { diff --git a/tests/lib/rules/no-escape-sequence-in-identifier.ts b/tests/lib/rules/no-escape-sequence-in-identifier.ts index d3f85cad..f1cc7d1d 100644 --- a/tests/lib/rules/no-escape-sequence-in-identifier.ts +++ b/tests/lib/rules/no-escape-sequence-in-identifier.ts @@ -10,7 +10,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-escape-sequence-in-identifier", rule as any, { +tester.run("no-escape-sequence-in-identifier", rule, { valid: ["{key: 42}"], invalid: [ { diff --git a/tests/lib/rules/no-floating-decimal.ts b/tests/lib/rules/no-floating-decimal.ts index ee004e34..1dc60780 100644 --- a/tests/lib/rules/no-floating-decimal.ts +++ b/tests/lib/rules/no-floating-decimal.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("no-floating-decimal", rule as any, { +tester.run("no-floating-decimal", rule, { valid: ["42", "42.0", "0.42"], invalid: [ { diff --git a/tests/lib/rules/no-hexadecimal-numeric-literals.ts b/tests/lib/rules/no-hexadecimal-numeric-literals.ts index c2968f92..4442b850 100644 --- a/tests/lib/rules/no-hexadecimal-numeric-literals.ts +++ b/tests/lib/rules/no-hexadecimal-numeric-literals.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("no-hexadecimal-numeric-literals", rule as any, { +tester.run("no-hexadecimal-numeric-literals", rule, { valid: ["0", "777", '"FFF"'], invalid: [ { diff --git a/tests/lib/rules/no-infinity.ts b/tests/lib/rules/no-infinity.ts index 22b809bd..73a56fc5 100644 --- a/tests/lib/rules/no-infinity.ts +++ b/tests/lib/rules/no-infinity.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("no-infinity", rule as any, { +tester.run("no-infinity", rule, { valid: ["NaN", "42", '"foo"', "{Infinity:42}"], invalid: [ { diff --git a/tests/lib/rules/no-irregular-whitespace.ts b/tests/lib/rules/no-irregular-whitespace.ts index e0d36922..a7bf5411 100644 --- a/tests/lib/rules/no-irregular-whitespace.ts +++ b/tests/lib/rules/no-irregular-whitespace.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("no-irregular-whitespace", rule as any, { +tester.run("no-irregular-whitespace", rule, { valid: [ `"\u0020"`, `"\u0009"`, diff --git a/tests/lib/rules/no-multi-str.ts b/tests/lib/rules/no-multi-str.ts index 08725911..a5054c70 100644 --- a/tests/lib/rules/no-multi-str.ts +++ b/tests/lib/rules/no-multi-str.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("no-multi-str", rule as any, { +tester.run("no-multi-str", rule, { valid: ['{"GOOD": "Line 1 \\nLine 2"}', '"Line 1 \\nLine 2"'], invalid: [ { @@ -25,11 +25,9 @@ tester.run("no-multi-str", rule as any, { filename: "test.vue", code: `"Line 1 \\\nLine 2"`, errors: 1, - ...({ - languageOptions: { - parser: vueParser, - }, - } as any), // FIXME: drop supports eslint6 ["Multiline support is limited to JSON5 only."], + languageOptions: { + parser: vueParser, + }, // FIXME: drop supports eslint6 ["Multiline support is limited to JSON5 only."], }, ], }); diff --git a/tests/lib/rules/no-nan.ts b/tests/lib/rules/no-nan.ts index 69ca5054..4b509829 100644 --- a/tests/lib/rules/no-nan.ts +++ b/tests/lib/rules/no-nan.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("no-nan", rule as any, { +tester.run("no-nan", rule, { valid: ["Infinity", "1234", '"foo"', "{NaN:42}"], invalid: [ { diff --git a/tests/lib/rules/no-number-props.ts b/tests/lib/rules/no-number-props.ts index 8b755e3f..b939b50d 100644 --- a/tests/lib/rules/no-number-props.ts +++ b/tests/lib/rules/no-number-props.ts @@ -10,7 +10,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-number-props", rule as any, { +tester.run("no-number-props", rule, { valid: ['{"key": 123}', "{key: 123}", "123", "[123]"], invalid: [ { diff --git a/tests/lib/rules/no-numeric-separators.ts b/tests/lib/rules/no-numeric-separators.ts index 8567504a..4720ee72 100644 --- a/tests/lib/rules/no-numeric-separators.ts +++ b/tests/lib/rules/no-numeric-separators.ts @@ -4,46 +4,43 @@ import { Linter } from "eslint"; import semver from "semver"; import * as jsonParser from "jsonc-eslint-parser"; import * as vueParser from "vue-eslint-parser"; -if (!semver.gte(Linter.version, "7.3.0")) { - // @ts-expect-error - return; -} -const tester = new RuleTester({ - languageOptions: { - ecmaVersion: 2021, - parser: jsonParser, - }, - ignoreMomoa: true, -}); -tester.run("no-numeric-separators", rule as any, { - valid: ['{"key": 1234}', "1234", "[1234]"], - invalid: [ - { - code: `{"key": 1_234}`, - output: `{"key": 1234}`, - errors: ["Numeric separators are not allowed."], - }, - { - code: `1_234`, - output: `1234`, - errors: ["Numeric separators are not allowed."], - }, - { - code: `[1_234]`, - output: `[1234]`, - errors: ["Numeric separators are not allowed."], +if (semver.gte(Linter.version, "7.3.0")) { + const tester = new RuleTester({ + languageOptions: { + ecmaVersion: 2021, + parser: jsonParser, }, - { - filename: "test.vue", - code: `{"a": 1_23}`, - output: `{"a": 123}`, - errors: ["Numeric separators are not allowed."], - ...({ + ignoreMomoa: true, + }); + + tester.run("no-numeric-separators", rule, { + valid: ['{"key": 1234}', "1234", "[1234]"], + invalid: [ + { + code: `{"key": 1_234}`, + output: `{"key": 1234}`, + errors: ["Numeric separators are not allowed."], + }, + { + code: `1_234`, + output: `1234`, + errors: ["Numeric separators are not allowed."], + }, + { + code: `[1_234]`, + output: `[1234]`, + errors: ["Numeric separators are not allowed."], + }, + { + filename: "test.vue", + code: `{"a": 1_23}`, + output: `{"a": 123}`, + errors: ["Numeric separators are not allowed."], languageOptions: { parser: vueParser, }, - } as any), - }, - ], -}); + }, + ], + }); +} diff --git a/tests/lib/rules/no-octal-escape.ts b/tests/lib/rules/no-octal-escape.ts index 5c11cfa4..ef8b2bf7 100644 --- a/tests/lib/rules/no-octal-escape.ts +++ b/tests/lib/rules/no-octal-escape.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("no-octal-escape", rule as any, { +tester.run("no-octal-escape", rule, { valid: ['{"GOOD": "Copyright \\u00A9"}'], invalid: [ { diff --git a/tests/lib/rules/no-octal-numeric-literals.ts b/tests/lib/rules/no-octal-numeric-literals.ts index 4797405f..42155882 100644 --- a/tests/lib/rules/no-octal-numeric-literals.ts +++ b/tests/lib/rules/no-octal-numeric-literals.ts @@ -10,7 +10,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-octal-numeric-literals", rule as any, { +tester.run("no-octal-numeric-literals", rule, { valid: ["0", "777"], invalid: [ { diff --git a/tests/lib/rules/no-octal.ts b/tests/lib/rules/no-octal.ts index 9959ad68..a825f673 100644 --- a/tests/lib/rules/no-octal.ts +++ b/tests/lib/rules/no-octal.ts @@ -10,7 +10,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-octal", rule as any, { +tester.run("no-octal", rule, { valid: ["0", "1", "9"], invalid: [ { diff --git a/tests/lib/rules/no-parenthesized.ts b/tests/lib/rules/no-parenthesized.ts index 11a864d6..9d4d0bc8 100644 --- a/tests/lib/rules/no-parenthesized.ts +++ b/tests/lib/rules/no-parenthesized.ts @@ -10,7 +10,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-parenthesized", rule as any, { +tester.run("no-parenthesized", rule, { valid: ["{42: 42}", "42", "[42]"], invalid: [ { diff --git a/tests/lib/rules/no-plus-sign.ts b/tests/lib/rules/no-plus-sign.ts index 02adc0f8..136890b9 100644 --- a/tests/lib/rules/no-plus-sign.ts +++ b/tests/lib/rules/no-plus-sign.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("no-plus-sign", rule as any, { +tester.run("no-plus-sign", rule, { valid: ["42", "-42", "-42.0"], invalid: [ { diff --git a/tests/lib/rules/no-regexp-literals.ts b/tests/lib/rules/no-regexp-literals.ts index 886cb1ba..b8e43b04 100644 --- a/tests/lib/rules/no-regexp-literals.ts +++ b/tests/lib/rules/no-regexp-literals.ts @@ -10,7 +10,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-regexp-literals", rule as any, { +tester.run("no-regexp-literals", rule, { valid: ['{"key": "value"}', '"string"', '["element"]'], invalid: [ { diff --git a/tests/lib/rules/no-sparse-arrays.ts b/tests/lib/rules/no-sparse-arrays.ts index 2a416703..4720927d 100644 --- a/tests/lib/rules/no-sparse-arrays.ts +++ b/tests/lib/rules/no-sparse-arrays.ts @@ -12,7 +12,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-sparse-arrays", rule as any, { +tester.run("no-sparse-arrays", rule, { valid: ["[1,2,3,4]", "[1,2,3,4,]"], invalid: [ { diff --git a/tests/lib/rules/no-template-literals.ts b/tests/lib/rules/no-template-literals.ts index c80e265b..b07ff172 100644 --- a/tests/lib/rules/no-template-literals.ts +++ b/tests/lib/rules/no-template-literals.ts @@ -11,7 +11,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-template-literals", rule as any, { +tester.run("no-template-literals", rule, { valid: ['{"key": "value"}', '"string"', '["element"]'], invalid: [ { diff --git a/tests/lib/rules/no-undefined-value.ts b/tests/lib/rules/no-undefined-value.ts index 36556cf7..0263fce9 100644 --- a/tests/lib/rules/no-undefined-value.ts +++ b/tests/lib/rules/no-undefined-value.ts @@ -10,7 +10,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-undefined-value", rule as any, { +tester.run("no-undefined-value", rule, { valid: ["null", "[1,,2]", "{undefined:1}"], invalid: [ { diff --git a/tests/lib/rules/no-unicode-codepoint-escapes.ts b/tests/lib/rules/no-unicode-codepoint-escapes.ts index 6e5ba9fd..2d52c606 100644 --- a/tests/lib/rules/no-unicode-codepoint-escapes.ts +++ b/tests/lib/rules/no-unicode-codepoint-escapes.ts @@ -10,7 +10,7 @@ const tester = new RuleTester({ ignoreMomoa: true, }); -tester.run("no-unicode-codepoint-escapes", rule as any, { +tester.run("no-unicode-codepoint-escapes", rule, { valid: ['"\\u0041"', '{"\\u0041": "string"}', "`\\u0042`"], invalid: [ { diff --git a/tests/lib/rules/no-useless-escape.ts b/tests/lib/rules/no-useless-escape.ts index f40e1e79..9a2cfee7 100644 --- a/tests/lib/rules/no-useless-escape.ts +++ b/tests/lib/rules/no-useless-escape.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("no-useless-escape", rule as any, { +tester.run("no-useless-escape", rule, { valid: ['"\\""'], invalid: [ { diff --git a/tests/lib/rules/object-curly-newline.ts b/tests/lib/rules/object-curly-newline.ts index 60e13981..063045af 100644 --- a/tests/lib/rules/object-curly-newline.ts +++ b/tests/lib/rules/object-curly-newline.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("object-curly-newline", rule as any, { +tester.run("object-curly-newline", rule, { valid: ['{"key": "value"}', '{\n"key": "value"\n}'], invalid: [ { diff --git a/tests/lib/rules/object-curly-spacing.ts b/tests/lib/rules/object-curly-spacing.ts index ba483951..713d59d9 100644 --- a/tests/lib/rules/object-curly-spacing.ts +++ b/tests/lib/rules/object-curly-spacing.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("object-curly-spacing", rule as any, { +tester.run("object-curly-spacing", rule, { valid: [ '{"key": "value"}', diff --git a/tests/lib/rules/object-property-newline.ts b/tests/lib/rules/object-property-newline.ts index eb888d94..36e95208 100644 --- a/tests/lib/rules/object-property-newline.ts +++ b/tests/lib/rules/object-property-newline.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("object-property-newline", rule as any, { +tester.run("object-property-newline", rule, { valid: [ ` { diff --git a/tests/lib/rules/quote-props.ts b/tests/lib/rules/quote-props.ts index af6489b7..939d2a09 100644 --- a/tests/lib/rules/quote-props.ts +++ b/tests/lib/rules/quote-props.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("quote-props", rule as any, { +tester.run("quote-props", rule, { valid: ['{"key": "value"}', '"string"', '["element"]'], invalid: [ { diff --git a/tests/lib/rules/quotes.ts b/tests/lib/rules/quotes.ts index 06601a0a..efee1943 100644 --- a/tests/lib/rules/quotes.ts +++ b/tests/lib/rules/quotes.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("quotes", rule as any, { +tester.run("quotes", rule, { valid: ['{"key": "value"}', '"string"', '["element"]'], invalid: [ { diff --git a/tests/lib/rules/sort-array-values.ts b/tests/lib/rules/sort-array-values.ts index 9c4b43cd..8de6e51a 100644 --- a/tests/lib/rules/sort-array-values.ts +++ b/tests/lib/rules/sort-array-values.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("sort-array-values", rule as any, { +tester.run("sort-array-values", rule, { valid: [ { code: '{"key": ["a", "b", "c"] }', diff --git a/tests/lib/rules/sort-keys.ts b/tests/lib/rules/sort-keys.ts index d87a8542..eab030e8 100644 --- a/tests/lib/rules/sort-keys.ts +++ b/tests/lib/rules/sort-keys.ts @@ -51,7 +51,7 @@ const OPTIONS_FOR_JSON_SCHEMA = [ }, ]; -tester.run("sort-keys", rule as any, { +tester.run("sort-keys", rule, { valid: [ '{"a": 1, "b": 2, "c": 3}', diff --git a/tests/lib/rules/space-unary-ops.ts b/tests/lib/rules/space-unary-ops.ts index 5793e21e..91e100f5 100644 --- a/tests/lib/rules/space-unary-ops.ts +++ b/tests/lib/rules/space-unary-ops.ts @@ -9,7 +9,7 @@ const tester = new RuleTester({ }, }); -tester.run("space-unary-ops", rule as any, { +tester.run("space-unary-ops", rule, { valid: ["-1", "+1", "-0", "+0"], invalid: [ { diff --git a/tests/lib/rules/valid-json-number.ts b/tests/lib/rules/valid-json-number.ts index b8cfd523..10571596 100644 --- a/tests/lib/rules/valid-json-number.ts +++ b/tests/lib/rules/valid-json-number.ts @@ -10,7 +10,7 @@ const tester = new RuleTester({ }, }); -tester.run("valid-json-number", rule as any, { +tester.run("valid-json-number", rule, { valid: [ "[123, 0.4, -42]", // not target diff --git a/tests/lib/rules/vue-custom-block/no-parsing-error.ts b/tests/lib/rules/vue-custom-block/no-parsing-error.ts index 7574865c..95069a44 100644 --- a/tests/lib/rules/vue-custom-block/no-parsing-error.ts +++ b/tests/lib/rules/vue-custom-block/no-parsing-error.ts @@ -10,7 +10,7 @@ const tester = new RuleTester({ }, }); -tester.run("vue-custom-block/no-parsing-error", rule as any, { +tester.run("vue-custom-block/no-parsing-error", rule, { valid: [ '{"key": "value"}', '"string"', diff --git a/tests/lib/test-lib/tester.ts b/tests/lib/test-lib/tester.ts index e8a9d760..492262af 100644 --- a/tests/lib/test-lib/tester.ts +++ b/tests/lib/test-lib/tester.ts @@ -3,6 +3,7 @@ import { getRuleTester } from "eslint-compat-utils/rule-tester"; import * as jsonParser from "jsonc-eslint-parser"; import semver from "semver"; import { getESLint } from "eslint-compat-utils/eslint"; +import type { RuleModule } from "../../../lib/types"; const RuleTester = getRuleTester(); const ESLint = getESLint(); @@ -51,15 +52,15 @@ class JSONRuleTester { : null; } - public run( + public run( name: string, - rule: any, + rule: RuleModule, tests: { valid: (string | ValidTestCase)[]; invalid: InvalidTestCase[]; }, ): void { - this.testerForBase.run(name, rule, { + this.testerForBase.run(name, rule as unknown as eslint.Rule.RuleModule, { ...tests, valid: tests.valid.map((test) => { if (typeof test === "string") { @@ -95,7 +96,7 @@ class JSONRuleTester { const testerForMomoa = this.testerForMomoa; if (!testerForMomoa) return; describe(`${name} with momoa`, () => { - testerForMomoa.run(name, rule, { + testerForMomoa.run(name, rule as unknown as eslint.Rule.RuleModule, { valid: valid.map((test) => { if (typeof test === "string") { return test; diff --git a/tools/new-rule.ts b/tools/new-rule.ts index 3ea1097a..a9f7531e 100644 --- a/tools/new-rule.ts +++ b/tools/new-rule.ts @@ -65,7 +65,7 @@ const tester = new RuleTester({ }, }) -tester.run("${ruleId}", rule as any, { +tester.run("${ruleId}", rule, { valid: [ '{"key": "value"}', '"string"', '["element"]' ],