-
-
Notifications
You must be signed in to change notification settings - Fork 750
feat(lint): implement no-unknown-property from eslint react
#7774
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🦋 Changeset detectedLatest commit: 30307bf The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
no-unknown-property from eslint react
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A good first draft :)
Also, this should implement the ignore option for the css rule.
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
Outdated
Show resolved
Hide resolved
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
Outdated
Show resolved
Hide resolved
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
Outdated
Show resolved
Hide resolved
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
Outdated
Show resolved
Hide resolved
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
Outdated
Show resolved
Hide resolved
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
Outdated
Show resolved
Hide resolved
crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/ignore/valid.options.json
Show resolved
Hide resolved
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
Outdated
Show resolved
Hide resolved
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
Outdated
Show resolved
Hide resolved
CodSpeed Performance ReportMerging #7774 will not alter performanceComparing Summary
Footnotes
|
- Remove to_lowercase from most places - Added react domain to the rule - Removed regex and replaced with custom if checks - Merged two constant arrays to avoid allocations - remove TextRange from State, to use ctx.query() - Used standard messages for diagnostics
WalkthroughAdds a new nursery lint rule Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used📓 Path-based instructions (1).changeset/*.md📄 CodeRabbit inference engine (CONTRIBUTING.md)
Files:
🧠 Learnings (6)📓 Common learnings📚 Learning: 2025-10-26T15:28:00.951ZApplied to files:
📚 Learning: 2025-08-05T14:43:29.581ZApplied to files:
📚 Learning: 2025-09-25T12:32:59.003ZApplied to files:
📚 Learning: 2025-10-24T21:24:58.650ZApplied to files:
📚 Learning: 2025-10-26T15:28:00.951ZApplied to files:
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
.changeset/small-words-show.md (1)
5-5: Tighten the changeset copy, add examples, and fix the link.
- Use past tense, proper naming (“eslint‑plugin‑react”), and end sentences with a period.
- Add tiny valid/invalid examples.
- Point to the correct rule page; the current slug likely collides with the CSS rule page. Update once the docs page exists.
Apply this diff:
-Added the new rule [`no-unknown-property`](https://biomejs.dev/linter/rules/no-unknown-property/) from eslint react +#### Lint rules. + +Added the new nursery rule [`noUnknownProperty`](<update-with-correct-docs-url>) ported from `eslint-plugin-react`. + +Examples: + +```jsx +/* valid */ +<App class="foo" /><div data-foo="bar" /> +``` + +```jsx +/* invalid */ +<div class="foo" /><div data-testID="bar" /> +```As per coding guidelines.
🧹 Nitpick comments (10)
crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.jsx (1)
1-6: Nice focused “ignore” case.Consider adding a sibling negative case (property not on the ignore list) to prove the rule still fires.
crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.jsx (1)
1-4: Confirm parity on custom components.Do we intend
requireDataLowercaseto apply to custom components like<App />? ESLint’s rule often limits DOM‑prop checks to host elements. If we want parity, scope this to intrinsic elements; if we want stricter Biome behaviour, keep as is and document it.crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/valid.jsx (1)
1-204: Big omnibus “valid” test – consider splitting by theme.Smaller themed fixtures (events, SVG, boolean attrs, data/aria, legacy attrs) make diffs and failures easier to triage. Also keep the React 19 popover block gated in a dedicated future test.
Quick sweep for potential tag‑specific mismatches (e.g.
allowFullScreenon non‑iframe) would be good to double‑check against the rule’s allowed‑tags map.crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/invalid.jsx (2)
21-38: Add popover/onBeforeToggle cases to lock React 19 supportPlease add invalid/valid cases for popover API:
- Attributes: popover, popovertarget, popovertargetaction.
- Events: onBeforeToggle/onToggle on allowed tags.
This prevents regressions and aligns with your commented code in the rule.
1-3: Consider a companion valid case for custom elementsAdd a valid fixture using a custom element (e.g., ) to assert the rule skips custom elements and tags with an is attribute. This documents intent.
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs (5)
1065-1077: Avoid avoidable allocations for attribute namesname/value_token().text_trimmed().to_string() and the manual namespace concatenation allocate on every attribute. Use TokenText and Cow to allocate only for namespaced cases.
@@ - let node_name = match node.name().ok()? { - AnyJsxAttributeName::JsxName(name) => { - name.value_token().ok()?.text_trimmed().to_string() - } - AnyJsxAttributeName::JsxNamespaceName(name) => { - let namespace = name.namespace().ok()?.value_token().ok()?; - let name = &name.name().ok()?.value_token().ok()?; - // There could be better way, but i couldn't extract namespaced attributes - // For e.g xlink:href - // without manually concatenating with ':' - namespace.text_trimmed().to_string() + ":" + name.text_trimmed() - } - }; + use std::borrow::Cow; + let node_name: Cow<'_, str> = match node.name().ok()? { + AnyJsxAttributeName::JsxName(name) => { + Cow::Borrowed(name.value_token().ok()?.text_trimmed()) + } + AnyJsxAttributeName::JsxNamespaceName(name) => { + let ns = name.namespace().ok()?.value_token().ok()?.text_trimmed(); + let local = name.name().ok()?.value_token().ok()?.text_trimmed(); + Cow::Owned(format!("{ns}:{local}")) + } + }; @@ - if options.ignore.contains(&node_name) { + if options.ignore.iter().any(|s| s == &*node_name) { return None; } @@ - let name = normalize_attribute_case(&node_name); + let name = normalize_attribute_case(&node_name);Also applies to: 1079-1081
1009-1014: Simplify tag_name_has_dot signatureThis always returns Some(..). Make it return bool and drop ? at call sites; avoids needless Option churn.
-fn tag_name_has_dot(node: &AnyJsxElement) -> Option<bool> { - Some(matches!( - node.name().ok()?, - AnyJsxElementName::JsxMemberName(_) - )) -} +fn tag_name_has_dot(node: &AnyJsxElement) -> bool { + matches!(node.name().ok(), Ok(AnyJsxElementName::JsxMemberName(_))) +} @@ - if tag_name_has_dot(&element)? { + if tag_name_has_dot(&element) { return None; }
1167-1183: Minor copy tweakThe diagnostic says “for React components”, but this rule validates DOM elements after gating out components. Suggest “in JSX” to avoid confusion.
- "Use '"{standard_name}"' instead of '"{name}"' for React components." + "Use '"{standard_name}"' instead of '"{name}"' in JSX."
1484-1510: Use case‑insensitive check for data‑ only after the prefix*Current has_uppercase(name) flags any uppercase anywhere, which is fine, but the option intent is about the part after data-. Consider restricting the scan to the suffix to keep the message crisp for odd inputs.
- if options.require_data_lowercase && has_uppercase(&name) { + if options.require_data_lowercase { + let suffix = &name["data-".len()..]; + if has_uppercase(suffix) { return Some(NoUnknownPropertyDiagnostic::DataLowercaseRequired { name: name.to_string(), lowercase_name: name.to_lowercase(), }); - } + } + }
226-231: Keys are sorted — guard test is defensive, not criticalThe
ATTRIBUTE_TAGS_MAPkeys are currently sorted and the code is correct. However, the suggestion to add a guard test is reasonable: without one, future edits could accidentally break sort order without triggering a compile-time error, andbinary_search_by_keywould silently fail at runtime.Consider adding a simple unit test at the end of the file to assert the map remains sorted:
#[cfg(test)] mod tests { use super::*; #[test] fn attribute_tags_map_is_sorted() { let keys: Vec<_> = ATTRIBUTE_TAGS_MAP.iter().map(|(k, _)| k).collect(); let mut sorted = keys.clone(); sorted.sort(); assert_eq!(keys, sorted, "ATTRIBUTE_TAGS_MAP keys must remain sorted for binary_search_by_key"); } }
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (11)
crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rsis excluded by!**/migrate/eslint_any_rule_to_biome.rsand included by**crates/biome_configuration/src/analyzer/linter/rules.rsis excluded by!**/rules.rsand included by**crates/biome_configuration/src/generated/domain_selector.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_diagnostics_categories/src/categories.rsis excluded by!**/categories.rsand included by**crates/biome_js_analyze/src/lint/nursery.rsis excluded by!**/nursery.rsand included by**crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.jsx.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/invalid.jsx.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.jsx.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/valid.jsx.snapis excluded by!**/*.snapand included by**packages/@biomejs/backend-jsonrpc/src/workspace.tsis excluded by!**/backend-jsonrpc/src/workspace.tsand included by**packages/@biomejs/biome/configuration_schema.jsonis excluded by!**/configuration_schema.jsonand included by**
📒 Files selected for processing (10)
.changeset/small-words-show.md(1 hunks)crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs(1 hunks)crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.jsx(1 hunks)crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.options.json(1 hunks)crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/invalid.jsx(1 hunks)crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.jsx(1 hunks)crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.options.json(1 hunks)crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/valid.jsx(1 hunks)crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/valid.package.json(1 hunks)crates/biome_rule_options/src/no_unknown_property.rs(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
crates/biome_*/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place core crates under /crates/biome_*/
Files:
crates/biome_rule_options/src/no_unknown_property.rscrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/valid.jsxcrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.options.jsoncrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.options.jsoncrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/invalid.jsxcrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.jsxcrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/valid.package.jsoncrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.jsxcrates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
**/*.rs
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.rs: Format Rust files before committing (e.g., viajust fwhich formats Rust)
Document rules, assists, and options with inline rustdoc in source
Files:
crates/biome_rule_options/src/no_unknown_property.rscrates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
crates/biome_*_{syntax,parser,formatter,analyze,factory,semantic}/**
📄 CodeRabbit inference engine (CLAUDE.md)
Maintain the per-language crate structure: biome_{lang}_{syntax,parser,formatter,analyze,factory,semantic}
Files:
crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/valid.jsxcrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.options.jsoncrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.options.jsoncrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/invalid.jsxcrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.jsxcrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/valid.package.jsoncrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.jsxcrates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
**/tests/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place test files under a tests/ directory in each crate
Files:
crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/valid.jsxcrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.options.jsoncrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.options.jsoncrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/invalid.jsxcrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.jsxcrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/valid.package.jsoncrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.jsx
.changeset/*.md
📄 CodeRabbit inference engine (CONTRIBUTING.md)
.changeset/*.md: In changesets, only use #### or ##### headers; other header levels are not allowed
Changesets should cover user-facing changes only; internal changes do not need changesets
Use past tense for what you did and present tense for current Biome behavior in changesets
When fixing a bug in a changeset, start with an issue link (e.g., “Fixed #1234: …”)
When referencing a rule or assist in a changeset, include a link to its page on the website
Include code blocks in changesets when applicable to illustrate changes
End every sentence in a changeset with a period
Files:
.changeset/small-words-show.md
🧠 Learnings (6)
📚 Learning: 2025-10-15T09:20:19.139Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:20:19.139Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : For options types, derive Serialize, Deserialize, Deserializable (and JsonSchema under the schema feature) and use #[serde(rename_all="camelCase", deny_unknown_fields, default)] with skip_serializing_if where appropriate
Applied to files:
crates/biome_rule_options/src/no_unknown_property.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/tests/specs/**/options.json : Use options.json files colocated with test inputs to override formatting options for all files in that folder
Applied to files:
crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.options.json
📚 Learning: 2025-08-05T14:43:29.581Z
Learnt from: dyc3
PR: biomejs/biome#7081
File: packages/@biomejs/biome/configuration_schema.json:7765-7781
Timestamp: 2025-08-05T14:43:29.581Z
Learning: The file `packages/biomejs/biome/configuration_schema.json` is auto-generated and should not be manually edited or reviewed for schema issues; any changes should be made at the code generation source.
Applied to files:
crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.options.jsoncrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.options.json
📚 Learning: 2025-10-15T09:20:19.139Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:20:19.139Z
Learning: Applies to crates/biome_analyze/**/tests/specs/**/*.{js,jsx,ts,tsx} : Place snapshot test cases under tests/specs/<group>/<ruleName>/ with files typically prefixed by invalid/ or valid/
Applied to files:
crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.options.jsoncrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.jsxcrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/valid.package.jsoncrates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.jsx
📚 Learning: 2025-10-15T09:20:19.139Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:20:19.139Z
Learning: A rule’s diagnostic should explain what the error is, why it’s triggered, and what to do (ideally via a code action or a note)
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
📚 Learning: 2025-10-15T09:21:24.116Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:21:24.116Z
Learning: A diagnostic must explain why something went wrong, using log advices and links to documentation when helpful
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
🧬 Code graph analysis (2)
crates/biome_rule_options/src/no_unknown_property.rs (1)
packages/@biomejs/backend-jsonrpc/src/workspace.ts (1)
NoUnknownPropertyOptions(8160-8163)
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs (2)
packages/@biomejs/backend-jsonrpc/src/workspace.ts (2)
RuleDomain(927-935)NoUnknownPropertyOptions(8160-8163)crates/biome_rowan/src/ast/mod.rs (1)
cast_ref(142-151)
🔇 Additional comments (4)
crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/ignore/valid.options.json (1)
1-16: No issues identified; convention verified.The per-file naming pattern (
<basename>.options.json) is indeed the established convention across analyser specs—over 20 examples confirm this, including othernoUnknownPropertysubfolder tests. The review comment is accurate.crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/valid.package.json (1)
1-6: Remove or document the React 16.4.0 fixture as a placeholder.The rule currently does not consult React versions (no version gating logic exists in the implementation). The commented-out
POPOVER_API_PROPSconstant suggests this is planned. Either drop the fixture file to avoid confusion, or add a comment documenting that it's a placeholder for future version-gated testing.crates/biome_js_analyze/tests/specs/nursery/noUnknownProperty/lowercase/invalid.options.json (1)
1-17: Verified: Options structure and JSON serialisation are correct.The struct at
crates/biome_rule_options/src/no_unknown_property.rshas the expected serde attributes:#[serde(rename_all = "camelCase", deny_unknown_fields, default)]with proper derives (Serialize,Deserialize,Deserializable,JsonSchema). The fieldrequire_data_lowercasecorrectly serialises to"requireDataLowercase"via camelCase conversion, matching the test JSON precisely. Pattern confirmed across 174.options.jsonfiles in the specs directory.crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs (1)
56-87: Code already correctly configured—no changes neededThe struct in
crates/biome_rule_options/src/no_unknown_property.rsalready has the proper serde setup:
#[serde(rename_all = "camelCase", deny_unknown_fields, default)]is present ✓- Rust field
require_data_lowercase(snake_case) correctly maps to JSONrequireDataLowercasevia the bulk rename- Documentation uses the correct camelCase field names
- Field
ignoreproperly uses#[serde(skip_serializing_if = "Vec::is_empty")]This follows the established pattern for options types in the codebase. The serde rename mechanism is already working as intended.
| pub struct NoUnknownPropertyOptions { | ||
| pub require_data_lowercase: bool, | ||
| #[serde(skip_serializing_if = "Vec::is_empty")] | ||
| pub ignore: Vec<String>, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Add rustdoc and check schema optionality for ignore.
- Please document the struct and fields (what each option does, defaults).
- Ensure the generated JSON schema doesn’t make
ignorerequired; TS shows it as required today.
Proposed doc comments:
#[serde(rename_all = "camelCase", deny_unknown_fields, default)]
pub struct NoUnknownPropertyOptions {
- pub require_data_lowercase: bool,
+ /// Enforce lower-case `data-*` attribute names when true. Default: false.
+ pub require_data_lowercase: bool,
#[serde(skip_serializing_if = "Vec::is_empty")]
- pub ignore: Vec<String>,
+ /// Additional attribute names to ignore (case-sensitive). Default: [].
+ pub ignore: Vec<String>,
}Verify schema/TS:
🏁 Script executed:
#!/bin/bash
# After codegen, check required fields under noUnknownProperty
jq -r '
.. | objects | select(has("title") and .title=="noUnknownProperty") |
.allOf[]?.then?.properties? // empty
' packages/@biomejs/biome/configuration_schema.json
rg -n 'interface NoUnknownPropertyOptions' packages/@biomejs/backend-jsonrpc/src/workspace.ts -n -A3Length of output: 117
🏁 Script executed:
#!/bin/bash
# Check current state of the Rust file to see if rustdoc is present
cat crates/biome_rule_options/src/no_unknown_property.rsLength of output: 456
Add rustdoc and fix schema optionality for ignore.
Confirmed: the struct lacks documentation, and the TypeScript interface incorrectly marks ignore as required. The #[serde(skip_serializing_if = "Vec::is_empty")] attribute means it should be optional in the schema.
Implement the proposed rustdoc additions and verify the codegen pipeline regenerates the TypeScript interface with ignore?: string[].
🤖 Prompt for AI Agents
In crates/biome_rule_options/src/no_unknown_property.rs around lines 6–10, add
rustdoc comments describing the struct and its fields, and make the `ignore`
field optional for schema generation by changing its type to Option<Vec<String>>
and updating serde attributes to use a default and skip serialization when None
(e.g. add #[serde(default, skip_serializing_if = "Option::is_none")]). After
updating the doc comments and the field type/serde attrs, run the codegen
pipeline to regenerate the TypeScript interface so it emits `ignore?: string[]`.
|
@dyc3 hey thank you for your comments, i have worked on your suggestions, and I think they are resolved. I believe these are the things I need to work on next
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs (1)
713-714: Event casing: add onBeforeToggle; drop ontoggle; prefer camelCase suggestionsCurrent list includes lowercase
"onbeforetoggle"and"ontoggle", but misses the canonical React props"onBeforeToggle"and (already present)"onToggle". As written,ontoggle/onbeforetogglewill be accepted and won’t auto‑fix to camelCase.- "onbeforetoggle", + "onBeforeToggle", @@ - "ontoggle", + // Intentionally omit lowercase "ontoggle" so it maps to "onToggle"Add tests asserting:
<div onbeforetoggle={() => {}} />→ diagnostic suggestingonBeforeToggle<div ontoggle={() => {}} />→ diagnostic suggestingonToggleThis keeps behaviour aligned with React 19’s events and improves auto‑fix.
Also applies to: 847-848
🧹 Nitpick comments (3)
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs (3)
1065-1077: Avoid unnecessary allocations for attribute names; make ignore check case‑insensitiveYou allocate for every attribute (
to_string, manual concat). We can avoid allocations in the common case and only allocate for namespaced attributes, while matchingignorewithout allocating.+use std::borrow::Cow; @@ - let node_name = match node.name().ok()? { - AnyJsxAttributeName::JsxName(name) => { - name.value_token().ok()?.text_trimmed().to_string() - } - AnyJsxAttributeName::JsxNamespaceName(name) => { - let namespace = name.namespace().ok()?.value_token().ok()?; - let name = &name.name().ok()?.value_token().ok()?; - // There could be better way, but i couldn't extract namespaced attributes - // For e.g xlink:href - // without manually concatenating with ':' - namespace.text_trimmed().to_string() + ":" + name.text_trimmed() - } - }; + let node_name_text: Cow<'_, str> = match node.name().ok()? { + AnyJsxAttributeName::JsxName(name) => { + Cow::Borrowed(name.value_token().ok()?.text_trimmed()) + } + AnyJsxAttributeName::JsxNamespaceName(name) => { + let ns = name.namespace().ok()?.value_token().ok()?.text_trimmed(); + let nm = name.name().ok()?.value_token().ok()?.text_trimmed(); + Cow::Owned(format!("{ns}:{nm}")) + } + }; @@ - if options.ignore.contains(&node_name) { + if options + .ignore + .iter() + .any(|s| s.eq_ignore_ascii_case(node_name_text.as_ref())) + { return None; } @@ - let name = normalize_attribute_case(&node_name); + let name = normalize_attribute_case(node_name_text.as_ref());This removes hot‑path allocations and makes
ignorefriendlier. Ifignoreis meant to be case‑sensitive, dropeq_ignore_ascii_case.Also applies to: 1079-1084
972-973: Redundantuseinside function
use biome_string_case::StrOnlyExtension;is already imported at the module level. Remove the inneruse.- use biome_string_case::StrOnlyExtension;
1169-1177: Offer quick‑fixes in diagnostics (rename)You already tell users what to do; wire in code actions to auto‑rename to
standard_nameand lower‑casedata-*attributes.Happy to sketch the
.actionplumbing if useful.Also applies to: 1205-1213
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
crates/biome_*_{syntax,parser,formatter,analyze,factory,semantic}/**
📄 CodeRabbit inference engine (CLAUDE.md)
Maintain the per-language crate structure: biome_{lang}_{syntax,parser,formatter,analyze,factory,semantic}
Files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
crates/biome_*/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place core crates under /crates/biome_*/
Files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
**/*.rs
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.rs: Format Rust files before committing (e.g., viajust fwhich formats Rust)
Document rules, assists, and options with inline rustdoc in source
Files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
🧠 Learnings (2)
📚 Learning: 2025-10-15T09:20:19.139Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:20:19.139Z
Learning: A rule’s diagnostic should explain what the error is, why it’s triggered, and what to do (ideally via a code action or a note)
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
📚 Learning: 2025-10-15T09:21:24.116Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_diagnostics/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:21:24.116Z
Learning: A diagnostic must explain why something went wrong, using log advices and links to documentation when helpful
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs (3)
packages/@biomejs/backend-jsonrpc/src/workspace.ts (2)
RuleDomain(927-935)NoUnknownPropertyOptions(8160-8163)crates/biome_analyze/src/rule.rs (4)
domains(625-628)sources(610-613)same(246-251)recommended(595-598)crates/biome_rowan/src/ast/mod.rs (1)
cast_ref(142-151)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: triage
- GitHub Check: Validate PR title
🔇 Additional comments (3)
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs (3)
73-89: No issues found—serde mapping is correctly configuredThe
NoUnknownPropertyOptionsstruct already includes#[serde(rename_all = "camelCase", deny_unknown_fields, default)], which ensures the Rust fieldrequire_data_lowercaseserialises asrequireDataLowercasein JSON, matching the documentation. All coding guidelines are satisfied.
95-100: The review comment is incorrect—bothRuleSourcevariants are valid and activeBoth
EslintReactXandEslintReactXyzare legitimate, properly-documented variants in theRuleSourceenum (lines 125 and 127 ofcrates/biome_analyze/src/rule.rs). They represent distinct ESLint React plugins with different outputs in the Display trait:
EslintReactXdisplays as "eslint-plugin-react-x"EslintReactXyzdisplays as "@eslint-react/eslint-plugin"The code compiles and is correct as written. The suggestion to consolidate to a single
EslintReactsource would lose important provenance information about which tool each rule originates from.Likely an incorrect or invalid review comment.
114-225: All constants are correctly sorted—no action needed.The verification confirms that
ATTRIBUTE_TAGS_MAP,DOM_ATTRIBUTE_NAMES, andSVGDOM_ATTRIBUTE_NAMESare all properly sorted by their first keys. Binary search will work as expected; the code is sound.
| name.value_token().ok()?.text_trimmed().to_string() | ||
| } | ||
| AnyJsxAttributeName::JsxNamespaceName(name) => { | ||
| let namespace = name.namespace().ok()?.value_token().ok()?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dyc3 And this issue as well, I couldn't figure out the method to have attributes with colon , something like xmlns:href from the element, and I had to manually concatenate : and convert to String
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could put namespaced attributes into a different map, and that would let you avoid the string allocation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dyc3 I couldn't figure out how to do that without repeating same line of code
So I resorted to this
let node_name = match node.name().ok()? {
AnyJsxAttributeName::JsxName(name) => name.syntax().text_trimmed(),
AnyJsxAttributeName::JsxNamespaceName(name) => name.syntax().text_trimmed(),
};
let node_name = node_name.to_string();
if options.ignore.contains(&node_name) {
return None;
}I had to use to_string() because, contains method requires borrowed String as argument
crates/biome_js_analyze/src/lint/nursery/no_unknown_property.rs
Outdated
Show resolved
Hide resolved
| name.value_token().ok()?.text_trimmed().to_string() | ||
| } | ||
| AnyJsxAttributeName::JsxNamespaceName(name) => { | ||
| let namespace = name.namespace().ok()?.value_token().ok()?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could put namespaced attributes into a different map, and that would let you avoid the string allocation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs (4)
107-113: Remove commented-out code or implement Popover API support.This commented block has been sitting here—either implement React 19 Popover API prop validation or remove it to keep the codebase tidy.
115-226: Consider sorting ATTRIBUTE_TAGS_MAP alphabetically for maintainability.The map entries aren't alphabetically sorted (e.g., "onCancel" appears after "onCanPlay", "onLoadedData" after "onLoadStart"). Whilst the HashMap lookup (line 1110) is unaffected, keeping the source sorted makes future edits less error-prone.
969-969: Remove redundant import.
StrOnlyExtensionis already imported at the module level (line 8); this local import is unnecessary.Apply this diff:
fn is_valid_data_attribute(name: &str) -> bool { - use biome_string_case::StrOnlyExtension; if !name.starts_with("data-") {
1188-1188: Improve formatting of allowed tags list.Add a space after the comma for better readability in the diagnostic message.
Apply this diff:
- "This attribute is only allowed on: "{allowed_tags.join(",")} + "This attribute is only allowed on: "{allowed_tags.join(", ")}
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
crates/biome_*_{syntax,parser,formatter,analyze,factory,semantic}/**
📄 CodeRabbit inference engine (CLAUDE.md)
Maintain the per-language crate structure: biome_{lang}_{syntax,parser,formatter,analyze,factory,semantic}
Files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
crates/biome_*/**
📄 CodeRabbit inference engine (CLAUDE.md)
Place core crates under /crates/biome_*/
Files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
**/*.rs
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.rs: Format Rust files before committing (e.g., viajust fwhich formats Rust)
Document rules, assists, and options with inline rustdoc in source
Files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
🧠 Learnings (1)
📚 Learning: 2025-10-24T21:24:58.631Z
Learnt from: CR
PR: biomejs/biome#0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.631Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : If a rule is inspired by an external source, populate sources in declare_lint_rule! with RuleSource::{Eslint,...} and same()/inspired()
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs (2)
packages/@biomejs/backend-jsonrpc/src/workspace.ts (2)
RuleDomain(927-935)NoUnknownAttributeOptions(8281-8284)crates/biome_rowan/src/ast/mod.rs (1)
cast_ref(142-151)
|
@dyc3 i have pushed new changes with updated name for rule. I haven't yet added support for popover api (react 19), should i leave it like this ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Biome targets more recent tech stacks. So if there are new things in React 19 that affect this rule, this rule should handle it.
.changeset/small-words-show.md
Outdated
| '@biomejs/biome': patch | ||
| --- | ||
|
|
||
| Added the new rule [`no-unknown-property`](https://biomejs.dev/linter/rules/no-unknown-property/) from eslint react |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bot is correct, but you need to link the issue like this: [#7657](https://github.com/biomejs/biome/issues/7657)
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
Outdated
Show resolved
Hide resolved
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
Outdated
Show resolved
Hide resolved
…hapa/biome into feat/no-unknown-property
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (5)
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs (5)
68-68: Update documentation example to match corrected rule name.The rule identifier should be
noUnknownPropertythroughout.- "noUnknownAttribute": { + "noUnknownProperty": {
85-85: Update documentation example to match corrected rule name.Same as above—align with
noUnknownProperty.- "noUnknownAttribute": { + "noUnknownProperty": {
95-95: Rule name must match tests and options configuration.The published rule ID
noUnknownAttributeconflicts with test fixtures and option definitions that expectnoUnknownProperty.- name: "noUnknownAttribute", + name: "noUnknownProperty",
1101-1104:requireDataLowercaseoption is defined but never enforced.The option exists in the schema and has diagnostic logic, but you never check
options.require_data_lowercasebefore returningNonehere.Add before the early return:
if is_valid_data_attribute(name) { + if options.require_data_lowercase.unwrap_or(false) + && name != &name.to_lowercase() + { + return Some(NoUnknownAttributeState::DataLowercaseRequired { + name: (*name).into(), + }); + } return None; }Note: You'll also need to add the
DataLowercaseRequiredvariant toNoUnknownAttributeStateand implement its diagnostic.
1126-1126:TokenTextdoesn't have atrim()method.
tag_nameisTokenText(line 1111). Use.text()instead.- if !allowed_tags.contains(&tag_name.trim()) { + if !allowed_tags.contains(&tag_name.text()) {
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (4)
crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/popover/valid.jsx.snapis excluded by!**/*.snapand included by**crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/valid.jsx.snapis excluded by!**/*.snapand included by**packages/@biomejs/backend-jsonrpc/src/workspace.tsis excluded by!**/backend-jsonrpc/src/workspace.tsand included by**packages/@biomejs/biome/configuration_schema.jsonis excluded by!**/configuration_schema.jsonand included by**
📒 Files selected for processing (5)
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs(1 hunks)crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/popover/valid.jsx(1 hunks)crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/popover/valid.package.json(1 hunks)crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/valid.jsx(1 hunks)crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/valid.package.json(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/popover/valid.package.json
- crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/popover/valid.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
- crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/valid.jsx
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{rs,toml}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Format Rust and TOML files before committing (e.g., via
just f)
Files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
**/*.rs
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Document rules, assists, and their options with inline rustdoc in the Rust source
Files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
🧠 Learnings (26)
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/tests/specs/**/*.jsonc : .jsonc snapshot test files must contain an array of code strings and are interpreted as script (no ESM import/export)
Applied to files:
crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/valid.package.json
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/tests/specs/**/{invalid*,valid*}.* : Name snapshot test files with invalid* and valid* prefixes to indicate reported vs non-reported cases
Applied to files:
crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/valid.package.json
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Set the language field in declare_lint_rule! to the most appropriate dialect (js/jsx/ts/tsx)
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/lint/nursery/**/*.rs : Place all new rules in the nursery group
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/a11y/**/*.rs : Rules in a11y group must have severity: error
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule documentation: first paragraph must be a single line summary
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : If a rule is inspired by an external source, populate sources in declare_lint_rule! with RuleSource::{Eslint,...} and same()/inspired()
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : In declare_lint_rule! macros, set version: "next"
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Provide informative diagnostics: explain what the error is, why it triggers, and what to do (prefer a code action or a note)
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : If a rule provides a code action, add fix_kind to declare_lint_rule! (FixKind::Safe or ::Unsafe)
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule names should use no<Concept> when forbidding a single concept (e.g., noDebugger)
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Use rule_category! macro to reference the diagnostic category created by declare_lint_rule!
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Prefer conventional naming families when applicable: use<Framework>..., noConstant<Concept>, noDuplicate<Concept>, noEmpty<Concept>, noExcessive<Concept>, noRedundant<Concept>, noUnused<Concept>, noUseless<Concept>, noInvalid<Concept>, useValid<Concept>, noUnknown<Concept>, noMisleading<Concept>, noRestricted<Concept>, noUndeclared<Concept>, noUnsafe<Concept>, useConsistent<Concept>, useShorthand<Concept>
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Rule names should use use<Concept> when mandating a single concept (e.g., useValidLang)
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/style/**/*.rs : Rules in style group must have severity: info or warn (prefer info if unsure)
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/suspicious/**/*.rs : Rules in suspicious group must have severity: warn or error (prefer warn if unsure)
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : Place per-rule options types in biome_rule_options crate under lib/, one file per rule
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Avoid avoidable string allocations; compare against &str or TokenText rather than allocating Strings
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Do not attempt to fix code; if a mandatory token/node is missing, return `None` instead
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : For non-mandatory tokens, use the provided helper constructors (e.g., `token`, `space_token`, `dynamic_token`)
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-15T09:22:46.002Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:46.002Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : When a token is mandatory and present in the AST, use the AST-provided token (e.g., `node.l_paren_token().format()`) instead of emitting a static token
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : In ### Invalid doc examples, each snippet must use the expect_diagnostic modifier and emit exactly one diagnostic
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Documentation must include a ## Examples section with ### Invalid before ### Valid
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/*_analyze/**/src/**/lint/**/*.rs : Avoid deep indentation by using combinators (map, filter, and_then) rather than nested if-let/unwrap chains
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-24T21:24:58.650Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-10-24T21:24:58.650Z
Learning: Applies to crates/biome_analyze/crates/biome_rule_options/lib/**/*.rs : Prefer Box<[Box<str>]> over Vec<String> for options string lists to reduce memory usage
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
📚 Learning: 2025-10-15T09:22:15.851Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-10-15T09:22:15.851Z
Learning: Applies to crates/biome_formatter/src/**/*.rs : After generation, remove usages of `format_verbatim_node` and implement real formatting with biome_formatter utilities
Applied to files:
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs
🧬 Code graph analysis (1)
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs (3)
packages/@biomejs/backend-jsonrpc/src/workspace.ts (2)
RuleDomain(927-935)NoUnknownAttributeOptions(8281-8283)crates/biome_analyze/src/rule.rs (4)
domains(625-628)sources(610-613)same(246-251)recommended(595-598)crates/biome_rowan/src/ast/mod.rs (1)
cast_ref(142-151)
🔇 Additional comments (1)
crates/biome_js_analyze/tests/specs/nursery/noUnknownAttribute/valid.package.json (1)
1-6: LGTM—test fixture is appropriate.This package.json properly sets up a React 16.4.0 environment for testing version-specific attribute handling.
| const POPOVER_API_PROPS_LOWERCASE: &[&str] = &[ | ||
| "onbeforetoggle", | ||
| "popover", | ||
| "popovertarget", | ||
| "popovertargetaction", | ||
| ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lowercase Popover props shouldn't be used as standard names.
The logic at lines 1045–1051 returns lowercase property names (e.g., "popovertarget") as the "standard name" for React < 19. React props are always camelCase; suggesting lowercase names will mislead users.
Consider either:
- Removing Popover API support for React < 19 entirely (simplest)
- Or returning
Nonewhen React < 19 so these props are flagged as unknown
🤖 Prompt for AI Agents
crates/biome_js_analyze/src/lint/nursery/no_unknown_attribute.rs lines 115-120:
the POPOVER_API_PROPS_LOWERCASE list causes the linter to suggest lowercase prop
names (e.g., "popovertarget") as the "standard name" for React < 19, which is
incorrect because React props must be camelCase; update the code that handles
popover props (around lines 1045–1051) to stop returning those lowercase names
for React < 19 — either remove/populate the POPOVER_API_PROPS_LOWERCASE usage
and treat these props as unsupported for React < 19 (simplest: delete the branch
that maps to lowercase names), or change the branch to return None when
react_version < 19 so the props are flagged unknown; implement the chosen
approach and adjust any tests accordingly.
|
I just fixed the clippy errors |
|
@dyc3 i have pushed new commits. I removed the wrong folder and had to revert the commit again. Please let me know if i need to do any fixes or any changes in the codebase Although its been 2-3weeks since my PR 😅 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Nice work!
Summary
This PR migrates the no_unknown_property rule from Eslint React. This closes #7657
However, my code is not ready for a good PR yet 😅. For some reasons, I am unable to test with the options although i have them inside options.json file. This code doesn't take care of the react version to handle some edge cases.
This PR may conflict with existing no-unknown-property rule from css, and may redirect to same url.
Test Plan
The tests are included according to the spec. Valid cases are inside valid.jsx and invalid cases in invalid.jsx. For valid and invalid cases with options, I have added them in different folder. For ignore options, the code is inside ignore folder and for requireDataLowerCase, they are stored inside lowercase folder.
Docs