@d3lm/lint-preset 1.5.4 → 1.5.6
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/README.md +11 -24
- package/dist/bin/comments.js +57 -14
- package/dist/bin/comments.js.map +1 -1
- package/dist/comments.cjs +55 -13
- package/dist/comments.cjs.map +1 -1
- package/dist/comments.d.cts +12 -7
- package/dist/comments.d.ts +12 -7
- package/dist/comments.js +55 -13
- package/dist/comments.js.map +1 -1
- package/package.json +1 -1
package/dist/comments.d.cts
CHANGED
|
@@ -4,8 +4,9 @@ interface WrapOptions {
|
|
|
4
4
|
/**
|
|
5
5
|
* Sets whether a line may not end with the first word of a sentence, clause, or parenthetical,
|
|
6
6
|
* like `This`, `the` after a comma, or `(the`. Such a word moves to the next line instead.
|
|
7
|
-
* It also sets whether
|
|
8
|
-
*
|
|
7
|
+
* It also sets whether a line avoids ending with the first two words of a sentence, and whether
|
|
8
|
+
* the first of two lines ends with a sentence instead of the start of the next one, as long as
|
|
9
|
+
* the second line is then no longer than the first.
|
|
9
10
|
*/
|
|
10
11
|
readonly avoidSentenceOrphans: boolean;
|
|
11
12
|
/**
|
|
@@ -74,7 +75,8 @@ interface ParagraphReport {
|
|
|
74
75
|
/**
|
|
75
76
|
* Holds the exact source lines for `startLine` through `endLine` when the paragraph is
|
|
76
77
|
* greedily wrapped to the width, or `null` when the paragraph isn't prose, e.g. code,
|
|
77
|
-
* a table, a diagram, or `@example`.
|
|
78
|
+
* a table, a diagram, or `@example`. A paragraph that is accepted with the layout for a
|
|
79
|
+
* wider width within the tolerance keeps its lines.
|
|
78
80
|
*/
|
|
79
81
|
readonly suggestion: readonly string[] | null;
|
|
80
82
|
}
|
|
@@ -213,16 +215,19 @@ interface CommentsConfig {
|
|
|
213
215
|
readonly singleLineWidth?: number;
|
|
214
216
|
/**
|
|
215
217
|
* Sets how many columns prose lines may go past `width` when that saves a line in a paragraph of
|
|
216
|
-
* three or more lines.
|
|
217
|
-
*
|
|
218
|
+
* three or more lines. A paragraph that already has the layout for a wider `width`, up to `width`
|
|
219
|
+
* plus this many columns, also passes as it is. It never goes past `maxWidth`. When `maxWidth` is
|
|
220
|
+
* omitted, it also sets a legacy hard limit of `width + tolerance`.
|
|
218
221
|
*/
|
|
219
222
|
readonly tolerance?: number;
|
|
220
223
|
/**
|
|
221
224
|
* Keep the first word of a new sentence or parenthetical off the end of a line, e.g.
|
|
222
225
|
* `...the module. This` or `...reflows (the` followed by the rest on the next line.
|
|
223
226
|
* A paragraph of two lines also ends its first line with a sentence when the rest fits
|
|
224
|
-
* on the second line and is no longer than the first, instead of with the start of
|
|
225
|
-
* next sentence, like `...the module. This one`.
|
|
227
|
+
* on the second line and is no longer than the first, instead of with the start of
|
|
228
|
+
* the next sentence, like `...the module. This one`. Other lines avoid ending with the
|
|
229
|
+
* first two words of a sentence, like `...opens. It allocates`, unless that makes them
|
|
230
|
+
* much less even. Defaults to `true`.
|
|
226
231
|
*/
|
|
227
232
|
readonly avoidSentenceOrphans?: boolean;
|
|
228
233
|
/**
|
package/dist/comments.d.ts
CHANGED
|
@@ -4,8 +4,9 @@ interface WrapOptions {
|
|
|
4
4
|
/**
|
|
5
5
|
* Sets whether a line may not end with the first word of a sentence, clause, or parenthetical,
|
|
6
6
|
* like `This`, `the` after a comma, or `(the`. Such a word moves to the next line instead.
|
|
7
|
-
* It also sets whether
|
|
8
|
-
*
|
|
7
|
+
* It also sets whether a line avoids ending with the first two words of a sentence, and whether
|
|
8
|
+
* the first of two lines ends with a sentence instead of the start of the next one, as long as
|
|
9
|
+
* the second line is then no longer than the first.
|
|
9
10
|
*/
|
|
10
11
|
readonly avoidSentenceOrphans: boolean;
|
|
11
12
|
/**
|
|
@@ -74,7 +75,8 @@ interface ParagraphReport {
|
|
|
74
75
|
/**
|
|
75
76
|
* Holds the exact source lines for `startLine` through `endLine` when the paragraph is
|
|
76
77
|
* greedily wrapped to the width, or `null` when the paragraph isn't prose, e.g. code,
|
|
77
|
-
* a table, a diagram, or `@example`.
|
|
78
|
+
* a table, a diagram, or `@example`. A paragraph that is accepted with the layout for a
|
|
79
|
+
* wider width within the tolerance keeps its lines.
|
|
78
80
|
*/
|
|
79
81
|
readonly suggestion: readonly string[] | null;
|
|
80
82
|
}
|
|
@@ -213,16 +215,19 @@ interface CommentsConfig {
|
|
|
213
215
|
readonly singleLineWidth?: number;
|
|
214
216
|
/**
|
|
215
217
|
* Sets how many columns prose lines may go past `width` when that saves a line in a paragraph of
|
|
216
|
-
* three or more lines.
|
|
217
|
-
*
|
|
218
|
+
* three or more lines. A paragraph that already has the layout for a wider `width`, up to `width`
|
|
219
|
+
* plus this many columns, also passes as it is. It never goes past `maxWidth`. When `maxWidth` is
|
|
220
|
+
* omitted, it also sets a legacy hard limit of `width + tolerance`.
|
|
218
221
|
*/
|
|
219
222
|
readonly tolerance?: number;
|
|
220
223
|
/**
|
|
221
224
|
* Keep the first word of a new sentence or parenthetical off the end of a line, e.g.
|
|
222
225
|
* `...the module. This` or `...reflows (the` followed by the rest on the next line.
|
|
223
226
|
* A paragraph of two lines also ends its first line with a sentence when the rest fits
|
|
224
|
-
* on the second line and is no longer than the first, instead of with the start of
|
|
225
|
-
* next sentence, like `...the module. This one`.
|
|
227
|
+
* on the second line and is no longer than the first, instead of with the start of
|
|
228
|
+
* the next sentence, like `...the module. This one`. Other lines avoid ending with the
|
|
229
|
+
* first two words of a sentence, like `...opens. It allocates`, unless that makes them
|
|
230
|
+
* much less even. Defaults to `true`.
|
|
226
231
|
*/
|
|
227
232
|
readonly avoidSentenceOrphans?: boolean;
|
|
228
233
|
/**
|
package/dist/comments.js
CHANGED
|
@@ -291,6 +291,8 @@ function hasWidow(lines) {
|
|
|
291
291
|
}
|
|
292
292
|
var FULLNESS_WEIGHT = 0.07;
|
|
293
293
|
var PARENTHETICAL_SPLIT_WEIGHT = 2;
|
|
294
|
+
var SENTENCE_START_COST = 25;
|
|
295
|
+
var MAX_SENTENCE_START_WORDS = 2;
|
|
294
296
|
var MAX_STEP = 15;
|
|
295
297
|
var EXTRA_LINES = 2;
|
|
296
298
|
function fewestLines(starts, target) {
|
|
@@ -378,7 +380,7 @@ function balanceTokens(tokens, firstLimit, restLimit, count, options, preferredL
|
|
|
378
380
|
afterOrphan: tokens.map((_, index) => {
|
|
379
381
|
return options.avoidSentenceOrphans && index >= 2 && isOrphan(tokens[index - 2], tokens[index - 1]);
|
|
380
382
|
}),
|
|
381
|
-
splitCosts
|
|
383
|
+
splitCosts: withSentenceStartCosts(tokens, splitCosts, options)
|
|
382
384
|
};
|
|
383
385
|
const targets = [];
|
|
384
386
|
for (let target = restLimit; target >= Math.max(longest, Math.floor(restLimit / 2)); target -= 1) {
|
|
@@ -444,6 +446,22 @@ function splitCostsOf(tokens, limit) {
|
|
|
444
446
|
}
|
|
445
447
|
return splitCosts;
|
|
446
448
|
}
|
|
449
|
+
function withSentenceStartCosts(tokens, splitCosts, options) {
|
|
450
|
+
if (!options.avoidSentenceOrphans || options.ignoreSentenceStarts) {
|
|
451
|
+
return splitCosts;
|
|
452
|
+
}
|
|
453
|
+
const costs = new Map(splitCosts);
|
|
454
|
+
for (const [index, token] of tokens.entries()) {
|
|
455
|
+
if (!endsSentence(token)) {
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
const last = Math.min(index + 1 + MAX_SENTENCE_START_WORDS, tokens.length - 1);
|
|
459
|
+
for (let end = index + 2; end <= last && !endsSentence(tokens[end - 1]); end += 1) {
|
|
460
|
+
costs.set(end, (costs.get(end) ?? 0) + SENTENCE_START_COST);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return costs;
|
|
464
|
+
}
|
|
447
465
|
function hasParentheticals(tokens, restLimit, options) {
|
|
448
466
|
if (options.parentheticalOverflow === void 0) {
|
|
449
467
|
return false;
|
|
@@ -1041,9 +1059,9 @@ function analyzeParagraph(paragraph, options) {
|
|
|
1041
1059
|
parentheticalOverflow: options.maxWidth === void 0 ? void 0 : options.maxWidth - options.width,
|
|
1042
1060
|
keepFirstLine: paragraph.kind === "tag"
|
|
1043
1061
|
};
|
|
1044
|
-
const layOut = (from, settings) => {
|
|
1045
|
-
const even2 = layoutTokens(from, firstLimit, restLimit, settings);
|
|
1046
|
-
return { even: even2, wrapped: breakAfterSentence(even2, firstLimit, restLimit, settings) };
|
|
1062
|
+
const layOut = (from, settings, extra) => {
|
|
1063
|
+
const even2 = layoutTokens(from, firstLimit + extra, restLimit + extra, settings);
|
|
1064
|
+
return { even: even2, wrapped: breakAfterSentence(even2, firstLimit + extra, restLimit + extra, settings) };
|
|
1047
1065
|
};
|
|
1048
1066
|
const units = bindLineStarts(paragraph.kind === "tag" ? bindTagHead(tokens) : tokens, startsLine);
|
|
1049
1067
|
const hardLimit = restLimit + (options.maxWidth === void 0 ? options.tolerance : options.maxWidth - options.width);
|
|
@@ -1060,9 +1078,9 @@ function analyzeParagraph(paragraph, options) {
|
|
|
1060
1078
|
return { ...first, text, verbatim: false, hardBreak: HARD_BREAK.test(text) };
|
|
1061
1079
|
});
|
|
1062
1080
|
};
|
|
1063
|
-
const settle = (settings) => {
|
|
1081
|
+
const settle = (settings, extra = 0) => {
|
|
1064
1082
|
let current = units;
|
|
1065
|
-
let { even: even2, wrapped: wrapped2 } = layOut(current, settings);
|
|
1083
|
+
let { even: even2, wrapped: wrapped2 } = layOut(current, settings, extra);
|
|
1066
1084
|
for (; ; ) {
|
|
1067
1085
|
const body = bodyOf(wrapped2);
|
|
1068
1086
|
const rewrap = structureOf(body);
|
|
@@ -1077,11 +1095,19 @@ function analyzeParagraph(paragraph, options) {
|
|
|
1077
1095
|
return { tier: "manual", reason: `rewrap would read as ${reading}` };
|
|
1078
1096
|
}
|
|
1079
1097
|
current = current.toSpliced(start - 1, 2, pair);
|
|
1080
|
-
({ even: even2, wrapped: wrapped2 } = layOut(current, settings));
|
|
1098
|
+
({ even: even2, wrapped: wrapped2 } = layOut(current, settings, extra));
|
|
1081
1099
|
}
|
|
1082
1100
|
};
|
|
1083
|
-
const
|
|
1084
|
-
|
|
1101
|
+
const layoutAt = (extra) => {
|
|
1102
|
+
const settings = {
|
|
1103
|
+
...layoutOptions,
|
|
1104
|
+
tolerance: layoutOptions.tolerance - extra,
|
|
1105
|
+
parentheticalOverflow: layoutOptions.parentheticalOverflow === void 0 ? void 0 : layoutOptions.parentheticalOverflow - extra
|
|
1106
|
+
};
|
|
1107
|
+
const settled = settle(settings, extra);
|
|
1108
|
+
return "wrapped" in settled ? settled : settle({ ...settings, keepSteps: true }, extra);
|
|
1109
|
+
};
|
|
1110
|
+
const layout = layoutAt(0);
|
|
1085
1111
|
if (!("wrapped" in layout)) {
|
|
1086
1112
|
return keep(layout);
|
|
1087
1113
|
}
|
|
@@ -1106,6 +1132,10 @@ function analyzeParagraph(paragraph, options) {
|
|
|
1106
1132
|
const free = settle({ ...layoutOptions, avoidSentenceOrphans: false });
|
|
1107
1133
|
return !("wrapped" in free) || sameLayout(free.wrapped, currentLines);
|
|
1108
1134
|
};
|
|
1135
|
+
const keepsOnlySentenceStarts = () => {
|
|
1136
|
+
const free = settle({ ...layoutOptions, ignoreSentenceStarts: true });
|
|
1137
|
+
return "wrapped" in free && (sameLayout(free.even, currentLines) || sameLayout(free.wrapped, currentLines));
|
|
1138
|
+
};
|
|
1109
1139
|
const splitsOnlyParenthetical = (line) => {
|
|
1110
1140
|
if (layoutOptions.parentheticalOverflow === void 0) {
|
|
1111
1141
|
return false;
|
|
@@ -1133,7 +1163,7 @@ function analyzeParagraph(paragraph, options) {
|
|
|
1133
1163
|
wrapped.findIndex((words, position) => words.join(" ") !== currentLines[position]?.join(" ")),
|
|
1134
1164
|
0
|
|
1135
1165
|
);
|
|
1136
|
-
if (lineIssues.length === 0 && sameLayout(even, currentLines)) {
|
|
1166
|
+
if (lineIssues.length === 0 && (sameLayout(even, currentLines) || keepsOnlySentenceStarts())) {
|
|
1137
1167
|
lineIssues.push({ type: "orphan", line });
|
|
1138
1168
|
} else if (lineIssues.length === 0) {
|
|
1139
1169
|
lineIssues.push({ type: splitsOnlyParenthetical(line) ? "split-parenthetical" : "unbalanced", line });
|
|
@@ -1142,10 +1172,22 @@ function analyzeParagraph(paragraph, options) {
|
|
|
1142
1172
|
}
|
|
1143
1173
|
}
|
|
1144
1174
|
}
|
|
1145
|
-
const
|
|
1175
|
+
const isVerdict = (issue) => ISSUE_TIERS[issue.type] === "verdict";
|
|
1176
|
+
const matchesWiderLayout = () => {
|
|
1177
|
+
for (let extra = 1; extra <= layoutOptions.tolerance; extra += 1) {
|
|
1178
|
+
const wider = layoutAt(extra);
|
|
1179
|
+
if ("wrapped" in wider && sameLayout(wider.wrapped, currentLines)) {
|
|
1180
|
+
return true;
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
return false;
|
|
1184
|
+
};
|
|
1185
|
+
const accepted = lineIssues.some((issue) => isVerdict(issue)) && matchesWiderLayout();
|
|
1186
|
+
const suggested = accepted ? currentLines : wrapped;
|
|
1187
|
+
const suggestion = suggested.map(
|
|
1146
1188
|
(words, position) => `${prefix}${position === 0 ? paragraph.marker : hang}${words.join(" ")}`
|
|
1147
1189
|
);
|
|
1148
|
-
const wrapIssues = lineIssues.map((issue) => lineIssue(issue.type, paragraph.lines[issue.line], options));
|
|
1190
|
+
const wrapIssues = lineIssues.filter((issue) => !accepted || !isVerdict(issue)).map((issue) => lineIssue(issue.type, paragraph.lines[issue.line], options));
|
|
1149
1191
|
const issues = byLine([...overflow, ...wrapIssues, ...styleIssues(paragraph, options)]);
|
|
1150
1192
|
return { ...base, reflowable: true, issues, suggestion };
|
|
1151
1193
|
}
|
|
@@ -1337,7 +1379,7 @@ When rules pull in different directions, the earlier one wins.
|
|
|
1337
1379
|
## Layout
|
|
1338
1380
|
|
|
1339
1381
|
- After you finish, the tool rewraps prose paragraphs, list items, and JSDoc tag descriptions. The width is a preferred target. A parenthetical may extend a line up to the configured maximum so it stays together, and lines may go up to the configured tolerance past the width when that saves a line. In longer paragraphs, balanced lines take priority over keeping every parenthetical on one line. The tool also avoids short last lines where possible. Leave these line breaks to the tool, except for the sentence-orphan case below.
|
|
1340
|
-
- Don't end a line with the first word of a new sentence, clause, or parenthetical, like \`This\` after a period, \`the\` after a comma, or \`(the\`. Move it to the next line instead. A long word, like an identifier or a code span, may stay at the end of a line when moving it would leave that line far shorter than the lines around it. Then leave the line breaks as they are.
|
|
1382
|
+
- Don't end a line with the first word of a new sentence, clause, or parenthetical, like \`This\` after a period, \`the\` after a comma, or \`(the\`. Move it to the next line instead. The same goes for the first two words of a sentence, like \`It allocates\` after a period, when the note points at them. A long word, like an identifier or a code span, may stay at the end of a line when moving it would leave that line far shorter than the lines around it. Then leave the line breaks as they are.
|
|
1341
1383
|
- In a paragraph of two lines, the first line ends with a sentence whenever the rest fits on the second line and is no longer than the first. Don't end it with the start of the next sentence, like \`A wrap\` in \`...lay out differently. A wrap\`. Move those words to the second line instead.
|
|
1342
1384
|
- A comment whose whole text is one paragraph stays on a single line when that line fits a separate, larger single-line width, even past the width. Only a longer comment wraps to the width.
|
|
1343
1385
|
- Separate paragraphs with an empty comment line.
|