reslop 0.2.3 → 0.2.4

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.
Files changed (80) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/README.md +8 -3
  3. package/bin/reslop.js +4 -2
  4. package/lib/api.js +2 -1
  5. package/lib/cli.js +19 -10
  6. package/lib/clipboard.js +6 -3
  7. package/lib/deps-diff.js +61 -115
  8. package/lib/deps.js +24 -61
  9. package/lib/detect.js +4 -2
  10. package/lib/diff/align.js +2 -1
  11. package/lib/diff/diff.js +6 -3
  12. package/lib/diff/display.js +2 -1
  13. package/lib/diff/inline.js +2 -1
  14. package/lib/diff/patch.js +2 -1
  15. package/lib/diff/unit.js +4 -2
  16. package/lib/editor.js +22 -4
  17. package/lib/files.js +38 -12
  18. package/lib/git-branches.js +107 -154
  19. package/lib/git-deps.js +20 -60
  20. package/lib/git-worktree.js +508 -0
  21. package/lib/git.js +23 -580
  22. package/lib/github.js +2 -1
  23. package/lib/gitlab.js +2 -1
  24. package/lib/highlight/bash.js +2 -1
  25. package/lib/highlight/css.js +2 -1
  26. package/lib/highlight/csv.js +2 -1
  27. package/lib/highlight/dot.js +2 -1
  28. package/lib/highlight/html.js +2 -1
  29. package/lib/highlight/json.js +2 -1
  30. package/lib/highlight/log.js +2 -1
  31. package/lib/highlight/txt.js +2 -1
  32. package/lib/highlight.js +2 -1
  33. package/lib/keys.js +2 -2
  34. package/lib/manifest.js +4 -2
  35. package/lib/npm-commands.js +83 -4
  36. package/lib/remote.js +20 -13
  37. package/lib/render/branches.js +6 -15
  38. package/lib/render/chrome.js +27 -7
  39. package/lib/render/commits.js +158 -46
  40. package/lib/render/diff.js +130 -47
  41. package/lib/render/files.js +4 -12
  42. package/lib/render/frame.js +3 -9
  43. package/lib/render/notes.js +4 -11
  44. package/lib/render/npm.js +1 -13
  45. package/lib/render/present.js +2 -1
  46. package/lib/render/primitives.js +28 -15
  47. package/lib/render/render.js +2 -1
  48. package/lib/render/unit.js +14 -11
  49. package/lib/report-model.js +6 -4
  50. package/lib/report-parse.js +8 -13
  51. package/lib/report-render.js +38 -21
  52. package/lib/report-run.js +12 -10
  53. package/lib/report-test.js +5 -4
  54. package/lib/report-tools.js +44 -18
  55. package/lib/review-merge.js +2 -1
  56. package/lib/review.js +6 -2
  57. package/lib/session/actions.js +49 -65
  58. package/lib/session/branches.js +13 -49
  59. package/lib/session/change-actions.js +2 -1
  60. package/lib/session/commit.js +34 -49
  61. package/lib/session/compose.js +37 -11
  62. package/lib/session/dispatch.js +17 -25
  63. package/lib/session/files-pane.js +6 -27
  64. package/lib/session/items.js +6 -3
  65. package/lib/session/lifecycle.js +8 -4
  66. package/lib/session/load.js +4 -2
  67. package/lib/session/navigation.js +1 -0
  68. package/lib/session/npm.js +54 -1
  69. package/lib/session/ops.js +15 -1
  70. package/lib/session/pointer.js +22 -3
  71. package/lib/session/review.js +2 -1
  72. package/lib/session/terminal.js +4 -2
  73. package/lib/session/update.js +2 -1
  74. package/lib/session/view.js +29 -3
  75. package/lib/session.js +37 -23
  76. package/lib/source.js +6 -3
  77. package/lib/update.js +5 -9
  78. package/lib/utilities.js +4 -2
  79. package/lib/wrap.js +3 -1
  80. package/package.json +1 -1
@@ -7,7 +7,7 @@ const primitives = require('./primitives.js');
7
7
 
8
8
  const { REPO_TODOS_LABEL } = files;
9
9
  const { wrapMultiline, cursorInWrap } = wrap;
10
- const { THEME, visibleWidth, truncateVisible, seq, EL, RESET, BOLD } = ansi;
10
+ const { THEME, truncateVisible } = ansi;
11
11
  const { paintBar, paintCheckBar, windowRows } = primitives;
12
12
  const { LIST_PANES, CHECK_LEAD, paneResult } = primitives;
13
13
 
@@ -73,6 +73,7 @@ const paintTodoList = (texts, focus, width, color, edit) => {
73
73
  fgRgb,
74
74
  bgRgb,
75
75
  color,
76
+ true,
76
77
  );
77
78
  rows.push(painted);
78
79
  owners.push(i);
@@ -168,16 +169,8 @@ const paintNotePanel = (view, width, color, cap) => {
168
169
  return paintIdleNote(view, width, color);
169
170
  };
170
171
 
171
- const paintTodoCaption = (width, color) => {
172
- const text = ` ${REPO_TODOS_LABEL}`;
173
- const clipped = truncateVisible(text, width);
174
- const pad = Math.max(0, width - visibleWidth(clipped));
175
- const filled = clipped + ' '.repeat(pad);
176
- if (!color) return filled;
177
- const fgRgb = THEME.buttonHotFg;
178
- const bgRgb = THEME.ctxBg;
179
- return `${BOLD}${seq(fgRgb, bgRgb)}${EL}${filled}${RESET}`;
180
- };
172
+ const paintTodoCaption = (width, color) =>
173
+ paintBar(` ${REPO_TODOS_LABEL}`, width, THEME.mutedFg, THEME.ctxBg, color);
181
174
 
182
175
  const paintBodyTodo = (view, width, color) => {
183
176
  const texts = view.todos ?? [];
package/lib/render/npm.js CHANGED
@@ -78,7 +78,7 @@ const paintNpmList = (view, width, color, bodyH, headerLines) => {
78
78
  const at = view.npmEditName ? 'replace' : 'end';
79
79
  extra = { row: painted.row, cursor: painted.cursor, at, index: cursor };
80
80
  }
81
- const painted = paintCursorList(
81
+ return paintCursorList(
82
82
  commands,
83
83
  cursor,
84
84
  width,
@@ -89,14 +89,6 @@ const paintNpmList = (view, width, color, bodyH, headerLines) => {
89
89
  extra,
90
90
  view.listScroll,
91
91
  );
92
- return paneResult({
93
- body: painted.body,
94
- fileHits: painted.fileHits,
95
- todoOwners: [],
96
- cursor: painted.cursor,
97
- splitBody: false,
98
- listScroll: painted.offset,
99
- });
100
92
  };
101
93
 
102
94
  const logStart = (view, count, rows) => {
@@ -213,10 +205,6 @@ const paintNpmLog = (view, width, color, bodyH) => {
213
205
  for (let i = 0; i < padY - top; i++) body.push(blank);
214
206
  return paneResult({
215
207
  body,
216
- fileHits: [],
217
- todoOwners: [],
218
- cursor: null,
219
- splitBody: false,
220
208
  });
221
209
  };
222
210
 
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const { ESC } = require('../ansi.js');
3
+ const ansi = require('../ansi.js');
4
+ const { ESC } = ansi;
4
5
 
5
6
  const presentCursor = (cursor) => {
6
7
  if (!cursor || cursor.x <= 0 || cursor.y <= 0) return `${ESC}[?25l`;
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  const ansi = require('../ansi.js');
4
+ const actions = require('../session/actions.js');
5
+ const { LIST_PANES } = actions;
4
6
 
5
7
  const { THEME, paint, visibleWidth, truncateVisible, seq, EL, RESET } = ansi;
6
8
 
@@ -8,7 +10,6 @@ const GUTTER_W = 2;
8
10
  const FILE_MARK = '▶';
9
11
  const FILE_LIST_PAD = 1;
10
12
  const CHECK_DONE = 'xX';
11
- const LIST_PANES = ['files', 'branches', 'commits', 'npm'];
12
13
  const CHECK_TOKEN = /\[([ xX])\]/;
13
14
  const CHECK_LEAD = /^\[[ xX]\] /;
14
15
 
@@ -34,14 +35,21 @@ const splitCheck = (text) => {
34
35
  return { before, mark, token, after };
35
36
  };
36
37
 
37
- const paintCheckBar = (text, width, fgRgb, bgRgb, color) => {
38
+ const paintCheckBar = (text, width, fgRgb, bgRgb, color, plain = false) => {
38
39
  const clipped = truncateVisible(text, width);
39
40
  const parts = color ? splitCheck(clipped) : null;
40
41
  if (!parts) return paintBar(text, width, fgRgb, bgRgb, color);
41
42
  const pad = Math.max(0, width - visibleWidth(clipped));
42
43
  const done = CHECK_DONE.includes(parts.mark);
43
- const chipFg = done ? THEME.checkDoneFg : THEME.checkFg;
44
- const chipBg = done ? THEME.checkDoneBg : THEME.checkBg;
44
+ let chipFg = THEME.checkFg;
45
+ let chipBg = THEME.checkBg;
46
+ if (plain) {
47
+ chipFg = fgRgb;
48
+ chipBg = bgRgb;
49
+ } else if (done) {
50
+ chipFg = THEME.checkDoneFg;
51
+ chipBg = THEME.checkDoneBg;
52
+ }
45
53
  const after = `${parts.after}${' '.repeat(pad)}`;
46
54
  let out = `${seq(fgRgb, bgRgb)}${EL}`;
47
55
  if (parts.before) out += paint(parts.before, fgRgb, bgRgb, color);
@@ -111,6 +119,16 @@ const extraIdx = (extraRow, cursor, count) => {
111
119
  return count;
112
120
  };
113
121
 
122
+ const paneResult = (fields = {}) => ({
123
+ body: fields.body ?? [],
124
+ fileHits: fields.fileHits ?? [],
125
+ todoOwners: fields.todoOwners ?? [],
126
+ todoChecks: fields.todoChecks ?? [],
127
+ cursor: fields.cursor ?? null,
128
+ splitBody: fields.splitBody === true,
129
+ listScroll: fields.listScroll ?? 0,
130
+ });
131
+
114
132
  const paintCursorList = (
115
133
  items,
116
134
  cursor,
@@ -153,7 +171,12 @@ const paintCursorList = (
153
171
  fileHits.push({ y, cursor: itemIdx });
154
172
  }
155
173
  if (pad) body.push(blank);
156
- return { body, fileHits, cursor: textCursor, offset: start };
174
+ return paneResult({
175
+ body,
176
+ fileHits,
177
+ cursor: textCursor,
178
+ listScroll: start,
179
+ });
157
180
  };
158
181
 
159
182
  const branchLabel = (name) => `${name ?? ''}`.trim();
@@ -183,16 +206,6 @@ const paintListEdit = (compose, width, color, edgeW = 0) => {
183
206
  return { row, cursor: { x: prefixW + col + 1 } };
184
207
  };
185
208
 
186
- const paneResult = (fields) => ({
187
- body: fields.body,
188
- fileHits: fields.fileHits,
189
- todoOwners: fields.todoOwners,
190
- todoChecks: fields.todoChecks ?? [],
191
- cursor: fields.cursor ?? null,
192
- splitBody: fields.splitBody === true,
193
- listScroll: fields.listScroll ?? 0,
194
- });
195
-
196
209
  const measureColumns = (entries, rowFields, align) => {
197
210
  const keys = Object.keys(align);
198
211
  const widths = Object.fromEntries(keys.map((key) => [key, 0]));
@@ -4,7 +4,8 @@ const chrome = require('./chrome.js');
4
4
  const notes = require('./notes.js');
5
5
  const diff = require('./diff.js');
6
6
  const present = require('./present.js');
7
- const { renderFrame } = require('./frame.js');
7
+ const frame = require('./frame.js');
8
+ const { renderFrame } = frame;
8
9
 
9
10
  const { QUIT_PROMPT, PUSH_PROMPT } = chrome;
10
11
  const { updatePrompt, dropPrompt } = chrome;
@@ -1,23 +1,29 @@
1
1
  'use strict';
2
2
 
3
- const { detectLang } = require('../detect.js');
3
+ const detect = require('../detect.js');
4
+ const { detectLang } = detect;
4
5
  const primitives = require('./primitives.js');
5
6
  const diff = require('./diff.js');
6
7
 
7
8
  const { paneResult } = primitives;
8
- const { paintDiffLine, codeCursorInRows } = diff;
9
- const { sameHunk } = require('../diff/diff.js');
9
+ const { paintDiffLine, codeCursorInRows, expandSoftRows } = diff;
10
+ const diffLib = require('../diff/diff.js');
11
+ const { sameHunk } = diffLib;
10
12
 
11
13
  const paintBodyUnit = (view, width, color) => {
12
14
  const lines = view.unitLines ?? [];
13
15
  const item = view.item;
14
16
  const lang = detectLang(view.reviewPath ?? '');
15
17
  const overlay = view.codeOverlay;
16
- const editing = view.mode === 'compose' && overlay;
17
- const { length } = lines;
18
+ const editing =
19
+ view.mode === 'compose' && overlay && typeof overlay.cursor === 'number';
20
+ const picked = editing ? overlay.scrollCol : 0;
21
+ const scrollCol = picked ?? 0;
22
+ const source = editing ? lines : expandSoftRows(lines, width, false, true);
23
+ const { length } = source;
18
24
  const body = new Array(length);
19
25
  for (let i = 0; i < length; i++) {
20
- const line = lines[i];
26
+ const line = source[i];
21
27
  const isBlock = item && sameHunk(line.item, item);
22
28
  const row = { ...line };
23
29
  if (editing) {
@@ -25,16 +31,13 @@ const paintBodyUnit = (view, width, color) => {
25
31
  } else if ((row.type === 'add' || row.type === 'del') && !isBlock) {
26
32
  row.mark = ' ';
27
33
  }
28
- body[i] = paintDiffLine(row, width, color, row.origin, lang);
34
+ body[i] = paintDiffLine(row, width, color, row.origin, lang, scrollCol);
29
35
  }
30
36
  const edit = overlay ? overlay.cursor : null;
31
- const cursor = codeCursorInRows(lines, false, width, edit);
37
+ const cursor = codeCursorInRows(source, false, width, edit, scrollCol);
32
38
  return paneResult({
33
39
  body,
34
- fileHits: [],
35
- todoOwners: [],
36
40
  cursor,
37
- splitBody: false,
38
41
  });
39
42
  };
40
43
 
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const { stripAnsi } = require('./ansi.js');
3
+ const ansi = require('./ansi.js');
4
+ const { stripAnsi } = ansi;
4
5
  const commands = require('./npm-commands.js');
5
6
 
6
7
  const { withoutNodeFrame, indentStack, relativize } = commands;
@@ -108,9 +109,10 @@ const shortTail = (text) => {
108
109
  const envelope = (reports, exit, stderr) => {
109
110
  const status = exit === null || exit === undefined ? 1 : exit;
110
111
  const ok = status === 0;
111
- const items = [];
112
- for (const item of reports) {
113
- items.push(report(item.tool, { ...item, ok }));
112
+ const items = new Array(reports.length);
113
+ for (let i = 0; i < reports.length; i++) {
114
+ const item = reports[i];
115
+ items[i] = report(item.tool, { ...item, ok });
114
116
  }
115
117
  return { ok, exit: status, reports: items, stderr: stderr || '' };
116
118
  };
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const { stripAnsi } = require('./ansi.js');
3
+ const ansi = require('./ansi.js');
4
+ const { stripAnsi } = ansi;
4
5
  const model = require('./report-model.js');
5
6
  const testParse = require('./report-test.js');
6
7
  const toolParse = require('./report-tools.js');
@@ -10,15 +11,7 @@ const { reduceStderr, shortTail, envelope } = model;
10
11
  const { parseTap, parseNodeJsonl, parseTestJson, parseSpec } = testParse;
11
12
  const { parseToolJson, parseToolText } = toolParse;
12
13
 
13
- const KNOWN = new Set([
14
- 'test',
15
- 'tsc',
16
- 'eslint',
17
- 'prettier',
18
- 'audit',
19
- 'outdated',
20
- 'ls',
21
- ]);
14
+ const KNOWN = ['test', 'tsc', 'eslint', 'prettier', 'audit', 'outdated', 'ls'];
22
15
 
23
16
  const toolHint = (program, args) => {
24
17
  const name = `${program ?? ''}`.split(/[/\\]/).pop();
@@ -75,15 +68,17 @@ const parseReports = (text, root) => {
75
68
 
76
69
  const withHint = (reports, text, exit, hint) => {
77
70
  if (reports.length || !`${text ?? ''}`.trim() || exit === 0) return reports;
78
- const tool = KNOWN.has(hint) ? hint : 'test';
71
+ const tool = KNOWN.includes(hint) ? hint : 'test';
79
72
  return [report(tool, { problems: [problem({ message: shortTail(text) })] })];
80
73
  };
81
74
 
82
75
  const buildDocument = (stdout, stderr, root, exit, hint) => {
83
76
  const text = stripAnsi(stdout);
84
77
  const reports = withHint(parseReports(text, root), text, exit, hint);
85
- const grouped = [];
86
- for (const item of reports) grouped.push(groupReport(item));
78
+ const grouped = new Array(reports.length);
79
+ for (let i = 0; i < reports.length; i++) {
80
+ grouped[i] = groupReport(reports[i]);
81
+ }
87
82
  return envelope(grouped, exit, reduceStderr(stderr, root));
88
83
  };
89
84
 
@@ -10,34 +10,51 @@ const NOTICE = [
10
10
  'rerun the same command with RESLOP_OUTPUT=raw.',
11
11
  ].join('\n');
12
12
 
13
- const addRow = (rows, key, value) => {
14
- if (value === null || value === undefined || value === '') return;
15
- rows.push([key, `${value}`]);
13
+ const SUMMARY_ROWS = 6;
14
+ const PROBLEM_FIELDS = 7;
15
+
16
+ const writeRow = (rows, index, key, value) => {
17
+ if (value === null || value === undefined || value === '') return index;
18
+ rows[index] = [key, `${value}`];
19
+ return index + 1;
16
20
  };
17
21
 
18
22
  const summaryRows = (stats) => {
19
- const rows = [];
20
- addRow(rows, 'passed', stats.passed);
21
- addRow(rows, 'failed', stats.failed);
22
- addRow(rows, 'skipped', stats.skipped);
23
- addRow(rows, 'errors', stats.errors);
24
- addRow(rows, 'warnings', stats.warnings);
25
- addRow(rows, 'duration', stats.duration);
23
+ const rows = new Array(SUMMARY_ROWS);
24
+ let index = 0;
25
+ index = writeRow(rows, index, 'passed', stats.passed);
26
+ index = writeRow(rows, index, 'failed', stats.failed);
27
+ index = writeRow(rows, index, 'skipped', stats.skipped);
28
+ index = writeRow(rows, index, 'errors', stats.errors);
29
+ index = writeRow(rows, index, 'warnings', stats.warnings);
30
+ index = writeRow(rows, index, 'duration', stats.duration);
31
+ rows.length = index;
26
32
  return rows;
27
33
  };
28
34
 
29
35
  const problemRows = (item) => {
30
- const rows = [];
31
- addRow(rows, 'severity', item.severity);
32
- addRow(rows, 'duration', item.duration);
33
- addRow(rows, 'code', item.code);
34
- addRow(rows, 'operator', item.operator);
35
- addRow(rows, 'expected', item.expected);
36
- addRow(rows, 'actual', item.actual);
37
- addRow(rows, 'message', item.message);
38
- for (const extra of item.extra) addRow(rows, extra[0], extra[1]);
39
- if (item.count > 1) addRow(rows, 'count', item.count);
40
- if (item.omitted > 0) addRow(rows, 'omitted', item.omitted);
36
+ const extra = item.extra;
37
+ let size = PROBLEM_FIELDS + extra.length;
38
+ if (item.count > 1) size += 1;
39
+ if (item.omitted > 0) size += 1;
40
+ const rows = new Array(size);
41
+ let index = 0;
42
+ index = writeRow(rows, index, 'severity', item.severity);
43
+ index = writeRow(rows, index, 'duration', item.duration);
44
+ index = writeRow(rows, index, 'code', item.code);
45
+ index = writeRow(rows, index, 'operator', item.operator);
46
+ index = writeRow(rows, index, 'expected', item.expected);
47
+ index = writeRow(rows, index, 'actual', item.actual);
48
+ index = writeRow(rows, index, 'message', item.message);
49
+ for (let i = 0; i < extra.length; i++) {
50
+ const pair = extra[i];
51
+ index = writeRow(rows, index, pair[0], pair[1]);
52
+ }
53
+ if (item.count > 1) index = writeRow(rows, index, 'count', item.count);
54
+ if (item.omitted > 0) {
55
+ index = writeRow(rows, index, 'omitted', item.omitted);
56
+ }
57
+ rows.length = index;
41
58
  return rows;
42
59
  };
43
60
 
package/lib/report-run.js CHANGED
@@ -1,12 +1,17 @@
1
1
  'use strict';
2
2
 
3
3
  const path = require('node:path');
4
- const { spawn } = require('node:child_process');
4
+ const childProcess = require('node:child_process');
5
+ const { spawn } = childProcess;
5
6
 
6
- const { spawnBase } = require('./utilities.js');
7
- const { writeLog } = require('./npm-commands.js');
8
- const { toolHint, buildDocument } = require('./report-parse.js');
9
- const { renderDocument } = require('./report-render.js');
7
+ const utilities = require('./utilities.js');
8
+ const { spawnBase } = utilities;
9
+ const npmCommands = require('./npm-commands.js');
10
+ const { writeLog } = npmCommands;
11
+ const reportParse = require('./report-parse.js');
12
+ const { toolHint, buildDocument } = reportParse;
13
+ const reportRender = require('./report-render.js');
14
+ const { renderDocument } = reportRender;
10
15
 
11
16
  const OUTPUTS = new Set(['md', 'raw']);
12
17
 
@@ -31,11 +36,8 @@ const winCommand = (program, args) => {
31
36
  };
32
37
 
33
38
  const spawnCommand = (program, args, options) => {
34
- const base = {
35
- cwd: options.cwd,
36
- env: options.env,
37
- stdio: options.stdio,
38
- };
39
+ const { cwd, env, stdio } = options;
40
+ const base = { cwd, env, stdio };
39
41
  if (process.platform !== 'win32') {
40
42
  return spawn(program, args, spawnBase(base));
41
43
  }
@@ -1,11 +1,12 @@
1
1
  'use strict';
2
2
 
3
3
  const model = require('./report-model.js');
4
- const { isPassingTest } = require('./npm-commands.js');
4
+ const npmCommands = require('./npm-commands.js');
5
+ const { isPassingTest } = npmCommands;
5
6
 
6
7
  const { summary, problem, report, userTrace } = model;
7
8
 
8
- const KNOWN = new Set([
9
+ const KNOWN = [
9
10
  'message',
10
11
  'error',
11
12
  'code',
@@ -19,7 +20,7 @@ const KNOWN = new Set([
19
20
  'location',
20
21
  'severity',
21
22
  'type',
22
- ]);
23
+ ];
23
24
 
24
25
  const show = (value) => {
25
26
  if (value === null || value === undefined) return '';
@@ -33,7 +34,7 @@ const show = (value) => {
33
34
  const extraFrom = (fields) => {
34
35
  const extra = [];
35
36
  for (const field of fields) {
36
- if (KNOWN.has(field[0])) continue;
37
+ if (KNOWN.includes(field[0])) continue;
37
38
  const value = show(field[1]);
38
39
  if (!value) continue;
39
40
  const shown = value.length > 500 ? `${value.slice(0, 500)}…` : value;
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const { parseAuditReport, parseOutdatedReport } = require('./deps.js');
3
+ const deps = require('./deps.js');
4
+ const { parseAuditReport, parseOutdatedReport } = deps;
4
5
  const model = require('./report-model.js');
5
6
 
6
7
  const { summary, problem, report, userTrace } = model;
@@ -160,21 +161,30 @@ const parsePrettier = (text, root) => {
160
161
  return report('prettier', { summary: stats, problems });
161
162
  };
162
163
 
164
+ const auditExtra = (item) => {
165
+ const size = (item.range ? 1 : 0) + (item.fix ? 1 : 0);
166
+ const extra = new Array(size);
167
+ let index = 0;
168
+ if (item.range) {
169
+ extra[index] = ['range', item.range];
170
+ index += 1;
171
+ }
172
+ if (item.fix) extra[index] = ['fix', item.fix];
173
+ return extra;
174
+ };
175
+
163
176
  const auditProblems = (text) => {
164
177
  const audit = parseAuditReport(text);
165
- const problems = [];
178
+ const problems = new Array(audit.size);
179
+ let index = 0;
166
180
  for (const item of audit.values()) {
167
- const extra = [];
168
- if (item.range) extra.push(['range', item.range]);
169
- if (item.fix) extra.push(['fix', item.fix]);
170
- problems.push(
171
- problem({
172
- severity: item.severity || 'error',
173
- name: item.name,
174
- message: item.title || '',
175
- extra,
176
- }),
177
- );
181
+ problems[index] = problem({
182
+ severity: item.severity || 'error',
183
+ name: item.name,
184
+ message: item.title || '',
185
+ extra: auditExtra(item),
186
+ });
187
+ index += 1;
178
188
  }
179
189
  return problems;
180
190
  };
@@ -285,16 +295,32 @@ const parseAuditText = (text) => {
285
295
  return report('audit', { summary: stats, problems });
286
296
  };
287
297
 
298
+ const TOOL_SLOTS = 4;
299
+
288
300
  const parseToolText = (text, root) => {
289
- const reports = [];
301
+ const reports = new Array(TOOL_SLOTS);
302
+ let index = 0;
290
303
  const eslint = parseEslintStylish(text, root);
291
- if (eslint) reports.push(eslint);
304
+ if (eslint) {
305
+ reports[index] = eslint;
306
+ index += 1;
307
+ }
292
308
  const tsc = parseTsc(text, root);
293
- if (tsc) reports.push(tsc);
309
+ if (tsc) {
310
+ reports[index] = tsc;
311
+ index += 1;
312
+ }
294
313
  const prettier = parsePrettier(text, root);
295
- if (prettier) reports.push(prettier);
314
+ if (prettier) {
315
+ reports[index] = prettier;
316
+ index += 1;
317
+ }
296
318
  const audit = parseAuditText(text);
297
- if (audit) reports.push(audit);
319
+ if (audit) {
320
+ reports[index] = audit;
321
+ index += 1;
322
+ }
323
+ reports.length = index;
298
324
  return reports;
299
325
  };
300
326
 
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const { TODO_FILE } = require('./files.js');
3
+ const files = require('./files.js');
4
+ const { TODO_FILE } = files;
4
5
 
5
6
  const flatText = (text) => `${text ?? ''}`.trim().replace(/\n/g, ' ');
6
7
 
package/lib/review.js CHANGED
@@ -3,8 +3,10 @@
3
3
  const fs = require('node:fs');
4
4
  const path = require('node:path');
5
5
 
6
- const { TODO_FILE, REVIEW_DIR } = require('./files.js');
7
- const { captureBaseline, mergeReview } = require('./review-merge.js');
6
+ const files = require('./files.js');
7
+ const { TODO_FILE, REVIEW_DIR } = files;
8
+ const reviewMerge = require('./review-merge.js');
9
+ const { captureBaseline, mergeReview } = reviewMerge;
8
10
 
9
11
  const createStore = (reviewPath, templates = []) => ({
10
12
  reviewPath,
@@ -240,6 +242,8 @@ const AGENT_INSTRUCTIONS = [
240
242
  '- If not `editing`, set `status` to `partial` if some remain, ' +
241
243
  'or `done` if all are `[x]`',
242
244
  '- Do not redo items already marked `[x]`',
245
+ '- Run the full check with `npm t`',
246
+ '- Run specific test files with `reslop t -- node --test <files>`',
243
247
  ].join('\n');
244
248
 
245
249
  const toInt = (text) => parseInt(text, 10);