diff --git a/.changeset/sour-beds-juggle.md b/.changeset/sour-beds-juggle.md new file mode 100644 index 000000000000..411aee89313f --- /dev/null +++ b/.changeset/sour-beds-juggle.md @@ -0,0 +1,11 @@ +--- +"@biomejs/biome": patch +--- + +Added the nursery rule [`noTopLevelLiterals`](https://biomejs.dev/linter/rules/no-top-level-literals/). It requires the root-level value to be an array or object. + +**Invalid:** + +```json +"just a string" +``` diff --git a/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs b/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs index 7d2d43723a3d..84edb1c32fed 100644 --- a/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs +++ b/crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs @@ -1473,6 +1473,18 @@ pub(crate) fn migrate_eslint_any_rule( .get_or_insert(Default::default()); rule.set_level(rule.level().max(rule_severity.into())); } + "json/top-level-interop" => { + if !options.include_nursery { + results.add(eslint_name, eslint_to_biome::RuleMigrationResult::Nursery); + return false; + } + let group = rules.nursery.get_or_insert_with(Default::default); + let rule = group + .unwrap_group_as_mut() + .no_top_level_literals + .get_or_insert(Default::default()); + rule.set_level(rule.level().max(rule_severity.into())); + } "jsx-a11y/alt-text" => { let group = rules.a11y.get_or_insert_with(Default::default); let rule = group diff --git a/crates/biome_configuration/src/analyzer/linter/rules.rs b/crates/biome_configuration/src/analyzer/linter/rules.rs index 8a4030983bed..7e8bbd6c6d0f 100644 --- a/crates/biome_configuration/src/analyzer/linter/rules.rs +++ b/crates/biome_configuration/src/analyzer/linter/rules.rs @@ -314,6 +314,7 @@ pub enum RuleName { NoTernary, NoThenProperty, NoThisInStatic, + NoTopLevelLiterals, NoTsIgnore, NoUnassignedVariables, NoUndeclaredDependencies, @@ -779,6 +780,7 @@ impl RuleName { Self::NoTernary => "noTernary", Self::NoThenProperty => "noThenProperty", Self::NoThisInStatic => "noThisInStatic", + Self::NoTopLevelLiterals => "noTopLevelLiterals", Self::NoTsIgnore => "noTsIgnore", Self::NoUnassignedVariables => "noUnassignedVariables", Self::NoUndeclaredDependencies => "noUndeclaredDependencies", @@ -1240,6 +1242,7 @@ impl RuleName { Self::NoTernary => RuleGroup::Nursery, Self::NoThenProperty => RuleGroup::Suspicious, Self::NoThisInStatic => RuleGroup::Complexity, + Self::NoTopLevelLiterals => RuleGroup::Nursery, Self::NoTsIgnore => RuleGroup::Suspicious, Self::NoUnassignedVariables => RuleGroup::Suspicious, Self::NoUndeclaredDependencies => RuleGroup::Correctness, @@ -1710,6 +1713,7 @@ impl std::str::FromStr for RuleName { "noTernary" => Ok(Self::NoTernary), "noThenProperty" => Ok(Self::NoThenProperty), "noThisInStatic" => Ok(Self::NoThisInStatic), + "noTopLevelLiterals" => Ok(Self::NoTopLevelLiterals), "noTsIgnore" => Ok(Self::NoTsIgnore), "noUnassignedVariables" => Ok(Self::NoUnassignedVariables), "noUndeclaredDependencies" => Ok(Self::NoUndeclaredDependencies), diff --git a/crates/biome_diagnostics_categories/src/categories.rs b/crates/biome_diagnostics_categories/src/categories.rs index 5e5b6b6881e0..fe889cccb9d4 100644 --- a/crates/biome_diagnostics_categories/src/categories.rs +++ b/crates/biome_diagnostics_categories/src/categories.rs @@ -256,16 +256,18 @@ define_categories! { "lint/nursery/useJsxCurlyBraceConvention": "https://biomejs.dev/linter/rules/use-jsx-curly-brace-convention", "lint/nursery/useLoneAnonymousOperation": "https://biomejs.dev/linter/rules/use-lone-anonymous-operation", "lint/nursery/useLoneExecutableDefinition": "https://biomejs.dev/linter/rules/use-lone-executable-definition", - "lint/nursery/useNullishCoalescing": "https://biomejs.dev/linter/rules/use-nullish-coalescing", "lint/nursery/useMaxParams": "https://biomejs.dev/linter/rules/use-max-params", "lint/nursery/useNamedCaptureGroup": "https://biomejs.dev/linter/rules/use-named-capture-group", + "lint/nursery/useNullishCoalescing": "https://biomejs.dev/linter/rules/use-nullish-coalescing", "lint/nursery/usePlaywrightValidDescribeCallback": "https://biomejs.dev/linter/rules/use-playwright-valid-describe-callback", "lint/nursery/useQwikMethodUsage": "https://biomejs.dev/linter/rules/use-qwik-method-usage", "lint/nursery/useQwikValidLexicalScope": "https://biomejs.dev/linter/rules/use-qwik-valid-lexical-scope", "lint/nursery/useRegexpExec": "https://biomejs.dev/linter/rules/use-regexp-exec", "lint/nursery/useRequiredScripts": "https://biomejs.dev/linter/rules/use-required-scripts", + "lint/nursery/useScopedStyles": "https://biomejs.dev/linter/rules/use-scoped-styles", "lint/nursery/useSortedClasses": "https://biomejs.dev/linter/rules/use-sorted-classes", "lint/nursery/useSpread": "https://biomejs.dev/linter/rules/use-spread", + "lint/nursery/noTopLevelLiterals": "https://biomejs.dev/linter/rules/no-top-level-literals", "lint/nursery/useUnicodeRegex": "https://biomejs.dev/linter/rules/use-unicode-regex", "lint/nursery/useUniqueArgumentNames": "https://biomejs.dev/linter/rules/use-unique-argument-names", "lint/nursery/useUniqueFieldDefinitionNames": "https://biomejs.dev/linter/rules/use-unique-field-definition-names", @@ -278,7 +280,6 @@ define_categories! { "lint/nursery/useVueDefineMacrosOrder": "https://biomejs.dev/linter/rules/use-vue-define-macros-order", "lint/nursery/useVueHyphenatedAttributes": "https://biomejs.dev/linter/rules/use-vue-hyphenated-attributes", "lint/nursery/useVueMultiWordComponentNames": "https://biomejs.dev/linter/rules/use-vue-multi-word-component-names", - "lint/nursery/useScopedStyles": "https://biomejs.dev/linter/rules/use-scoped-styles", "lint/nursery/useVueVForKey": "https://biomejs.dev/linter/rules/use-vue-v-for-key", "lint/nursery/useVueValidTemplateRoot": "https://biomejs.dev/linter/rules/use-vue-valid-template-root", "lint/nursery/useVueValidVBind": "https://biomejs.dev/linter/rules/use-vue-valid-v-bind", diff --git a/crates/biome_json_analyze/src/lint/nursery/no_top_level_literals.rs b/crates/biome_json_analyze/src/lint/nursery/no_top_level_literals.rs new file mode 100644 index 000000000000..50582663dac7 --- /dev/null +++ b/crates/biome_json_analyze/src/lint/nursery/no_top_level_literals.rs @@ -0,0 +1,100 @@ +use biome_analyze::{ + Ast, Rule, RuleDiagnostic, RuleSource, context::RuleContext, declare_lint_rule, +}; +use biome_console::markup; +use biome_json_syntax::{AnyJsonValue, JsonRoot}; +use biome_rowan::AstNode; +use biome_rule_options::no_top_level_literals::NoTopLevelLiteralsOptions; + +declare_lint_rule! { + /// Require the JSON top-level value to be an array or object. + /// + /// The JSON specification technically allows any JSON value (object, array, string, number, boolean, or null) to be used as the top-level element of a JSON document. + /// However, some older JSON parsers, especially those created before [RFC 7158](https://datatracker.ietf.org/doc/html/rfc7158)/[4627](https://datatracker.ietf.org/doc/html/rfc4627) was fully adopted, only support objects or arrays as the root element. + /// + /// Additionally, some security practices (such as those preventing JSON hijacking attacks) rely on the assumption that the top-level value is an object or array. + /// Using an object or array at the top level also provides better extensibility for your data structures over time. + /// + /// ## Examples + /// + /// ### Invalid + /// + /// ```json,expect_diagnostic + /// "just a string" + /// ``` + /// + /// ```json,expect_diagnostic + /// 42 + /// ``` + /// + /// ```json,expect_diagnostic + /// true + /// ``` + /// + /// ```json,expect_diagnostic + /// null + /// ``` + /// + /// ### Valid + /// + /// ```json + /// { + /// "property": "value", + /// "otherProperty": 123 + /// } + /// ``` + /// + /// ```json + /// ["element", "anotherElement"] + /// ``` + /// + /// ```json + /// {} + /// ``` + /// + /// ```json + /// [] + /// ``` + /// + pub NoTopLevelLiterals { + version: "next", + name: "noTopLevelLiterals", + language: "json", + recommended: false, + sources: &[RuleSource::EslintJson("top-level-interop").same()], + } +} + +impl Rule for NoTopLevelLiterals { + type Query = Ast; + type State = (); + type Signals = Option; + type Options = NoTopLevelLiteralsOptions; + + fn run(ctx: &RuleContext) -> Self::Signals { + let node = ctx.query(); + let value = node.value().ok()?; + + match value { + AnyJsonValue::JsonObjectValue(_) => None, + AnyJsonValue::JsonArrayValue(_) => None, + _ => Some(()), + } + } + + fn diagnostic(ctx: &RuleContext, _state: &Self::State) -> Option { + let span = ctx.query().range(); + Some( + RuleDiagnostic::new( + rule_category!(), + span, + markup! { + "Expected the top-level value to be an array or object." + }, + ) + .note(markup! { + "Some JSON parsers only support objects or arrays as the root element. Wrap your value in an array or object to ensure compatibility." + }), + ) + } +} diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/boolean.json b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/boolean.json new file mode 100644 index 000000000000..27ba77ddaf61 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/boolean.json @@ -0,0 +1 @@ +true diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/boolean.json.snap b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/boolean.json.snap new file mode 100644 index 000000000000..65d739c49e52 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/boolean.json.snap @@ -0,0 +1,26 @@ +--- +source: crates/biome_json_analyze/tests/spec_tests.rs +expression: boolean.json +--- +# Input +```json +true + +``` + +# Diagnostics +``` +boolean.json:1:1 lint/nursery/noTopLevelLiterals ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i Expected the top-level value to be an array or object. + + > 1 │ true + │ ^^^^ + 2 │ + + i Some JSON parsers only support objects or arrays as the root element. Wrap your value in an array or object to ensure compatibility. + + i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information. + + +``` diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/null.json b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/null.json new file mode 100644 index 000000000000..19765bd501b6 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/null.json @@ -0,0 +1 @@ +null diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/null.json.snap b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/null.json.snap new file mode 100644 index 000000000000..9aed637fb338 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/null.json.snap @@ -0,0 +1,26 @@ +--- +source: crates/biome_json_analyze/tests/spec_tests.rs +expression: null.json +--- +# Input +```json +null + +``` + +# Diagnostics +``` +null.json:1:1 lint/nursery/noTopLevelLiterals ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i Expected the top-level value to be an array or object. + + > 1 │ null + │ ^^^^ + 2 │ + + i Some JSON parsers only support objects or arrays as the root element. Wrap your value in an array or object to ensure compatibility. + + i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information. + + +``` diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/number.json b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/number.json new file mode 100644 index 000000000000..d81cc0710eb6 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/number.json @@ -0,0 +1 @@ +42 diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/number.json.snap b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/number.json.snap new file mode 100644 index 000000000000..692a92b88748 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/number.json.snap @@ -0,0 +1,26 @@ +--- +source: crates/biome_json_analyze/tests/spec_tests.rs +expression: number.json +--- +# Input +```json +42 + +``` + +# Diagnostics +``` +number.json:1:1 lint/nursery/noTopLevelLiterals ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i Expected the top-level value to be an array or object. + + > 1 │ 42 + │ ^^ + 2 │ + + i Some JSON parsers only support objects or arrays as the root element. Wrap your value in an array or object to ensure compatibility. + + i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information. + + +``` diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/string.json b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/string.json new file mode 100644 index 000000000000..7deb8b173227 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/string.json @@ -0,0 +1 @@ +"just a string" diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/string.json.snap b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/string.json.snap new file mode 100644 index 000000000000..7c18fd68050d --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/invalid/string.json.snap @@ -0,0 +1,26 @@ +--- +source: crates/biome_json_analyze/tests/spec_tests.rs +expression: string.json +--- +# Input +```json +"just a string" + +``` + +# Diagnostics +``` +string.json:1:1 lint/nursery/noTopLevelLiterals ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i Expected the top-level value to be an array or object. + + > 1 │ "just a string" + │ ^^^^^^^^^^^^^^^ + 2 │ + + i Some JSON parsers only support objects or arrays as the root element. Wrap your value in an array or object to ensure compatibility. + + i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information. + + +``` diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/array.json b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/array.json new file mode 100644 index 000000000000..1e5af6591a3a --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/array.json @@ -0,0 +1,5 @@ +[ + "one", + "two", + "three" +] diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/array.json.snap b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/array.json.snap new file mode 100644 index 000000000000..2ce95ff7b812 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/array.json.snap @@ -0,0 +1,13 @@ +--- +source: crates/biome_json_analyze/tests/spec_tests.rs +expression: array.json +--- +# Input +```json +[ + "one", + "two", + "three" +] + +``` diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/empty-array.json b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/empty-array.json new file mode 100644 index 000000000000..fe51488c7066 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/empty-array.json @@ -0,0 +1 @@ +[] diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/empty-array.json.snap b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/empty-array.json.snap new file mode 100644 index 000000000000..d2fec95f3413 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/empty-array.json.snap @@ -0,0 +1,9 @@ +--- +source: crates/biome_json_analyze/tests/spec_tests.rs +expression: empty-array.json +--- +# Input +```json +[] + +``` diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/empty-object.json b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/empty-object.json new file mode 100644 index 000000000000..0967ef424bce --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/empty-object.json @@ -0,0 +1 @@ +{} diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/empty-object.json.snap b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/empty-object.json.snap new file mode 100644 index 000000000000..9f3acbc4ead6 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/empty-object.json.snap @@ -0,0 +1,9 @@ +--- +source: crates/biome_json_analyze/tests/spec_tests.rs +expression: empty-object.json +--- +# Input +```json +{} + +``` diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/object.json b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/object.json new file mode 100644 index 000000000000..3e746ae55b96 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/object.json @@ -0,0 +1,5 @@ +{ + "one": "value", + "two": "value", + "three": "value" +} diff --git a/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/object.json.snap b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/object.json.snap new file mode 100644 index 000000000000..66c4b632c1b4 --- /dev/null +++ b/crates/biome_json_analyze/tests/specs/nursery/noTopLevelLiterals/valid/object.json.snap @@ -0,0 +1,13 @@ +--- +source: crates/biome_json_analyze/tests/spec_tests.rs +expression: object.json +--- +# Input +```json +{ + "one": "value", + "two": "value", + "three": "value" +} + +``` diff --git a/crates/biome_rule_options/src/lib.rs b/crates/biome_rule_options/src/lib.rs index 9bbf6842a310..3e86f88791c4 100644 --- a/crates/biome_rule_options/src/lib.rs +++ b/crates/biome_rule_options/src/lib.rs @@ -228,6 +228,7 @@ pub mod no_template_curly_in_string; pub mod no_ternary; pub mod no_then_property; pub mod no_this_in_static; +pub mod no_top_level_literals; pub mod no_ts_ignore; pub mod no_unassigned_variables; pub mod no_undeclared_dependencies; diff --git a/crates/biome_rule_options/src/no_top_level_literals.rs b/crates/biome_rule_options/src/no_top_level_literals.rs new file mode 100644 index 000000000000..b750105c598f --- /dev/null +++ b/crates/biome_rule_options/src/no_top_level_literals.rs @@ -0,0 +1,6 @@ +use biome_deserialize_macros::{Deserializable, Merge}; +use serde::{Deserialize, Serialize}; +#[derive(Default, Clone, Debug, Deserialize, Deserializable, Merge, Eq, PartialEq, Serialize)] +#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] +#[serde(rename_all = "camelCase", deny_unknown_fields, default)] +pub struct NoTopLevelLiteralsOptions {} diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 3288cff34b0d..8b41272c70c8 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -2276,6 +2276,11 @@ See https://biomejs.dev/linter/rules/no-ternary */ noTernary?: NoTernaryConfiguration; /** + * Require the JSON top-level value to be an array or object. +See https://biomejs.dev/linter/rules/no-top-level-literals + */ + noTopLevelLiterals?: NoTopLevelLiteralsConfiguration; + /** * Disallow the use of undeclared environment variables. See https://biomejs.dev/linter/rules/no-undeclared-env-vars */ @@ -4201,6 +4206,9 @@ export type NoSyncScriptsConfiguration = export type NoTernaryConfiguration = | RulePlainConfiguration | RuleWithNoTernaryOptions; +export type NoTopLevelLiteralsConfiguration = + | RulePlainConfiguration + | RuleWithNoTopLevelLiteralsOptions; export type NoUndeclaredEnvVarsConfiguration = | RulePlainConfiguration | RuleWithNoUndeclaredEnvVarsOptions; @@ -5883,6 +5891,10 @@ export interface RuleWithNoTernaryOptions { level: RulePlainConfiguration; options?: NoTernaryOptions; } +export interface RuleWithNoTopLevelLiteralsOptions { + level: RulePlainConfiguration; + options?: NoTopLevelLiteralsOptions; +} export interface RuleWithNoUndeclaredEnvVarsOptions { level: RulePlainConfiguration; options?: NoUndeclaredEnvVarsOptions; @@ -7381,6 +7393,7 @@ export type NoScriptUrlOptions = {}; export type NoShadowOptions = {}; export type NoSyncScriptsOptions = {}; export type NoTernaryOptions = {}; +export type NoTopLevelLiteralsOptions = {}; export interface NoUndeclaredEnvVarsOptions { /** * Environment variables that should always be allowed. @@ -8430,16 +8443,18 @@ export type Category = | "lint/nursery/useJsxCurlyBraceConvention" | "lint/nursery/useLoneAnonymousOperation" | "lint/nursery/useLoneExecutableDefinition" - | "lint/nursery/useNullishCoalescing" | "lint/nursery/useMaxParams" | "lint/nursery/useNamedCaptureGroup" + | "lint/nursery/useNullishCoalescing" | "lint/nursery/usePlaywrightValidDescribeCallback" | "lint/nursery/useQwikMethodUsage" | "lint/nursery/useQwikValidLexicalScope" | "lint/nursery/useRegexpExec" | "lint/nursery/useRequiredScripts" + | "lint/nursery/useScopedStyles" | "lint/nursery/useSortedClasses" | "lint/nursery/useSpread" + | "lint/nursery/noTopLevelLiterals" | "lint/nursery/useUnicodeRegex" | "lint/nursery/useUniqueArgumentNames" | "lint/nursery/useUniqueFieldDefinitionNames" @@ -8452,7 +8467,6 @@ export type Category = | "lint/nursery/useVueDefineMacrosOrder" | "lint/nursery/useVueHyphenatedAttributes" | "lint/nursery/useVueMultiWordComponentNames" - | "lint/nursery/useScopedStyles" | "lint/nursery/useVueVForKey" | "lint/nursery/useVueValidTemplateRoot" | "lint/nursery/useVueValidVBind" diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index 9674bfb4b581..aad037dd5f11 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -4982,6 +4982,16 @@ "type": "object", "additionalProperties": false }, + "NoTopLevelLiteralsConfiguration": { + "oneOf": [ + { "$ref": "#/$defs/RulePlainConfiguration" }, + { "$ref": "#/$defs/RuleWithNoTopLevelLiteralsOptions" } + ] + }, + "NoTopLevelLiteralsOptions": { + "type": "object", + "additionalProperties": false + }, "NoTsIgnoreConfiguration": { "oneOf": [ { "$ref": "#/$defs/RulePlainConfiguration" }, @@ -6081,6 +6091,13 @@ { "type": "null" } ] }, + "noTopLevelLiterals": { + "description": "Require the JSON top-level value to be an array or object.\nSee https://biomejs.dev/linter/rules/no-top-level-literals", + "anyOf": [ + { "$ref": "#/$defs/NoTopLevelLiteralsConfiguration" }, + { "type": "null" } + ] + }, "noUndeclaredEnvVars": { "description": "Disallow the use of undeclared environment variables.\nSee https://biomejs.dev/linter/rules/no-undeclared-env-vars", "anyOf": [ @@ -9113,6 +9130,15 @@ "additionalProperties": false, "required": ["level"] }, + "RuleWithNoTopLevelLiteralsOptions": { + "type": "object", + "properties": { + "level": { "$ref": "#/$defs/RulePlainConfiguration" }, + "options": { "$ref": "#/$defs/NoTopLevelLiteralsOptions" } + }, + "additionalProperties": false, + "required": ["level"] + }, "RuleWithNoTsIgnoreOptions": { "type": "object", "properties": {