Skip to content

Gemini data x rules eslint v7#27

Open
AlbertSmit wants to merge 8 commits intomainfrom
gemini-data-x-rules-eslint-v7
Open

Gemini data x rules eslint v7#27
AlbertSmit wants to merge 8 commits intomainfrom
gemini-data-x-rules-eslint-v7

Conversation

@AlbertSmit
Copy link
Contributor

@AlbertSmit AlbertSmit commented Nov 25, 2025

Note

Dit zit nu in beta 1.1.0-beta.0 als test-run.


OM als developer doc:

Gebaseerd op dit:

Screenshot 2025-11-05 at 16 54 04

Summary by CodeRabbit

  • New Features

    • Added 10 new linting rules for data-x conventions and one style rule discouraging place-content: center.
    • Added shared data-x configuration used by the new rules.
  • Documentation

    • Added READMEs for each new rule with usage examples.
  • Tests

    • Added unit tests covering valid and invalid cases for all new rules.
  • Chores

    • Bumped package version to 1.1.0-beta.0.

@coderabbitai
Copy link

coderabbitai bot commented Nov 25, 2025

Walkthrough

Adds a shared data-x configuration, registers ten new data-x-* ESLint rules in the main rules export, and introduces a new position-center lint rule. Each rule includes implementation, README, and unit tests.

Changes

Cohort / File(s) Summary
Main Entry Point
index.js
Registered multiple new rules in module.exports.rules: data-x-required, data-x-latin-only, data-x-clickout-prefix, data-x-unique-id, data-x-cta-prefix, data-x-onpage-action-format, data-x-context, data-x-toggle-prefix, data-x-sectioning-elements, data-x-form-naming.
Shared Configuration
lib/data-x-config.js
New module exporting action verb groups, standalone verbs, prefixes, sectioningElements, and helper functions (getAllActionVerbs, getActionVerbPattern, getStandaloneActionVerbPattern).
data-x Required
rules/data-x-required/index.js, rules/data-x-required/readme.md, rules/data-x-required/test.js
Rule enforcing presence of data-x on <a> and <button> elements; docs and tests added.
data-x Latin Only
rules/data-x-latin-only/index.js, rules/data-x-latin-only/readme.md, rules/data-x-latin-only/test.js
Rule enforcing ASCII letters/digits/hyphens/underscores for data-x values on anchors and buttons; docs and tests added.
data-x Clickout Prefix
rules/data-x-clickout-prefix/index.js, rules/data-x-clickout-prefix/readme.md, rules/data-x-clickout-prefix/test.js
Rule requiring clickout- prefix for external link data-x values (href starting with http(s)://); docs and tests added.
data-x Unique ID
rules/data-x-unique-id/index.js, rules/data-x-unique-id/readme.md, rules/data-x-unique-id/test.js
Rule detecting elements produced in .map/list contexts and requiring data-x-id when data-x is used in repeated items; docs and tests added.
data-x CTA Prefix
rules/data-x-cta-prefix/index.js, rules/data-x-cta-prefix/readme.md, rules/data-x-cta-prefix/test.js
Rule detecting CTA-like data-x values on anchors and enforcing a cta- (or other recognized) prefix; docs and tests added.
data-x On-Page Action Format
rules/data-x-onpage-action-format/index.js, rules/data-x-onpage-action-format/readme.md, rules/data-x-onpage-action-format/test.js
Rule validating on-page action formats using data-x-config verb patterns (verb-target or standalone, allows cta- variants); docs and tests added.
data-x Context
rules/data-x-context/index.js, rules/data-x-context/readme.md, rules/data-x-context/test.js
Rule requiring data-x-context when data-x is present on <a> and <button> elements; docs and tests added.
data-x Toggle Prefix
rules/data-x-toggle-prefix/index.js, rules/data-x-toggle-prefix/readme.md, rules/data-x-toggle-prefix/test.js
Rule enforcing toggle- prefix for toggle-like components (including elements with aria-expanded), with normalization logic; docs and tests added.
data-x Sectioning Elements
rules/data-x-sectioning-elements/index.js, rules/data-x-sectioning-elements/readme.md, rules/data-x-sectioning-elements/test.js
Rule requiring data-x on semantic sectioning elements (form, section, header, footer, nav, main, aside); docs and tests added.
data-x Form Naming
rules/data-x-form-naming/index.js, rules/data-x-form-naming/readme.md, rules/data-x-form-naming/test.js
Rule enforcing -form suffix for data-x values on <form> elements; docs and tests added.
position-center Rule
rules/position-center/index.js, rules/position-center/readme.md, rules/position-center/test.js
New CSS rule flagging place-content: center usages (literal and template literal forms) and recommending alternatives; includes suggestions and tests.
Package
package.json
Version bumped from 1.0.3 to 1.1.0-beta.0.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Gemini data x rules eslint v7' is vague and generic, using non-descriptive terms that don't clearly convey the main changes in the changeset. Replace with a more specific title that describes the primary change, such as 'Add 10 ESLint rules for data-x attribute validation' or 'Implement data-x attribute linting rules for tracking attributes'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch gemini-data-x-rules-eslint-v7

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@EECOLOR
Copy link
Member

EECOLOR commented Nov 25, 2025

@AlbertSmit Cool! Laat nog iemand anders het Google Docsje checken met de valid en invalid rules. Dan kan die daarna door :-D

… to enforce `data-x` attributes on sectioning elements and naming conventions for forms.
@AlbertSmit
Copy link
Contributor Author

(dit ligt nu bij Paul, ik heb het OM als developer document geupdatet, daar gaat hij nog goedkeuring op geven).

@AlbertSmit AlbertSmit requested a review from guid-ooo January 29, 2026 14:44
…ve several legacy `data-x` rules, and update `data-x-onpage-action-format`.
@AlbertSmit AlbertSmit marked this pull request as ready for review February 4, 2026 12:37
@AlbertSmit
Copy link
Contributor Author

@coderabbitai give this another go.

@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

@AlbertSmit: I'll review the PR now.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@rules/data-x-cta-prefix/readme.md`:
- Line 7: Update the README for the data-x-cta-prefix rule to use the standard
verb form "sign up" instead of "signup": locate the sentence listing common CTA
actions ("apply, submit, register, signup, download, contact, etc.") in
rules/data-x-cta-prefix/readme.md and replace "signup" with "sign up" so the CTA
verbs are consistently presented; ensure spacing and punctuation remain
consistent with the surrounding list.

In `@rules/data-x-latin-only/index.js`:
- Around line 6-29: The error message in messages.nonLatinDataX states only a–z
are allowed but the regex latinPattern (/^[a-zA-Z0-9\-_]+$/) permits A–Z as
well; update the message to reflect the actual allowed character set (A–Z, a–z,
0–9, hyphens, underscores) or change latinPattern to enforce lowercase only.
Locate messages.nonLatinDataX and latinPattern in the rule (referenced by
nonLatinDataX, latinPattern, JSXOpeningElement, getLiteralPropValue) and make
the message and regex consistent so the reported text matches the implemented
validation.

In `@rules/data-x-sectioning-elements/index.js`:
- Around line 13-14: The JSXOpeningElement handler currently reads
node.name.name which will throw for JSXMemberExpression or JSXNamespacedName;
update the JSXOpeningElement visitor to guard by checking that node.name exists
and node.name.type === 'JSXIdentifier' before accessing node.name.name (or
otherwise bail/return early), so the code that sets elementName only runs for
identifier names; reference the JSXOpeningElement function and the elementName
variable when applying this guard.

In `@rules/data-x-toggle-prefix/index.js`:
- Around line 29-48: The toggle detection currently tests dataXValue against
togglePatterns before stripping open/close/show/hide prefixes, so values like
"open-accordion" are missed; modify the logic in
rules/data-x-toggle-prefix/index.js to first normalize dataXValue by removing
/^(open-|close-|show-|hide-)/, then run togglePatterns.test on the normalized
value, and preserve existing behavior around
ariaExpanded/getProp/hasAriaExpanded and reporting via context.report with
dataXProp and the computed baseValue.
🧹 Nitpick comments (6)
lib/data-x-config.js (1)

37-53: Avoid this-based helpers to prevent destructuring bugs.
If consumers destructure these helpers, this becomes undefined and the methods break. Prefer referencing module exports directly.

♻️ Suggested change
   getAllActionVerbs() {
-    return Object.values(this.actionVerbs).flat()
+    return Object.values(module.exports.actionVerbs).flat()
   },

   getActionVerbPattern() {
-    return this.getAllActionVerbs().join('|')
+    return module.exports.getAllActionVerbs().join('|')
   },

   getStandaloneActionVerbPattern() {
-    return this.standaloneActionVerbs.join('|')
+    return module.exports.standaloneActionVerbs.join('|')
   },
rules/data-x-cta-prefix/index.js (1)

1-33: Consider deriving allowed prefixes from shared config to avoid drift.
Hard-coded prefix checks can diverge from lib/data-x-config.js over time.

♻️ Suggested change
-const getProp = require('jsx-ast-utils/getProp')
-const getLiteralPropValue = require('jsx-ast-utils/getLiteralPropValue')
+const getProp = require('jsx-ast-utils/getProp')
+const getLiteralPropValue = require('jsx-ast-utils/getLiteralPropValue')
+const { prefixes } = require('../../lib/data-x-config')
+
+const allowedPrefixes = [
+  prefixes.cta,
+  prefixes.clickout,
+  prefixes.toggle,
+  prefixes.link,
+  'nav-',
+  'scroll-',
+]

@@
-        if (
-          dataXValue.startsWith('cta-') ||
-          dataXValue.startsWith('nav-') ||
-          dataXValue.startsWith('clickout-') ||
-          dataXValue.startsWith('toggle-') ||
-          dataXValue.startsWith('scroll-')
-        ) {
+        if (allowedPrefixes.some((prefix) => dataXValue.startsWith(prefix))) {
           return
         }
rules/data-x-sectioning-elements/index.js (1)

16-17: Import sectioningElements from shared config.

The sectioningElements array is exported from lib/data-x-config.js and used by both data-x-required and data-x-sectioning-elements rules. Importing from the shared configuration instead of hardcoding the array improves consistency and maintainability.

♻️ Suggested refactor
 const hasProp = require('jsx-ast-utils/hasProp')
+const { sectioningElements } = require('../../lib/data-x-config')

 module.exports = {
   // ...
   create(context) {
     return {
       JSXOpeningElement(node) {
         const elementName = node.name.type === 'JSXIdentifier' ? node.name.name : null
         if (!elementName) return
         
-        // Check for sectioning elements defined in documentation
-        const sectioningElements = ['form', 'section', 'header', 'footer', 'nav', 'main', 'aside']
-        
         if (!sectioningElements.includes(elementName)) return
rules/position-center/index.js (1)

33-39: TemplateLiteral with expressions may bypass the check.

The current logic only examines the first quasi, so a template literal with expressions (e.g., `${'center'}` or `cen${'ter'}`) would not be flagged. This is likely an uncommon edge case, but worth noting.

rules/data-x-onpage-action-format/index.js (1)

32-38: Consider caching the RegExp instances outside the visitor.

The onpageActionPattern and validFormat RegExp objects are recreated on every JSXOpeningElement visit. For better performance, consider moving them to module scope or memoizing.

♻️ Proposed optimization
 const verbPattern = dataXConfig.getActionVerbPattern()
 const standaloneVerbPattern = dataXConfig.getStandaloneActionVerbPattern()
+
+const onpageActionPattern = new RegExp(`^(cta-)?(${verbPattern})($|-)`, 'i')
+const validFormat = new RegExp(`^(cta-)?(${verbPattern})-[a-z0-9_-]+$`, 'i')
+const standaloneActionPattern = standaloneVerbPattern
+  ? new RegExp(`^(cta-)?(${standaloneVerbPattern})$`, 'i')
+  : null

 module.exports = {
   // ...
   create(context) {
     return {
       JSXOpeningElement(node) {
         // ...
-        const onpageActionPattern = new RegExp(`^(cta-)?(${verbPattern})($|-)`, 'i')
         
         if (!onpageActionPattern.test(dataXValue)) return

-        const validFormat = new RegExp(`^(cta-)?(${verbPattern})-[a-z0-9_-]+$`, 'i')
-        
-        const standaloneActionPattern = standaloneVerbPattern
-          ? new RegExp(`^(cta-)?(${standaloneVerbPattern})$`, 'i')
-          : null
-
-        const isStandaloneAction = standaloneActionPattern
-          ? standaloneActionPattern.test(dataXValue)
-          : false
+        const isStandaloneAction = standaloneActionPattern?.test(dataXValue) ?? false

         if (!validFormat.test(dataXValue) && !isStandaloneAction) {
rules/data-x-context/index.js (1)

19-21: Error message references "page template" but rule applies globally.

The message says 'Missing required "data-x-context" attribute on {{elementType}} element in page template', but the rule doesn't actually differentiate page templates from other contexts. Either the message should be updated or the rule should be scoped appropriately (e.g., via file path patterns in ESLint config).

♻️ Suggested message update
     messages: {
-      missingDataXContext: 'Missing required "data-x-context" attribute on {{elementType}} element in page template',
+      missingDataXContext: 'Missing required "data-x-context" attribute on {{elementType}} element',
       invalidDataXContext: '"data-x-context" value "{{value}}" is not allowed. Allowed values: {{allowedValues}}',
     },

test('data-x-unique-id', {
valid: [
{ code: '<a data-x="nav-home">Home</a>' },
{ code: '<button data-x="submit">Submit</button>' },
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is 'submit' specifiek genoeg?

Copy link

@coderabbitai coderabbitai bot left a 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

🤖 Fix all issues with AI agents
In `@rules/data-x-context/index.js`:
- Around line 14-29: The rule currently reports missing data-x-context even when
data-x-context may be supplied via a JSX spread; modify the JSXOpeningElement
visitor (which uses getProp and inspects node.attributes for 'data-x' and
'data-x-context') to first check for any attribute of type JSXSpreadAttribute on
node.attributes and skip validation (return early) if found, so you don't call
context.report for elements where data-x-context could be provided through a
spread.
🧹 Nitpick comments (1)
rules/data-x-context/test.js (1)

4-22: Add a test case for JSX spread attributes to define intended behavior.

Right now the suite only covers explicit attributes. A spread case will lock down whether the rule should skip or still enforce when data-x-context might be provided via {...props}.

Comment on lines +14 to +29
JSXOpeningElement(node) {
const elementName = node.name.name

// Only check <a> and <button> elements
if (elementName !== 'a' && elementName !== 'button') return

const dataXProp = getProp(node.attributes, 'data-x')
if (!dataXProp) return

const dataXContextProp = getProp(node.attributes, 'data-x-context')
if (!dataXContextProp) {
context.report({
node,
messageId: 'missingDataXContext',
data: { elementType: elementName }
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -name "index.js" -path "*/data-x-context/*" | head -5

Repository: kaliberjs/eslint-plugin

Length of output: 98


🏁 Script executed:

find . -type f -name "*.js" | grep -i "data-x-context"

Repository: kaliberjs/eslint-plugin

Length of output: 129


🏁 Script executed:

git ls-files | grep -i "data-x"

Repository: kaliberjs/eslint-plugin

Length of output: 1143


🏁 Script executed:

git ls-files | head -20

Repository: kaliberjs/eslint-plugin

Length of output: 598


🏁 Script executed:

ls -la

Repository: kaliberjs/eslint-plugin

Length of output: 1168


🏁 Script executed:

find . -type d -name "rules" | head -5

Repository: kaliberjs/eslint-plugin

Length of output: 256


🏁 Script executed:

fd "data-x-context" --type f

Repository: kaliberjs/eslint-plugin

Length of output: 49


🏁 Script executed:

find . -type f -path "*/rules/*" -name "*.js" | head -20

Repository: kaliberjs/eslint-plugin

Length of output: 853


🏁 Script executed:

ls -la && pwd

Repository: kaliberjs/eslint-plugin

Length of output: 1187


🏁 Script executed:

rg "getProp" --type js -l | head -10

Repository: kaliberjs/eslint-plugin

Length of output: 400


🏁 Script executed:

rg "jsx-ast-utils" --type js | head -20

Repository: kaliberjs/eslint-plugin

Length of output: 1895


🏁 Script executed:

rg "JSXSpreadAttribute" --type js -A 5 -B 5 | head -50

Repository: kaliberjs/eslint-plugin

Length of output: 3084


🌐 Web query:

jsx-ast-utils getProp JSXSpreadAttribute behavior documentation

💡 Result:

In jsx-ast-utils, getProp(props, prop, options) primarily returns the JSXAttribute node for a named attribute (case-insensitive by default), or undefined if not found. [1]

Behavior with JSXSpreadAttribute ({...x})

getProp has special handling for spread attributes only when the spread argument is an object literal:

  • If it encounters a JSXSpreadAttribute whose argument is an ObjectExpression (e.g. <Comp {...{ foo: 1 }} />), it will search that object’s properties for a matching key and, if found, convert that object Property into a synthetic JSXAttribute and return it. [2]
  • If the spread argument is not an object literal (e.g. <Comp {...props} />), getProp cannot inspect it, so it won’t “find” props that might exist inside that runtime object. [2]
  • It also explicitly does not resolve key from object-literal spreads (it checks propToFind !== 'key'), referencing the React RFC about key not being a normal prop. [2]

Contrast: hasProp and spread

hasProp has a spreadStrict option (default true): if a spread exists, it assumes the searched prop is not in the spread unless you set spreadStrict: false. [3]

Sources
[1] jsx-ast-utils README (API: getProp) https://www.npmjs.com/package/jsx-ast-utils
[2] src/getProp.js implementation (spread/object-literal handling + key exception) https://app.unpkg.com/jsx-ast-utils@3.3.5/files/src/getProp.js
[3] src/hasProp.js implementation (spreadStrict) https://app.unpkg.com/jsx-ast-utils@3.3.5/files/src/hasProp.js


🏁 Script executed:

cat package.json 2>/dev/null | grep -A 5 -B 5 "jsx-ast-utils" || echo "No package.json or jsx-ast-utils not found"

Repository: kaliberjs/eslint-plugin

Length of output: 299


🏁 Script executed:

ls -la rules/data-x-context/index.js 2>/dev/null || echo "File not found at specified path"

Repository: kaliberjs/eslint-plugin

Length of output: 144


🏁 Script executed:

cat -n rules/data-x-context/index.js

Repository: kaliberjs/eslint-plugin

Length of output: 1173


🏁 Script executed:

cat -n rules/data-x-context/test.js | head -100

Repository: kaliberjs/eslint-plugin

Length of output: 998


🏁 Script executed:

cat rules/data-x-context/test.js

Repository: kaliberjs/eslint-plugin

Length of output: 837


🏁 Script executed:

cat -n rules/jsx-key/index.js | grep -A 20 -B 5 "JSXSpreadAttribute"

Repository: kaliberjs/eslint-plugin

Length of output: 629


🏁 Script executed:

cat rules/data-x-context/readme.md

Repository: kaliberjs/eslint-plugin

Length of output: 671


Skip validation when JSXSpreadAttribute is present to avoid false positives.

When data-x is explicit but data-x-context is provided via {...props}, getProp won't detect it from the spread, causing false positives. The test suite currently lacks coverage for spread attribute scenarios. Add a guard to skip validation when a spread exists.

Proposed guard
       JSXOpeningElement(node) {
         const elementName = node.name.name

         // Only check <a> and <button> elements
         if (elementName !== 'a' && elementName !== 'button') return
+
+        const hasSpread = node.attributes.some(attr => attr.type === 'JSXSpreadAttribute')
+        if (hasSpread) return
🤖 Prompt for AI Agents
In `@rules/data-x-context/index.js` around lines 14 - 29, The rule currently
reports missing data-x-context even when data-x-context may be supplied via a
JSX spread; modify the JSXOpeningElement visitor (which uses getProp and
inspects node.attributes for 'data-x' and 'data-x-context') to first check for
any attribute of type JSXSpreadAttribute on node.attributes and skip validation
(return early) if found, so you don't call context.report for elements where
data-x-context could be provided through a spread.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe dit niet zo strak enforcen dit gaat er voor zorgen dat het veel contextuele knowledge moet hebben bij het toevoegen van buttons en dat het meer frustratie geeft dan helpt.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Comments