hanlint 0.0.13 → 0.0.15
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/cli/main.js +25 -8
- package/src/document/sourceText.js +15 -7
- package/src/report/sheet.js +0 -0
package/data/version.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version": "0.0.
|
|
1
|
+
{"version": "0.0.15"}
|
package/package.json
CHANGED
package/src/cli/main.js
CHANGED
|
@@ -1005,6 +1005,11 @@ function relativeLabel(path) {
|
|
|
1005
1005
|
return label.split(sep).join("/").replaceAll("\\", "/");
|
|
1006
1006
|
}
|
|
1007
1007
|
|
|
1008
|
+
/** 표의 자리 글자. 뜻은 파이썬 SheetRow.place 가 소유한다. @param {import("../report/sheet.js").SheetRow} row */
|
|
1009
|
+
function placeOf(row) {
|
|
1010
|
+
return row.column > 0 ? `${row.file}:${row.line}:${row.column}` : `${row.file}:${row.line}`;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1008
1013
|
/** 표의 고침을 파일에 쓴다. 뜻은 파이썬 applySheet 가 소유한다. @param {string} sheetPath @param {boolean} dryRun @returns {[string[], string[]]} */
|
|
1009
1014
|
function applySheet(sheetPath, dryRun) {
|
|
1010
1015
|
const parsed = parseSheet(readFileSync(sheetPath, "utf-8"));
|
|
@@ -1020,21 +1025,33 @@ function applySheet(sheetPath, dryRun) {
|
|
|
1020
1025
|
for (const file of [...byFile.keys()].sort()) {
|
|
1021
1026
|
const rows = /** @type {import("../report/sheet.js").SheetRow[]} */ (byFile.get(file));
|
|
1022
1027
|
if (!existsSync(file)) {
|
|
1023
|
-
failed.push(...rows.map((row) => `${row
|
|
1028
|
+
failed.push(...rows.map((row) => `${placeOf(row)}: 파일이 없다`));
|
|
1024
1029
|
continue;
|
|
1025
1030
|
}
|
|
1026
1031
|
const lines = readFileSync(file, "utf-8").split("\n");
|
|
1027
1032
|
let changed = false;
|
|
1028
|
-
|
|
1029
|
-
|
|
1033
|
+
// 한 줄에 고침이 여럿이면 뒤 칸부터. 앞 칸을 먼저 바꾸면 길이가 달라져 뒤 칸의 자리가 어긋난다.
|
|
1034
|
+
for (const row of [...rows].sort((a, b) => a.line - b.line || b.column - a.column)) {
|
|
1035
|
+
const place = placeOf(row);
|
|
1030
1036
|
if (row.line < 1 || row.line > lines.length) {
|
|
1031
1037
|
failed.push(`${place}: 그 줄이 없다`);
|
|
1032
1038
|
continue;
|
|
1033
1039
|
}
|
|
1034
|
-
|
|
1035
|
-
if (
|
|
1036
|
-
|
|
1037
|
-
|
|
1040
|
+
let newLine = lines[row.line - 1];
|
|
1041
|
+
if (row.column > 0) {
|
|
1042
|
+
const start = row.column - 1;
|
|
1043
|
+
if (newLine.slice(start, start + row.text.length) !== row.text) {
|
|
1044
|
+
failed.push(`${place}: 그 칸에 그 글이 없다. 표를 다시 뽑는다`);
|
|
1045
|
+
continue;
|
|
1046
|
+
}
|
|
1047
|
+
newLine = newLine.slice(0, start) + row.fix + newLine.slice(start + row.text.length);
|
|
1048
|
+
} else {
|
|
1049
|
+
const [replaced, count] = replaceLiteral(newLine, row.text, row.fix);
|
|
1050
|
+
if (count !== 1) {
|
|
1051
|
+
failed.push(`${place}: 글이 그 줄에 ${count}번 있다. 한 번이어야 바꾼다`);
|
|
1052
|
+
continue;
|
|
1053
|
+
}
|
|
1054
|
+
newLine = replaced;
|
|
1038
1055
|
}
|
|
1039
1056
|
lines[row.line - 1] = newLine;
|
|
1040
1057
|
changed = true;
|
|
@@ -1078,7 +1095,7 @@ function runSheet(args) {
|
|
|
1078
1095
|
const label = relativeLabel(file);
|
|
1079
1096
|
for (const literal of sourceLiterals(readFileSync(file, "utf-8"), label)) {
|
|
1080
1097
|
const findings = runAll(fingerprint(literal.plain, config), config).filter((finding) => finding.severity === "error");
|
|
1081
|
-
if (findings.length || options["--all"]) rows.push({ file: label, line: literal.line, text: literal.text, findings, fix: "" });
|
|
1098
|
+
if (findings.length || options["--all"]) rows.push({ file: label, line: literal.line, text: literal.text, findings, fix: "", column: literal.column });
|
|
1082
1099
|
}
|
|
1083
1100
|
}
|
|
1084
1101
|
emit(format === "json" ? renderSheetJson(rows, config.preset, files.length) : renderSheet(rows, config.preset, files.length), output);
|
|
@@ -20,6 +20,7 @@ const RUST_TEST_MARKER = "#[cfg(test)]";
|
|
|
20
20
|
* @property {number} line 1부터 세는 줄 번호. 여러 줄을 이은 러스트 문자열은 시작 줄이다
|
|
21
21
|
* @property {string} text 따옴표와 태그를 뺀 글. 파일에 있는 그대로라 되돌려 쓸 때 찾을 수 있다
|
|
22
22
|
* @property {string} plain 검사에 쓰는 글. 식 (`${...}`, `{...}`) 을 비우고 공백을 하나로 모았다
|
|
23
|
+
* @property {number} column 1부터 세는 칸. 그 줄에서 text 가 시작하는 자리
|
|
23
24
|
*/
|
|
24
25
|
|
|
25
26
|
/** 템플릿 리터럴의 `${ ... }` 식을 (중첩 괄호를 세어) 같은 길이의 빈칸으로 바꾼다. @param {string} source */
|
|
@@ -88,9 +89,16 @@ function closingQuote(line, start) {
|
|
|
88
89
|
return -1;
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
/**
|
|
92
|
+
/** `index` 의 `>` 가 JSX 여는 태그의 끝인가. 뜻은 파이썬 tagCloses 가 소유한다. @param {string} line @param {number} index */
|
|
93
|
+
function tagCloses(line, index) {
|
|
94
|
+
if (index === 0 || line[index + 1] === "=") return false;
|
|
95
|
+
const before = line[index - 1];
|
|
96
|
+
return "\"'}".includes(before) || /[A-Za-z0-9]/.test(before);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** 한 줄의 글 마디를 [시작 자리, 글] 로 나온 차례로. 뜻은 파이썬 lineLiterals 가 소유한다. @param {string} line @returns {[number, string][]} */
|
|
92
100
|
export function lineLiterals(line) {
|
|
93
|
-
/** @type {string[]} */
|
|
101
|
+
/** @type {[number, string][]} */
|
|
94
102
|
const found = [];
|
|
95
103
|
let index = 0;
|
|
96
104
|
while (index < line.length) {
|
|
@@ -98,15 +106,15 @@ export function lineLiterals(line) {
|
|
|
98
106
|
if (QUOTES.includes(char)) {
|
|
99
107
|
const end = closingQuote(line, index);
|
|
100
108
|
if (end < 0) break;
|
|
101
|
-
found.push(line.slice(index + 1, end));
|
|
109
|
+
found.push([index + 1, line.slice(index + 1, end)]);
|
|
102
110
|
index = end + 1;
|
|
103
111
|
continue;
|
|
104
112
|
}
|
|
105
|
-
if (char === ">" && (
|
|
113
|
+
if (char === ">" && tagCloses(line, index)) {
|
|
106
114
|
const end = line.indexOf("<", index + 1);
|
|
107
115
|
if (end > index) {
|
|
108
116
|
const inner = line.slice(index + 1, end);
|
|
109
|
-
found.push(inner);
|
|
117
|
+
found.push([index + 1, inner]);
|
|
110
118
|
if (!inner.includes("{")) {
|
|
111
119
|
index = end;
|
|
112
120
|
continue;
|
|
@@ -123,10 +131,10 @@ export function sourceLiterals(source, path = "") {
|
|
|
123
131
|
/** @type {SourceLiteral[]} */
|
|
124
132
|
const found = [];
|
|
125
133
|
userFacingSource(source, path).split("\n").forEach((line, index) => {
|
|
126
|
-
for (const raw of lineLiterals(line)) {
|
|
134
|
+
for (const [start, raw] of lineLiterals(line)) {
|
|
127
135
|
const text = raw.trim();
|
|
128
136
|
const plain = plainText(text);
|
|
129
|
-
if (text && KOREAN.test(plain)) found.push({ line: index + 1, text, plain });
|
|
137
|
+
if (text && KOREAN.test(plain)) found.push({ line: index + 1, text, plain, column: start + (raw.length - raw.trimStart().length) + 1 });
|
|
130
138
|
}
|
|
131
139
|
});
|
|
132
140
|
return found;
|
package/src/report/sheet.js
CHANGED
|
Binary file
|