npm package: @nuitsukera/refine
Description: Remove comments from JavaScript/TypeScript, CSS/SCSS/LESS, HTML, Vue and related files
Author: nuitsukera
Latest version: 1.0.3

﻿# refine

Remove comments from JavaScript, TypeScript, JSX, TSX, Vue, HTML, CSS/SCSS/LESS and more — with parallel processing, watch mode, `.refineignore` support and JSON reports.

---

## Installation

### Local (per-project)

```bash
# bun
bun add -D @nuitsukera/refine

# npm
npm install --save-dev @nuitsukera/refine
```

After installing, run the setup wizard once:

```bash
# bun
bunx refine init

# npm
npx refine init
```

A `refine.json` is created in the project root (or merged into your existing `config.json` if you prefer). A post-install tip is shown automatically if no config is found.

### Global

```bash
# bun
bun install -g @nuitsukera/refine

# npm
npm install -g @nuitsukera/refine
```

Once installed globally you can call `refine` from any directory. A default global config is automatically created on install:

- **Linux / Mac:** `~/.config/refine/refine.json`
- **Windows:** `%APPDATA%\refine\refine.json`

Edit that file to customise the default behavior for all projects.

---

## Quick start

```bash
# 1. Create config in your project root (interactive)
refine init

# 2. Run (auto-detects refine.json)
refine

# 3. Dry run — preview what would change, no files modified
refine --dry-run

# 4. Watch mode — reprocess on every file change
refine --watch
```

---

## Console output

Every run prints a per-file report of exactly what was removed and on which line:

```
refine ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ℹ Scanning files...
✓ Found 2 files to process

Processing Files ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ℹ Total files to process: 2

src/utils/helper.ts ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ✖ 4 comments removed

   1 │ - /** @file helper.ts — utility functions
  15 │ - // internal state
  42 │ - // TODO: cleanup later
  88 │ - /* legacy fallback */

src/components/Button.tsx ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ✖ 2 comments removed

   3 │ - // @deprecated
  27 │ - /* unused */

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Results ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Files Processed 2  ·  Files Skipped 0  ·  Comments Removed 6  ·  Comments Preserved 0  ·  Processing Time 12ms

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ Done!
```

In `--dry-run` mode each file is tagged `[dry run]` and nothing is written to disk:

```
src/utils/helper.ts ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  ✖ 4 comments removed [dry run]

   1 │ - /** @file helper.ts — utility functions
  15 │ - // internal state
```

---

## Config file auto-detection

When no `-c` flag is passed, the CLI looks for a config in this order:

1. `refine.json` in `process.cwd()`
2. `.refine.json` in `process.cwd()`
3. `refine` key inside `config.json` in `process.cwd()`
4. Global config (`~/.config/refine/refine.json` on Linux/Mac, `%APPDATA%\refine\refine.json` on Windows)

If none is found, built-in defaults are used and a hint to run `refine init` is shown.

---

## `init` command

```bash
# Default: creates refine.json in the current directory
refine init

# Custom filename
refine init --output my-config.json
```

If the target config file already exists, `refine init` exits with a warning:

```
⚠ Config file already exists: refine.json
  Delete it first or use --output to specify a different path.
```

If **`config.json`** already exists in the project root and you run `init` without `--output`, an interactive prompt asks:

```
⚠ A config.json already exists in this directory.

How would you like to add refine config?
  [1] Merge into existing config.json  (adds "refine" key, keeps everything else)
  [2] Create a separate refine.json file
  [3] Use a custom filename
  Choice (1-3):
```

**Option 1** — the CLI reads `config.json` transparently via the `"refine"` key:

```json
{
  "someOtherTool": {},
  "refine": {
    "targetDirectory": "./src",
    "removeJSDoc": false
  }
}
```

```bash
refine -c config.json
```

---

## CLI options

```
Usage: refine [options] [command]

Options:
  -c, --config <path>       Path to config file (auto-detected if not specified)
  -d, --directory <path>    Target directory to process
  -o, --output <path>       Output directory (overwrites originals if omitted)
  -e, --extensions <list>   Comma-separated extensions to process (e.g. .js,.ts,.vue)
  --concurrency <n>         Number of parallel workers (default: 8)
  --report <path>           Write a JSON report to the specified file
  --watch                   Watch target directory and re-process on changes
  --dry-run                 Run without making changes
  -v, --verbose             Verbose output (includes per-file line counts)
  --remove-jsdoc            Remove JSDoc comments
  --keep-todo               Keep TODO comments
  --keep-fixme              Keep FIXME comments
  --keep-note               Keep NOTE comments
  -V, --version             Output the version number
  -h, --help                Display help for command

Commands:
  init [options]            Create the refine config in the current project directory
```

---

## `.refineignore`

Place a `.refineignore` file in your target directory to exclude paths using gitignore-style patterns:

```gitignore
# Ignore generated files
dist/
build/
**/*.min.js

# Ignore a specific folder
src/vendor/
```

The file name can be customised via the `ignoreFile` config field.

---

## Watch mode

```bash
refine --watch
```

Watches the target directory recursively. Any change to a matching file triggers a debounced (500 ms) re-run. Press `Ctrl+C` to stop.

Combine with other flags:

```bash
refine --watch --dry-run --verbose
```

---

## JSON report

```bash
refine --report report.json
```

After processing, a report is written to `report.json`:

```json
{
  "timestamp": "2025-01-01T00:00:00.000Z",
  "config": { ... },
  "stats": {
    "filesProcessed": 42,
    "filesSkipped": 3,
    "commentsRemoved": 187,
    "commentsPreserved": 12,
    "filesWithErrors": [],
    "processingTime": 340
  }
}
```

---

## Configuration reference

| Field              | Type       | Default                                                                         | Description                                        |
|--------------------|------------|---------------------------------------------------------------------------------|----------------------------------------------------|
| `targetDirectory`  | `string`   | `"./src"`                                                                       | Directory to scan for files                        |
| `outputDirectory`  | `string?`  | `undefined`                                                                     | Output directory (overwrites originals if omitted) |
| `fileExtensions`   | `string[]` | `[".js",".mjs",".cjs",".ts",".jsx",".tsx",".vue",".svelte",".astro",".html",".htm",".jsonc"]` | File extensions to process          |
| `excludeFiles`     | `string[]` | `["*.config.js","*.config.ts"]`                                                 | File glob patterns to exclude                      |
| `excludeDirs`      | `string[]` | `["node_modules","dist","build",".git"]`                                        | Directories to exclude                             |
| `ignoreFile`       | `string?`  | `".refineignore"`                                                               | Gitignore-style ignore file inside target dir      |
| `preserveComments` | `string[]` | `["// @ts-expect-error","// @ts-ignore","/// <reference","#!/usr/bin/env node","// biome-ignore","/* webpackIgnore:","/* webpackChunkName:"]` | Exact comment strings to always keep  |
| `preservePatterns` | `string[]` | `["^\\s*//\\s*@ts-","^\\s*///\\s*<reference","^#!/","biome-ignore","webpack[A-Za-z]"]` | Regex patterns for comments to always keep |
| `removeJSDoc`      | `boolean`  | `false`                                                                         | Remove JSDoc blocks (`/** ... */`)                 |
| `removeTODO`       | `boolean`  | `true`                                                                          | Remove `// TODO:` comments                         |
| `removeFIXME`      | `boolean`  | `true`                                                                          | Remove `// FIXME:` comments                        |
| `removeNOTE`       | `boolean`  | `true`                                                                          | Remove `// NOTE:` comments                         |
| `dryRun`           | `boolean`  | `false`                                                                         | Preview only, no files written                     |
| `verbose`          | `boolean`  | `false`                                                                         | Detailed log output with per-file line counts      |
| `concurrency`      | `number?`  | `8`                                                                             | Number of parallel worker threads                  |
| `reportPath`       | `string?`  | `undefined`                                                                     | Path to write JSON report after processing         |

---

## Safety Guard

refine has a built-in **Safety Guard** layer that runs before any config evaluation. The comments listed below are **always preserved**, regardless of what `refine.json` says — no config option can override them.

| Category | What is protected |
|---|---|
| **URLs** | Any comment containing `http://` or `https://` |
| **Biome** | `biome-ignore` |
| **ESLint** | `eslint-disable`, `eslint-enable`, `eslint-env` |
| **TypeScript** | `// @ts-*`, `/// <reference ...>` |
| **Prettier** | `prettier-ignore` |
| **Stylelint** | `stylelint-disable`, `stylelint-enable` |
| **Tailwind** | `tailwind-ignore` |
| **Webpack** | `/* webpackIgnore */`, `/* webpackChunkName */`, etc. |
| **Vite / Rollup** | `vite-ignore`, `@rollup/` |
| **Coverage** | `istanbul ignore`, `c8 ignore`, `v8 ignore` |
| **Node.js** | Shebangs (`#!/`), `"use client"`, `"use server"`, `"use strict"` |
| **JSX pragmas** | `@jsx`, `@jsxRuntime`, `@jsxImportSource` |
| **License / Copyright** | Any header containing `license`, `copyright`, `(c)` or `©` |
| **Source maps** | `sourceMappingURL` |
| **JetBrains IDEs** | `noinspection` |

> This means patterns like `.replace(/\//g, "_")` (regex literals with `/`) and CDN URLs inside strings are also protected from being mis-detected as comment content.

---

## Supported file types

| Extension                          | Parser                                |
|------------------------------------|---------------------------------------|
| `.js` `.mjs` `.cjs` `.ts`          | JavaScript / TypeScript               |
| `.jsx` `.tsx`                      | JSX / TSX                             |
| `.vue`                             | Vue SFC (template + script + style)   |
| `.svelte` `.astro`                 | Vue-style (template + script + style) |
| `.html` `.htm`                     | HTML (`<!-- -->` + IE conditionals)   |
| `.css`                             | CSS (`/* */`)                         |
| `.scss` `.sass` `.less`            | SCSS / SASS / LESS (`/* */` + `//`)   |
| `.jsonc`                           | JSONC                                 |

---

## Development scripts

| Command               | Description                                         |
|-----------------------|-----------------------------------------------------|
| `bun start`           | Run CLI from source (`src/cli.ts`)                  |
| `bun run dev`         | Run with file watch (auto-restart on change)        |
| `bun run build`       | Compile TypeScript → `dist/`                        |
| `bun run rebuild`     | Clean `dist/` then compile TypeScript → `dist/`     |
| `bun run watch`       | Compile TypeScript in watch mode                    |
| `bun run prepare`     | Rebuild + generate `refine.json` for development    |
| `bun test`            | Run tests                                           |
| `bun run lint`        | Lint `src/` with Biome                              |
| `bun run format`      | Format `src/` with Biome                            |
| `bun run clean`       | Remove the `dist/` directory                        |

---

## How it works (local vs global)

| Install type              | How to run                          | Config location                                                                           |
|---------------------------|-------------------------------------|-------------------------------------------------------------------------------------------|
| Local (`bun add -D`)      | `bunx refine` / package.json script | Project root (`process.cwd()`)                                                              |
| Global (`bun install -g`) | `refine` from any terminal          | `~/.config/refine/refine.json` (Linux/Mac) · `%APPDATA%\refine\refine.json` (Windows)    |

Config file paths and all relative paths inside it are resolved against the directory from which `refine` is called (`process.cwd()`), never against the package installation directory.

---

## Requirements

- [Node.js](https://nodejs.org) >= 18.0.0
- [Bun](https://bun.sh) >= 1.0.0 *(required only for development / building from source)*

---

## License

MIT