Skip to content

Commit 47f100b

Browse files
authored
fix: only apply fix once for the whole file (#309)
close #308
1 parent 94a08af commit 47f100b

File tree

6 files changed

+100
-133
lines changed

6 files changed

+100
-133
lines changed

packages/eslint-plugin-mdx/src/rules/remark.ts

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,20 @@ import type { ParserOptions } from 'eslint-mdx'
55
import { DEFAULT_EXTENSIONS, MARKDOWN_EXTENSIONS } from 'eslint-mdx'
66
import { createSyncFn } from 'synckit'
77
import type { FrozenProcessor } from 'unified'
8+
import type { VFile, VFileOptions } from 'vfile'
89
import vfile from 'vfile'
910

1011
import { getPhysicalFilename, getRemarkProcessor } from './helpers'
11-
import type { ProcessSync, RemarkLintMessage } from './types'
12+
import type { RemarkLintMessage } from './types'
1213

13-
const processSync = createSyncFn(require.resolve('../worker')) as ProcessSync
14+
const processSync = createSyncFn(require.resolve('../worker')) as (
15+
fileOptions: VFileOptions,
16+
physicalFilename: string,
17+
isFile: boolean,
18+
) => {
19+
messages: VFile['messages']
20+
content: string
21+
}
1422

1523
const brokenCache = new WeakMap<FrozenProcessor, true>()
1624

@@ -54,12 +62,18 @@ export const remark: Rule.RuleModule = {
5462
}
5563

5664
const file = vfile(fileOptions)
65+
let fixedText: string
5766

5867
let broken = brokenCache.get(remarkProcessor)
5968

6069
if (broken) {
61-
const { messages } = processSync(fileOptions, physicalFilename, isMdx)
70+
const { messages, content } = processSync(
71+
fileOptions,
72+
physicalFilename,
73+
isMdx,
74+
)
6275
file.messages = messages
76+
fixedText = content
6377
} else {
6478
try {
6579
remarkProcessor.processSync(file)
@@ -70,20 +84,30 @@ export const remark: Rule.RuleModule = {
7084
'`processSync` finished async. Use `process` instead'
7185
) {
7286
brokenCache.set(remarkProcessor, (broken = true))
73-
const { messages } = processSync(
87+
const { messages, content } = processSync(
7488
fileOptions,
7589
physicalFilename,
7690
isMdx,
7791
)
7892
file.messages = messages
79-
} else {
80-
if (!file.messages.includes(err)) {
81-
file.message(err).fatal = true
82-
}
93+
fixedText = content
94+
} else if (!file.messages.includes(err)) {
95+
file.message(err).fatal = true
8396
}
8497
}
8598
}
8699

100+
if (!broken) {
101+
fixedText = file.toString()
102+
}
103+
104+
fixedText =
105+
filename === physicalFilename || sourceText.endsWith('\n')
106+
? fixedText
107+
: fixedText.slice(0, -1)
108+
109+
let fixed = 0
110+
87111
for (const {
88112
source,
89113
reason,
@@ -120,27 +144,16 @@ export const remark: Rule.RuleModule = {
120144
},
121145
},
122146
node,
123-
fix(fixer) {
124-
/* istanbul ignore if */
125-
if (start.offset == null) {
126-
return null
127-
}
128-
const range: [number, number] = [
129-
start.offset,
130-
/* istanbul ignore next */
131-
end.offset == null ? start.offset + 1 : end.offset,
132-
]
133-
const partialText = sourceText.slice(...range)
134-
const fixed = broken
135-
? processSync(partialText, physicalFilename, isMdx)
136-
: remarkProcessor.processSync(partialText).toString()
137-
return fixer.replaceTextRange(
138-
range,
139-
partialText.endsWith('\n')
140-
? /* istanbul ignore next */ fixed
141-
: fixed.slice(0, -1), // remove redundant new line
142-
)
143-
},
147+
fix:
148+
fixedText === sourceText
149+
? null
150+
: () =>
151+
fixed++
152+
? null
153+
: {
154+
range: [0, sourceText.length],
155+
text: fixedText,
156+
},
144157
})
145158
}
146159
},

packages/eslint-plugin-mdx/src/rules/types.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { Linter } from 'eslint'
22
import type { ExpressionStatement, Node } from 'estree'
33
import type { Attacher } from 'unified'
4-
import type { VFile, VFileOptions } from 'vfile'
54

65
export interface WithParent {
76
parent: NodeWithParent
@@ -26,16 +25,3 @@ export interface RemarkLintMessage {
2625
ruleId: string
2726
severity: Linter.Severity
2827
}
29-
30-
export interface ProcessSync {
31-
(text: string, physicalFilename: string, isFile: boolean): string
32-
(fileOptions: VFileOptions, physicalFilename: string, isFile: boolean): Pick<
33-
VFile,
34-
'messages'
35-
>
36-
(
37-
textOrFileOptions: string | VFileOptions,
38-
physicalFilename: string,
39-
isFile: boolean,
40-
): string | VFileOptions
41-
}

packages/eslint-plugin-mdx/src/worker.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,22 @@ import { getRemarkProcessor } from './rules'
77
// eslint-disable-next-line @typescript-eslint/no-floating-promises
88
runAsWorker(
99
async (
10-
textOrFileOptions: string | VFileOptions,
10+
fileOptions: VFileOptions,
1111
physicalFilename: string,
1212
isMdx: boolean,
1313
) => {
1414
const remarkProcessor = getRemarkProcessor(physicalFilename, isMdx)
15-
const file = vfile(textOrFileOptions)
15+
const file = vfile(fileOptions)
1616
try {
1717
await remarkProcessor.process(file)
1818
} catch (err) {
1919
if (!file.messages.includes(err)) {
2020
file.message(err).fatal = true
2121
}
2222
}
23-
return typeof textOrFileOptions === 'string'
24-
? file.toString()
25-
: { messages: file.messages }
23+
return {
24+
messages: file.messages,
25+
content: file.toString(),
26+
}
2627
},
2728
)

test/__snapshots__/fixtures.test.ts.snap

Lines changed: 0 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,6 @@ Array [
66
"column": 1,
77
"endColumn": 6,
88
"endLine": 3,
9-
"fix": Object {
10-
"range": Array [
11-
7,
12-
12,
13-
],
14-
"text": "# abc",
15-
},
169
"line": 3,
1710
"message": "Do not use headings with similar content (1:1)",
1811
"nodeType": "Program",
@@ -23,13 +16,6 @@ Array [
2316
"column": 1,
2417
"endColumn": 6,
2518
"endLine": 3,
26-
"fix": Object {
27-
"range": Array [
28-
7,
29-
12,
30-
],
31-
"text": "# abc",
32-
},
3319
"line": 3,
3420
"message": "Don’t use multiple top level headings (1:1)",
3521
"nodeType": "Program",
@@ -40,13 +26,6 @@ Array [
4026
"column": 1,
4127
"endColumn": 6,
4228
"endLine": 36,
43-
"fix": Object {
44-
"range": Array [
45-
406,
46-
411,
47-
],
48-
"text": "# abc",
49-
},
5029
"line": 36,
5130
"message": "Do not use headings with similar content (1:1)",
5231
"nodeType": "Program",
@@ -57,13 +36,6 @@ Array [
5736
"column": 1,
5837
"endColumn": 6,
5938
"endLine": 36,
60-
"fix": Object {
61-
"range": Array [
62-
406,
63-
411,
64-
],
65-
"text": "# abc",
66-
},
6739
"line": 36,
6840
"message": "Don’t use multiple top level headings (1:1)",
6941
"nodeType": "Program",
@@ -74,13 +46,6 @@ Array [
7446
"column": 1,
7547
"endColumn": 6,
7648
"endLine": 46,
77-
"fix": Object {
78-
"range": Array [
79-
472,
80-
477,
81-
],
82-
"text": "# abc",
83-
},
8449
"line": 46,
8550
"message": "Do not use headings with similar content (3:1)",
8651
"nodeType": "Program",
@@ -91,13 +56,6 @@ Array [
9156
"column": 1,
9257
"endColumn": 6,
9358
"endLine": 46,
94-
"fix": Object {
95-
"range": Array [
96-
472,
97-
477,
98-
],
99-
"text": "# abc",
100-
},
10159
"line": 46,
10260
"message": "Don’t use multiple top level headings (3:1)",
10361
"nodeType": "Program",
@@ -121,13 +79,6 @@ Array [
12179
"column": 1,
12280
"endColumn": 16,
12381
"endLine": 27,
124-
"fix": Object {
125-
"range": Array [
126-
550,
127-
565,
128-
],
129-
"text": "# Hello, world!",
130-
},
13182
"line": 27,
13283
"message": "Don’t use multiple top level headings (3:1)",
13384
"nodeType": "Program",
@@ -160,13 +111,6 @@ Array [
160111
"column": 1,
161112
"endColumn": 36,
162113
"endLine": 35,
163-
"fix": Object {
164-
"range": Array [
165-
653,
166-
688,
167-
],
168-
"text": "# Here's a text gradient shortcode!",
169-
},
170114
"line": 35,
171115
"message": "Don’t use multiple top level headings (3:1)",
172116
"nodeType": "Program",
@@ -202,13 +146,6 @@ Array [
202146
"column": 1,
203147
"endColumn": 6,
204148
"endLine": 3,
205-
"fix": Object {
206-
"range": Array [
207-
7,
208-
12,
209-
],
210-
"text": "# abc",
211-
},
212149
"line": 3,
213150
"message": "Do not use headings with similar content (1:1)",
214151
"nodeType": "Program",
@@ -219,13 +156,6 @@ Array [
219156
"column": 1,
220157
"endColumn": 6,
221158
"endLine": 3,
222-
"fix": Object {
223-
"range": Array [
224-
7,
225-
12,
226-
],
227-
"text": "# abc",
228-
},
229159
"line": 3,
230160
"message": "Don’t use multiple top level headings (1:1)",
231161
"nodeType": "Program",
@@ -295,13 +225,6 @@ Array [
295225
"column": 1,
296226
"endColumn": 6,
297227
"endLine": 3,
298-
"fix": Object {
299-
"range": Array [
300-
7,
301-
12,
302-
],
303-
"text": "# abc",
304-
},
305228
"line": 3,
306229
"message": "Do not use headings with similar content (1:1)",
307230
"nodeType": "Program",
@@ -312,13 +235,6 @@ Array [
312235
"column": 1,
313236
"endColumn": 6,
314237
"endLine": 3,
315-
"fix": Object {
316-
"range": Array [
317-
7,
318-
12,
319-
],
320-
"text": "# abc",
321-
},
322238
"line": 3,
323239
"message": "Don’t use multiple top level headings (1:1)",
324240
"nodeType": "Program",

test/fixtures/style/.remarkrc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"settings": {
3+
"emphasis": "*",
4+
"strong": "*"
5+
},
6+
"plugins": [
7+
[
8+
"lint-emphasis-marker",
9+
"*"
10+
],
11+
[
12+
"lint-strong-marker",
13+
"*"
14+
]
15+
]
16+
}

0 commit comments

Comments
 (0)