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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ekz/lexical-eslint-plugin

v0.40.1

Published

Lexical specific linting rules for ESLint

Readme

@lexical/eslint-plugin

This ESLint plugin enforces the Lexical $function convention.

Installation

Assuming you already have ESLint installed, run:

npm install @lexical/eslint-plugin --save-dev

Then extend the recommended eslint config:

{
  "extends": [
    // ...
    "plugin:@lexical/recommended"
  ]
}

Custom Configuration

If you want more fine-grained configuration, you can instead add a snippet like this to your ESLint configuration file:

{
  "plugins": [
    // ...
    "@lexical"
  ],
  "rules": {
    // ...
    "@ekz/lexical-rules-of-lexical": "error"
  }
}

Advanced configuration

Most of the heuristics in @lexical/rules-of-lexical can be extended with additional terms or patterns.

The code example below is shown using the default implementations for each option. When you configure these they are combined with the default implementations using "OR", the default implementations can not be overridden. These terms and patterns are only shown for reference and pasting this example into your project is not useful.

If the string begins with a "^" or "(" then it is treated as a RegExp, otherwise it will be an exact match. A string may also be used instead of an array of strings.

{
  "plugins": [
    // ...
    "@lexical"
  ],
  "rules": {
    // ...
    "@ekz/lexical-rules-of-lexical": [
      "error",
      {
        "isDollarFunction": ["^\\$[a-z_]"],
        "isIgnoredFunction": [],
        "isLexicalProvider": [
          "parseEditorState",
          "read",
          "registerCommand",
          "registerNodeTransform",
          "update"
        ],
        "isSafeDollarFunction": ["^\\$is"]
      }
    ]
  }
}

isDollarFunction

Base case: /^\$[a-z_]/

This defines the $function convention, which by default is any function that starts with a dollar sign followed by a lowercase latin letter. You may have a secondary convention in your codebase, such as non-latin letters, or an internal prefix that you want to consider (e.g. "^INTERNAL_\\$").

isIgnoredFunction

Base case: None

Functions that match these patterns are ignored from analysis, they may call Lexical $functions but are not considered to be a dollar function themselves.

isLexicalProvider

Base case: /^(parseEditorState|read|registerCommand|registerNodeTransform|update)$/

These are functions that allow their function argument to use Lexical $functions.

isSafeDollarFunction

Base case: /^\$is/

These $functions are considered safe to call from anywhere, generally these functions are runtime type checks that do not depend on any other state.

Valid and Invalid Examples

Valid Examples

$functions may be called by other $functions

function $namedCorrectly() {
  return $getRoot();
}

$functions may be called in functions defined when calling the following methods (the heuristic only considers the method name):

  • editor.update
  • editorState.read
  • editor.registerCommand
  • editor.registerNodeTransform
function validUsesEditorOrState(editor) {
  editor.update(() => $getRoot());
  editor.getLatestState().read(() => $getRoot());
}

$functions may be called from class methods

class CustomNode extends ElementNode {
  appendText(string) {
    this.appendChild($createTextNode(string));
  }
}

Invalid Examples

Rename autofix

function invalidFunction() {
  return $getRoot();
}
function $callsInvalidFunction() {
  return invalidFunction();
}

Autofix: The function is renamed with a $ prefix. Any references to this name in this module are also always renamed.

function $invalidFunction() {
  return $getRoot();
}
function $callsInvalidFunction() {
  return $invalidFunction();
}

Rename & deprecate autofix

export function exportedInvalidFunction() {
  return $getRoot();
}

Autofix: The exported function is renamed with a $ prefix. The previous name is also exported and marked deprecated, because automatic renaming of references to that name is limited to the module's scope.

export function $exportedInvalidFunction() {
  return $getRoot();
}
/** @deprecated renamed to {@link $exportedInvalidFunction} by @lexical/eslint-plugin rules-of-lexical */
export const exportedInvalidFunction = $exportedInvalidFunction;

Rename scope conflict

import {$getRoot} from '@ekz/lexical';
function InvalidComponent() {
  const [editor] = useLexicalComposerContext();
  const getRoot = useCallback(() => $getRoot(), []);
  return (<button onClick={() => editor.update(() => getRoot())} />);
}

Autofix: The function is renamed with a $ prefix and _ suffix since the suggested name was already in scope.

import {$getRoot} from '@ekz/lexical';
function InvalidComponent() {
  const [editor] = useLexicalComposerContext();
  const $getRoot_ = useCallback(() => $getRoot(), []);
  return (<button onClick={() => editor.update(() => $getRoot_())} />);
}