diff --git a/.changeset/v-vapor-rule.md b/.changeset/v-vapor-rule.md new file mode 100644 index 000000000000..39344981aaf5 --- /dev/null +++ b/.changeset/v-vapor-rule.md @@ -0,0 +1,5 @@ +--- +"@biomejs/biome": patch +--- + +Added the nursery rule `useVueVapor` to enforce ` + /// ``` + /// + /// ### Valid + /// + /// ```vue + /// + /// ``` + /// + pub UseVueVapor { + version: "next", + name: "useVueVapor", + language: "html", + recommended: false, + domains: &[RuleDomain::Vue], + sources: &[], + fix_kind: FixKind::Unsafe, + } +} + +impl Rule for UseVueVapor { + type Query = Ast; + type State = (); + type Signals = Option; + type Options = UseVueVaporOptions; + + fn run(ctx: &RuleContext) -> Self::Signals { + let opening = ctx.query(); + + let name = opening.name().ok()?; + let name_token = name.value_token().ok()?; + if !name_token.text_trimmed().eq_ignore_ascii_case("script") { + return None; + } + + let attributes = opening.attributes(); + attributes.find_by_name("setup")?; + + if attributes.find_by_name("vapor").is_some() { + return None; + } + + Some(()) + } + + fn diagnostic(ctx: &RuleContext, _state: &Self::State) -> Option { + Some( + RuleDiagnostic::new( + rule_category!(), + ctx.query().range(), + markup! { + "This "" + + + + diff --git a/crates/biome_html_analyze/tests/specs/nursery/useVueVapor/invalid.vue.snap b/crates/biome_html_analyze/tests/specs/nursery/useVueVapor/invalid.vue.snap new file mode 100644 index 000000000000..3a3a480e67d9 --- /dev/null +++ b/crates/biome_html_analyze/tests/specs/nursery/useVueVapor/invalid.vue.snap @@ -0,0 +1,66 @@ +--- +source: crates/biome_html_analyze/tests/spec_tests.rs +expression: invalid.vue +--- +# Input +```html + + + + + + + + +``` + +# Diagnostics +``` +invalid.vue:3:1 lint/nursery/useVueVapor FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + i This + + i Add vapor to opt in to Vue Vapor mode: + 6 │ + > 7 │ + + i Add vapor to opt in to Vue Vapor mode: + + + + + + diff --git a/crates/biome_html_analyze/tests/specs/nursery/useVueVapor/valid.vue.snap b/crates/biome_html_analyze/tests/specs/nursery/useVueVapor/valid.vue.snap new file mode 100644 index 000000000000..33c0e0673378 --- /dev/null +++ b/crates/biome_html_analyze/tests/specs/nursery/useVueVapor/valid.vue.snap @@ -0,0 +1,23 @@ +--- +source: crates/biome_html_analyze/tests/spec_tests.rs +expression: valid.vue +--- +# Input +```html + + + + + + + + + + +``` diff --git a/crates/biome_rule_options/src/lib.rs b/crates/biome_rule_options/src/lib.rs index 1cc128909ad6..6464645f7254 100644 --- a/crates/biome_rule_options/src/lib.rs +++ b/crates/biome_rule_options/src/lib.rs @@ -416,5 +416,6 @@ pub mod use_vue_valid_v_on; pub mod use_vue_valid_v_once; pub mod use_vue_valid_v_pre; pub mod use_vue_valid_v_text; +pub mod use_vue_vapor; pub mod use_while; pub mod use_yield; diff --git a/crates/biome_rule_options/src/use_vue_vapor.rs b/crates/biome_rule_options/src/use_vue_vapor.rs new file mode 100644 index 000000000000..22ee82dd9635 --- /dev/null +++ b/crates/biome_rule_options/src/use_vue_vapor.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 UseVueVaporOptions {} diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 1bd519a79312..c46d44240ca3 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -2257,6 +2257,11 @@ See See */ useVueValidVText?: UseVueValidVTextConfiguration; + /** + * Enforce opting in to Vue Vapor mode in \