pickier 0.1.36 → 0.1.38
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/dist/bin/cli.js +681 -584
- package/dist/rules/node/prefer-global-buffer.d.ts +5 -3
- package/dist/rules/node/prefer-global-process.d.ts +5 -3
- package/dist/src/index.js +873 -776
- package/package.json +1 -1
package/dist/src/index.js
CHANGED
|
@@ -8881,129 +8881,410 @@ var init_config = __esm(() => {
|
|
|
8881
8881
|
config5 = defaultConfig4;
|
|
8882
8882
|
});
|
|
8883
8883
|
|
|
8884
|
-
// src/
|
|
8885
|
-
function
|
|
8886
|
-
const
|
|
8887
|
-
|
|
8888
|
-
|
|
8889
|
-
|
|
8890
|
-
|
|
8891
|
-
|
|
8892
|
-
|
|
8893
|
-
|
|
8894
|
-
if (ch === "\\") {
|
|
8884
|
+
// src/rules/shell/_shared.ts
|
|
8885
|
+
function maskShellStrings(line) {
|
|
8886
|
+
const n = line.length;
|
|
8887
|
+
const out = Array.from({ length: n }, (_, i2) => line[i2]);
|
|
8888
|
+
let i = 0;
|
|
8889
|
+
while (i < n) {
|
|
8890
|
+
const ch = line[i];
|
|
8891
|
+
if (ch === "#" && (i === 0 || /\s/.test(line[i - 1]))) {
|
|
8892
|
+
while (i < n) {
|
|
8893
|
+
out[i] = " ";
|
|
8895
8894
|
i++;
|
|
8896
|
-
continue;
|
|
8897
8895
|
}
|
|
8898
|
-
|
|
8899
|
-
inStr = null;
|
|
8900
|
-
continue;
|
|
8896
|
+
break;
|
|
8901
8897
|
}
|
|
8902
|
-
if (ch === "
|
|
8903
|
-
|
|
8898
|
+
if (ch === "$" && line[i + 1] === "'") {
|
|
8899
|
+
i += 2;
|
|
8900
|
+
while (i < n) {
|
|
8901
|
+
if (line[i] === "\\" && i + 1 < n) {
|
|
8902
|
+
out[i] = " ";
|
|
8903
|
+
out[i + 1] = " ";
|
|
8904
|
+
i += 2;
|
|
8905
|
+
continue;
|
|
8906
|
+
}
|
|
8907
|
+
if (line[i] === "'") {
|
|
8908
|
+
i++;
|
|
8909
|
+
break;
|
|
8910
|
+
}
|
|
8911
|
+
out[i] = " ";
|
|
8912
|
+
i++;
|
|
8913
|
+
}
|
|
8904
8914
|
continue;
|
|
8905
8915
|
}
|
|
8906
|
-
if (ch === "
|
|
8907
|
-
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
if (depth === 0)
|
|
8911
|
-
return code.slice(i + 1).trim().length === 0;
|
|
8916
|
+
if (ch === "$" && line[i + 1] === '"') {
|
|
8917
|
+
i++;
|
|
8918
|
+
i = maskDoubleQuoted(line, i, out);
|
|
8919
|
+
continue;
|
|
8912
8920
|
}
|
|
8913
|
-
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
|
|
8923
|
-
|
|
8924
|
-
|
|
8925
|
-
|
|
8926
|
-
|
|
8927
|
-
|
|
8928
|
-
|
|
8929
|
-
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
|
|
8933
|
-
|
|
8934
|
-
|
|
8935
|
-
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
|
|
8950
|
-
|
|
8921
|
+
if (ch === "$" && line[i + 1] === "{") {
|
|
8922
|
+
i += 2;
|
|
8923
|
+
let depth = 1;
|
|
8924
|
+
while (i < n && depth > 0) {
|
|
8925
|
+
const c = line[i];
|
|
8926
|
+
if (c === "\\" && i + 1 < n) {
|
|
8927
|
+
out[i] = " ";
|
|
8928
|
+
out[i + 1] = " ";
|
|
8929
|
+
i += 2;
|
|
8930
|
+
continue;
|
|
8931
|
+
}
|
|
8932
|
+
if (c === "'") {
|
|
8933
|
+
i++;
|
|
8934
|
+
while (i < n && line[i] !== "'") {
|
|
8935
|
+
out[i] = " ";
|
|
8936
|
+
i++;
|
|
8937
|
+
}
|
|
8938
|
+
if (i < n)
|
|
8939
|
+
i++;
|
|
8940
|
+
continue;
|
|
8941
|
+
}
|
|
8942
|
+
if (c === '"') {
|
|
8943
|
+
i = maskDoubleQuoted(line, i, out);
|
|
8944
|
+
continue;
|
|
8945
|
+
}
|
|
8946
|
+
if (c === "{") {
|
|
8947
|
+
depth++;
|
|
8948
|
+
i++;
|
|
8949
|
+
continue;
|
|
8950
|
+
}
|
|
8951
|
+
if (c === "}") {
|
|
8952
|
+
depth--;
|
|
8953
|
+
i++;
|
|
8954
|
+
continue;
|
|
8955
|
+
}
|
|
8956
|
+
out[i] = " ";
|
|
8957
|
+
i++;
|
|
8958
|
+
}
|
|
8951
8959
|
continue;
|
|
8952
8960
|
}
|
|
8953
|
-
if (
|
|
8954
|
-
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8961
|
+
if (ch === "$" && line[i + 1] === "(" && line[i + 2] === "(") {
|
|
8962
|
+
i += 3;
|
|
8963
|
+
let depth = 2;
|
|
8964
|
+
while (i < n && depth > 0) {
|
|
8965
|
+
const c = line[i];
|
|
8966
|
+
if (c === "(") {
|
|
8967
|
+
depth++;
|
|
8968
|
+
i++;
|
|
8969
|
+
continue;
|
|
8970
|
+
}
|
|
8971
|
+
if (c === ")") {
|
|
8972
|
+
depth--;
|
|
8973
|
+
i++;
|
|
8974
|
+
continue;
|
|
8975
|
+
}
|
|
8976
|
+
out[i] = " ";
|
|
8977
|
+
i++;
|
|
8958
8978
|
}
|
|
8959
8979
|
continue;
|
|
8960
8980
|
}
|
|
8961
|
-
|
|
8962
|
-
|
|
8963
|
-
|
|
8964
|
-
|
|
8981
|
+
if (ch === "$" && line[i + 1] === "(") {
|
|
8982
|
+
i += 2;
|
|
8983
|
+
let depth = 1;
|
|
8984
|
+
while (i < n && depth > 0) {
|
|
8985
|
+
const c = line[i];
|
|
8986
|
+
if (c === "\\" && i + 1 < n) {
|
|
8987
|
+
out[i] = " ";
|
|
8988
|
+
out[i + 1] = " ";
|
|
8989
|
+
i += 2;
|
|
8990
|
+
continue;
|
|
8991
|
+
}
|
|
8992
|
+
if (c === "'") {
|
|
8993
|
+
i++;
|
|
8994
|
+
while (i < n && line[i] !== "'") {
|
|
8995
|
+
out[i] = " ";
|
|
8996
|
+
i++;
|
|
8997
|
+
}
|
|
8998
|
+
if (i < n)
|
|
8999
|
+
i++;
|
|
9000
|
+
continue;
|
|
9001
|
+
}
|
|
9002
|
+
if (c === '"') {
|
|
9003
|
+
i = maskDoubleQuoted(line, i, out);
|
|
9004
|
+
continue;
|
|
9005
|
+
}
|
|
9006
|
+
if (c === "(") {
|
|
9007
|
+
depth++;
|
|
9008
|
+
i++;
|
|
9009
|
+
continue;
|
|
9010
|
+
}
|
|
9011
|
+
if (c === ")") {
|
|
9012
|
+
depth--;
|
|
9013
|
+
i++;
|
|
9014
|
+
continue;
|
|
9015
|
+
}
|
|
9016
|
+
out[i] = " ";
|
|
9017
|
+
i++;
|
|
9018
|
+
}
|
|
9019
|
+
continue;
|
|
8965
9020
|
}
|
|
8966
|
-
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
9021
|
+
if (ch === "'") {
|
|
9022
|
+
i++;
|
|
9023
|
+
while (i < n && line[i] !== "'") {
|
|
9024
|
+
out[i] = " ";
|
|
9025
|
+
i++;
|
|
9026
|
+
}
|
|
9027
|
+
if (i < n)
|
|
9028
|
+
i++;
|
|
8973
9029
|
continue;
|
|
8974
9030
|
}
|
|
8975
|
-
if (
|
|
8976
|
-
|
|
8977
|
-
|
|
9031
|
+
if (ch === '"') {
|
|
9032
|
+
i = maskDoubleQuoted(line, i, out);
|
|
9033
|
+
continue;
|
|
8978
9034
|
}
|
|
8979
|
-
if (
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
9035
|
+
if (ch === "`") {
|
|
9036
|
+
i++;
|
|
9037
|
+
while (i < n && line[i] !== "`") {
|
|
9038
|
+
if (line[i] === "\\" && i + 1 < n) {
|
|
9039
|
+
out[i] = " ";
|
|
9040
|
+
out[i + 1] = " ";
|
|
9041
|
+
i += 2;
|
|
9042
|
+
continue;
|
|
9043
|
+
}
|
|
9044
|
+
out[i] = " ";
|
|
9045
|
+
i++;
|
|
9046
|
+
}
|
|
9047
|
+
if (i < n)
|
|
9048
|
+
i++;
|
|
9049
|
+
continue;
|
|
8983
9050
|
}
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
if (
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9051
|
+
i++;
|
|
9052
|
+
}
|
|
9053
|
+
return out.join("");
|
|
9054
|
+
}
|
|
9055
|
+
function maskDoubleQuoted(line, start, out) {
|
|
9056
|
+
const n = line.length;
|
|
9057
|
+
let i = start + 1;
|
|
9058
|
+
while (i < n) {
|
|
9059
|
+
const c = line[i];
|
|
9060
|
+
if (c === "\\" && i + 1 < n) {
|
|
9061
|
+
out[i] = " ";
|
|
9062
|
+
out[i + 1] = " ";
|
|
9063
|
+
i += 2;
|
|
9064
|
+
continue;
|
|
9065
|
+
}
|
|
9066
|
+
if (c === '"')
|
|
9067
|
+
return i + 1;
|
|
9068
|
+
if (c === "$" && line[i + 1] === "(" && line[i + 2] === "(") {
|
|
9069
|
+
i += 3;
|
|
9070
|
+
let depth = 2;
|
|
9071
|
+
while (i < n && depth > 0) {
|
|
9072
|
+
const x = line[i];
|
|
9073
|
+
if (x === "(") {
|
|
9074
|
+
depth++;
|
|
9075
|
+
i++;
|
|
9076
|
+
continue;
|
|
9077
|
+
}
|
|
9078
|
+
if (x === ")") {
|
|
9079
|
+
depth--;
|
|
9080
|
+
i++;
|
|
9081
|
+
continue;
|
|
9082
|
+
}
|
|
9083
|
+
out[i] = " ";
|
|
9084
|
+
i++;
|
|
9085
|
+
}
|
|
9086
|
+
continue;
|
|
9087
|
+
}
|
|
9088
|
+
if (c === "$" && line[i + 1] === "(") {
|
|
9089
|
+
i += 2;
|
|
9090
|
+
let depth = 1;
|
|
9091
|
+
while (i < n && depth > 0) {
|
|
9092
|
+
const x = line[i];
|
|
9093
|
+
if (x === "\\" && i + 1 < n) {
|
|
9094
|
+
out[i] = " ";
|
|
9095
|
+
out[i + 1] = " ";
|
|
9096
|
+
i += 2;
|
|
9097
|
+
continue;
|
|
9098
|
+
}
|
|
9099
|
+
if (x === "'") {
|
|
9100
|
+
i++;
|
|
9101
|
+
while (i < n && line[i] !== "'") {
|
|
9102
|
+
out[i] = " ";
|
|
9103
|
+
i++;
|
|
9104
|
+
}
|
|
9105
|
+
if (i < n)
|
|
9106
|
+
i++;
|
|
9107
|
+
continue;
|
|
9108
|
+
}
|
|
9109
|
+
if (x === '"') {
|
|
9110
|
+
i = maskDoubleQuoted(line, i, out);
|
|
9111
|
+
continue;
|
|
9112
|
+
}
|
|
9113
|
+
if (x === "(") {
|
|
9114
|
+
depth++;
|
|
9115
|
+
i++;
|
|
9116
|
+
continue;
|
|
9117
|
+
}
|
|
9118
|
+
if (x === ")") {
|
|
9119
|
+
depth--;
|
|
9120
|
+
i++;
|
|
9121
|
+
continue;
|
|
9122
|
+
}
|
|
9123
|
+
out[i] = " ";
|
|
9124
|
+
i++;
|
|
9125
|
+
}
|
|
9126
|
+
continue;
|
|
9127
|
+
}
|
|
9128
|
+
if (c === "$" && line[i + 1] === "{") {
|
|
9129
|
+
i += 2;
|
|
9130
|
+
let depth = 1;
|
|
9131
|
+
while (i < n && depth > 0) {
|
|
9132
|
+
const x = line[i];
|
|
9133
|
+
if (x === "{") {
|
|
9134
|
+
depth++;
|
|
9135
|
+
i++;
|
|
9136
|
+
continue;
|
|
9137
|
+
}
|
|
9138
|
+
if (x === "}") {
|
|
9139
|
+
depth--;
|
|
9140
|
+
i++;
|
|
9141
|
+
continue;
|
|
9142
|
+
}
|
|
9143
|
+
out[i] = " ";
|
|
9144
|
+
i++;
|
|
9145
|
+
}
|
|
9146
|
+
continue;
|
|
9147
|
+
}
|
|
9148
|
+
out[i] = " ";
|
|
9149
|
+
i++;
|
|
9150
|
+
}
|
|
9151
|
+
return i;
|
|
9152
|
+
}
|
|
9153
|
+
function heredocDelimiter(line) {
|
|
9154
|
+
const masked = maskShellStrings(line);
|
|
9155
|
+
const m = masked.match(/<<-?/);
|
|
9156
|
+
if (!m || m.index === undefined)
|
|
9157
|
+
return null;
|
|
9158
|
+
const after = line.slice(m.index + m[0].length);
|
|
9159
|
+
const delim = after.match(/^\s*(['"]?)(\w+)\1/);
|
|
9160
|
+
if (!delim)
|
|
9161
|
+
return null;
|
|
9162
|
+
return delim[2];
|
|
9163
|
+
}
|
|
9164
|
+
|
|
9165
|
+
// src/format.ts
|
|
9166
|
+
function isHangingControlLine(code) {
|
|
9167
|
+
const m = RE_CONTROL_OPEN.exec(code);
|
|
9168
|
+
if (!m)
|
|
9169
|
+
return /^(?:else|do)\s*$/.test(code);
|
|
9170
|
+
let depth = 0;
|
|
9171
|
+
let inStr = null;
|
|
9172
|
+
for (let i = m[0].length - 1;i < code.length; i++) {
|
|
9173
|
+
const ch = code[i];
|
|
9174
|
+
if (inStr) {
|
|
9175
|
+
if (ch === "\\") {
|
|
9176
|
+
i++;
|
|
9177
|
+
continue;
|
|
9178
|
+
}
|
|
9179
|
+
if (ch === inStr)
|
|
9180
|
+
inStr = null;
|
|
9181
|
+
continue;
|
|
9182
|
+
}
|
|
9183
|
+
if (ch === "'" || ch === '"' || ch === "`") {
|
|
9184
|
+
inStr = ch;
|
|
9185
|
+
continue;
|
|
9186
|
+
}
|
|
9187
|
+
if (ch === "(") {
|
|
9188
|
+
depth++;
|
|
9189
|
+
} else if (ch === ")") {
|
|
9190
|
+
depth--;
|
|
9191
|
+
if (depth === 0)
|
|
9192
|
+
return code.slice(i + 1).trim().length === 0;
|
|
9193
|
+
}
|
|
9194
|
+
}
|
|
9195
|
+
return false;
|
|
9196
|
+
}
|
|
9197
|
+
function getFileExt(filePath) {
|
|
9198
|
+
const idx = filePath.lastIndexOf(".");
|
|
9199
|
+
return idx >= 0 ? filePath.slice(idx) : "";
|
|
9200
|
+
}
|
|
9201
|
+
function isCodeFileExt(filePath) {
|
|
9202
|
+
return CODE_EXTS.has(getFileExt(filePath));
|
|
9203
|
+
}
|
|
9204
|
+
function isJsonFileExt(filePath) {
|
|
9205
|
+
return JSON_EXTS.has(getFileExt(filePath));
|
|
9206
|
+
}
|
|
9207
|
+
function isYamlFileExt(filePath) {
|
|
9208
|
+
return YAML_EXTS.has(getFileExt(filePath));
|
|
9209
|
+
}
|
|
9210
|
+
function isShellFileExt(filePath) {
|
|
9211
|
+
return SHELL_EXTS.has(getFileExt(filePath));
|
|
9212
|
+
}
|
|
9213
|
+
function isShellFile(filePath, content) {
|
|
9214
|
+
return isShellFileExt(filePath) || SHELL_SHEBANG_RE.test(content);
|
|
9215
|
+
}
|
|
9216
|
+
function processShellLinesFused(content, cfg) {
|
|
9217
|
+
const lines = content.split(`
|
|
9218
|
+
`);
|
|
9219
|
+
const len = lines.length;
|
|
9220
|
+
const result = new Array(len);
|
|
9221
|
+
const indentSize = cfg.format.indent;
|
|
9222
|
+
const useTab = cfg.format.indentStyle === "tabs";
|
|
9223
|
+
let indentLevel = 0;
|
|
9224
|
+
let inHeredoc = false;
|
|
9225
|
+
let heredocDelim = "";
|
|
9226
|
+
let inCase = false;
|
|
9227
|
+
let caseDepth = 0;
|
|
9228
|
+
for (let idx = 0;idx < len; idx++) {
|
|
9229
|
+
const line = lines[idx];
|
|
9230
|
+
if (line.length === 0 || /^\s*$/.test(line)) {
|
|
9231
|
+
result[idx] = "";
|
|
9232
|
+
continue;
|
|
9233
|
+
}
|
|
9234
|
+
if (inHeredoc) {
|
|
9235
|
+
result[idx] = line;
|
|
9236
|
+
if (line.trim() === heredocDelim) {
|
|
9237
|
+
inHeredoc = false;
|
|
9238
|
+
heredocDelim = "";
|
|
9239
|
+
}
|
|
9240
|
+
continue;
|
|
9241
|
+
}
|
|
9242
|
+
const delim = heredocDelimiter(line);
|
|
9243
|
+
if (delim) {
|
|
9244
|
+
inHeredoc = true;
|
|
9245
|
+
heredocDelim = delim;
|
|
9246
|
+
}
|
|
9247
|
+
let wsEnd = 0;
|
|
9248
|
+
while (wsEnd < line.length && (line.charCodeAt(wsEnd) === 32 || line.charCodeAt(wsEnd) === 9))
|
|
9249
|
+
wsEnd++;
|
|
9250
|
+
const trimmed = line.slice(wsEnd).trimEnd();
|
|
9251
|
+
if (trimmed.startsWith("#") && idx > 0) {
|
|
9252
|
+
const indent2 = useTab ? "\t".repeat(indentLevel) : " ".repeat(indentLevel * indentSize);
|
|
9253
|
+
result[idx] = indent2 + trimmed;
|
|
9254
|
+
continue;
|
|
9255
|
+
}
|
|
9256
|
+
if (/^case\b/.test(trimmed) && /\bin\s*$/.test(trimmed)) {
|
|
9257
|
+
caseDepth++;
|
|
9258
|
+
inCase = true;
|
|
9259
|
+
}
|
|
9260
|
+
if (/^esac\b/.test(trimmed)) {
|
|
9261
|
+
caseDepth = Math.max(0, caseDepth - 1);
|
|
9262
|
+
if (caseDepth === 0)
|
|
9263
|
+
inCase = false;
|
|
9264
|
+
}
|
|
9265
|
+
const isCasePattern = inCase && /\)\s*$/.test(trimmed) && !/\$\(/.test(trimmed) && !/^\s*\(/.test(trimmed) && !trimmed.startsWith("#");
|
|
9266
|
+
const isCaseTerminator = /^;[;&]\s*$/.test(trimmed);
|
|
9267
|
+
const shouldDecrease = /^(?:fi|done|esac|elif|else)\b/.test(trimmed) || /^\}/.test(trimmed);
|
|
9268
|
+
if (shouldDecrease)
|
|
9269
|
+
indentLevel = Math.max(0, indentLevel - 1);
|
|
9270
|
+
if (isCaseTerminator)
|
|
9271
|
+
indentLevel = Math.max(0, indentLevel - 1);
|
|
9272
|
+
const indent = useTab ? "\t".repeat(indentLevel) : " ".repeat(indentLevel * indentSize);
|
|
9273
|
+
result[idx] = indent + trimmed;
|
|
9274
|
+
if (/^then\b/.test(trimmed) || /^do\b/.test(trimmed) || /^else\b/.test(trimmed))
|
|
9275
|
+
indentLevel++;
|
|
9276
|
+
else if (/^if\b/.test(trimmed) && /\bthen\s*$/.test(trimmed))
|
|
9277
|
+
indentLevel++;
|
|
9278
|
+
else if (/^elif\b/.test(trimmed) && /\bthen\s*$/.test(trimmed))
|
|
9279
|
+
indentLevel++;
|
|
9280
|
+
else if (/^(?:while|for|until)\b/.test(trimmed) && /\bdo\s*$/.test(trimmed))
|
|
9281
|
+
indentLevel++;
|
|
9282
|
+
else if (/^case\b/.test(trimmed) && /\bin\s*$/.test(trimmed))
|
|
9283
|
+
indentLevel++;
|
|
9284
|
+
else if (isCasePattern)
|
|
9285
|
+
indentLevel++;
|
|
9286
|
+
else if (/\{\s*$/.test(trimmed) && !trimmed.startsWith("#"))
|
|
9287
|
+
indentLevel++;
|
|
9007
9288
|
}
|
|
9008
9289
|
return result.join(`
|
|
9009
9290
|
`);
|
|
@@ -9031,16 +9312,25 @@ function makeIndent(visualLevels, cfg) {
|
|
|
9031
9312
|
}
|
|
9032
9313
|
function convertDoubleToSingle(str) {
|
|
9033
9314
|
const inner = str.slice(1, -1);
|
|
9034
|
-
|
|
9035
|
-
result = result.replace(/'/g, '"');
|
|
9315
|
+
const result = inner.replace(/\\"/g, '"');
|
|
9036
9316
|
return `'${result}'`;
|
|
9037
9317
|
}
|
|
9038
9318
|
function convertSingleToDouble(str) {
|
|
9039
9319
|
const inner = str.slice(1, -1);
|
|
9040
|
-
|
|
9041
|
-
result = result.replace(/"/g, "'");
|
|
9320
|
+
const result = inner.replace(/\\'/g, "'");
|
|
9042
9321
|
return `"${result}"`;
|
|
9043
9322
|
}
|
|
9323
|
+
function hasUnescapedChar(content, ch) {
|
|
9324
|
+
for (let i = 0;i < content.length; i++) {
|
|
9325
|
+
if (content[i] === "\\") {
|
|
9326
|
+
i++;
|
|
9327
|
+
continue;
|
|
9328
|
+
}
|
|
9329
|
+
if (content[i] === ch)
|
|
9330
|
+
return true;
|
|
9331
|
+
}
|
|
9332
|
+
return false;
|
|
9333
|
+
}
|
|
9044
9334
|
function fixQuotes(content, preferred, filePath) {
|
|
9045
9335
|
if (!isCodeFileExt(filePath))
|
|
9046
9336
|
return content;
|
|
@@ -9115,11 +9405,12 @@ function fixQuotesLine(line, preferred) {
|
|
|
9115
9405
|
}
|
|
9116
9406
|
const closeChar = inString === 1 ? "'" : '"';
|
|
9117
9407
|
if (ch === closeChar) {
|
|
9118
|
-
const
|
|
9408
|
+
const stringContent = line.slice(stringStart + 1, i);
|
|
9409
|
+
const targetQuote = wantSingle ? "'" : '"';
|
|
9410
|
+
const needConvert = (inString === 2 && wantSingle || inString === 1 && !wantSingle) && !hasUnescapedChar(stringContent, targetQuote);
|
|
9119
9411
|
if (needConvert) {
|
|
9120
9412
|
if (stringStart > segStart)
|
|
9121
9413
|
parts.push(line.slice(segStart, stringStart));
|
|
9122
|
-
const stringContent = line.slice(stringStart + 1, i);
|
|
9123
9414
|
if (inString === 2)
|
|
9124
9415
|
parts.push(convertDoubleToSingle(`"${stringContent}"`));
|
|
9125
9416
|
else
|
|
@@ -9495,6 +9786,20 @@ function formatCode(src, cfg, filePath) {
|
|
|
9495
9786
|
return `${joined}
|
|
9496
9787
|
`;
|
|
9497
9788
|
}
|
|
9789
|
+
function quoteConvertible(line, openIdx, quote, target) {
|
|
9790
|
+
for (let j = openIdx + 1;j < line.length; j++) {
|
|
9791
|
+
const c = line[j];
|
|
9792
|
+
if (c === "\\") {
|
|
9793
|
+
j++;
|
|
9794
|
+
continue;
|
|
9795
|
+
}
|
|
9796
|
+
if (c === quote)
|
|
9797
|
+
return true;
|
|
9798
|
+
if (c === target)
|
|
9799
|
+
return false;
|
|
9800
|
+
}
|
|
9801
|
+
return true;
|
|
9802
|
+
}
|
|
9498
9803
|
function detectQuoteIssues(line, preferred) {
|
|
9499
9804
|
if (/^\s*\/\/\/\s*<reference/.test(line)) {
|
|
9500
9805
|
return [];
|
|
@@ -9513,21 +9818,18 @@ function detectQuoteIssues(line, preferred) {
|
|
|
9513
9818
|
continue;
|
|
9514
9819
|
}
|
|
9515
9820
|
if (!inString) {
|
|
9821
|
+
if (ch === "/" && line[i + 1] === "/") {
|
|
9822
|
+
break;
|
|
9823
|
+
}
|
|
9516
9824
|
if (ch === "'") {
|
|
9517
|
-
if (preferred === "double") {
|
|
9518
|
-
|
|
9519
|
-
if (beforeSlash === -1 || beforeSlash > i) {
|
|
9520
|
-
indices.push(i);
|
|
9521
|
-
}
|
|
9825
|
+
if (preferred === "double" && quoteConvertible(line, i, "'", '"')) {
|
|
9826
|
+
indices.push(i);
|
|
9522
9827
|
}
|
|
9523
9828
|
inString = "single";
|
|
9524
9829
|
continue;
|
|
9525
9830
|
} else if (ch === '"') {
|
|
9526
|
-
if (preferred === "single") {
|
|
9527
|
-
|
|
9528
|
-
if (beforeSlash === -1 || beforeSlash > i) {
|
|
9529
|
-
indices.push(i);
|
|
9530
|
-
}
|
|
9831
|
+
if (preferred === "single" && quoteConvertible(line, i, '"', "'")) {
|
|
9832
|
+
indices.push(i);
|
|
9531
9833
|
}
|
|
9532
9834
|
inString = "double";
|
|
9533
9835
|
continue;
|
|
@@ -9617,16 +9919,20 @@ function isRegexStart(input, slashIdx) {
|
|
|
9617
9919
|
function scanRegexEnd(input, start) {
|
|
9618
9920
|
let i = start + 1;
|
|
9619
9921
|
let inClass = false;
|
|
9922
|
+
let classStart = -1;
|
|
9620
9923
|
while (i < input.length) {
|
|
9621
9924
|
const c = input[i];
|
|
9622
9925
|
if (c === "\\") {
|
|
9623
9926
|
i += 2;
|
|
9624
9927
|
continue;
|
|
9625
9928
|
}
|
|
9626
|
-
if (c === "[") {
|
|
9929
|
+
if (c === "[" && !inClass) {
|
|
9627
9930
|
inClass = true;
|
|
9628
|
-
|
|
9629
|
-
|
|
9931
|
+
classStart = i;
|
|
9932
|
+
} else if (c === "]" && inClass) {
|
|
9933
|
+
const bodyStart = input[classStart + 1] === "^" ? classStart + 2 : classStart + 1;
|
|
9934
|
+
if (i !== bodyStart)
|
|
9935
|
+
inClass = false;
|
|
9630
9936
|
} else if (c === "/" && !inClass) {
|
|
9631
9937
|
i++;
|
|
9632
9938
|
while (i < input.length && /[a-z]/i.test(input[i]))
|
|
@@ -18828,7 +19134,7 @@ var init_no_empty = __esm(() => {
|
|
|
18828
19134
|
const beforeBlock = line.substring(0, line.lastIndexOf("{")).trim();
|
|
18829
19135
|
const isStatementBlock = /(?:if|else|for|while|do|try|catch|finally|function|\})\s*$/.test(beforeBlock);
|
|
18830
19136
|
const isObjectLiteral = /[=:]$/.test(beforeBlock) || /return\s*$/.test(beforeBlock);
|
|
18831
|
-
if (isStatementBlock && !isObjectLiteral
|
|
19137
|
+
if (isStatementBlock && !isObjectLiteral) {
|
|
18832
19138
|
issues.push({
|
|
18833
19139
|
filePath: ctx.filePath,
|
|
18834
19140
|
line: i + 1,
|
|
@@ -22256,7 +22562,9 @@ var init_prefer_const = __esm(() => {
|
|
|
22256
22562
|
for (const { name, fixable } of decls) {
|
|
22257
22563
|
if (!fixable)
|
|
22258
22564
|
continue;
|
|
22259
|
-
|
|
22565
|
+
const wordIdx = line.search(new RegExp(`\\b${name.replace(/\$/g, "\\$")}\\b`));
|
|
22566
|
+
const nameIdx = wordIdx !== -1 ? wordIdx : line.indexOf(name);
|
|
22567
|
+
issues.push({ filePath: ctx.filePath, line: i + 1, column: Math.max(1, nameIdx + 1), ruleId: "prefer-const", message: `'${name}' is never reassigned. Use 'const' instead`, severity: "error", help: `Change 'let ${name}' to 'const ${name}' since the variable is never reassigned. This makes your code more predictable and prevents accidental mutations` });
|
|
22260
22568
|
}
|
|
22261
22569
|
}
|
|
22262
22570
|
return issues;
|
|
@@ -23757,69 +24065,73 @@ var init_code_block_style = __esm(() => {
|
|
|
23757
24065
|
});
|
|
23758
24066
|
|
|
23759
24067
|
// src/rules/markdown/code-fence-style.ts
|
|
23760
|
-
|
|
23761
|
-
|
|
23762
|
-
|
|
23763
|
-
|
|
23764
|
-
|
|
24068
|
+
function fenceBoundaryLines(lines) {
|
|
24069
|
+
const out = new Set;
|
|
24070
|
+
let fenceChar = null;
|
|
24071
|
+
let fenceLen = 0;
|
|
24072
|
+
for (let i = 0;i < lines.length; i++) {
|
|
24073
|
+
const trimmed = lines[i].trim();
|
|
24074
|
+
if (fenceChar === null) {
|
|
24075
|
+
const open = trimmed.match(/^(`{3,}|~{3,})(.*)$/);
|
|
24076
|
+
if (open) {
|
|
24077
|
+
const ch = open[1][0];
|
|
24078
|
+
if (ch === "`" && open[2].includes("`"))
|
|
24079
|
+
continue;
|
|
24080
|
+
fenceChar = ch;
|
|
24081
|
+
fenceLen = open[1].length;
|
|
24082
|
+
out.add(i);
|
|
24083
|
+
}
|
|
24084
|
+
} else {
|
|
24085
|
+
const close = trimmed.match(/^(`{3,}|~{3,})\s*$/);
|
|
24086
|
+
if (close && close[1][0] === fenceChar && close[1].length >= fenceLen) {
|
|
24087
|
+
out.add(i);
|
|
24088
|
+
fenceChar = null;
|
|
24089
|
+
fenceLen = 0;
|
|
24090
|
+
}
|
|
24091
|
+
}
|
|
24092
|
+
}
|
|
24093
|
+
return out;
|
|
24094
|
+
}
|
|
24095
|
+
var codeFenceStyleRule;
|
|
24096
|
+
var init_code_fence_style = __esm(() => {
|
|
24097
|
+
codeFenceStyleRule = {
|
|
24098
|
+
meta: {
|
|
24099
|
+
docs: "Code fence style should be consistent (backtick or tilde)"
|
|
23765
24100
|
},
|
|
23766
24101
|
check: (text, ctx) => {
|
|
23767
24102
|
const issues = [];
|
|
23768
24103
|
const lines = text.split(/\r?\n/);
|
|
24104
|
+
const boundaries = fenceBoundaryLines(lines);
|
|
23769
24105
|
const options = ctx.options || {};
|
|
23770
24106
|
const style = options.style || "consistent";
|
|
23771
24107
|
let detectedStyle = null;
|
|
23772
|
-
for (
|
|
24108
|
+
for (const i of boundaries) {
|
|
23773
24109
|
const line = lines[i];
|
|
23774
|
-
const isBacktick = /^`{3,}/.test(line);
|
|
23775
|
-
const
|
|
23776
|
-
if (
|
|
23777
|
-
if (
|
|
24110
|
+
const isBacktick = /^`{3,}/.test(line.trim());
|
|
24111
|
+
const fenceStyle = isBacktick ? "backtick" : "tilde";
|
|
24112
|
+
if (style === "backtick" || style === "tilde") {
|
|
24113
|
+
if (fenceStyle !== style) {
|
|
23778
24114
|
issues.push({
|
|
23779
24115
|
filePath: ctx.filePath,
|
|
23780
24116
|
line: i + 1,
|
|
23781
24117
|
column: 1,
|
|
23782
24118
|
ruleId: "markdown/code-fence-style",
|
|
23783
|
-
message: "Expected tilde (~~~) code fence",
|
|
24119
|
+
message: style === "tilde" ? "Expected tilde (~~~) code fence" : "Expected backtick (```) code fence",
|
|
23784
24120
|
severity: "error"
|
|
23785
24121
|
});
|
|
23786
|
-
} else if (style === "consistent") {
|
|
23787
|
-
if (detectedStyle === null) {
|
|
23788
|
-
detectedStyle = "backtick";
|
|
23789
|
-
} else if (detectedStyle === "tilde") {
|
|
23790
|
-
issues.push({
|
|
23791
|
-
filePath: ctx.filePath,
|
|
23792
|
-
line: i + 1,
|
|
23793
|
-
column: 1,
|
|
23794
|
-
ruleId: "markdown/code-fence-style",
|
|
23795
|
-
message: "Code fence style should be consistent throughout document",
|
|
23796
|
-
severity: "error"
|
|
23797
|
-
});
|
|
23798
|
-
}
|
|
23799
24122
|
}
|
|
23800
|
-
} else if (
|
|
23801
|
-
if (
|
|
24123
|
+
} else if (style === "consistent") {
|
|
24124
|
+
if (detectedStyle === null) {
|
|
24125
|
+
detectedStyle = fenceStyle;
|
|
24126
|
+
} else if (detectedStyle !== fenceStyle) {
|
|
23802
24127
|
issues.push({
|
|
23803
24128
|
filePath: ctx.filePath,
|
|
23804
24129
|
line: i + 1,
|
|
23805
24130
|
column: 1,
|
|
23806
24131
|
ruleId: "markdown/code-fence-style",
|
|
23807
|
-
message: "
|
|
24132
|
+
message: "Code fence style should be consistent throughout document",
|
|
23808
24133
|
severity: "error"
|
|
23809
24134
|
});
|
|
23810
|
-
} else if (style === "consistent") {
|
|
23811
|
-
if (detectedStyle === null) {
|
|
23812
|
-
detectedStyle = "tilde";
|
|
23813
|
-
} else if (detectedStyle === "backtick") {
|
|
23814
|
-
issues.push({
|
|
23815
|
-
filePath: ctx.filePath,
|
|
23816
|
-
line: i + 1,
|
|
23817
|
-
column: 1,
|
|
23818
|
-
ruleId: "markdown/code-fence-style",
|
|
23819
|
-
message: "Code fence style should be consistent throughout document",
|
|
23820
|
-
severity: "error"
|
|
23821
|
-
});
|
|
23822
|
-
}
|
|
23823
24135
|
}
|
|
23824
24136
|
}
|
|
23825
24137
|
}
|
|
@@ -23829,32 +24141,22 @@ var init_code_fence_style = __esm(() => {
|
|
|
23829
24141
|
const options = ctx.options || {};
|
|
23830
24142
|
const style = options.style || "consistent";
|
|
23831
24143
|
const lines = text.split(/\r?\n/);
|
|
24144
|
+
const boundaries = fenceBoundaryLines(lines);
|
|
23832
24145
|
let targetStyle = "backtick";
|
|
23833
|
-
if (style === "backtick") {
|
|
23834
|
-
targetStyle =
|
|
23835
|
-
} else
|
|
23836
|
-
|
|
23837
|
-
|
|
23838
|
-
|
|
23839
|
-
if (/^`{3,}/.test(line)) {
|
|
23840
|
-
targetStyle = "backtick";
|
|
23841
|
-
break;
|
|
23842
|
-
} else if (/^~{3,}/.test(line)) {
|
|
23843
|
-
targetStyle = "tilde";
|
|
23844
|
-
break;
|
|
23845
|
-
}
|
|
24146
|
+
if (style === "backtick" || style === "tilde") {
|
|
24147
|
+
targetStyle = style;
|
|
24148
|
+
} else {
|
|
24149
|
+
for (const i of boundaries) {
|
|
24150
|
+
targetStyle = /^`{3,}/.test(lines[i].trim()) ? "backtick" : "tilde";
|
|
24151
|
+
break;
|
|
23846
24152
|
}
|
|
23847
24153
|
}
|
|
23848
|
-
const
|
|
23849
|
-
|
|
23850
|
-
|
|
23851
|
-
|
|
23852
|
-
|
|
23853
|
-
|
|
23854
|
-
return line.replace(/^(`{3,})(.*)$/, (_match, _backticks, rest) => {
|
|
23855
|
-
return `~~~${rest}`;
|
|
23856
|
-
});
|
|
23857
|
-
}
|
|
24154
|
+
const targetChar = targetStyle === "backtick" ? "`" : "~";
|
|
24155
|
+
const sourceRun = targetStyle === "backtick" ? /^(\s*)(~{3,})(.*)$/ : /^(\s*)(`{3,})(.*)$/;
|
|
24156
|
+
const fixedLines = lines.map((line, i) => {
|
|
24157
|
+
if (!boundaries.has(i))
|
|
24158
|
+
return line;
|
|
24159
|
+
return line.replace(sourceRun, (_m, ws, run, rest) => `${ws}${targetChar.repeat(run.length)}${rest}`);
|
|
23858
24160
|
});
|
|
23859
24161
|
return fixedLines.join(`
|
|
23860
24162
|
`);
|
|
@@ -23972,16 +24274,12 @@ var init_emphasis_style = __esm(() => {
|
|
|
23972
24274
|
const options = ctx.options || {};
|
|
23973
24275
|
const style = options.style || "consistent";
|
|
23974
24276
|
let detectedStyle = null;
|
|
23975
|
-
|
|
24277
|
+
const inCode = getCodeBlockLines(lines);
|
|
23976
24278
|
for (let i = 0;i < lines.length; i++) {
|
|
23977
24279
|
const line = lines[i];
|
|
23978
|
-
if (
|
|
23979
|
-
inFence = !inFence;
|
|
23980
|
-
continue;
|
|
23981
|
-
}
|
|
23982
|
-
if (inFence)
|
|
24280
|
+
if (inCode.has(i))
|
|
23983
24281
|
continue;
|
|
23984
|
-
const stripped = line
|
|
24282
|
+
const stripped = maskInlineCode(line);
|
|
23985
24283
|
const asteriskMatches = stripped.matchAll(/(?<!\*)\*(?!\*)([^*]+)\*(?!\*)/g);
|
|
23986
24284
|
for (const match of asteriskMatches) {
|
|
23987
24285
|
if (style === "underscore") {
|
|
@@ -24957,15 +25255,11 @@ var init_no_bare_urls = __esm(() => {
|
|
|
24957
25255
|
check: (text, ctx) => {
|
|
24958
25256
|
const issues = [];
|
|
24959
25257
|
const lines = text.split(/\r?\n/);
|
|
24960
|
-
|
|
25258
|
+
const codeLines = getCodeBlockLines(lines);
|
|
24961
25259
|
let inHtmlComment = false;
|
|
24962
25260
|
for (let i = 0;i < lines.length; i++) {
|
|
24963
25261
|
const line = lines[i];
|
|
24964
|
-
if (
|
|
24965
|
-
inFence = !inFence;
|
|
24966
|
-
continue;
|
|
24967
|
-
}
|
|
24968
|
-
if (inFence)
|
|
25262
|
+
if (codeLines.has(i))
|
|
24969
25263
|
continue;
|
|
24970
25264
|
if (line.includes("<!--"))
|
|
24971
25265
|
inHtmlComment = true;
|
|
@@ -24995,14 +25289,10 @@ var init_no_bare_urls = __esm(() => {
|
|
|
24995
25289
|
},
|
|
24996
25290
|
fix: (text) => {
|
|
24997
25291
|
const lines = text.split(/\r?\n/);
|
|
24998
|
-
|
|
25292
|
+
const codeLines = getCodeBlockLines(lines);
|
|
24999
25293
|
let inHtmlComment = false;
|
|
25000
|
-
const fixedLines = lines.map((line) => {
|
|
25001
|
-
if (
|
|
25002
|
-
inFence = !inFence;
|
|
25003
|
-
return line;
|
|
25004
|
-
}
|
|
25005
|
-
if (inFence)
|
|
25294
|
+
const fixedLines = lines.map((line, i) => {
|
|
25295
|
+
if (codeLines.has(i))
|
|
25006
25296
|
return line;
|
|
25007
25297
|
if (line.includes("<!--"))
|
|
25008
25298
|
inHtmlComment = true;
|
|
@@ -25324,7 +25614,19 @@ var init_no_hard_tabs = __esm(() => {
|
|
|
25324
25614
|
return issues;
|
|
25325
25615
|
},
|
|
25326
25616
|
fix: (text) => {
|
|
25327
|
-
|
|
25617
|
+
const lines = text.split(/\r?\n/);
|
|
25618
|
+
let inFence = false;
|
|
25619
|
+
const fixed = lines.map((line) => {
|
|
25620
|
+
if (/^(?:`{3,}|~{3,})/.test(line.trim())) {
|
|
25621
|
+
inFence = !inFence;
|
|
25622
|
+
return line;
|
|
25623
|
+
}
|
|
25624
|
+
if (inFence)
|
|
25625
|
+
return line;
|
|
25626
|
+
return line.replace(/\t/g, " ");
|
|
25627
|
+
});
|
|
25628
|
+
return fixed.join(`
|
|
25629
|
+
`);
|
|
25328
25630
|
}
|
|
25329
25631
|
};
|
|
25330
25632
|
});
|
|
@@ -25387,7 +25689,10 @@ var init_no_missing_space_atx = __esm(() => {
|
|
|
25387
25689
|
check: (text, ctx) => {
|
|
25388
25690
|
const issues = [];
|
|
25389
25691
|
const lines = text.split(/\r?\n/);
|
|
25692
|
+
const codeLines = getCodeBlockLines(lines);
|
|
25390
25693
|
for (let i = 0;i < lines.length; i++) {
|
|
25694
|
+
if (codeLines.has(i))
|
|
25695
|
+
continue;
|
|
25391
25696
|
const line = lines[i];
|
|
25392
25697
|
const match = line.match(/^(#{1,6})([^\s#])/);
|
|
25393
25698
|
if (match) {
|
|
@@ -25405,7 +25710,10 @@ var init_no_missing_space_atx = __esm(() => {
|
|
|
25405
25710
|
},
|
|
25406
25711
|
fix: (text) => {
|
|
25407
25712
|
const lines = text.split(/\r?\n/);
|
|
25408
|
-
const
|
|
25713
|
+
const codeLines = getCodeBlockLines(lines);
|
|
25714
|
+
const fixedLines = lines.map((line, i) => {
|
|
25715
|
+
if (codeLines.has(i))
|
|
25716
|
+
return line;
|
|
25409
25717
|
return line.replace(/^(#{1,6})([^\s#])/, "$1 $2");
|
|
25410
25718
|
});
|
|
25411
25719
|
return fixedLines.join(`
|
|
@@ -25424,7 +25732,10 @@ var init_no_missing_space_closed_atx = __esm(() => {
|
|
|
25424
25732
|
check: (text, ctx) => {
|
|
25425
25733
|
const issues = [];
|
|
25426
25734
|
const lines = text.split(/\r?\n/);
|
|
25735
|
+
const codeLines = getCodeBlockLines(lines);
|
|
25427
25736
|
for (let i = 0;i < lines.length; i++) {
|
|
25737
|
+
if (codeLines.has(i))
|
|
25738
|
+
continue;
|
|
25428
25739
|
const line = lines[i];
|
|
25429
25740
|
const match = line.match(/^(#{1,6})\s+(.+?)(#{1,6})\s*$/);
|
|
25430
25741
|
if (match) {
|
|
@@ -25526,7 +25837,10 @@ var init_no_multiple_space_atx = __esm(() => {
|
|
|
25526
25837
|
check: (text, ctx) => {
|
|
25527
25838
|
const issues = [];
|
|
25528
25839
|
const lines = text.split(/\r?\n/);
|
|
25840
|
+
const codeLines = getCodeBlockLines(lines);
|
|
25529
25841
|
for (let i = 0;i < lines.length; i++) {
|
|
25842
|
+
if (codeLines.has(i))
|
|
25843
|
+
continue;
|
|
25530
25844
|
const line = lines[i];
|
|
25531
25845
|
const match = line.match(/^(#{1,6})\s{2,}/);
|
|
25532
25846
|
if (match) {
|
|
@@ -25544,7 +25858,10 @@ var init_no_multiple_space_atx = __esm(() => {
|
|
|
25544
25858
|
},
|
|
25545
25859
|
fix: (text) => {
|
|
25546
25860
|
const lines = text.split(/\r?\n/);
|
|
25547
|
-
const
|
|
25861
|
+
const codeLines = getCodeBlockLines(lines);
|
|
25862
|
+
const fixedLines = lines.map((line, i) => {
|
|
25863
|
+
if (codeLines.has(i))
|
|
25864
|
+
return line;
|
|
25548
25865
|
return line.replace(/^(#{1,6})\s{2,}/, "$1 ");
|
|
25549
25866
|
});
|
|
25550
25867
|
return fixedLines.join(`
|
|
@@ -25563,7 +25880,10 @@ var init_no_multiple_space_blockquote = __esm(() => {
|
|
|
25563
25880
|
check: (text, ctx) => {
|
|
25564
25881
|
const issues = [];
|
|
25565
25882
|
const lines = text.split(/\r?\n/);
|
|
25883
|
+
const codeLines = getCodeBlockLines(lines);
|
|
25566
25884
|
for (let i = 0;i < lines.length; i++) {
|
|
25885
|
+
if (codeLines.has(i))
|
|
25886
|
+
continue;
|
|
25567
25887
|
const line = lines[i];
|
|
25568
25888
|
const match = line.match(/^(\s*)(>+)\s{2,}/);
|
|
25569
25889
|
if (match) {
|
|
@@ -25582,7 +25902,10 @@ var init_no_multiple_space_blockquote = __esm(() => {
|
|
|
25582
25902
|
},
|
|
25583
25903
|
fix: (text) => {
|
|
25584
25904
|
const lines = text.split(/\r?\n/);
|
|
25585
|
-
const
|
|
25905
|
+
const codeLines = getCodeBlockLines(lines);
|
|
25906
|
+
const fixedLines = lines.map((line, i) => {
|
|
25907
|
+
if (codeLines.has(i))
|
|
25908
|
+
return line;
|
|
25586
25909
|
return line.replace(/^(\s*>+)\s{2,}/, "$1 ");
|
|
25587
25910
|
});
|
|
25588
25911
|
return fixedLines.join(`
|
|
@@ -25601,7 +25924,10 @@ var init_no_multiple_space_closed_atx = __esm(() => {
|
|
|
25601
25924
|
check: (text, ctx) => {
|
|
25602
25925
|
const issues = [];
|
|
25603
25926
|
const lines = text.split(/\r?\n/);
|
|
25927
|
+
const codeLines = getCodeBlockLines(lines);
|
|
25604
25928
|
for (let i = 0;i < lines.length; i++) {
|
|
25929
|
+
if (codeLines.has(i))
|
|
25930
|
+
continue;
|
|
25605
25931
|
const line = lines[i];
|
|
25606
25932
|
const openMatch = line.match(/^(#{1,6})\s{2,}(?:\S.*?|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF])#{1,6}\s*$/);
|
|
25607
25933
|
if (openMatch) {
|
|
@@ -25675,14 +26001,10 @@ var init_no_space_in_code = __esm(() => {
|
|
|
25675
26001
|
check: (text, ctx) => {
|
|
25676
26002
|
const issues = [];
|
|
25677
26003
|
const lines = text.split(/\r?\n/);
|
|
25678
|
-
|
|
26004
|
+
const codeLines = getCodeBlockLines(lines);
|
|
25679
26005
|
for (let i = 0;i < lines.length; i++) {
|
|
25680
26006
|
const line = lines[i];
|
|
25681
|
-
if (
|
|
25682
|
-
inFence = !inFence;
|
|
25683
|
-
continue;
|
|
25684
|
-
}
|
|
25685
|
-
if (inFence)
|
|
26007
|
+
if (codeLines.has(i))
|
|
25686
26008
|
continue;
|
|
25687
26009
|
const codeSpanPattern = /(`+)([\s\S]*?)\1/g;
|
|
25688
26010
|
for (const match of line.matchAll(codeSpanPattern)) {
|
|
@@ -25703,15 +26025,11 @@ var init_no_space_in_code = __esm(() => {
|
|
|
25703
26025
|
},
|
|
25704
26026
|
fix: (text) => {
|
|
25705
26027
|
const lines = text.split(/\r?\n/);
|
|
25706
|
-
|
|
26028
|
+
const codeLines = getCodeBlockLines(lines);
|
|
25707
26029
|
const result = [];
|
|
25708
|
-
for (
|
|
25709
|
-
|
|
25710
|
-
|
|
25711
|
-
result.push(line);
|
|
25712
|
-
continue;
|
|
25713
|
-
}
|
|
25714
|
-
if (inFence) {
|
|
26030
|
+
for (let i = 0;i < lines.length; i++) {
|
|
26031
|
+
const line = lines[i];
|
|
26032
|
+
if (codeLines.has(i)) {
|
|
25715
26033
|
result.push(line);
|
|
25716
26034
|
continue;
|
|
25717
26035
|
}
|
|
@@ -25743,14 +26061,10 @@ var init_no_space_in_emphasis = __esm(() => {
|
|
|
25743
26061
|
check: (text, ctx) => {
|
|
25744
26062
|
const issues = [];
|
|
25745
26063
|
const lines = text.split(/\r?\n/);
|
|
25746
|
-
|
|
26064
|
+
const codeLines = getCodeBlockLines(lines);
|
|
25747
26065
|
for (let i = 0;i < lines.length; i++) {
|
|
25748
26066
|
const line = lines[i];
|
|
25749
|
-
if (
|
|
25750
|
-
inFence = !inFence;
|
|
25751
|
-
continue;
|
|
25752
|
-
}
|
|
25753
|
-
if (inFence)
|
|
26067
|
+
if (codeLines.has(i))
|
|
25754
26068
|
continue;
|
|
25755
26069
|
const stripped = line.replace(/`[^`]+`/g, (m) => "\x01".repeat(m.length));
|
|
25756
26070
|
for (const pattern of EMPHASIS_SPACE_PATTERNS) {
|
|
@@ -25770,15 +26084,11 @@ var init_no_space_in_emphasis = __esm(() => {
|
|
|
25770
26084
|
},
|
|
25771
26085
|
fix: (text) => {
|
|
25772
26086
|
const lines = text.split(/\r?\n/);
|
|
25773
|
-
|
|
26087
|
+
const codeLines = getCodeBlockLines(lines);
|
|
25774
26088
|
const result = [];
|
|
25775
|
-
for (
|
|
25776
|
-
|
|
25777
|
-
|
|
25778
|
-
result.push(line);
|
|
25779
|
-
continue;
|
|
25780
|
-
}
|
|
25781
|
-
if (inFence) {
|
|
26089
|
+
for (let i = 0;i < lines.length; i++) {
|
|
26090
|
+
const line = lines[i];
|
|
26091
|
+
if (codeLines.has(i)) {
|
|
25782
26092
|
result.push(line);
|
|
25783
26093
|
continue;
|
|
25784
26094
|
}
|
|
@@ -25893,7 +26203,14 @@ var init_no_trailing_punctuation = __esm(() => {
|
|
|
25893
26203
|
const punctuation = options.punctuation || ".,;:!?";
|
|
25894
26204
|
const punctRegex = new RegExp(`[${punctuation.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}]+$`);
|
|
25895
26205
|
const lines = text.split(/\r?\n/);
|
|
26206
|
+
let inFence = false;
|
|
25896
26207
|
const fixedLines = lines.map((line, i) => {
|
|
26208
|
+
if (/^(?:`{3,}|~{3,})/.test(line.trim())) {
|
|
26209
|
+
inFence = !inFence;
|
|
26210
|
+
return line;
|
|
26211
|
+
}
|
|
26212
|
+
if (inFence)
|
|
26213
|
+
return line;
|
|
25897
26214
|
const atxMatch = line.match(/^(#{1,6}\s+)(.+?)(\s*#+\s*)?$/);
|
|
25898
26215
|
if (atxMatch) {
|
|
25899
26216
|
const prefix = atxMatch[1];
|
|
@@ -26734,17 +27051,13 @@ var init_ul_style = __esm(() => {
|
|
|
26734
27051
|
check: (text, ctx) => {
|
|
26735
27052
|
const issues = [];
|
|
26736
27053
|
const lines = text.split(/\r?\n/);
|
|
27054
|
+
const codeLines = getCodeBlockLines(lines);
|
|
26737
27055
|
const options = ctx.options || {};
|
|
26738
27056
|
const style = options.style || "consistent";
|
|
26739
27057
|
let detectedStyle = null;
|
|
26740
|
-
let inFence = false;
|
|
26741
27058
|
for (let i = 0;i < lines.length; i++) {
|
|
26742
27059
|
const line = lines[i];
|
|
26743
|
-
if (
|
|
26744
|
-
inFence = !inFence;
|
|
26745
|
-
continue;
|
|
26746
|
-
}
|
|
26747
|
-
if (inFence)
|
|
27060
|
+
if (codeLines.has(i))
|
|
26748
27061
|
continue;
|
|
26749
27062
|
const match = line.match(/^(\s*)([*\-+])\s+/);
|
|
26750
27063
|
if (match) {
|
|
@@ -26798,6 +27111,7 @@ var init_ul_style = __esm(() => {
|
|
|
26798
27111
|
const options = ctx.options || {};
|
|
26799
27112
|
const style = options.style || "consistent";
|
|
26800
27113
|
const lines = text.split(/\r?\n/);
|
|
27114
|
+
const codeLines = getCodeBlockLines(lines);
|
|
26801
27115
|
let targetMarker = "*";
|
|
26802
27116
|
if (style === "asterisk") {
|
|
26803
27117
|
targetMarker = "*";
|
|
@@ -26806,21 +27120,18 @@ var init_ul_style = __esm(() => {
|
|
|
26806
27120
|
} else if (style === "plus") {
|
|
26807
27121
|
targetMarker = "+";
|
|
26808
27122
|
} else if (style === "consistent") {
|
|
26809
|
-
for (
|
|
26810
|
-
|
|
27123
|
+
for (let i = 0;i < lines.length; i++) {
|
|
27124
|
+
if (codeLines.has(i))
|
|
27125
|
+
continue;
|
|
27126
|
+
const match = lines[i].match(/^(\s*)([*\-+])\s+/);
|
|
26811
27127
|
if (match) {
|
|
26812
27128
|
targetMarker = match[2];
|
|
26813
27129
|
break;
|
|
26814
27130
|
}
|
|
26815
27131
|
}
|
|
26816
27132
|
}
|
|
26817
|
-
|
|
26818
|
-
|
|
26819
|
-
if (/^(?:`{3,}|~{3,})/.test(line.trim())) {
|
|
26820
|
-
inFence = !inFence;
|
|
26821
|
-
return line;
|
|
26822
|
-
}
|
|
26823
|
-
if (inFence)
|
|
27133
|
+
const fixedLines = lines.map((line, i) => {
|
|
27134
|
+
if (codeLines.has(i))
|
|
26824
27135
|
return line;
|
|
26825
27136
|
return line.replace(/^(\s*)([*\-+])(\s+)/, `$1${targetMarker}$3`);
|
|
26826
27137
|
});
|
|
@@ -27024,36 +27335,26 @@ var init_prefer_global_buffer = __esm(() => {
|
|
|
27024
27335
|
check(content, context) {
|
|
27025
27336
|
const issues = [];
|
|
27026
27337
|
const lines = content.split(/\r?\n/);
|
|
27027
|
-
const
|
|
27028
|
-
|
|
27029
|
-
|
|
27030
|
-
|
|
27031
|
-
|
|
27032
|
-
|
|
27033
|
-
|
|
27034
|
-
|
|
27035
|
-
|
|
27036
|
-
|
|
27037
|
-
|
|
27038
|
-
|
|
27039
|
-
|
|
27040
|
-
|
|
27041
|
-
|
|
27042
|
-
|
|
27043
|
-
|
|
27044
|
-
|
|
27045
|
-
|
|
27046
|
-
|
|
27047
|
-
line: i + 1,
|
|
27048
|
-
column,
|
|
27049
|
-
ruleId: "node/prefer-global/buffer",
|
|
27050
|
-
message: `Unexpected use of the global variable 'Buffer'. Use 'require("buffer").Buffer' instead`,
|
|
27051
|
-
severity: "error",
|
|
27052
|
-
help: 'Import Buffer explicitly: const { Buffer } = require("buffer")'
|
|
27053
|
-
});
|
|
27054
|
-
}
|
|
27055
|
-
}
|
|
27056
|
-
}
|
|
27338
|
+
const importRe = /(?:import\b[^;\n]*\bfrom\s*|require\s*\(\s*)['"](?:node:)?buffer['"]/;
|
|
27339
|
+
for (let i = 0;i < lines.length; i++) {
|
|
27340
|
+
const line = lines[i];
|
|
27341
|
+
const trimmed = line.trim();
|
|
27342
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("/*") || trimmed.startsWith("*"))
|
|
27343
|
+
continue;
|
|
27344
|
+
const match = line.match(importRe);
|
|
27345
|
+
if (!match || match.index === undefined)
|
|
27346
|
+
continue;
|
|
27347
|
+
if (!/\bBuffer\b/.test(line))
|
|
27348
|
+
continue;
|
|
27349
|
+
issues.push({
|
|
27350
|
+
filePath: context.filePath,
|
|
27351
|
+
line: i + 1,
|
|
27352
|
+
column: match.index + 1,
|
|
27353
|
+
ruleId: "node/prefer-global/buffer",
|
|
27354
|
+
message: "Unexpected import of 'Buffer'. Use the global 'Buffer' instead",
|
|
27355
|
+
severity: "error",
|
|
27356
|
+
help: "`Buffer` is a global in Node.js \u2014 remove the import and use it directly."
|
|
27357
|
+
});
|
|
27057
27358
|
}
|
|
27058
27359
|
return issues;
|
|
27059
27360
|
}
|
|
@@ -27071,36 +27372,24 @@ var init_prefer_global_process = __esm(() => {
|
|
|
27071
27372
|
check(content, context) {
|
|
27072
27373
|
const issues = [];
|
|
27073
27374
|
const lines = content.split(/\r?\n/);
|
|
27074
|
-
const
|
|
27075
|
-
|
|
27076
|
-
|
|
27077
|
-
|
|
27078
|
-
|
|
27079
|
-
|
|
27080
|
-
|
|
27081
|
-
|
|
27082
|
-
|
|
27083
|
-
|
|
27084
|
-
|
|
27085
|
-
|
|
27086
|
-
|
|
27087
|
-
|
|
27088
|
-
|
|
27089
|
-
|
|
27090
|
-
|
|
27091
|
-
|
|
27092
|
-
issues.push({
|
|
27093
|
-
filePath: context.filePath,
|
|
27094
|
-
line: i + 1,
|
|
27095
|
-
column,
|
|
27096
|
-
ruleId: "node/prefer-global/process",
|
|
27097
|
-
message: `Unexpected use of the global variable 'process'. Use 'require("process")' instead`,
|
|
27098
|
-
severity: "error",
|
|
27099
|
-
help: 'Import process explicitly: const process = require("process")'
|
|
27100
|
-
});
|
|
27101
|
-
}
|
|
27102
|
-
}
|
|
27103
|
-
}
|
|
27375
|
+
const importRe = /(?:import\b[^;\n]*\bfrom\s*|require\s*\(\s*)['"](?:node:)?process['"]/;
|
|
27376
|
+
for (let i = 0;i < lines.length; i++) {
|
|
27377
|
+
const line = lines[i];
|
|
27378
|
+
const trimmed = line.trim();
|
|
27379
|
+
if (trimmed.startsWith("//") || trimmed.startsWith("/*") || trimmed.startsWith("*"))
|
|
27380
|
+
continue;
|
|
27381
|
+
const match = line.match(importRe);
|
|
27382
|
+
if (!match || match.index === undefined)
|
|
27383
|
+
continue;
|
|
27384
|
+
issues.push({
|
|
27385
|
+
filePath: context.filePath,
|
|
27386
|
+
line: i + 1,
|
|
27387
|
+
column: match.index + 1,
|
|
27388
|
+
ruleId: "node/prefer-global/process",
|
|
27389
|
+
message: "Unexpected import of 'process'. Use the global 'process' instead",
|
|
27390
|
+
severity: "error",
|
|
27391
|
+
help: "`process` is a global in Node.js \u2014 remove the import and use it directly."
|
|
27392
|
+
});
|
|
27104
27393
|
}
|
|
27105
27394
|
return issues;
|
|
27106
27395
|
}
|
|
@@ -27260,7 +27549,7 @@ function startsWithShebang(code) {
|
|
|
27260
27549
|
return /^#!\s*\//.test(code);
|
|
27261
27550
|
}
|
|
27262
27551
|
function stripComments(code) {
|
|
27263
|
-
return code.replace(/\/\*
|
|
27552
|
+
return code.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*/g, "");
|
|
27264
27553
|
}
|
|
27265
27554
|
function crawlExportsOrImports(value, basePath, isImports, visitor) {
|
|
27266
27555
|
_crawl(value, basePath, isImports, visitor);
|
|
@@ -27741,11 +28030,15 @@ var init_local_dependency = __esm(() => {
|
|
|
27741
28030
|
if (!pkg)
|
|
27742
28031
|
return [];
|
|
27743
28032
|
const issues = [];
|
|
27744
|
-
|
|
27745
|
-
|
|
27746
|
-
|
|
28033
|
+
const fields = ["dependencies", "optionalDependencies", "peerDependencies"];
|
|
28034
|
+
for (const field of fields) {
|
|
28035
|
+
const deps = pkg[field];
|
|
28036
|
+
if (!deps || typeof deps !== "object")
|
|
28037
|
+
continue;
|
|
28038
|
+
for (const depName of Object.keys(deps)) {
|
|
28039
|
+
const depVersion = deps[depName];
|
|
27747
28040
|
if (typeof depVersion === "string" && (depVersion.startsWith("file:") || depVersion.startsWith("link:"))) {
|
|
27748
|
-
issues.push(createIssue(context.filePath, content, [
|
|
28041
|
+
issues.push(createIssue(context.filePath, content, [field, depName], "publint/local-dependency", `The "${depName}" dependency references "${depVersion}" that will likely not work when installed by end-users.`, "error", "Local file references (file: or link:) are not portable and will fail for consumers of the package."));
|
|
27749
28042
|
}
|
|
27750
28043
|
}
|
|
27751
28044
|
}
|
|
@@ -29434,7 +29727,7 @@ function parseRegexLiteral(content, idx) {
|
|
|
29434
29727
|
return null;
|
|
29435
29728
|
const pattern = content.slice(idx + 1, closedAt);
|
|
29436
29729
|
let flagEnd = closedAt + 1;
|
|
29437
|
-
while (flagEnd < content.length && /[
|
|
29730
|
+
while (flagEnd < content.length && /[gimsuvy]/.test(content[flagEnd]))
|
|
29438
29731
|
flagEnd++;
|
|
29439
29732
|
if (/\\[1-9]/.test(pattern))
|
|
29440
29733
|
return null;
|
|
@@ -29552,7 +29845,7 @@ function skipRegexLiteral(content, idx) {
|
|
|
29552
29845
|
inClass = false;
|
|
29553
29846
|
} else if (c === "/" && !inClass) {
|
|
29554
29847
|
i++;
|
|
29555
|
-
while (i < content.length && /[
|
|
29848
|
+
while (i < content.length && /[gimsuvy]/.test(content[i]))
|
|
29556
29849
|
i++;
|
|
29557
29850
|
return i;
|
|
29558
29851
|
} else if (c === `
|
|
@@ -30249,16 +30542,12 @@ var init_quote_variables = __esm(() => {
|
|
|
30249
30542
|
inHeredoc = false;
|
|
30250
30543
|
continue;
|
|
30251
30544
|
}
|
|
30252
|
-
const
|
|
30253
|
-
if (
|
|
30254
|
-
inHeredoc = true;
|
|
30255
|
-
heredocDelim = heredocMatch[2];
|
|
30256
|
-
continue;
|
|
30257
|
-
}
|
|
30258
|
-
const heredocMatch2 = line.match(/<<-?\s*(\w+)/);
|
|
30259
|
-
if (heredocMatch2 && !heredocMatch) {
|
|
30545
|
+
const delim = heredocDelimiter(line);
|
|
30546
|
+
if (delim) {
|
|
30260
30547
|
inHeredoc = true;
|
|
30261
|
-
heredocDelim =
|
|
30548
|
+
heredocDelim = delim;
|
|
30549
|
+
if (new RegExp(`<<-?\\s*['"]${delim}['"]`).test(line))
|
|
30550
|
+
continue;
|
|
30262
30551
|
}
|
|
30263
30552
|
const trimmed = line.replace(/^\s+/, "");
|
|
30264
30553
|
if (trimmed.startsWith("#"))
|
|
@@ -30487,381 +30776,104 @@ var init_indent = __esm(() => {
|
|
|
30487
30776
|
inHeredoc = false;
|
|
30488
30777
|
continue;
|
|
30489
30778
|
}
|
|
30490
|
-
const heredocMatch = line.match(/<<-?\s*['"]?(\w+)['"]?/);
|
|
30491
|
-
if (heredocMatch) {
|
|
30492
|
-
inHeredoc = true;
|
|
30493
|
-
heredocDelim = heredocMatch[1];
|
|
30494
|
-
}
|
|
30495
|
-
const trimmed = line.replace(/^\s+/, "");
|
|
30496
|
-
if (i === 0 && trimmed.startsWith("#!"))
|
|
30497
|
-
continue;
|
|
30498
|
-
if (/^case\b/.test(trimmed) && /\bin\s*$/.test(trimmed)) {
|
|
30499
|
-
caseDepth++;
|
|
30500
|
-
inCase = true;
|
|
30501
|
-
}
|
|
30502
|
-
if (/^esac\b/.test(trimmed)) {
|
|
30503
|
-
caseDepth = Math.max(0, caseDepth - 1);
|
|
30504
|
-
if (caseDepth === 0)
|
|
30505
|
-
inCase = false;
|
|
30506
|
-
}
|
|
30507
|
-
if (shouldDecreaseBefore(trimmed))
|
|
30508
|
-
expectedLevel = Math.max(0, expectedLevel - 1);
|
|
30509
|
-
let actualSpaces = 0;
|
|
30510
|
-
for (let j = 0;j < line.length; j++) {
|
|
30511
|
-
if (line[j] === " ") {
|
|
30512
|
-
actualSpaces++;
|
|
30513
|
-
} else if (line[j] === "\t") {
|
|
30514
|
-
actualSpaces += indentSize;
|
|
30515
|
-
} else {
|
|
30516
|
-
break;
|
|
30517
|
-
}
|
|
30518
|
-
}
|
|
30519
|
-
const expectedSpaces = expectedLevel * indentSize;
|
|
30520
|
-
if (actualSpaces !== expectedSpaces && !trimmed.startsWith("#")) {
|
|
30521
|
-
issues.push({
|
|
30522
|
-
filePath: ctx.filePath,
|
|
30523
|
-
line: i + 1,
|
|
30524
|
-
column: 1,
|
|
30525
|
-
ruleId: "shell/indent",
|
|
30526
|
-
message: `Expected ${expectedSpaces} spaces of indentation, found ${actualSpaces}`,
|
|
30527
|
-
severity: "warning"
|
|
30528
|
-
});
|
|
30529
|
-
}
|
|
30530
|
-
if (shouldIncreaseAfter(trimmed, inCase))
|
|
30531
|
-
expectedLevel++;
|
|
30532
|
-
}
|
|
30533
|
-
return issues;
|
|
30534
|
-
},
|
|
30535
|
-
fix(content, ctx) {
|
|
30536
|
-
const lines = content.split(/\r?\n/);
|
|
30537
|
-
const indentSize = ctx.config.format.indent || 2;
|
|
30538
|
-
const useTab = ctx.config.format.indentStyle === "tabs";
|
|
30539
|
-
const result = [];
|
|
30540
|
-
let level = 0;
|
|
30541
|
-
let inHeredoc = false;
|
|
30542
|
-
let heredocDelim = "";
|
|
30543
|
-
let inCase = false;
|
|
30544
|
-
let caseDepth = 0;
|
|
30545
|
-
for (let i = 0;i < lines.length; i++) {
|
|
30546
|
-
const line = lines[i];
|
|
30547
|
-
if (/^\s*$/.test(line)) {
|
|
30548
|
-
result.push("");
|
|
30549
|
-
continue;
|
|
30550
|
-
}
|
|
30551
|
-
if (inHeredoc) {
|
|
30552
|
-
result.push(line);
|
|
30553
|
-
if (line.trim() === heredocDelim)
|
|
30554
|
-
inHeredoc = false;
|
|
30555
|
-
continue;
|
|
30556
|
-
}
|
|
30557
|
-
const heredocMatch = line.match(/<<-?\s*['"]?(\w+)['"]?/);
|
|
30558
|
-
if (heredocMatch) {
|
|
30559
|
-
inHeredoc = true;
|
|
30560
|
-
heredocDelim = heredocMatch[1];
|
|
30561
|
-
}
|
|
30562
|
-
const trimmed = line.replace(/^\s+/, "").trimEnd();
|
|
30563
|
-
if (i === 0 && trimmed.startsWith("#!")) {
|
|
30564
|
-
result.push(trimmed);
|
|
30565
|
-
continue;
|
|
30566
|
-
}
|
|
30567
|
-
if (/^case\b/.test(trimmed) && /\bin\s*$/.test(trimmed)) {
|
|
30568
|
-
caseDepth++;
|
|
30569
|
-
inCase = true;
|
|
30570
|
-
}
|
|
30571
|
-
if (/^esac\b/.test(trimmed)) {
|
|
30572
|
-
caseDepth = Math.max(0, caseDepth - 1);
|
|
30573
|
-
if (caseDepth === 0)
|
|
30574
|
-
inCase = false;
|
|
30575
|
-
}
|
|
30576
|
-
if (shouldDecreaseBefore(trimmed))
|
|
30577
|
-
level = Math.max(0, level - 1);
|
|
30578
|
-
const indent = useTab ? "\t".repeat(level) : " ".repeat(level * indentSize);
|
|
30579
|
-
result.push(indent + trimmed);
|
|
30580
|
-
if (shouldIncreaseAfter(trimmed, inCase))
|
|
30581
|
-
level++;
|
|
30582
|
-
}
|
|
30583
|
-
return result.join(`
|
|
30584
|
-
`);
|
|
30585
|
-
}
|
|
30586
|
-
};
|
|
30587
|
-
});
|
|
30588
|
-
|
|
30589
|
-
// src/rules/shell/_shared.ts
|
|
30590
|
-
function maskShellStrings(line) {
|
|
30591
|
-
const n = line.length;
|
|
30592
|
-
const out = Array.from({ length: n }, (_, i2) => line[i2]);
|
|
30593
|
-
let i = 0;
|
|
30594
|
-
while (i < n) {
|
|
30595
|
-
const ch = line[i];
|
|
30596
|
-
if (ch === "#" && (i === 0 || /\s/.test(line[i - 1]))) {
|
|
30597
|
-
while (i < n) {
|
|
30598
|
-
out[i] = " ";
|
|
30599
|
-
i++;
|
|
30600
|
-
}
|
|
30601
|
-
break;
|
|
30602
|
-
}
|
|
30603
|
-
if (ch === "$" && line[i + 1] === "'") {
|
|
30604
|
-
i += 2;
|
|
30605
|
-
while (i < n) {
|
|
30606
|
-
if (line[i] === "\\" && i + 1 < n) {
|
|
30607
|
-
out[i] = " ";
|
|
30608
|
-
out[i + 1] = " ";
|
|
30609
|
-
i += 2;
|
|
30610
|
-
continue;
|
|
30611
|
-
}
|
|
30612
|
-
if (line[i] === "'") {
|
|
30613
|
-
i++;
|
|
30614
|
-
break;
|
|
30615
|
-
}
|
|
30616
|
-
out[i] = " ";
|
|
30617
|
-
i++;
|
|
30618
|
-
}
|
|
30619
|
-
continue;
|
|
30620
|
-
}
|
|
30621
|
-
if (ch === "$" && line[i + 1] === '"') {
|
|
30622
|
-
i++;
|
|
30623
|
-
i = maskDoubleQuoted(line, i, out);
|
|
30624
|
-
continue;
|
|
30625
|
-
}
|
|
30626
|
-
if (ch === "$" && line[i + 1] === "{") {
|
|
30627
|
-
i += 2;
|
|
30628
|
-
let depth = 1;
|
|
30629
|
-
while (i < n && depth > 0) {
|
|
30630
|
-
const c = line[i];
|
|
30631
|
-
if (c === "\\" && i + 1 < n) {
|
|
30632
|
-
out[i] = " ";
|
|
30633
|
-
out[i + 1] = " ";
|
|
30634
|
-
i += 2;
|
|
30635
|
-
continue;
|
|
30636
|
-
}
|
|
30637
|
-
if (c === "'") {
|
|
30638
|
-
i++;
|
|
30639
|
-
while (i < n && line[i] !== "'") {
|
|
30640
|
-
out[i] = " ";
|
|
30641
|
-
i++;
|
|
30642
|
-
}
|
|
30643
|
-
if (i < n)
|
|
30644
|
-
i++;
|
|
30645
|
-
continue;
|
|
30646
|
-
}
|
|
30647
|
-
if (c === '"') {
|
|
30648
|
-
i = maskDoubleQuoted(line, i, out);
|
|
30649
|
-
continue;
|
|
30650
|
-
}
|
|
30651
|
-
if (c === "{") {
|
|
30652
|
-
depth++;
|
|
30653
|
-
i++;
|
|
30654
|
-
continue;
|
|
30655
|
-
}
|
|
30656
|
-
if (c === "}") {
|
|
30657
|
-
depth--;
|
|
30658
|
-
i++;
|
|
30659
|
-
continue;
|
|
30660
|
-
}
|
|
30661
|
-
out[i] = " ";
|
|
30662
|
-
i++;
|
|
30663
|
-
}
|
|
30664
|
-
continue;
|
|
30665
|
-
}
|
|
30666
|
-
if (ch === "$" && line[i + 1] === "(" && line[i + 2] === "(") {
|
|
30667
|
-
i += 3;
|
|
30668
|
-
let depth = 2;
|
|
30669
|
-
while (i < n && depth > 0) {
|
|
30670
|
-
const c = line[i];
|
|
30671
|
-
if (c === "(") {
|
|
30672
|
-
depth++;
|
|
30673
|
-
i++;
|
|
30674
|
-
continue;
|
|
30675
|
-
}
|
|
30676
|
-
if (c === ")") {
|
|
30677
|
-
depth--;
|
|
30678
|
-
i++;
|
|
30679
|
-
continue;
|
|
30680
|
-
}
|
|
30681
|
-
out[i] = " ";
|
|
30682
|
-
i++;
|
|
30683
|
-
}
|
|
30684
|
-
continue;
|
|
30685
|
-
}
|
|
30686
|
-
if (ch === "$" && line[i + 1] === "(") {
|
|
30687
|
-
i += 2;
|
|
30688
|
-
let depth = 1;
|
|
30689
|
-
while (i < n && depth > 0) {
|
|
30690
|
-
const c = line[i];
|
|
30691
|
-
if (c === "\\" && i + 1 < n) {
|
|
30692
|
-
out[i] = " ";
|
|
30693
|
-
out[i + 1] = " ";
|
|
30694
|
-
i += 2;
|
|
30695
|
-
continue;
|
|
30696
|
-
}
|
|
30697
|
-
if (c === "'") {
|
|
30698
|
-
i++;
|
|
30699
|
-
while (i < n && line[i] !== "'") {
|
|
30700
|
-
out[i] = " ";
|
|
30701
|
-
i++;
|
|
30702
|
-
}
|
|
30703
|
-
if (i < n)
|
|
30704
|
-
i++;
|
|
30705
|
-
continue;
|
|
30706
|
-
}
|
|
30707
|
-
if (c === '"') {
|
|
30708
|
-
i = maskDoubleQuoted(line, i, out);
|
|
30709
|
-
continue;
|
|
30710
|
-
}
|
|
30711
|
-
if (c === "(") {
|
|
30712
|
-
depth++;
|
|
30713
|
-
i++;
|
|
30714
|
-
continue;
|
|
30715
|
-
}
|
|
30716
|
-
if (c === ")") {
|
|
30717
|
-
depth--;
|
|
30718
|
-
i++;
|
|
30719
|
-
continue;
|
|
30720
|
-
}
|
|
30721
|
-
out[i] = " ";
|
|
30722
|
-
i++;
|
|
30723
|
-
}
|
|
30724
|
-
continue;
|
|
30725
|
-
}
|
|
30726
|
-
if (ch === "'") {
|
|
30727
|
-
i++;
|
|
30728
|
-
while (i < n && line[i] !== "'") {
|
|
30729
|
-
out[i] = " ";
|
|
30730
|
-
i++;
|
|
30731
|
-
}
|
|
30732
|
-
if (i < n)
|
|
30733
|
-
i++;
|
|
30734
|
-
continue;
|
|
30735
|
-
}
|
|
30736
|
-
if (ch === '"') {
|
|
30737
|
-
i = maskDoubleQuoted(line, i, out);
|
|
30738
|
-
continue;
|
|
30739
|
-
}
|
|
30740
|
-
if (ch === "`") {
|
|
30741
|
-
i++;
|
|
30742
|
-
while (i < n && line[i] !== "`") {
|
|
30743
|
-
if (line[i] === "\\" && i + 1 < n) {
|
|
30744
|
-
out[i] = " ";
|
|
30745
|
-
out[i + 1] = " ";
|
|
30746
|
-
i += 2;
|
|
30747
|
-
continue;
|
|
30748
|
-
}
|
|
30749
|
-
out[i] = " ";
|
|
30750
|
-
i++;
|
|
30751
|
-
}
|
|
30752
|
-
if (i < n)
|
|
30753
|
-
i++;
|
|
30754
|
-
continue;
|
|
30755
|
-
}
|
|
30756
|
-
i++;
|
|
30757
|
-
}
|
|
30758
|
-
return out.join("");
|
|
30759
|
-
}
|
|
30760
|
-
function maskDoubleQuoted(line, start, out) {
|
|
30761
|
-
const n = line.length;
|
|
30762
|
-
let i = start + 1;
|
|
30763
|
-
while (i < n) {
|
|
30764
|
-
const c = line[i];
|
|
30765
|
-
if (c === "\\" && i + 1 < n) {
|
|
30766
|
-
out[i] = " ";
|
|
30767
|
-
out[i + 1] = " ";
|
|
30768
|
-
i += 2;
|
|
30769
|
-
continue;
|
|
30770
|
-
}
|
|
30771
|
-
if (c === '"')
|
|
30772
|
-
return i + 1;
|
|
30773
|
-
if (c === "$" && line[i + 1] === "(" && line[i + 2] === "(") {
|
|
30774
|
-
i += 3;
|
|
30775
|
-
let depth = 2;
|
|
30776
|
-
while (i < n && depth > 0) {
|
|
30777
|
-
const x = line[i];
|
|
30778
|
-
if (x === "(") {
|
|
30779
|
-
depth++;
|
|
30780
|
-
i++;
|
|
30781
|
-
continue;
|
|
30782
|
-
}
|
|
30783
|
-
if (x === ")") {
|
|
30784
|
-
depth--;
|
|
30785
|
-
i++;
|
|
30786
|
-
continue;
|
|
30787
|
-
}
|
|
30788
|
-
out[i] = " ";
|
|
30789
|
-
i++;
|
|
30790
|
-
}
|
|
30791
|
-
continue;
|
|
30792
|
-
}
|
|
30793
|
-
if (c === "$" && line[i + 1] === "(") {
|
|
30794
|
-
i += 2;
|
|
30795
|
-
let depth = 1;
|
|
30796
|
-
while (i < n && depth > 0) {
|
|
30797
|
-
const x = line[i];
|
|
30798
|
-
if (x === "\\" && i + 1 < n) {
|
|
30799
|
-
out[i] = " ";
|
|
30800
|
-
out[i + 1] = " ";
|
|
30801
|
-
i += 2;
|
|
30779
|
+
const heredocMatch = line.match(/<<-?\s*['"]?(\w+)['"]?/);
|
|
30780
|
+
if (heredocMatch) {
|
|
30781
|
+
inHeredoc = true;
|
|
30782
|
+
heredocDelim = heredocMatch[1];
|
|
30783
|
+
}
|
|
30784
|
+
const trimmed = line.replace(/^\s+/, "");
|
|
30785
|
+
if (i === 0 && trimmed.startsWith("#!"))
|
|
30802
30786
|
continue;
|
|
30787
|
+
if (/^case\b/.test(trimmed) && /\bin\s*$/.test(trimmed)) {
|
|
30788
|
+
caseDepth++;
|
|
30789
|
+
inCase = true;
|
|
30803
30790
|
}
|
|
30804
|
-
if (
|
|
30805
|
-
|
|
30806
|
-
|
|
30807
|
-
|
|
30808
|
-
|
|
30791
|
+
if (/^esac\b/.test(trimmed)) {
|
|
30792
|
+
caseDepth = Math.max(0, caseDepth - 1);
|
|
30793
|
+
if (caseDepth === 0)
|
|
30794
|
+
inCase = false;
|
|
30795
|
+
}
|
|
30796
|
+
if (shouldDecreaseBefore(trimmed))
|
|
30797
|
+
expectedLevel = Math.max(0, expectedLevel - 1);
|
|
30798
|
+
let actualSpaces = 0;
|
|
30799
|
+
for (let j = 0;j < line.length; j++) {
|
|
30800
|
+
if (line[j] === " ") {
|
|
30801
|
+
actualSpaces++;
|
|
30802
|
+
} else if (line[j] === "\t") {
|
|
30803
|
+
actualSpaces += indentSize;
|
|
30804
|
+
} else {
|
|
30805
|
+
break;
|
|
30809
30806
|
}
|
|
30810
|
-
if (i < n)
|
|
30811
|
-
i++;
|
|
30812
|
-
continue;
|
|
30813
30807
|
}
|
|
30814
|
-
|
|
30815
|
-
|
|
30816
|
-
|
|
30808
|
+
const expectedSpaces = expectedLevel * indentSize;
|
|
30809
|
+
if (actualSpaces !== expectedSpaces && !trimmed.startsWith("#")) {
|
|
30810
|
+
issues.push({
|
|
30811
|
+
filePath: ctx.filePath,
|
|
30812
|
+
line: i + 1,
|
|
30813
|
+
column: 1,
|
|
30814
|
+
ruleId: "shell/indent",
|
|
30815
|
+
message: `Expected ${expectedSpaces} spaces of indentation, found ${actualSpaces}`,
|
|
30816
|
+
severity: "warning"
|
|
30817
|
+
});
|
|
30817
30818
|
}
|
|
30818
|
-
if (
|
|
30819
|
-
|
|
30820
|
-
|
|
30819
|
+
if (shouldIncreaseAfter(trimmed, inCase))
|
|
30820
|
+
expectedLevel++;
|
|
30821
|
+
}
|
|
30822
|
+
return issues;
|
|
30823
|
+
},
|
|
30824
|
+
fix(content, ctx) {
|
|
30825
|
+
const lines = content.split(/\r?\n/);
|
|
30826
|
+
const indentSize = ctx.config.format.indent || 2;
|
|
30827
|
+
const useTab = ctx.config.format.indentStyle === "tabs";
|
|
30828
|
+
const result = [];
|
|
30829
|
+
let level = 0;
|
|
30830
|
+
let inHeredoc = false;
|
|
30831
|
+
let heredocDelim = "";
|
|
30832
|
+
let inCase = false;
|
|
30833
|
+
let caseDepth = 0;
|
|
30834
|
+
for (let i = 0;i < lines.length; i++) {
|
|
30835
|
+
const line = lines[i];
|
|
30836
|
+
if (/^\s*$/.test(line)) {
|
|
30837
|
+
result.push("");
|
|
30821
30838
|
continue;
|
|
30822
30839
|
}
|
|
30823
|
-
if (
|
|
30824
|
-
|
|
30825
|
-
|
|
30840
|
+
if (inHeredoc) {
|
|
30841
|
+
result.push(line);
|
|
30842
|
+
if (line.trim() === heredocDelim)
|
|
30843
|
+
inHeredoc = false;
|
|
30826
30844
|
continue;
|
|
30827
30845
|
}
|
|
30828
|
-
|
|
30829
|
-
|
|
30830
|
-
|
|
30831
|
-
|
|
30832
|
-
}
|
|
30833
|
-
if (c === "$" && line[i + 1] === "{") {
|
|
30834
|
-
i += 2;
|
|
30835
|
-
let depth = 1;
|
|
30836
|
-
while (i < n && depth > 0) {
|
|
30837
|
-
const x = line[i];
|
|
30838
|
-
if (x === "{") {
|
|
30839
|
-
depth++;
|
|
30840
|
-
i++;
|
|
30841
|
-
continue;
|
|
30846
|
+
const heredocMatch = line.match(/<<-?\s*['"]?(\w+)['"]?/);
|
|
30847
|
+
if (heredocMatch) {
|
|
30848
|
+
inHeredoc = true;
|
|
30849
|
+
heredocDelim = heredocMatch[1];
|
|
30842
30850
|
}
|
|
30843
|
-
|
|
30844
|
-
|
|
30845
|
-
|
|
30851
|
+
const trimmed = line.replace(/^\s+/, "").trimEnd();
|
|
30852
|
+
if (i === 0 && trimmed.startsWith("#!")) {
|
|
30853
|
+
result.push(trimmed);
|
|
30846
30854
|
continue;
|
|
30847
30855
|
}
|
|
30848
|
-
|
|
30849
|
-
|
|
30856
|
+
if (/^case\b/.test(trimmed) && /\bin\s*$/.test(trimmed)) {
|
|
30857
|
+
caseDepth++;
|
|
30858
|
+
inCase = true;
|
|
30859
|
+
}
|
|
30860
|
+
if (/^esac\b/.test(trimmed)) {
|
|
30861
|
+
caseDepth = Math.max(0, caseDepth - 1);
|
|
30862
|
+
if (caseDepth === 0)
|
|
30863
|
+
inCase = false;
|
|
30864
|
+
}
|
|
30865
|
+
if (shouldDecreaseBefore(trimmed))
|
|
30866
|
+
level = Math.max(0, level - 1);
|
|
30867
|
+
const indent = useTab ? "\t".repeat(level) : " ".repeat(level * indentSize);
|
|
30868
|
+
result.push(indent + trimmed);
|
|
30869
|
+
if (shouldIncreaseAfter(trimmed, inCase))
|
|
30870
|
+
level++;
|
|
30850
30871
|
}
|
|
30851
|
-
|
|
30872
|
+
return result.join(`
|
|
30873
|
+
`);
|
|
30852
30874
|
}
|
|
30853
|
-
|
|
30854
|
-
|
|
30855
|
-
}
|
|
30856
|
-
return i;
|
|
30857
|
-
}
|
|
30858
|
-
function heredocDelimiter(line) {
|
|
30859
|
-
const masked = maskShellStrings(line);
|
|
30860
|
-
const m = masked.match(/<<-?\s*['"]?(\w+)['"]?/);
|
|
30861
|
-
if (!m)
|
|
30862
|
-
return null;
|
|
30863
|
-
return m[1];
|
|
30864
|
-
}
|
|
30875
|
+
};
|
|
30876
|
+
});
|
|
30865
30877
|
|
|
30866
30878
|
// src/rules/shell/keyword-spacing.ts
|
|
30867
30879
|
var keywordSpacingRule;
|
|
@@ -31022,10 +31034,10 @@ var init_no_trailing_whitespace = __esm(() => {
|
|
|
31022
31034
|
inHeredoc = false;
|
|
31023
31035
|
continue;
|
|
31024
31036
|
}
|
|
31025
|
-
const
|
|
31026
|
-
if (
|
|
31037
|
+
const delim = heredocDelimiter(line);
|
|
31038
|
+
if (delim) {
|
|
31027
31039
|
inHeredoc = true;
|
|
31028
|
-
heredocDelim =
|
|
31040
|
+
heredocDelim = delim;
|
|
31029
31041
|
}
|
|
31030
31042
|
if (/[ \t]+$/.test(line)) {
|
|
31031
31043
|
const trailingMatch = line.match(/[ \t]+$/);
|
|
@@ -31042,7 +31054,24 @@ var init_no_trailing_whitespace = __esm(() => {
|
|
|
31042
31054
|
return issues;
|
|
31043
31055
|
},
|
|
31044
31056
|
fix(content) {
|
|
31045
|
-
|
|
31057
|
+
const lines = content.split(/\r?\n/);
|
|
31058
|
+
let inHeredoc = false;
|
|
31059
|
+
let heredocDelim = "";
|
|
31060
|
+
const fixed = lines.map((line) => {
|
|
31061
|
+
if (inHeredoc) {
|
|
31062
|
+
if (line.trim() === heredocDelim)
|
|
31063
|
+
inHeredoc = false;
|
|
31064
|
+
return line;
|
|
31065
|
+
}
|
|
31066
|
+
const delim = heredocDelimiter(line);
|
|
31067
|
+
if (delim) {
|
|
31068
|
+
inHeredoc = true;
|
|
31069
|
+
heredocDelim = delim;
|
|
31070
|
+
}
|
|
31071
|
+
return line.replace(/[ \t]+$/, "");
|
|
31072
|
+
});
|
|
31073
|
+
return fixed.join(`
|
|
31074
|
+
`);
|
|
31046
31075
|
}
|
|
31047
31076
|
};
|
|
31048
31077
|
});
|
|
@@ -31440,21 +31469,26 @@ var init_heredoc_indent = __esm(() => {
|
|
|
31440
31469
|
const trimmed = line.replace(/^\s+/, "");
|
|
31441
31470
|
if (trimmed.startsWith("#"))
|
|
31442
31471
|
continue;
|
|
31443
|
-
const
|
|
31444
|
-
if (
|
|
31445
|
-
|
|
31446
|
-
|
|
31447
|
-
|
|
31448
|
-
|
|
31449
|
-
|
|
31450
|
-
|
|
31451
|
-
|
|
31452
|
-
|
|
31453
|
-
|
|
31454
|
-
|
|
31455
|
-
|
|
31456
|
-
|
|
31457
|
-
|
|
31472
|
+
const indent = line.match(/^\s+/);
|
|
31473
|
+
if (!indent)
|
|
31474
|
+
continue;
|
|
31475
|
+
const masked = maskShellStrings(line);
|
|
31476
|
+
const op = masked.match(/(?<!<)<<(?![<-])/);
|
|
31477
|
+
if (!op || op.index === undefined)
|
|
31478
|
+
continue;
|
|
31479
|
+
const after = line.slice(op.index + 2);
|
|
31480
|
+
const delimMatch = after.match(/^\s*(['"]?)(\w+)\1\s*$/);
|
|
31481
|
+
if (delimMatch) {
|
|
31482
|
+
const delim = delimMatch[2];
|
|
31483
|
+
issues.push({
|
|
31484
|
+
filePath: ctx.filePath,
|
|
31485
|
+
line: i + 1,
|
|
31486
|
+
column: op.index + 1,
|
|
31487
|
+
ruleId: "shell/heredoc-indent",
|
|
31488
|
+
message: `Use <<- instead of << for indented heredoc (delimiter '${delim}' must be at column 0 otherwise)`,
|
|
31489
|
+
severity: "warning",
|
|
31490
|
+
help: "Use <<- to strip leading tabs from heredoc content, allowing proper indentation"
|
|
31491
|
+
});
|
|
31458
31492
|
}
|
|
31459
31493
|
}
|
|
31460
31494
|
return issues;
|
|
@@ -31482,17 +31516,18 @@ var init_no_broken_redirect = __esm(() => {
|
|
|
31482
31516
|
inHeredoc = false;
|
|
31483
31517
|
continue;
|
|
31484
31518
|
}
|
|
31485
|
-
const
|
|
31486
|
-
if (
|
|
31519
|
+
const delim = heredocDelimiter(line);
|
|
31520
|
+
if (delim) {
|
|
31487
31521
|
inHeredoc = true;
|
|
31488
|
-
heredocDelim =
|
|
31522
|
+
heredocDelim = delim;
|
|
31489
31523
|
}
|
|
31490
31524
|
const trimmed = line.replace(/^\s+/, "");
|
|
31491
31525
|
if (trimmed.startsWith("#"))
|
|
31492
31526
|
continue;
|
|
31493
|
-
const
|
|
31527
|
+
const masked = maskShellStrings(line);
|
|
31528
|
+
const brokenPattern = masked.match(/2>&1\s+>(?!&)\s*\S/);
|
|
31494
31529
|
if (brokenPattern) {
|
|
31495
|
-
const col =
|
|
31530
|
+
const col = masked.indexOf("2>&1");
|
|
31496
31531
|
issues.push({
|
|
31497
31532
|
filePath: ctx.filePath,
|
|
31498
31533
|
line: i + 1,
|
|
@@ -31790,8 +31825,6 @@ function createSpellRule(ruleId, filterFn) {
|
|
|
31790
31825
|
for (const { word, offset: wordOffset } of words) {
|
|
31791
31826
|
if (word.length < minLen)
|
|
31792
31827
|
continue;
|
|
31793
|
-
if (word.length <= 2)
|
|
31794
|
-
continue;
|
|
31795
31828
|
if (word === word.toUpperCase() && word.length <= 5)
|
|
31796
31829
|
continue;
|
|
31797
31830
|
if (userWords.has(word.toLowerCase()))
|
|
@@ -32048,9 +32081,36 @@ var init_arrow_spacing = __esm(() => {
|
|
|
32048
32081
|
return issues;
|
|
32049
32082
|
},
|
|
32050
32083
|
fix(content) {
|
|
32051
|
-
|
|
32052
|
-
|
|
32053
|
-
|
|
32084
|
+
const lines = content.split(`
|
|
32085
|
+
`);
|
|
32086
|
+
for (let li = 0;li < lines.length; li++) {
|
|
32087
|
+
const line = lines[li];
|
|
32088
|
+
const trimmed = line.trim();
|
|
32089
|
+
if (!trimmed || trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("/*"))
|
|
32090
|
+
continue;
|
|
32091
|
+
let out = "";
|
|
32092
|
+
let last = 0;
|
|
32093
|
+
ARROW_RE.lastIndex = 0;
|
|
32094
|
+
let m;
|
|
32095
|
+
while ((m = ARROW_RE.exec(line)) !== null) {
|
|
32096
|
+
const idx = m.index;
|
|
32097
|
+
if (isInStringOrComment3(line, idx))
|
|
32098
|
+
continue;
|
|
32099
|
+
const before = line[idx - 1];
|
|
32100
|
+
const after = line[idx + 2];
|
|
32101
|
+
const needBefore = idx > 0 && before !== " " && before !== "\t";
|
|
32102
|
+
const needAfter = after !== undefined && after !== " " && after !== "\t";
|
|
32103
|
+
if (!needBefore && !needAfter)
|
|
32104
|
+
continue;
|
|
32105
|
+
out += line.slice(last, idx);
|
|
32106
|
+
out += `${needBefore ? " " : ""}=>${needAfter ? " " : ""}`;
|
|
32107
|
+
last = idx + 2;
|
|
32108
|
+
}
|
|
32109
|
+
if (last > 0)
|
|
32110
|
+
lines[li] = out + line.slice(last);
|
|
32111
|
+
}
|
|
32112
|
+
return lines.join(`
|
|
32113
|
+
`);
|
|
32054
32114
|
}
|
|
32055
32115
|
};
|
|
32056
32116
|
});
|
|
@@ -33307,11 +33367,14 @@ var init_dot_location = __esm(() => {
|
|
|
33307
33367
|
check(content, context) {
|
|
33308
33368
|
const issues = [];
|
|
33309
33369
|
const lines = content.split(/\r?\n/);
|
|
33370
|
+
const inTemplate = computeLineStartsInTemplate(content);
|
|
33310
33371
|
for (let i = 0;i < lines.length; i++) {
|
|
33311
33372
|
const line = lines[i];
|
|
33312
33373
|
const trimmed = line.trim();
|
|
33313
33374
|
if (!trimmed || trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("/*"))
|
|
33314
33375
|
continue;
|
|
33376
|
+
if (inTemplate[i + 1])
|
|
33377
|
+
continue;
|
|
33315
33378
|
if (trimmed.endsWith(".") && i + 1 < lines.length) {
|
|
33316
33379
|
const nextTrimmed = lines[i + 1].trim();
|
|
33317
33380
|
if (nextTrimmed && /^[a-zA-Z_$]/.test(nextTrimmed)) {
|
|
@@ -33331,10 +33394,11 @@ var init_dot_location = __esm(() => {
|
|
|
33331
33394
|
fix(content) {
|
|
33332
33395
|
const lines = content.split(/\r?\n/);
|
|
33333
33396
|
const result = [];
|
|
33397
|
+
const inTemplate = computeLineStartsInTemplate(content);
|
|
33334
33398
|
for (let i = 0;i < lines.length; i++) {
|
|
33335
33399
|
const line = lines[i];
|
|
33336
33400
|
const trimmed = line.trim();
|
|
33337
|
-
if (trimmed.endsWith(".") && i + 1 < lines.length) {
|
|
33401
|
+
if (trimmed.endsWith(".") && !inTemplate[i + 1] && i + 1 < lines.length) {
|
|
33338
33402
|
const nextLine = lines[i + 1];
|
|
33339
33403
|
const nextTrimmed = nextLine.trim();
|
|
33340
33404
|
if (nextTrimmed && /^[a-zA-Z_$]/.test(nextTrimmed)) {
|
|
@@ -37064,32 +37128,60 @@ var init_prefer_nullish_coalescing = __esm(() => {
|
|
|
37064
37128
|
const lines = text.split(/\r?\n/);
|
|
37065
37129
|
let inBlockComment = false;
|
|
37066
37130
|
for (let i = 0;i < lines.length; i++) {
|
|
37067
|
-
|
|
37068
|
-
const
|
|
37131
|
+
const originalLine = lines[i];
|
|
37132
|
+
const chars = originalLine.split("");
|
|
37133
|
+
const n = chars.length;
|
|
37134
|
+
let k = 0;
|
|
37069
37135
|
if (inBlockComment) {
|
|
37070
|
-
const endIdx =
|
|
37071
|
-
if (endIdx
|
|
37072
|
-
line = line.slice(endIdx + 2);
|
|
37073
|
-
inBlockComment = false;
|
|
37074
|
-
} else {
|
|
37136
|
+
const endIdx = originalLine.indexOf("*/");
|
|
37137
|
+
if (endIdx < 0)
|
|
37075
37138
|
continue;
|
|
37076
|
-
|
|
37139
|
+
for (let p = 0;p <= endIdx + 1; p++)
|
|
37140
|
+
chars[p] = " ";
|
|
37141
|
+
inBlockComment = false;
|
|
37142
|
+
k = endIdx + 2;
|
|
37077
37143
|
}
|
|
37078
|
-
|
|
37079
|
-
|
|
37080
|
-
|
|
37081
|
-
|
|
37082
|
-
|
|
37083
|
-
|
|
37084
|
-
|
|
37085
|
-
|
|
37086
|
-
|
|
37144
|
+
let inStr = null;
|
|
37145
|
+
for (;k < n; k++) {
|
|
37146
|
+
const ch = chars[k];
|
|
37147
|
+
if (inStr) {
|
|
37148
|
+
if (ch === "\\") {
|
|
37149
|
+
chars[k] = " ";
|
|
37150
|
+
if (k + 1 < n) {
|
|
37151
|
+
chars[k + 1] = " ";
|
|
37152
|
+
k++;
|
|
37153
|
+
}
|
|
37154
|
+
continue;
|
|
37155
|
+
}
|
|
37156
|
+
if (ch === inStr) {
|
|
37157
|
+
inStr = null;
|
|
37158
|
+
continue;
|
|
37159
|
+
}
|
|
37160
|
+
chars[k] = " ";
|
|
37161
|
+
continue;
|
|
37087
37162
|
}
|
|
37163
|
+
if (ch === "/" && chars[k + 1] === "/") {
|
|
37164
|
+
for (let p = k;p < n; p++)
|
|
37165
|
+
chars[p] = " ";
|
|
37166
|
+
break;
|
|
37167
|
+
}
|
|
37168
|
+
if (ch === "/" && chars[k + 1] === "*") {
|
|
37169
|
+
const endIdx = originalLine.indexOf("*/", k + 2);
|
|
37170
|
+
if (endIdx < 0) {
|
|
37171
|
+
for (let p = k;p < n; p++)
|
|
37172
|
+
chars[p] = " ";
|
|
37173
|
+
inBlockComment = true;
|
|
37174
|
+
break;
|
|
37175
|
+
}
|
|
37176
|
+
for (let p = k;p <= endIdx + 1; p++)
|
|
37177
|
+
chars[p] = " ";
|
|
37178
|
+
k = endIdx + 1;
|
|
37179
|
+
continue;
|
|
37180
|
+
}
|
|
37181
|
+
if (ch === '"' || ch === "'" || ch === "`")
|
|
37182
|
+
inStr = ch;
|
|
37088
37183
|
}
|
|
37089
|
-
|
|
37090
|
-
line = line.slice(0, lineComment);
|
|
37091
|
-
}
|
|
37092
|
-
const cleanedLine = line.replace(/(['"`])(?:(?!\1)[^\\]|\\.)*?\1/g, '""');
|
|
37184
|
+
const cleanedLine = chars.join("");
|
|
37093
37185
|
const orPattern = /\|\|/g;
|
|
37094
37186
|
let match;
|
|
37095
37187
|
while ((match = orPattern.exec(cleanedLine)) !== null) {
|
|
@@ -37184,11 +37276,10 @@ var init_prefer_nullish_coalescing = __esm(() => {
|
|
|
37184
37276
|
const looksLikeDefaultValue = /^["'`\d]/.test(rightOperand) || /^\{/.test(rightOperand) || /^[\w$]+\(/.test(rightOperand) || /^[\w$.[\]]+$/.test(rightOperand);
|
|
37185
37277
|
const looksLikeNullableValue = /^[\w$]+$/.test(leftOperand) || /^[\w$.?[\]()]+$/.test(leftOperand);
|
|
37186
37278
|
if (looksLikeDefaultValue && looksLikeNullableValue) {
|
|
37187
|
-
const actualIdx = originalLine.indexOf("||", Math.max(0, idx - 5));
|
|
37188
37279
|
issues.push({
|
|
37189
37280
|
filePath: ctx.filePath,
|
|
37190
37281
|
line: i + 1,
|
|
37191
|
-
column:
|
|
37282
|
+
column: idx + 1,
|
|
37192
37283
|
ruleId: "ts/prefer-nullish-coalescing",
|
|
37193
37284
|
message: "Prefer nullish coalescing operator (??) over logical OR (||)",
|
|
37194
37285
|
severity: "error",
|
|
@@ -38004,7 +38095,7 @@ function createIgnoreMatcher(ignoreGlobs, cwd = process21.cwd()) {
|
|
|
38004
38095
|
return (absPath) => {
|
|
38005
38096
|
const normalizedAbs = toPosixPath(absPath);
|
|
38006
38097
|
const normalizedCwd = toPosixPath(cwd).replace(/\/$/, "");
|
|
38007
|
-
const isOutsideProject = !normalizedAbs.startsWith(normalizedCwd);
|
|
38098
|
+
const isOutsideProject = normalizedAbs !== normalizedCwd && !normalizedAbs.startsWith(`${normalizedCwd}/`);
|
|
38008
38099
|
const rel = isOutsideProject ? normalizedAbs : normalizedAbs.slice(normalizedCwd.length);
|
|
38009
38100
|
for (const pattern of compiled) {
|
|
38010
38101
|
if (isOutsideProject && !universalRaw.has(pattern.raw))
|
|
@@ -38286,35 +38377,30 @@ async function runFormat(globs, options) {
|
|
|
38286
38377
|
return extSet.has(ext);
|
|
38287
38378
|
});
|
|
38288
38379
|
trace("filtered files", files.length);
|
|
38289
|
-
let changed = 0;
|
|
38290
38380
|
let checked = 0;
|
|
38381
|
+
const unformatted = [];
|
|
38291
38382
|
for (const file of files) {
|
|
38292
38383
|
trace("format start", relative6(process23.cwd(), file));
|
|
38293
38384
|
const src = readFileSync9(file, "utf8");
|
|
38294
38385
|
const fmt = formatCode(src, cfg, file);
|
|
38295
|
-
|
|
38296
|
-
|
|
38297
|
-
|
|
38298
|
-
changed++;
|
|
38299
|
-
}
|
|
38300
|
-
checked++;
|
|
38301
|
-
} else if (options.write) {
|
|
38302
|
-
if (fmt !== src) {
|
|
38386
|
+
const differs = fmt !== src;
|
|
38387
|
+
if (options.write) {
|
|
38388
|
+
if (differs)
|
|
38303
38389
|
writeFileSync10(file, fmt, "utf8");
|
|
38304
|
-
changed++;
|
|
38305
|
-
}
|
|
38306
|
-
checked++;
|
|
38307
|
-
} else {
|
|
38308
|
-
if (fmt !== src) {
|
|
38309
|
-
getLogger().debug(`${relative6(process23.cwd(), file)} needs formatting`);
|
|
38310
|
-
changed++;
|
|
38311
|
-
}
|
|
38312
|
-
checked++;
|
|
38313
38390
|
}
|
|
38391
|
+
if (differs)
|
|
38392
|
+
unformatted.push(relative6(process23.cwd(), file));
|
|
38393
|
+
checked++;
|
|
38314
38394
|
}
|
|
38315
|
-
const
|
|
38316
|
-
if (
|
|
38317
|
-
|
|
38395
|
+
const changed = unformatted.length;
|
|
38396
|
+
if (changed > 0) {
|
|
38397
|
+
for (const file of unformatted)
|
|
38398
|
+
console.log(colors.gray(` ${file}`));
|
|
38399
|
+
console.log(options.write ? colors.gray(`Formatted ${changed} of ${checked} file(s).`) : colors.yellow(`${changed} of ${checked} file(s) need formatting. Run with --write to fix.`));
|
|
38400
|
+
} else {
|
|
38401
|
+
const isVerbose = options.verbose !== undefined ? options.verbose : cfg.verbose;
|
|
38402
|
+
if (isVerbose)
|
|
38403
|
+
console.log(colors.gray(`Checked ${checked} files, all formatted.`));
|
|
38318
38404
|
}
|
|
38319
38405
|
return options.check && changed > 0 ? 1 : 0;
|
|
38320
38406
|
}
|
|
@@ -38337,7 +38423,7 @@ __export(exports_linter, {
|
|
|
38337
38423
|
applyPlugins: () => applyPlugins
|
|
38338
38424
|
});
|
|
38339
38425
|
import { readdirSync as readdirSync9, readFileSync as readFileSync10, statSync as statSync6, writeFileSync as writeFileSync11 } from "fs";
|
|
38340
|
-
import { isAbsolute as isAbsolute8, join as join11, relative as relative7, resolve as resolve23 } from "path";
|
|
38426
|
+
import { isAbsolute as isAbsolute8, join as join11, relative as relative7, resolve as resolve23, sep } from "path";
|
|
38341
38427
|
import process25 from "process";
|
|
38342
38428
|
function getLogger2() {
|
|
38343
38429
|
if (!_logger2)
|
|
@@ -38394,7 +38480,8 @@ async function runLintProgrammatic(globs, options, signal) {
|
|
|
38394
38480
|
const isGlobbingOutsideProject = patterns.some((p) => {
|
|
38395
38481
|
const base = p.replace(/\/?\*\*\/*\*\*$/, "");
|
|
38396
38482
|
const absBase = isAbsolute8(base) ? base : resolve23(process25.cwd(), base);
|
|
38397
|
-
|
|
38483
|
+
const cwd = process25.cwd();
|
|
38484
|
+
return absBase !== cwd && !absBase.startsWith(cwd + sep);
|
|
38398
38485
|
});
|
|
38399
38486
|
const globIgnores = isGlobbingOutsideProject ? [...UNIVERSAL_IGNORES] : cfg.ignores;
|
|
38400
38487
|
const ignoreMatcher = createIgnoreMatcher(globIgnores);
|
|
@@ -39425,7 +39512,10 @@ function scanContentOptimized(filePath, content, cfg, suppress, commentLines) {
|
|
|
39425
39512
|
}
|
|
39426
39513
|
} else {
|
|
39427
39514
|
if (inString === "double" && ch === '"' || inString === "single" && ch === "'" || inString === "template" && ch === "`") {
|
|
39428
|
-
|
|
39515
|
+
let backslashes = 0;
|
|
39516
|
+
for (let p = k - 1;p >= 0 && line[p] === "\\"; p--)
|
|
39517
|
+
backslashes++;
|
|
39518
|
+
if (backslashes % 2 === 0)
|
|
39429
39519
|
inString = null;
|
|
39430
39520
|
}
|
|
39431
39521
|
}
|
|
@@ -39502,6 +39592,12 @@ function scanContentOptimized(filePath, content, cfg, suppress, commentLines) {
|
|
|
39502
39592
|
const strippedLine = stripComments2(stripRegexLiterals(line));
|
|
39503
39593
|
const conditionLine = strippedLine.replace(/'[^']*'|"[^"]*"/g, '""');
|
|
39504
39594
|
const checkCond = (cond) => /[^=!<>]=(?![=>])/.test(cond);
|
|
39595
|
+
const condParenColumn = (keyword) => {
|
|
39596
|
+
const km = line.match(keyword);
|
|
39597
|
+
if (km && km.index !== undefined)
|
|
39598
|
+
return km.index + km[0].length;
|
|
39599
|
+
return Math.max(1, line.indexOf("(") + 1);
|
|
39600
|
+
};
|
|
39505
39601
|
const m1 = conditionLine.match(/\b(?:if|while)\s*\(([^)]*)\)/);
|
|
39506
39602
|
if (m1) {
|
|
39507
39603
|
const cond = m1[1];
|
|
@@ -39510,7 +39606,7 @@ function scanContentOptimized(filePath, content, cfg, suppress, commentLines) {
|
|
|
39510
39606
|
issues.push({
|
|
39511
39607
|
filePath,
|
|
39512
39608
|
line: lineNo,
|
|
39513
|
-
column:
|
|
39609
|
+
column: condParenColumn(/\b(?:if|while)\s*\(/),
|
|
39514
39610
|
ruleId: "no-cond-assign",
|
|
39515
39611
|
message: "Unexpected assignment within a conditional expression",
|
|
39516
39612
|
severity: wantNoCondAssign,
|
|
@@ -39530,7 +39626,7 @@ function scanContentOptimized(filePath, content, cfg, suppress, commentLines) {
|
|
|
39530
39626
|
issues.push({
|
|
39531
39627
|
filePath,
|
|
39532
39628
|
line: lineNo,
|
|
39533
|
-
column:
|
|
39629
|
+
column: condParenColumn(/\bfor\s*\(/),
|
|
39534
39630
|
ruleId: "no-cond-assign",
|
|
39535
39631
|
message: "Unexpected assignment within a conditional expression",
|
|
39536
39632
|
severity: wantNoCondAssign,
|
|
@@ -39597,7 +39693,8 @@ async function runLint(globs, options) {
|
|
|
39597
39693
|
const isGlobbingOutsideProject = patterns.some((p) => {
|
|
39598
39694
|
const base = p.replace(/\/?\*\*\/*\*\*$/, "");
|
|
39599
39695
|
const absBase = isAbsolute8(base) ? base : resolve23(process25.cwd(), base);
|
|
39600
|
-
|
|
39696
|
+
const cwd = process25.cwd();
|
|
39697
|
+
return absBase !== cwd && !absBase.startsWith(cwd + sep);
|
|
39601
39698
|
});
|
|
39602
39699
|
const globIgnores = isGlobbingOutsideProject ? [...UNIVERSAL_IGNORES] : cfg.ignores;
|
|
39603
39700
|
const ignoreMatcher = createIgnoreMatcher(globIgnores);
|