JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 356222
  • Score
    100M100P100Q170845F
  • License MIT

Comment-as-command for one-off codemod with ESLint

Package Exports

  • eslint-plugin-command
  • eslint-plugin-command/commands
  • eslint-plugin-command/config
  • eslint-plugin-command/types

Readme

eslint-plugin-command

npm version npm downloads

Comment-as-command for one-off codemod with ESLint.

Install

npm i eslint-plugin-command -D

In your flat config eslint.config.mjs:

// eslint.config.mjs
import command from 'eslint-plugin-command/config'

export default [
  // ... your other flat config
  command(),
]

Built-in Commands

to-function

Convert an arrow function to a standard function declaration.

Trigger with /// to-function comment (triple slashes) one line above the arrow function.

Triggers:

  • /// to-function
  • /// to-fn
  • /// 2f
/// to-function
const foo = async (msg: string): void => {
  console.log(msg)
}

Will be converted to (the command comment will be removed along the way):

async function foo(msg: string): void {
  console.log(msg)
}

to-arrow

Convert a standard function declaration to an arrow function.

Triggers:

  • /// to-arrow
  • /// 2a
/// to-arrow
function foo(msg: string): void {
  console.log(msg)
}

Will be converted to:

const foo = (msg: string): void => {
  console.log(msg)
}

keep-sorted

Keep the object keys or array items sorted.

Triggers:

  • /// keep-sorted
  • // @keep-sorted
/// keep-sorted
const obj = {
  b: 2,
  a: 1,
  c: 3,
}

Will be converted to:

/// keep-sorted
const obj = {
  a: 1,
  b: 2,
  c: 3,
}

Different from the other commands, the comment will not be removed after transformation to keep the sorting.

to-for-each

Convert for-of/for-in loop to .forEach().

Triggers:

  • /// to-for-each
  • /// foreach
/// to-for-each
for (const item of items) {
  if (!item)
    continue
  console.log(item)
}

Will be converted to:

items.forEach((item) => {
  if (!item)
    return
  console.log(item)
})

For for-in loop:

/// to-for-each
for (const key in obj) {
  if (!obj[key])
    continue
  console.log(obj[key])
}

Will be converted to:

Object.keys(obj).forEach((key) => {
  if (!obj[key])
    return
  console.log(obj[key])
})

to-for-of

Convert .forEach() to for-of loop.

Triggers:

  • /// to-for-of
  • /// forof
/// to-for-of
items.forEach((item) => {
  if (!item)
    return
  console.log(item)
})

Will be converted to:

for (const item of items) {
  if (!item)
    continue
  console.log(item)
}

to-dynamic-import

Convert import statement to dynamic import.

Triggers:

  • /// to-dynamic-import
  • /// to-dynamic
/// to-dynamic-import
import bar, { foo } from './foo'

Will be converted to:

const { default: bar, foo } = await import('./foo')

to-string-literal

Convert template literals to string literals.

Triggers:

  • /// to-string-literal
  • /// to-sl
  • /// 2string-literal
  • /// 2sl

or if you fancy @:

  • // @to-string-literal
  • // @to-sl
  • // @2string-literal
  • // @2sl
/// @2sl
const foo = `foo`

// @2sl
const quxx = `${qux}quxx`

// Also supports using numbers to specify which items need to be converted (starts from 1)
// @2sl 1 3
const bar = `bar`; const baz = `baz`; const qux = `qux`

Will be converted to:

const foo = 'bar'

// eslint-disable-next-line prefer-template
const quxx = qux + 'quxx'

const bar = 'bar'; const baz = `baz`; const qux = 'qux'

to-template-literal

Convert string literals to template literals.

Triggers:

  • /// to-template-literal
  • /// to-tl
  • /// 2template-literal
  • /// 2tl

or if you fancy @:

  • // @to-template-literal
  • // @to-tl
  • // @2template-literal
  • // @2tl
/// @2tl
const bar = 'bar'

// @2tl
// eslint-disable-next-line prefer-template
const quxx = qux + 'quxx'

// Also supports using numbers to specify which items need to be converted (starts from 1)
// @2tl 1 3
const foo = 'foo'; const baz = 'baz'; const qux = 'qux'

Will be converted to:

const bar = `bar`

const quxx = `${qux}quxx`

const foo = `foo`; const baz = 'baz'; const qux = `qux`

Custom Commands

It's also possible to define your custom commands.

// eslint.config.mjs
import command from 'eslint-plugin-command/config'
import { builtinCommands, defineCommand } from 'eslint-plugin-command/commands'

const myCommand = defineCommand({
  name: 'my-command',
  // RegExp to match the command comment (without leading `//`)
  match: /^@my-command$/,
  action(context) {
    // Do something with the context
  },
})

export default [
  // ... your other flat config
  command({
    commands: [
      ...builtinCommands,
      myCommand,
    ]
  }),
]

You can refer to the built-in commands for examples.

Sponsors

License

MIT License © 2023-PRESENT Anthony Fu