eslint-plugin-oxfmt 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,31 +5,65 @@
5
5
  [![NPM DOWNLOADS](https://img.shields.io/npm/dy/eslint-plugin-oxfmt.svg)](https://www.npmjs.com/package/eslint-plugin-oxfmt)
6
6
  [![LICENSE](https://img.shields.io/github/license/ntnyq/eslint-plugin-oxfmt.svg)](https://github.com/ntnyq/eslint-plugin-oxfmt/blob/main/LICENSE)
7
7
 
8
- An ESLint plugin that format code via oxfmt.
8
+ > An ESLint plugin for formatting code with [oxfmt](https://github.com/oxc-project/oxc) - A blazing fast formatter powered by Rust.
9
9
 
10
- ## Install
10
+ ## Features
11
11
 
12
- ```shell
13
- npm install eslint-plugin-oxfmt
12
+ - ⚡️ **Blazing Fast** - Powered by [oxfmt](https://github.com/oxc-project/oxc), written in Rust
13
+ - 🔧 **Auto-fix** - Automatically format code on save or via ESLint's fix command
14
+ - 🎯 **ESLint Integration** - Seamlessly integrates with ESLint v9+ flat config
15
+ - 📦 **Zero Config** - Works out of the box with sensible defaults
16
+ - 🎨 **Highly Configurable** - Support for all oxfmt formatting options
17
+ - 🌐 **Multi-language Support** - JavaScript, TypeScript, JSX, TSX and more
18
+
19
+ ## Requirements
20
+
21
+ - **ESLint**: `>= 9.0.0` (Only supports ESLint flat config)
22
+ - **Node.js**: `>= 18.0.0`
23
+
24
+ ## Installation
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ npm install -D eslint-plugin-oxfmt
14
30
  ```
15
31
 
16
- ```shell
17
- yarn add eslint-plugin-oxfmt
32
+ ```bash
33
+ yarn add -D eslint-plugin-oxfmt
18
34
  ```
19
35
 
20
- ```shell
21
- pnpm add eslint-plugin-oxfmt
36
+ ```bash
37
+ pnpm add -D eslint-plugin-oxfmt
22
38
  ```
23
39
 
24
40
  ## Usage
25
41
 
26
- ```ts
42
+ ### Quick Start
43
+
44
+ Add the plugin to your ESLint flat config file:
45
+
46
+ ```js
27
47
  // eslint.config.mjs
48
+ import pluginOxfmt from 'eslint-plugin-oxfmt'
49
+
50
+ export default [
51
+ {
52
+ ...pluginOxfmt.configs.recommended,
53
+ files: ['**/*.{js,ts,mjs,cjs,jsx,tsx}'],
54
+ },
55
+ ]
56
+ ```
28
57
 
58
+ ### Custom Configuration
59
+
60
+ You can customize the formatting options by configuring the rule:
61
+
62
+ ```js
63
+ // eslint.config.mjs
29
64
  import pluginOxfmt from 'eslint-plugin-oxfmt'
30
- import { defineConfig } from 'eslint/config'
31
65
 
32
- export default defineConfig([
66
+ export default [
33
67
  {
34
68
  ...pluginOxfmt.configs.recommended,
35
69
  files: ['**/*.{js,ts,mjs,cjs,jsx,tsx}'],
@@ -37,17 +71,148 @@ export default defineConfig([
37
71
  'oxfmt/oxfmt': [
38
72
  'error',
39
73
  {
74
+ // Formatting options
40
75
  semi: false,
41
- useTabs: true,
42
- singleAttributePerLine: true,
76
+ singleQuote: true,
77
+ tabWidth: 2,
78
+ useTabs: false,
43
79
  trailingComma: 'all',
80
+ printWidth: 100,
81
+ arrowParens: 'avoid',
82
+
83
+ // JSX specific options
84
+ jsxSingleQuote: false,
85
+ bracketSameLine: false,
86
+ singleAttributePerLine: false,
87
+
88
+ // Object formatting
89
+ bracketSpacing: true,
90
+ quoteProps: 'as-needed',
91
+
92
+ // Line endings
93
+ endOfLine: 'lf',
94
+ insertFinalNewline: true,
44
95
  },
45
96
  ],
46
97
  },
47
98
  },
48
- ])
99
+ ]
100
+ ```
101
+
102
+ ## Configuration Options
103
+
104
+ All options are optional and default to sensible values.
105
+
106
+ ### Basic Options
107
+
108
+ | Option | Type | Default | Description |
109
+ | ------------- | --------- | ------- | ------------------------------------------ |
110
+ | `semi` | `boolean` | `true` | Add semicolons at the end of statements |
111
+ | `singleQuote` | `boolean` | `false` | Use single quotes instead of double quotes |
112
+ | `tabWidth` | `number` | `2` | Number of spaces per indentation level |
113
+ | `useTabs` | `boolean` | `false` | Use tabs for indentation |
114
+ | `printWidth` | `number` | `100` | Maximum line length for wrapping |
115
+
116
+ ### Trailing Commas
117
+
118
+ | Option | Type | Default | Description |
119
+ | --------------- | -------------------------- | ------- | ---------------------------- |
120
+ | `trailingComma` | `'all' \| 'es5' \| 'none'` | `'all'` | Where to add trailing commas |
121
+
122
+ ### Arrow Functions
123
+
124
+ | Option | Type | Default | Description |
125
+ | ------------- | --------------------- | ---------- | -------------------------------------------------------- |
126
+ | `arrowParens` | `'always' \| 'avoid'` | `'always'` | Include parentheses around sole arrow function parameter |
127
+
128
+ ### JSX Options
129
+
130
+ | Option | Type | Default | Description |
131
+ | ------------------------ | --------- | ------- | -------------------------------------- |
132
+ | `jsxSingleQuote` | `boolean` | `false` | Use single quotes in JSX attributes |
133
+ | `bracketSameLine` | `boolean` | `false` | Put `>` on the same line in JSX |
134
+ | `singleAttributePerLine` | `boolean` | `false` | Force single attribute per line in JSX |
135
+
136
+ ### Object Formatting
137
+
138
+ | Option | Type | Default | Description |
139
+ | ---------------- | ------------------------------------------- | ------------- | ------------------------------------------------ |
140
+ | `bracketSpacing` | `boolean` | `true` | Print spaces between brackets in object literals |
141
+ | `quoteProps` | `'as-needed' \| 'consistent' \| 'preserve'` | `'as-needed'` | When to quote object property names |
142
+ | `objectWrap` | `'preserve' \| 'collapse' \| 'always'` | `'preserve'` | How to wrap object literals |
143
+
144
+ ### Line Endings
145
+
146
+ | Option | Type | Default | Description |
147
+ | -------------------- | ------------------------ | ------- | ------------------------------------ |
148
+ | `endOfLine` | `'lf' \| 'crlf' \| 'cr'` | `'lf'` | Line ending character(s) |
149
+ | `insertFinalNewline` | `boolean` | `true` | Insert a newline at the end of files |
150
+
151
+ ### Advanced Options
152
+
153
+ | Option | Type | Default | Description |
154
+ | ----------------------------- | ----------------- | -------- | ----------------------------------------- |
155
+ | `embeddedLanguageFormatting` | `'auto' \| 'off'` | `'auto'` | Control formatting of quoted code |
156
+ | `experimentalSortImports` | `object` | - | Experimental import sorting configuration |
157
+ | `experimentalSortPackageJson` | `boolean` | - | Experimental package.json sorting |
158
+
159
+ ## Rules
160
+
161
+ ### `oxfmt/oxfmt`
162
+
163
+ This plugin provides a single rule that formats your code using oxfmt.
164
+
165
+ - Recommended: `error`
166
+ - Fixable: Yes (automatically applies formatting)
167
+ - Type: Layout
168
+
169
+ ## Examples
170
+
171
+ ### Format on Save in VS Code
172
+
173
+ Add this to your `.vscode/settings.json`:
174
+
175
+ ```json
176
+ {
177
+ "editor.codeActionsOnSave": {
178
+ "source.fixAll.eslint": "explicit"
179
+ },
180
+ "eslint.validate": [
181
+ "javascript",
182
+ "javascriptreact",
183
+ "typescript",
184
+ "typescriptreact"
185
+ ]
186
+ }
187
+ ```
188
+
189
+ ### Run from Command Line
190
+
191
+ ```bash
192
+ # Check for formatting issues
193
+ npx eslint .
194
+
195
+ # Fix formatting issues
196
+ npx eslint . --fix
49
197
  ```
50
198
 
199
+ ## Why oxfmt?
200
+
201
+ [oxfmt](https://github.com/oxc-project/oxc) is a modern, blazing-fast formatter written in Rust as part of the [Oxc project](https://oxc-project.github.io/). It aims to be a drop-in replacement for Prettier with significantly better performance.
202
+
203
+ ### Benefits
204
+
205
+ - **Performance**: 50-100x faster than Prettier
206
+ - **Compatibility**: Designed to be Prettier-compatible
207
+ - **Modern**: Built with modern JavaScript/TypeScript in mind
208
+ - **Maintained**: Part of the actively developed Oxc project
209
+
210
+ ## Related Projects
211
+
212
+ - [oxc](https://github.com/oxc-project/oxc) - The Oxidation Compiler
213
+ - [oxlint](https://github.com/oxc-project/oxc) - A fast linter
214
+ - [ESLint](https://eslint.org/) - Pluggable JavaScript linter
215
+
51
216
  ## License
52
217
 
53
218
  [MIT](./LICENSE) License © 2025-PRESENT [ntnyq](https://github.com/ntnyq)
package/dist/index.mjs CHANGED
@@ -5,7 +5,7 @@ import { DIFFERENCE, generateDifferences } from "generate-differences";
5
5
 
6
6
  //#region rolldown:runtime
7
7
  var __defProp = Object.defineProperty;
8
- var __export = (all, symbols) => {
8
+ var __exportAll = (all, symbols) => {
9
9
  let target = {};
10
10
  for (var name$2 in all) {
11
11
  __defProp(target, name$2, {
@@ -21,7 +21,7 @@ var __export = (all, symbols) => {
21
21
 
22
22
  //#endregion
23
23
  //#region node_modules/.pnpm/eslint-parser-plain@0.1.1/node_modules/eslint-parser-plain/dist/index.mjs
24
- var dist_exports = /* @__PURE__ */ __export({
24
+ var dist_exports = /* @__PURE__ */ __exportAll({
25
25
  meta: () => meta$1,
26
26
  parseForESLint: () => parseForESLint
27
27
  });
@@ -67,7 +67,7 @@ const configs = { recommended };
67
67
  //#endregion
68
68
  //#region package.json
69
69
  var name = "eslint-plugin-oxfmt";
70
- var version = "0.0.1";
70
+ var version = "0.0.3";
71
71
 
72
72
  //#endregion
73
73
  //#region src/meta.ts
@@ -81,13 +81,32 @@ const meta = {
81
81
  const dirWorkers = fileURLToPath(new URL("../workers", import.meta.url));
82
82
 
83
83
  //#endregion
84
- //#region node_modules/.pnpm/show-invisibles@0.0.1/node_modules/show-invisibles/dist/index.mjs
85
- const DEFAULT_MAPPINGS = /* @__PURE__ */ new Map([
84
+ //#region node_modules/.pnpm/show-invisibles@0.0.2/node_modules/show-invisibles/dist/index.js
85
+ const DEFAULT_MAPPINGS = new Map([
86
86
  [" ", "·"],
87
87
  ["\n", "⏎"],
88
88
  ["\r", "␍"],
89
89
  [" ", "↹"]
90
90
  ]);
91
+ /**
92
+ * Converts invisible characters to a commonly recognizable visible form
93
+ *
94
+ * @param input - The string with invisibles to convert
95
+ * @param options - options {@link Options}
96
+ * @returns The converted string
97
+ *
98
+ * @example
99
+ *
100
+ * ```ts
101
+ * import { showInvisibles } from 'show-invisibles'
102
+ *
103
+ * const input = `1 2\n3\t4\r5`
104
+ *
105
+ * console.log(showInvisibles(input))
106
+ *
107
+ * // => 1·2⏎3↹4␍5
108
+ * ```
109
+ */
91
110
  function showInvisibles(input, options = {}) {
92
111
  const { mappings = DEFAULT_MAPPINGS } = options;
93
112
  if (typeof input !== "string") throw new TypeError(`Expected input to type string, got ${typeof input}`);
@@ -230,6 +249,10 @@ const oxfmt = {
230
249
  type: "array",
231
250
  items: { type: "string" }
232
251
  },
252
+ insertFinalNewline: {
253
+ description: `Whether to insert a final newline at the end of the file. (Default: true)`,
254
+ type: "boolean"
255
+ },
233
256
  jsxSingleQuote: {
234
257
  description: `Use single quotes instead of double quotes in JSX. (Default: false)`,
235
258
  type: "boolean"
@@ -293,7 +316,10 @@ const oxfmt = {
293
316
  return { Program() {
294
317
  const sourceText = context.sourceCode.text;
295
318
  try {
296
- const formatResult = formatViaOxfmt(context.filename, sourceText, { ...context.options?.[0] });
319
+ const formatResult = formatViaOxfmt(context.filename, sourceText, {
320
+ ...context.options?.[0],
321
+ cwd: context.cwd
322
+ });
297
323
  if (formatResult.errors?.length) for (const error of formatResult.errors) {
298
324
  const label = error.labels?.[0];
299
325
  if (label) {
@@ -47,6 +47,8 @@ export type OxfmtOxfmt = []|[{
47
47
 
48
48
  ignorePatterns?: string[]
49
49
 
50
+ insertFinalNewline?: boolean
51
+
50
52
  jsxSingleQuote?: boolean
51
53
 
52
54
  objectWrap?: ("preserve" | "collapse" | "always")
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "eslint-plugin-oxfmt",
3
3
  "type": "module",
4
- "version": "0.0.1",
5
- "description": "An ESLint plugin that format code via oxfmt.",
4
+ "version": "0.0.3",
5
+ "description": "An ESLint plugin for formatting code with oxfmt.",
6
6
  "keywords": [
7
7
  "eslint",
8
8
  "eslint-plugin",
@@ -46,14 +46,14 @@
46
46
  "eslint": "^9.5.0"
47
47
  },
48
48
  "dependencies": {
49
- "generate-differences": "^0.1.0",
50
- "oxfmt": "^0.19.0",
49
+ "generate-differences": "^0.1.1",
50
+ "load-oxfmt-config": "^0.0.3",
51
+ "oxfmt": "^0.21.0",
51
52
  "synckit": "^0.11.11"
52
53
  },
53
54
  "devDependencies": {
54
55
  "@ntnyq/eslint-config": "^5.8.0",
55
56
  "@ntnyq/prettier-config": "^3.0.1",
56
- "@types/json-schema": "^7.0.15",
57
57
  "@types/node": "^25.0.3",
58
58
  "@typescript/native-preview": "7.0.0-dev.20251204.1",
59
59
  "bumpp": "^10.3.2",
@@ -62,13 +62,12 @@
62
62
  "eslint-typegen": "^2.3.0",
63
63
  "eslint-vitest-rule-tester": "^3.0.1",
64
64
  "husky": "^9.1.7",
65
- "json-schema": "^0.4.0",
66
65
  "nano-staged": "^0.9.0",
67
66
  "npm-run-all2": "^8.0.4",
68
67
  "prettier": "^3.7.4",
69
- "show-invisibles": "^0.0.1",
68
+ "show-invisibles": "^0.0.2",
70
69
  "tinyglobby": "^0.2.15",
71
- "tsdown": "^0.18.1",
70
+ "tsdown": "^0.18.4",
72
71
  "tsx": "^4.21.0",
73
72
  "typescript": "^5.9.3",
74
73
  "vitest": "^4.0.16"
package/workers/oxfmt.mjs CHANGED
@@ -1,10 +1,18 @@
1
1
  // @ts-check
2
2
 
3
+ import { loadOxfmtConfig } from 'load-oxfmt-config'
3
4
  import { format } from 'oxfmt'
4
5
  import { runAsWorker } from 'synckit'
5
6
 
6
7
  /**
7
- * @import { FormatOptions } from 'oxfmt'
8
+ * @typedef {object} PluginOptions
9
+ * @property {boolean} [useConfig] - Whether to use oxfmt configuration file
10
+ * @property {string} cwd - Current working directory for resolving configuration
11
+ * @property {string} [configPath] - Custom path to oxfmt configuration file
12
+ */
13
+
14
+ /**
15
+ * @typedef {import('oxfmt').FormatOptions & PluginOptions} Options
8
16
  */
9
17
 
10
18
  runAsWorker(
@@ -18,11 +26,22 @@ runAsWorker(
18
26
  */
19
27
  sourceText,
20
28
  /**'
21
- * @type {FormatOptions} format options
29
+ * @type {Options} format options
22
30
  */
23
31
  options,
24
32
  ) => {
25
- const formatResult = await format(filename, sourceText, options)
33
+ const { configPath, cwd, useConfig = true, ...formatOptions } = options
34
+ const mergedOptions = {
35
+ ...(useConfig
36
+ ? await loadOxfmtConfig({
37
+ configPath,
38
+ cwd,
39
+ })
40
+ : {}),
41
+ ...formatOptions,
42
+ }
43
+
44
+ const formatResult = await format(filename, sourceText, mergedOptions)
26
45
  return formatResult
27
46
  },
28
47
  )