@d3lm/lint-preset 1.5.2 → 1.5.5

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/comments.cjs CHANGED
@@ -201,6 +201,9 @@ function parentheticalGroups(tokens, limit) {
201
201
  }
202
202
  return groups;
203
203
  }
204
+ function parentheticalAround(tokens, at, limit) {
205
+ return parentheticalGroups(tokens, limit).find((group) => group.start < at && at < group.end);
206
+ }
204
207
  function bindParentheticals(tokens, limit) {
205
208
  const groups = new Map(parentheticalGroups(tokens, limit).map((group) => [group.start, group.end]));
206
209
  const units = [];
@@ -290,6 +293,8 @@ function hasWidow(lines) {
290
293
  }
291
294
  var FULLNESS_WEIGHT = 0.07;
292
295
  var PARENTHETICAL_SPLIT_WEIGHT = 2;
296
+ var SENTENCE_START_COST = 25;
297
+ var MAX_SENTENCE_START_WORDS = 2;
293
298
  var MAX_STEP = 15;
294
299
  var EXTRA_LINES = 2;
295
300
  function fewestLines(starts, target) {
@@ -377,7 +382,7 @@ function balanceTokens(tokens, firstLimit, restLimit, count, options, preferredL
377
382
  afterOrphan: tokens.map((_, index) => {
378
383
  return options.avoidSentenceOrphans && index >= 2 && isOrphan(tokens[index - 2], tokens[index - 1]);
379
384
  }),
380
- splitCosts
385
+ splitCosts: withSentenceStartCosts(tokens, splitCosts, options)
381
386
  };
382
387
  const targets = [];
383
388
  for (let target = restLimit; target >= Math.max(longest, Math.floor(restLimit / 2)); target -= 1) {
@@ -443,6 +448,22 @@ function splitCostsOf(tokens, limit) {
443
448
  }
444
449
  return splitCosts;
445
450
  }
451
+ function withSentenceStartCosts(tokens, splitCosts, options) {
452
+ if (!options.avoidSentenceOrphans || options.ignoreSentenceStarts) {
453
+ return splitCosts;
454
+ }
455
+ const costs = new Map(splitCosts);
456
+ for (const [index, token] of tokens.entries()) {
457
+ if (!endsSentence(token)) {
458
+ continue;
459
+ }
460
+ const last = Math.min(index + 1 + MAX_SENTENCE_START_WORDS, tokens.length - 1);
461
+ for (let end = index + 2; end <= last && !endsSentence(tokens[end - 1]); end += 1) {
462
+ costs.set(end, (_nullishCoalesce(costs.get(end), () => ( 0))) + SENTENCE_START_COST);
463
+ }
464
+ }
465
+ return costs;
466
+ }
446
467
  function hasParentheticals(tokens, restLimit, options) {
447
468
  if (options.parentheticalOverflow === void 0) {
448
469
  return false;
@@ -605,6 +626,7 @@ var ISSUE_TIERS = {
605
626
  widow: "verdict",
606
627
  unbalanced: "verdict",
607
628
  orphan: "hint",
629
+ "split-parenthetical": "hint",
608
630
  banner: "hint",
609
631
  "em-dash": "hint",
610
632
  semicolon: "hint",
@@ -1100,9 +1122,48 @@ function analyzeParagraph(paragraph, options) {
1100
1122
  if (hasWidow(currentLines) && !hasWidow(wrapped)) {
1101
1123
  lineIssues.push({ type: "widow", line: currentLines.length - 1 });
1102
1124
  }
1103
- if (lineIssues.length === 0 && overflow.length === 0 && (currentLines.length === wrapped.length || options.maxWidth !== void 0)) {
1104
- const line = wrapped.findIndex((words, position) => words.join(" ") !== _optionalChain([currentLines, 'access', _38 => _38[position], 'optionalAccess', _39 => _39.join, 'call', _40 => _40(" ")]));
1105
- lineIssues.push({ type: sameLayout(even, currentLines) ? "orphan" : "unbalanced", line: Math.max(line, 0) });
1125
+ const keepsOnlyOrphans = () => {
1126
+ const free = settle({ ...layoutOptions, avoidSentenceOrphans: false });
1127
+ return !("wrapped" in free) || sameLayout(free.wrapped, currentLines);
1128
+ };
1129
+ const keepsOnlySentenceStarts = () => {
1130
+ const free = settle({ ...layoutOptions, ignoreSentenceStarts: true });
1131
+ return "wrapped" in free && (sameLayout(free.even, currentLines) || sameLayout(free.wrapped, currentLines));
1132
+ };
1133
+ const splitsOnlyParenthetical = (line) => {
1134
+ if (layoutOptions.parentheticalOverflow === void 0) {
1135
+ return false;
1136
+ }
1137
+ const tokenCount = (lines) => tokenize(lines.flat().join(" ")).length;
1138
+ const end = tokenCount(currentLines.slice(0, line + 1));
1139
+ const group = parentheticalAround(tokens, end, restLimit + layoutOptions.parentheticalOverflow);
1140
+ if (!group) {
1141
+ return false;
1142
+ }
1143
+ const keepsGroup = wrapped.every((_, position) => {
1144
+ const breakAt = tokenCount(wrapped.slice(0, position + 1));
1145
+ return breakAt <= group.start || breakAt >= group.end;
1146
+ });
1147
+ if (!keepsGroup) {
1148
+ return false;
1149
+ }
1150
+ const restOptions = { ...layoutOptions, keepFirstLine: false };
1151
+ const rest = bindLineStarts(tokens.slice(end), startsLine);
1152
+ const restLines = layoutTokens(rest, restLimit, restLimit, restOptions);
1153
+ return sameLayout(breakAfterSentence(restLines, restLimit, restLimit, restOptions), currentLines.slice(line + 1));
1154
+ };
1155
+ if (overflow.length === 0 && (currentLines.length === wrapped.length || options.maxWidth !== void 0)) {
1156
+ const line = Math.max(
1157
+ wrapped.findIndex((words, position) => words.join(" ") !== _optionalChain([currentLines, 'access', _38 => _38[position], 'optionalAccess', _39 => _39.join, 'call', _40 => _40(" ")])),
1158
+ 0
1159
+ );
1160
+ if (lineIssues.length === 0 && (sameLayout(even, currentLines) || keepsOnlySentenceStarts())) {
1161
+ lineIssues.push({ type: "orphan", line });
1162
+ } else if (lineIssues.length === 0) {
1163
+ lineIssues.push({ type: splitsOnlyParenthetical(line) ? "split-parenthetical" : "unbalanced", line });
1164
+ } else if (lineIssues.every((issue) => issue.type === "orphan") && !sameLayout(even, currentLines) && !keepsOnlyOrphans()) {
1165
+ lineIssues.push({ type: "unbalanced", line });
1166
+ }
1106
1167
  }
1107
1168
  }
1108
1169
  const suggestion = wrapped.map(
@@ -1235,7 +1296,9 @@ function inspectSource(source, filename, options) {
1235
1296
  options.width,
1236
1297
  Math.min(_nullishCoalesce(options.singleLineWidth, () => ( options.width)), _nullishCoalesce(options.maxWidth, () => ( Infinity)))
1237
1298
  );
1238
- const paragraphOptions = shape.paragraphs.length === 1 && singleLineLength(shape.paragraphs[0], options) <= singleLineWidth ? { ...options, width: singleLineWidth } : options;
1299
+ const singleLineLimit = Math.min(singleLineWidth + options.tolerance, _nullishCoalesce(options.maxWidth, () => ( Infinity)));
1300
+ const singleLine = shape.paragraphs.length === 1 ? singleLineLength(shape.paragraphs[0], options) : Infinity;
1301
+ const paragraphOptions = singleLine <= singleLineLimit ? { ...options, width: Math.max(singleLineWidth, singleLine) } : options;
1239
1302
  const lines = sourceLines.slice(shape.startLine, shape.endLine + 1);
1240
1303
  reports.push({
1241
1304
  file: filename,
@@ -1298,7 +1361,7 @@ When rules pull in different directions, the earlier one wins.
1298
1361
  ## Layout
1299
1362
 
1300
1363
  - 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.
1301
- - 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.
1364
+ - 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.
1302
1365
  - 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.
1303
1366
  - 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.
1304
1367
  - Separate paragraphs with an empty comment line.