@d3lm/lint-preset 1.5.0 → 1.5.2

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
@@ -290,6 +290,8 @@ function hasWidow(lines) {
290
290
  }
291
291
  var FULLNESS_WEIGHT = 0.07;
292
292
  var PARENTHETICAL_SPLIT_WEIGHT = 2;
293
+ var MAX_STEP = 15;
294
+ var EXTRA_LINES = 2;
293
295
  function fewestLines(starts, target) {
294
296
  const total = starts.length - 1;
295
297
  const fewest = new Int32Array(total + 1);
@@ -422,7 +424,56 @@ function balanceTokens(tokens, firstLimit, restLimit, count, options, preferredL
422
424
  const bounds = [0, ...best.breaks, total];
423
425
  return bounds.slice(0, -1).map((start, index) => tokens.slice(start, bounds[index + 1]));
424
426
  }
427
+ function hasStep(lines, offset = 0) {
428
+ return lines.some((line, index) => {
429
+ if (index === 0) {
430
+ return false;
431
+ }
432
+ const before = lineLength(lines[index - 1]) + (index === 1 ? offset : 0);
433
+ return lineLength(line) - before > MAX_STEP;
434
+ });
435
+ }
436
+ function splitCostsOf(tokens, limit) {
437
+ const splitCosts = /* @__PURE__ */ new Map();
438
+ for (const group of parentheticalGroups(tokens, limit)) {
439
+ const length = lineLength(tokens.slice(group.start, group.end));
440
+ for (let at = group.start + 1; at < group.end; at += 1) {
441
+ splitCosts.set(at, length * PARENTHETICAL_SPLIT_WEIGHT);
442
+ }
443
+ }
444
+ return splitCosts;
445
+ }
446
+ function hasParentheticals(tokens, restLimit, options) {
447
+ if (options.parentheticalOverflow === void 0) {
448
+ return false;
449
+ }
450
+ return bindParentheticals(tokens, restLimit + options.parentheticalOverflow).some((token) => isParenthetical(token));
451
+ }
425
452
  function layoutTokens(tokens, firstLimit, restLimit, options) {
453
+ const lines = layoutLines(tokens, firstLimit, restLimit, options);
454
+ const offset = restLimit - firstLimit;
455
+ if (options.keepFirstLine || options.keepSteps || !hasStep(lines, offset)) {
456
+ return lines;
457
+ }
458
+ const overflow = hasParentheticals(tokens, restLimit, options) ? _nullishCoalesce(options.parentheticalOverflow, () => ( 0)) : 0;
459
+ const splitCosts = overflow > 0 ? splitCostsOf(tokens, restLimit + overflow) : /* @__PURE__ */ new Map();
460
+ for (let count = lines.length + 1; count <= lines.length + EXTRA_LINES; count += 1) {
461
+ const even = balanceTokens(
462
+ tokens,
463
+ firstLimit + overflow,
464
+ restLimit + overflow,
465
+ count,
466
+ options,
467
+ restLimit,
468
+ splitCosts
469
+ );
470
+ if (even && !hasStep(even, offset)) {
471
+ return even;
472
+ }
473
+ }
474
+ return lines;
475
+ }
476
+ function layoutLines(tokens, firstLimit, restLimit, options) {
426
477
  if (options.parentheticalOverflow !== void 0) {
427
478
  const grouped = bindParentheticals(tokens, restLimit + options.parentheticalOverflow);
428
479
  if (grouped.some((token) => isParenthetical(token))) {
@@ -456,14 +507,7 @@ function layoutTokens(tokens, firstLimit, restLimit, options) {
456
507
  return expanded;
457
508
  });
458
509
  }
459
- const splitCosts = /* @__PURE__ */ new Map();
460
- const groups = parentheticalGroups(tokens, restLimit + options.parentheticalOverflow);
461
- for (const group of groups) {
462
- const length = lineLength(tokens.slice(group.start, group.end));
463
- for (let at = group.start + 1; at < group.end; at += 1) {
464
- splitCosts.set(at, length * PARENTHETICAL_SPLIT_WEIGHT);
465
- }
466
- }
510
+ const splitCosts = splitCostsOf(tokens, restLimit + options.parentheticalOverflow);
467
511
  const preferred = wrapTokens(tokens, firstLimit, restLimit, { ...options, parentheticalOverflow: void 0 });
468
512
  for (let count = minimumLines; count <= Math.max(preferred.length + 1, preserved.length); count += 1) {
469
513
  const balanced2 = balanceTokens(
@@ -493,6 +537,19 @@ function layoutTokens(tokens, firstLimit, restLimit, options) {
493
537
  return lines;
494
538
  }
495
539
  }
540
+ if (options.tolerance > 0 && greedy.length > 2) {
541
+ const fewer = balanceTokens(
542
+ tokens,
543
+ firstLimit + options.tolerance,
544
+ restLimit + options.tolerance,
545
+ greedy.length - 1,
546
+ options,
547
+ restLimit
548
+ );
549
+ if (fewer && !hasStep(fewer, restLimit - firstLimit)) {
550
+ return fewer;
551
+ }
552
+ }
496
553
  const balanced = balanceTokens(tokens, firstLimit, restLimit, greedy.length, options);
497
554
  if (balanced) {
498
555
  return balanced;
@@ -982,11 +1039,11 @@ function analyzeParagraph(paragraph, options) {
982
1039
  parentheticalOverflow: options.maxWidth === void 0 ? void 0 : options.maxWidth - options.width,
983
1040
  keepFirstLine: paragraph.kind === "tag"
984
1041
  };
985
- const layOut = (from) => {
986
- const even2 = layoutTokens(from, firstLimit, restLimit, layoutOptions);
987
- return { even: even2, wrapped: breakAfterSentence(even2, firstLimit, restLimit, layoutOptions) };
1042
+ const layOut = (from, settings) => {
1043
+ const even2 = layoutTokens(from, firstLimit, restLimit, settings);
1044
+ return { even: even2, wrapped: breakAfterSentence(even2, firstLimit, restLimit, settings) };
988
1045
  };
989
- let units = bindLineStarts(paragraph.kind === "tag" ? bindTagHead(tokens) : tokens, startsLine);
1046
+ const units = bindLineStarts(paragraph.kind === "tag" ? bindTagHead(tokens) : tokens, startsLine);
990
1047
  const hardLimit = restLimit + (options.maxWidth === void 0 ? options.tolerance : options.maxWidth - options.width);
991
1048
  const written = currentLines.map((words) => ` ${words.join(" ")} `);
992
1049
  const staysInLimit = (unit) => {
@@ -995,29 +1052,38 @@ function analyzeParagraph(paragraph, options) {
995
1052
  if (!units.every((unit) => staysInLimit(unit))) {
996
1053
  return keep({ tier: "manual", reason: "unbreakable text across lines" });
997
1054
  }
998
- let { even, wrapped } = layOut(units);
999
1055
  const bodyOf = (lines) => {
1000
1056
  return lines.map((words, position) => {
1001
1057
  const text = `${position === 0 ? paragraph.marker : hang}${words.join(" ")}`;
1002
1058
  return { ...first, text, verbatim: false, hardBreak: HARD_BREAK.test(text) };
1003
1059
  });
1004
1060
  };
1005
- for (; ; ) {
1006
- const body = bodyOf(wrapped);
1007
- const rewrap = structureOf(body);
1008
- if (!rewrap) {
1009
- break;
1010
- }
1011
- const tipping = body.findIndex((_, position) => structureOf(body.slice(0, position + 1)) !== void 0);
1012
- const start = wrapped.slice(0, Math.max(tipping, 1)).flat().length;
1013
- const pair = `${units[start - 1]} ${units[start]}`;
1014
- if (body.length < 2 || !staysInLimit(pair)) {
1015
- const reading = rewrap.tier === "code-like" ? "code" : rewrap.reason;
1016
- return keep({ tier: "manual", reason: `rewrap would read as ${reading}` });
1061
+ const settle = (settings) => {
1062
+ let current = units;
1063
+ let { even: even2, wrapped: wrapped2 } = layOut(current, settings);
1064
+ for (; ; ) {
1065
+ const body = bodyOf(wrapped2);
1066
+ const rewrap = structureOf(body);
1067
+ if (!rewrap) {
1068
+ return { even: even2, wrapped: wrapped2 };
1069
+ }
1070
+ const tipping = body.findIndex((_, position) => structureOf(body.slice(0, position + 1)) !== void 0);
1071
+ const start = wrapped2.slice(0, Math.max(tipping, 1)).flat().length;
1072
+ const pair = `${current[start - 1]} ${current[start]}`;
1073
+ if (body.length < 2 || !staysInLimit(pair)) {
1074
+ const reading = rewrap.tier === "code-like" ? "code" : rewrap.reason;
1075
+ return { tier: "manual", reason: `rewrap would read as ${reading}` };
1076
+ }
1077
+ current = current.toSpliced(start - 1, 2, pair);
1078
+ ({ even: even2, wrapped: wrapped2 } = layOut(current, settings));
1017
1079
  }
1018
- units = units.toSpliced(start - 1, 2, pair);
1019
- ({ even, wrapped } = layOut(units));
1080
+ };
1081
+ const settled = settle(layoutOptions);
1082
+ const layout = "wrapped" in settled ? settled : settle({ ...layoutOptions, keepSteps: true });
1083
+ if (!("wrapped" in layout)) {
1084
+ return keep(layout);
1020
1085
  }
1086
+ const { even, wrapped } = layout;
1021
1087
  const matchesLayout = sameLayout(wrapped, currentLines);
1022
1088
  const lineIssues = [];
1023
1089
  const overflow = options.maxWidth === void 0 ? [] : overflowIssues(paragraph.lines, options);
@@ -1231,7 +1297,7 @@ When rules pull in different directions, the earlier one wins.
1231
1297
 
1232
1298
  ## Layout
1233
1299
 
1234
- - 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. 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.
1300
+ - 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.
1235
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.
1236
1302
  - 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.
1237
1303
  - 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.