-
-
Notifications
You must be signed in to change notification settings - Fork 29
/
parser.ts
101 lines (85 loc) · 2.47 KB
/
parser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import path from 'node:path'
import type { Linter } from 'eslint'
import type { VFileMessage } from 'vfile-message'
import { arrayify, normalizePosition, getPhysicalFilename } from './helpers'
import { performSyncWork } from './sync'
import type { ParserOptions, WorkerParseResult } from './types'
export const DEFAULT_EXTENSIONS: readonly string[] = ['.mdx']
export const MARKDOWN_EXTENSIONS: readonly string[] = ['.md']
export class Parser {
constructor() {
this.parse = this.parse.bind(this)
this.parseForESLint = this.parseForESLint.bind(this)
}
parse(code: string, options: ParserOptions) {
return this.parseForESLint(code, options).ast
}
parseForESLint(
code: string,
{
filePath,
sourceType,
ignoreRemarkConfig,
extensions,
markdownExtensions,
}: ParserOptions,
): Linter.ESLintParseResult {
const extname = path.extname(filePath)
const isMdx = [...DEFAULT_EXTENSIONS, ...arrayify(extensions)].includes(
extname,
)
const isMarkdown = [
...MARKDOWN_EXTENSIONS,
...arrayify(markdownExtensions),
].includes(extname)
if (!isMdx && !isMarkdown) {
throw new Error(
'Unsupported file extension, make sure setting the `extensions` or `markdownExtensions` option correctly.',
)
}
const physicalFilename = getPhysicalFilename(filePath)
let result: WorkerParseResult
try {
result = performSyncWork({
fileOptions: {
path: physicalFilename,
value: code,
},
physicalFilename,
isMdx,
ignoreRemarkConfig,
})
} catch (err: unknown) {
/* istanbul ignore if */
if (process.argv.includes('--debug')) {
console.error(err)
}
const { message, line, column, place } = err as VFileMessage
const point = place && ('start' in place ? place.start : place)
throw Object.assign(
new SyntaxError(message, {
cause: err,
}),
{
lineNumber: line,
column,
index: /* istanbul ignore next */ point?.offset,
},
)
}
const { root, body, comments, tokens } = result
return {
ast: {
...normalizePosition(root.position),
type: 'Program',
sourceType,
body,
comments,
tokens,
},
}
}
}
export const parser = new Parser()
// eslint-disable-next-line @typescript-eslint/unbound-method
export const { parse, parseForESLint } = parser