npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

eslint-plugin-no-attribute-string-literals

v1.0.0

Published

An ESLint plugin to find strings in JSX attribute literals

Downloads

9

Readme

no-attribute-string-literals ESLint Plugin

Ensure JSX attributes follow specific naming or value constraints. This linter is especially useful for identifying strings in your code that should be localized.

Installation

npm install eslint-plugin-no-attribute-string-literals --save-dev

Usage

After installation, add the plugin to your ESLint configuration:

{
  "plugins": ["no-attribute-string-literals"],
  "rules": {
    "no-attribute-string-literals/no-attribute-string-literals": [
      "error",
      // see below for option details
      {
        "only": [],
        "ignore": []
      }
    ]
  }
}

Rule Details

This rule targets JSX attributes with string literals that don't follow specific constraints set by the user. The primary intention is to leverage the ignore option, which specifies which attributes are permissible. The only option can be utilized in unique scenarios where you'd like to focus on a particular subset of attributes, but it's less commonly used.

For instance:

Valid

<Button disabled size={3} />

Invalid

<Button variant="outlined" />
<Icon icon={"star"} />

Options

interface NoAttributeStringLiteralsRuleOptions {
  ignore?: InputOption | InputOption[];
  only?: InputOption | InputOption[];
}

type InputOption =
  | { and: InputOption[] }
  | { or: InputOption[] }
  | { not: InputOption }
  | {
      /**
       * List of attributes to match.
       *
       * For instance, to match the attribute `foo` in `<Component foo="text" />`,
       * add "foo" to this list.
       */
      attributes?: string[];

      /**
       * Regex patterns for attribute names.
       *
       * E.g., to match all `data-` attributes in `<Component data-testid="a" />`,
       * use the pattern "^data-\w+".
       */
      attributePatterns?: string[];

      /**
       * List of attribute values to match.
       *
       * For instance, to match the value `outlined` in `<Component variant="outlined" />`,
       * add "outlined" to this list.
       */
      values?: string[];

      /**
       * Regex patterns for attribute values.
       *
       * E.g., to match values like `dark-mode` in `<Component theme="dark-mode" />`,
       * use the pattern "^dark-\w+".
       */
      valuePatterns?: string[];

      /**
       * List of component names to match.
       *
       * For instance, to match the `<Button />` component,
       * add "Button" to this list.
       */
      components?: string[];

      /**
       * Regex patterns for component names.
       *
       * E.g., to match any component with "Btn" in its name like `<SubmitBtn />` or `<CancelBtn />`,
       * use the pattern ".*Btn".
       */
      componentPatterns?: string[];
    };

The ignore Option

This is the primary filter used to specify exceptions or conditions for which attributes should not be reported. Attributes matching its conditions are excluded from being reported.

The only Option

This is a less commonly used option. If specified, only attributes matching its conditions will be considered. If omitted, all attributes are initially selected. If the only option is present with ignore, the only option will determine which attributes to consider and then the ignore option is used to ignore any attributes that match.

Logical Conditions in InputOption

Three logical operators aid in crafting your criteria:

  • OR (or): Any condition within the or block being true makes the entire block true.
  • AND (and): All conditions within the and block must be true for the entire block to be true.
  • NOT (not): Inverts the result of its condition.

When multiple keys are present in the input object, they follow the "OR" logic. If you desire an "AND" relationship, use the and condition explicitly. For example, to enforce that an attribute must be from the Button component AND named 'as', you'd use:

{
  "and": [{ "components": ["Button"] }, { "attributes": ["as"] }]
}

Examples

1. Ensuring Localization

A common scenario in internationalized applications is to ensure strings are localized. By default, you might want to flag all string literals within JSX attributes to remind developers to use localized strings.

ESLint Config:

{
  "rules": {
    "no-attribute-string-literals/no-attribute-string-literals": "error"
  }
}

Invalid Code:

<Header title="Welcome" />

Valid Code:

<Header title={t('welcome_message')} />

2. Allowing Specific Data Attributes

For automated testing, data-testid attributes are commonly used. While you might want to localize most string literals, this is an exception.

ESLint Config:

{
  "rules": {
    "no-attribute-string-literals/no-attribute-string-literals": [
      "error",
      {
        "ignore": {
          "attributes": ["data-testid"]
        }
      }
    ]
  }
}

Valid Code:

<Button data-testid="submit-button" />

3. Special Case for Specific Components

Imagine you have certain components where some attributes are always expected to have string literals. For instance, you have a <RouterLink> component where the to attribute specifies a route.

ESLint Config:

{
  "rules": {
    "no-attribute-string-literals/no-attribute-string-literals": [
      "error",
      {
        "ignore": {
          "and": [{ "components": ["RouterLink"] }, { "attributes": ["to"] }]
        }
      }
    ]
  }
}

Valid Code:

<RouterLink to="/dashboard" />

4. Allowing Specific Attribute Values

There might be scenarios where you want to allow specific string values for an attribute. For instance, you have a <ThemeSwitch> component where the mode attribute can only be "dark" or "light".

ESLint Config:

{
  "rules": {
    "no-attribute-string-literals/no-attribute-string-literals": [
      "error",
      {
        "ignore": {
          "and": [
            { "components": ["ThemeSwitch"] },
            { "values": ["dark", "light"] }
          ]
        }
      }
    ]
  }
}

Valid Code:

<ThemeSwitch mode="dark" />

5. Pattern Matching for Component Names

You may have a set of components following a naming pattern, and you want to ensure certain attributes for all those components have string literals. For instance, any component with "Form" in its name should be allowed to have a placeholder attribute.

ESLint Config:

{
  "rules": {
    "no-attribute-string-literals/no-attribute-string-literals": [
      "error",
      {
        "ignore": {
          "and": [
            { "componentPatterns": [".*Form$"] },
            { "attributes": ["placeholder"] }
          ]
        }
      }
    ]
  }
}

Valid Code:

<TextInputForm placeholder="Enter your name" />
<DateInputForm placeholder="Select a date" />