@d3lm/lint-preset 1.5.1 → 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/README.md CHANGED
@@ -245,7 +245,7 @@ comments agent # hand suspicious comments to an agent, then
245
245
  comments check --cwd ../other-app # run as if started in another project
246
246
  ```
247
247
 
248
- Without targets, only comments in uncommitted changes and untracked files are checked. `--staged` limits that to staged changes, `--base main` checks everything since the merge base with `main`, and `--repo` checks every file. Targets can be files, directories, `file:line`, or `file:start-end`. A comment that contains `comments-ignore` is skipped. A file with a syntax error is skipped as a whole and named in a warning, because the parser stops at the error and never sees the comments after it. JSX is read in `.js` files too.
248
+ Without targets, only comments in uncommitted changes and untracked files are checked. `--base main` checks everything since the merge base with `main`, and `--repo` checks every file. `--whole-files` checks every comment in the changed files instead of only the comments on changed lines. Targets can be files, directories, `file:line`, or `file:start-end`. A comment that contains `comments-ignore` is skipped. A file with a syntax error is skipped as a whole and named in a warning, because the parser stops at the error and never sees the comments after it. JSX is read in `.js` files too.
249
249
 
250
250
  With `--json`, each paragraph of a comment comes with its issues and a `suggestion` that holds the exact rewrapped lines. Code blocks, `@example`, tables, drawings, directives, and other [text kept as written](#text-kept-as-written) have no suggestion.
251
251
 
@@ -294,7 +294,7 @@ A comment with an issue in a part that is kept is handed to the agent, which can
294
294
  */
295
295
  ```
296
296
 
297
- The separate `singleLineWidth` allowance is capped by `maxWidth`. Code and documented layout regions retain their exemptions. An indivisible token in measured prose that exceeds `maxWidth` is reported as overflow; the wrapper preserves it, so resolving that case requires changing the maximum or the comment manually. The legacy `tolerance` option sets a maximum of `width + tolerance` when `maxWidth` is omitted; an explicit `maxWidth` takes precedence. Direct `analyzeSource` callers can omit `maxWidth` to retain the legacy width/tolerance behavior.
297
+ The separate `singleLineWidth` allowance is capped by `maxWidth`. Code and documented layout regions retain their exemptions. An indivisible token in measured prose that exceeds `maxWidth` is reported as overflow; the wrapper preserves it, so resolving that case requires changing the maximum or the comment manually. `tolerance` lets prose lines go up to that many columns past `width` when that saves a line in a paragraph of three or more lines, and it never goes past `maxWidth`. It defaults to 0. When `maxWidth` is omitted, `tolerance` also sets a legacy maximum of `width + tolerance`. Direct `analyzeSource` callers can omit `maxWidth` to retain the legacy width/tolerance behavior.
298
298
 
299
299
  Like prettier, `comments` looks for a config file in the current directory and its parents, up to the repository root. The config can be a `comments.config.{ts,mts,js,mjs,cjs}`, `.commentsrc`, or `.commentsrc.json` file, or a `comments` key in `package.json`. All options are optional.
300
300
 
@@ -306,6 +306,8 @@ export default defineConfig({
306
306
  // defaults to prettier's printWidth, or 80
307
307
  width: 100,
308
308
  maxWidth: 120,
309
+ // prose lines may go this many columns past `width` when that saves a line
310
+ tolerance: 0,
309
311
  // a comment that is one paragraph stays on one line up to this length, and wraps to `width` beyond it
310
312
  singleLineWidth: 120,
311
313
  avoidSentenceOrphans: true,
@@ -24,7 +24,7 @@ When rules pull in different directions, the earlier one wins.
24
24
 
25
25
  ## Layout
26
26
 
27
- - 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.
27
+ - 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.
28
28
  - 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.
29
29
  - 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.
30
30
  - 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.
@@ -825,6 +825,19 @@ function layoutLines(tokens, firstLimit, restLimit, options) {
825
825
  return lines;
826
826
  }
827
827
  }
828
+ if (options.tolerance > 0 && greedy.length > 2) {
829
+ const fewer = balanceTokens(
830
+ tokens,
831
+ firstLimit + options.tolerance,
832
+ restLimit + options.tolerance,
833
+ greedy.length - 1,
834
+ options,
835
+ restLimit
836
+ );
837
+ if (fewer && !hasStep(fewer, restLimit - firstLimit)) {
838
+ return fewer;
839
+ }
840
+ }
828
841
  const balanced = balanceTokens(tokens, firstLimit, restLimit, greedy.length, options);
829
842
  if (balanced) {
830
843
  return balanced;
@@ -2167,23 +2180,12 @@ function snapshotChanges(root) {
2167
2180
  var DIFF_FLAGS = ["diff", "-U0", "--no-color", "--no-ext-diff", "--no-renames", "--src-prefix=a/", "--dst-prefix=b/"];
2168
2181
  function getChangedLines(root, scope = {}) {
2169
2182
  if (!hasHead(root)) {
2170
- const files = scope.staged ? splitPaths(gitOrThrow(root, ["diff", "-z", "--cached", "--name-only", "--diff-filter=d"])) : listFiles2(root);
2171
- return new Map(files.map((file) => [file, "all"]));
2172
- }
2173
- let args;
2174
- if (scope.staged) {
2175
- args = [...DIFF_FLAGS, "--cached", "HEAD"];
2176
- } else if (scope.base) {
2177
- const mergeBase = gitOrThrow(root, ["merge-base", scope.base, "HEAD"]).trim();
2178
- args = [...DIFF_FLAGS, mergeBase];
2179
- } else {
2180
- args = [...DIFF_FLAGS, "HEAD"];
2183
+ return new Map(listFiles2(root).map((file) => [file, "all"]));
2181
2184
  }
2182
- const changed = parseUnifiedDiff(gitOrThrow(root, args));
2183
- if (!scope.staged) {
2184
- for (const file of listUntrackedFiles(root)) {
2185
- changed.set(file, "all");
2186
- }
2185
+ const target = scope.base ? gitOrThrow(root, ["merge-base", scope.base, "HEAD"]).trim() : "HEAD";
2186
+ const changed = parseUnifiedDiff(gitOrThrow(root, [...DIFF_FLAGS, target]));
2187
+ for (const file of listUntrackedFiles(root)) {
2188
+ changed.set(file, "all");
2187
2189
  }
2188
2190
  return changed;
2189
2191
  }
@@ -2298,7 +2300,7 @@ var Project = class {
2298
2300
  throw new Error("comments: not a git repository, so pass files or directories explicitly");
2299
2301
  }
2300
2302
  for (const [file, lines] of getChangedLines(this.root, scope)) {
2301
- add(path4.join(this.root, file), lines);
2303
+ add(path4.join(this.root, file), scope.wholeFiles ? "all" : lines);
2302
2304
  }
2303
2305
  return files;
2304
2306
  }
@@ -2809,8 +2811,8 @@ Targets are files, directories, file:line, or file:start-end. Without targets, o
2809
2811
  overlapping uncommitted changes (and untracked files) are considered.
2810
2812
 
2811
2813
  Options:
2812
- --staged Only consider staged changes
2813
2814
  --base <ref> Consider changes since the merge base with <ref>
2815
+ --whole-files Consider every comment in the changed files, not only comments on changed lines
2814
2816
  --repo Consider every file in the repository
2815
2817
  --suspicious Only comments with layout issues (overflow, early line ends, last lines of one or two words)
2816
2818
  or hints (possible orphans, em-dashes, banners, ...). For agent and hook (the default), only
@@ -2830,7 +2832,7 @@ Config overrides (take precedence over the config file):
2830
2832
  --width <n> Preferred comment line length
2831
2833
  --max-width <n> Hard limit for prose (default: 120, never below width)
2832
2834
  --single-line-width <n> Longest line a one-paragraph comment may stay on (default: 120)
2833
- --tolerance <n> Legacy hard limit of width + n, unless max-width is set
2835
+ --tolerance <n> Columns prose may go past width to save a line, within max-width (default: 0)
2834
2836
  --[no-]orphans Keep a sentence's first word off the end of a line, and end the first of two lines
2835
2837
  with a sentence when the second is no longer than the first (default: on)
2836
2838
  --[no-]style Look for possible semicolons, em-dashes, dashes, label colons, emphasis, and banners
@@ -2856,8 +2858,8 @@ var OPTIONS = {
2856
2858
  "max-files": { type: "string" },
2857
2859
  "max-agents": { type: "string" },
2858
2860
  instructions: { type: "string" },
2859
- staged: { type: "boolean" },
2860
2861
  base: { type: "string" },
2862
+ "whole-files": { type: "boolean" },
2861
2863
  repo: { type: "boolean" },
2862
2864
  suspicious: { type: "boolean" },
2863
2865
  all: { type: "boolean" },
@@ -2944,7 +2946,7 @@ async function createProject(cwd, values) {
2944
2946
  return { project, configPath: loaded.filepath };
2945
2947
  }
2946
2948
  function scopeFrom(positionals, values) {
2947
- return { targets: positionals, staged: values.staged, base: values.base, repo: values.repo };
2949
+ return { targets: positionals, base: values.base, wholeFiles: values["whole-files"], repo: values.repo };
2948
2950
  }
2949
2951
  function selectFrom(values, project) {
2950
2952
  if (values.all) {
@@ -3005,9 +3007,8 @@ function commentsOf(analyses) {
3005
3007
  function hintEmptyScope(analyses, scope) {
3006
3008
  const isDefaultScope = (scope.targets ?? []).length === 0 && !scope.repo && !scope.base;
3007
3009
  if (analyses.length === 0 && isDefaultScope) {
3008
- const changes = scope.staged ? "staged changes" : "uncommitted changes";
3009
3010
  log2(
3010
- `comments: no ${changes} in JavaScript or TypeScript files. Pass --repo, --base <ref>, or files to widen the scope.`
3011
+ "comments: no uncommitted changes in JavaScript or TypeScript files. Pass --repo, --base <ref>, or files to widen the scope."
3011
3012
  );
3012
3013
  }
3013
3014
  }