hanlint 0.0.16 → 0.0.17
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/data/version.json +1 -1
- package/package.json +1 -1
- package/src/document/sourceText.js +97 -32
package/data/version.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version": "0.0.
|
|
1
|
+
{"version": "0.0.17"}
|
package/package.json
CHANGED
|
@@ -9,7 +9,6 @@ export const SOURCE_SUFFIXES = [".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx", ".
|
|
|
9
9
|
const KOREAN = /[가-힣]/;
|
|
10
10
|
// 문자열의 경계. 줄을 앞에서부터 훑어 여는 따옴표에서 같은 닫는 따옴표까지를 한 마디로 본다. 파이썬 sourceText.py 와 같다.
|
|
11
11
|
const QUOTES = ["'", '"', "`"];
|
|
12
|
-
const EXPRESSION = /\{[^{}]*\}/g;
|
|
13
12
|
const BLOCK_COMMENT = /\/\*[\s\S]*?\*\//g;
|
|
14
13
|
const DEVELOPER_LINE = /new Error\(|console\.|panic!\(|expect\(|assert/;
|
|
15
14
|
const RUST_CONTINUATION = /\\\r?\n[ \t]*/g;
|
|
@@ -23,28 +22,53 @@ const RUST_TEST_MARKER = "#[cfg(test)]";
|
|
|
23
22
|
* @property {number} column 1부터 세는 칸. 그 줄에서 text 가 시작하는 자리
|
|
24
23
|
*/
|
|
25
24
|
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
let
|
|
25
|
+
/** `start` 의 `{` 를 닫는 `}` 의 자리. 뜻은 파이썬 balancedEnd 가 소유한다. @param {string} line @param {number} start */
|
|
26
|
+
function balancedEnd(line, start) {
|
|
27
|
+
let depth = 0;
|
|
28
|
+
let index = start;
|
|
29
|
+
while (index < line.length) {
|
|
30
|
+
const char = line[index];
|
|
31
|
+
if (QUOTES.includes(char)) {
|
|
32
|
+
const end = closingQuote(line, index);
|
|
33
|
+
if (end < 0) return -1;
|
|
34
|
+
index = end + 1;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (char === "{") depth += 1;
|
|
38
|
+
else if (char === "}") {
|
|
39
|
+
depth -= 1;
|
|
40
|
+
if (depth === 0) return index;
|
|
41
|
+
}
|
|
42
|
+
index += 1;
|
|
43
|
+
}
|
|
44
|
+
return -1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** 글에 낀 식 `{...}` 와 `${...}` 의 [시작, 끝 다음]. 뜻은 파이썬 expressionSpans 가 소유한다. @param {string} text @returns {[number, number][]} */
|
|
48
|
+
export function expressionSpans(text) {
|
|
49
|
+
/** @type {[number, number][]} */
|
|
50
|
+
const spans = [];
|
|
29
51
|
let index = 0;
|
|
30
|
-
while (index <
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
depth -= 1;
|
|
38
|
-
if (depth === 0) break;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
output += " ".repeat(cursor + 1 - index);
|
|
42
|
-
index = cursor + 1;
|
|
52
|
+
while (index < text.length) {
|
|
53
|
+
if (text[index] === "{") {
|
|
54
|
+
const end = balancedEnd(text, index);
|
|
55
|
+
if (end < 0) break;
|
|
56
|
+
const start = index > 0 && text[index - 1] === "$" ? index - 1 : index;
|
|
57
|
+
spans.push([start, end + 1]);
|
|
58
|
+
index = end + 1;
|
|
43
59
|
continue;
|
|
44
60
|
}
|
|
45
|
-
output += source[index];
|
|
46
61
|
index += 1;
|
|
47
62
|
}
|
|
63
|
+
return spans;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** 템플릿 리터럴의 `${ ... }` 식을 같은 길이의 빈칸으로 바꾼다. 뜻은 파이썬 withoutTemplateExpressions 가 소유한다. @param {string} source */
|
|
67
|
+
export function withoutTemplateExpressions(source) {
|
|
68
|
+
let output = source;
|
|
69
|
+
for (const [start, end] of expressionSpans(source)) {
|
|
70
|
+
if (source[start] === "$") output = output.slice(0, start) + " ".repeat(end - start) + output.slice(end);
|
|
71
|
+
}
|
|
48
72
|
return output;
|
|
49
73
|
}
|
|
50
74
|
|
|
@@ -68,12 +92,17 @@ export function userFacingSource(source, path) {
|
|
|
68
92
|
|
|
69
93
|
/** 검사에 쓰는 글. 식을 비우고 공백을 하나로 모은다. @param {string} text */
|
|
70
94
|
export function plainText(text) {
|
|
71
|
-
let
|
|
72
|
-
|
|
73
|
-
|
|
95
|
+
let plain = "";
|
|
96
|
+
let cursor = 0;
|
|
97
|
+
for (const [start, end] of expressionSpans(text)) {
|
|
98
|
+
plain += text.slice(cursor, start) + " ";
|
|
99
|
+
cursor = end;
|
|
100
|
+
}
|
|
101
|
+
plain += text.slice(cursor);
|
|
102
|
+
return plain.replace(/\s+/g, " ").trim();
|
|
74
103
|
}
|
|
75
104
|
|
|
76
|
-
/** `start` 의 따옴표를 닫는 자리.
|
|
105
|
+
/** `start` 의 따옴표를 닫는 자리. 백틱 안의 `${...}` 은 통째로 건너뛴다. 뜻은 파이썬 closingQuote 가 소유한다. @param {string} line @param {number} start */
|
|
77
106
|
function closingQuote(line, start) {
|
|
78
107
|
const quote = line[start];
|
|
79
108
|
let index = start + 1;
|
|
@@ -83,6 +112,12 @@ function closingQuote(line, start) {
|
|
|
83
112
|
index += 2;
|
|
84
113
|
continue;
|
|
85
114
|
}
|
|
115
|
+
if (quote === "`" && char === "$" && line[index + 1] === "{") {
|
|
116
|
+
const end = balancedEnd(line, index + 1);
|
|
117
|
+
if (end < 0) return -1;
|
|
118
|
+
index = end + 1;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
86
121
|
if (char === quote) return index;
|
|
87
122
|
index += 1;
|
|
88
123
|
}
|
|
@@ -96,8 +131,36 @@ function tagCloses(line, index) {
|
|
|
96
131
|
return "\"'}".includes(before) || /[A-Za-z0-9]/.test(before);
|
|
97
132
|
}
|
|
98
133
|
|
|
99
|
-
/**
|
|
100
|
-
|
|
134
|
+
/** `start` 부터의 JSX 글이 끝나는 `<` 의 자리. 식 안의 `<` 는 글의 끝이 아니다. 뜻은 파이썬 jsxTextEnd 가 소유한다. @param {string} line @param {number} start */
|
|
135
|
+
function jsxTextEnd(line, start) {
|
|
136
|
+
let index = start;
|
|
137
|
+
while (index < line.length) {
|
|
138
|
+
const char = line[index];
|
|
139
|
+
if (char === "<") return index;
|
|
140
|
+
if (char === "{") {
|
|
141
|
+
const end = balancedEnd(line, index);
|
|
142
|
+
if (end < 0) return -1;
|
|
143
|
+
index = end + 1;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
index += 1;
|
|
147
|
+
}
|
|
148
|
+
return -1;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** 글에 낀 식 안의 글 마디. 뜻은 파이썬 innerLiterals 가 소유한다. @param {string} text @param {number} offset @returns {[number, string][]} */
|
|
152
|
+
function innerLiterals(text, offset) {
|
|
153
|
+
/** @type {[number, string][]} */
|
|
154
|
+
const found = [];
|
|
155
|
+
for (const [start, end] of expressionSpans(text)) {
|
|
156
|
+
const brace = text[start] === "$" ? start + 1 : start;
|
|
157
|
+
found.push(...lineLiterals(text.slice(brace + 1, end - 1), offset + brace + 1));
|
|
158
|
+
}
|
|
159
|
+
return found;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** 한 줄의 글 마디를 [시작 자리, 글] 로 나온 차례로. 뜻은 파이썬 lineLiterals 가 소유한다. @param {string} line @param {number} [offset] @returns {[number, string][]} */
|
|
163
|
+
export function lineLiterals(line, offset = 0) {
|
|
101
164
|
/** @type {[number, string][]} */
|
|
102
165
|
const found = [];
|
|
103
166
|
let index = 0;
|
|
@@ -106,23 +169,25 @@ export function lineLiterals(line) {
|
|
|
106
169
|
if (QUOTES.includes(char)) {
|
|
107
170
|
const end = closingQuote(line, index);
|
|
108
171
|
if (end < 0) break;
|
|
109
|
-
|
|
172
|
+
const raw = line.slice(index + 1, end);
|
|
173
|
+
found.push([offset + index + 1, raw]);
|
|
174
|
+
if (char === "`") found.push(...innerLiterals(raw, offset + index + 1));
|
|
110
175
|
index = end + 1;
|
|
111
176
|
continue;
|
|
112
177
|
}
|
|
113
178
|
if (char === ">" && tagCloses(line, index)) {
|
|
114
|
-
const end = line
|
|
179
|
+
const end = jsxTextEnd(line, index + 1);
|
|
115
180
|
if (end > index) {
|
|
116
|
-
const
|
|
117
|
-
found.push([index + 1,
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
181
|
+
const raw = line.slice(index + 1, end);
|
|
182
|
+
found.push([offset + index + 1, raw]);
|
|
183
|
+
found.push(...innerLiterals(raw, offset + index + 1));
|
|
184
|
+
index = end;
|
|
185
|
+
continue;
|
|
122
186
|
}
|
|
123
187
|
}
|
|
124
188
|
index += 1;
|
|
125
189
|
}
|
|
190
|
+
found.sort((a, b) => a[0] - b[0]);
|
|
126
191
|
return found;
|
|
127
192
|
}
|
|
128
193
|
|