-
Notifications
You must be signed in to change notification settings - Fork 65
/
Copy pathmarkdown-language.js
140 lines (123 loc) · 3.84 KB
/
markdown-language.js
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/**
* @fileoverview Functions to fix up rules to provide missing methods on the `context` object.
* @author Nicholas C. Zakas
*/
/* eslint class-methods-use-this: 0 -- Required to complete interface. */
//------------------------------------------------------------------------------
// Imports
//------------------------------------------------------------------------------
import { MarkdownSourceCode } from "./markdown-source-code.js";
import { fromMarkdown } from "mdast-util-from-markdown";
import { gfmFromMarkdown } from "mdast-util-gfm";
import { gfm } from "micromark-extension-gfm";
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
/** @typedef {import("mdast").Root} RootNode */
/** @typedef {import("@eslint/core").Language} Language */
/** @typedef {import("@eslint/core").File} File */
/** @typedef {import("@eslint/core").ParseResult<RootNode>} ParseResult */
/** @typedef {import("@eslint/core").OkParseResult<RootNode>} OkParseResult */
/** @typedef {import("@eslint/core").SyntaxElement} SyntaxElement */
/** @typedef {"commonmark"|"gfm"} ParserMode */
//-----------------------------------------------------------------------------
// Exports
//-----------------------------------------------------------------------------
/**
* Markdown Language Object
* @implements {Language}
*/
export class MarkdownLanguage {
/**
* The type of file to read.
* @type {"text"}
*/
fileType = "text";
/**
* The line number at which the parser starts counting.
* @type {0|1}
*/
lineStart = 1;
/**
* The column number at which the parser starts counting.
* @type {0|1}
*/
columnStart = 1;
/**
* The name of the key that holds the type of the node.
* @type {string}
*/
nodeTypeKey = "type";
/**
* The Markdown parser mode.
* @type {ParserMode}
*/
#mode = "commonmark";
/**
* Creates a new instance.
* @param {Object} options The options to use for this instance.
* @param {ParserMode} [options.mode] The Markdown parser mode to use.
*/
constructor({ mode } = {}) {
if (mode) {
this.#mode = mode;
}
}
/* eslint-disable no-unused-vars -- Required to complete interface. */
/**
* Validates the language options.
* @param {Object} languageOptions The language options to validate.
* @returns {void}
* @throws {Error} When the language options are invalid.
*/
validateLanguageOptions(languageOptions) {
// no-op
}
/* eslint-enable no-unused-vars -- Required to complete interface. */
/**
* Parses the given file into an AST.
* @param {File} file The virtual file to parse.
* @returns {ParseResult} The result of parsing.
*/
parse(file) {
// Note: BOM already removed
const text = /** @type {string} */ (file.body);
/*
* Check for parsing errors first. If there's a parsing error, nothing
* else can happen. However, a parsing error does not throw an error
* from this method - it's just considered a fatal error message, a
* problem that ESLint identified just like any other.
*/
try {
const options =
this.#mode === "gfm"
? {
extensions: [gfm()],
mdastExtensions: [gfmFromMarkdown()],
}
: { extensions: [] };
const root = fromMarkdown(text, options);
return {
ok: true,
ast: root,
};
} catch (ex) {
return {
ok: false,
errors: [ex],
};
}
}
/**
* Creates a new `MarkdownSourceCode` object from the given information.
* @param {File} file The virtual file to create a `MarkdownSourceCode` object from.
* @param {OkParseResult} parseResult The result returned from `parse()`.
* @returns {MarkdownSourceCode} The new `MarkdownSourceCode` object.
*/
createSourceCode(file, parseResult) {
return new MarkdownSourceCode({
text: /** @type {string} */ (file.body),
ast: parseResult.ast,
});
}
}