@wingsbutterfly/dsh-rtk 0.1.0

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 (94) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/LICENSE +21 -0
  3. package/README.md +214 -0
  4. package/README.zh.md +211 -0
  5. package/THIRD_PARTY_NOTICES.md +51 -0
  6. package/docs/assets/how-it-works.svg +47 -0
  7. package/docs/verification.md +279 -0
  8. package/lib/command.d.ts +41 -0
  9. package/lib/command.d.ts.map +1 -0
  10. package/lib/command.js +137 -0
  11. package/lib/command.js.map +1 -0
  12. package/lib/compact/build.d.ts +15 -0
  13. package/lib/compact/build.d.ts.map +1 -0
  14. package/lib/compact/build.js +140 -0
  15. package/lib/compact/build.js.map +1 -0
  16. package/lib/compact/detect.d.ts +22 -0
  17. package/lib/compact/detect.d.ts.map +1 -0
  18. package/lib/compact/detect.js +54 -0
  19. package/lib/compact/detect.js.map +1 -0
  20. package/lib/compact/dsh-result.d.ts +49 -0
  21. package/lib/compact/dsh-result.d.ts.map +1 -0
  22. package/lib/compact/dsh-result.js +84 -0
  23. package/lib/compact/dsh-result.js.map +1 -0
  24. package/lib/compact/git.d.ts +21 -0
  25. package/lib/compact/git.d.ts.map +1 -0
  26. package/lib/compact/git.js +197 -0
  27. package/lib/compact/git.js.map +1 -0
  28. package/lib/compact/index.d.ts +39 -0
  29. package/lib/compact/index.d.ts.map +1 -0
  30. package/lib/compact/index.js +236 -0
  31. package/lib/compact/index.js.map +1 -0
  32. package/lib/compact/linter.d.ts +12 -0
  33. package/lib/compact/linter.d.ts.map +1 -0
  34. package/lib/compact/linter.js +118 -0
  35. package/lib/compact/linter.js.map +1 -0
  36. package/lib/compact/search.d.ts +16 -0
  37. package/lib/compact/search.d.ts.map +1 -0
  38. package/lib/compact/search.js +67 -0
  39. package/lib/compact/search.js.map +1 -0
  40. package/lib/compact/source.d.ts +22 -0
  41. package/lib/compact/source.d.ts.map +1 -0
  42. package/lib/compact/source.js +224 -0
  43. package/lib/compact/source.js.map +1 -0
  44. package/lib/compact/test-output.d.ts +12 -0
  45. package/lib/compact/test-output.d.ts.map +1 -0
  46. package/lib/compact/test-output.js +168 -0
  47. package/lib/compact/test-output.js.map +1 -0
  48. package/lib/compact/text.d.ts +22 -0
  49. package/lib/compact/text.d.ts.map +1 -0
  50. package/lib/compact/text.js +87 -0
  51. package/lib/compact/text.js.map +1 -0
  52. package/lib/config.d.ts +243 -0
  53. package/lib/config.d.ts.map +1 -0
  54. package/lib/config.js +183 -0
  55. package/lib/config.js.map +1 -0
  56. package/lib/index.d.ts +46 -0
  57. package/lib/index.d.ts.map +1 -0
  58. package/lib/index.js +405 -0
  59. package/lib/index.js.map +1 -0
  60. package/lib/metrics.d.ts +35 -0
  61. package/lib/metrics.d.ts.map +1 -0
  62. package/lib/metrics.js +51 -0
  63. package/lib/metrics.js.map +1 -0
  64. package/lib/rtk-executable.d.ts +51 -0
  65. package/lib/rtk-executable.d.ts.map +1 -0
  66. package/lib/rtk-executable.js +75 -0
  67. package/lib/rtk-executable.js.map +1 -0
  68. package/lib/rtk-rewrite.d.ts +88 -0
  69. package/lib/rtk-rewrite.d.ts.map +1 -0
  70. package/lib/rtk-rewrite.js +150 -0
  71. package/lib/rtk-rewrite.js.map +1 -0
  72. package/lib/runtime-guard.d.ts +31 -0
  73. package/lib/runtime-guard.d.ts.map +1 -0
  74. package/lib/runtime-guard.js +32 -0
  75. package/lib/runtime-guard.js.map +1 -0
  76. package/package.json +82 -0
  77. package/scripts/link-dsh.mjs +135 -0
  78. package/src/command.ts +174 -0
  79. package/src/compact/build.ts +154 -0
  80. package/src/compact/detect.ts +54 -0
  81. package/src/compact/dsh-result.ts +99 -0
  82. package/src/compact/git.ts +209 -0
  83. package/src/compact/index.ts +284 -0
  84. package/src/compact/linter.ts +126 -0
  85. package/src/compact/search.ts +73 -0
  86. package/src/compact/source.ts +244 -0
  87. package/src/compact/test-output.ts +184 -0
  88. package/src/compact/text.ts +86 -0
  89. package/src/config.ts +263 -0
  90. package/src/index.ts +431 -0
  91. package/src/metrics.ts +84 -0
  92. package/src/rtk-executable.ts +117 -0
  93. package/src/rtk-rewrite.ts +179 -0
  94. package/src/runtime-guard.ts +44 -0
@@ -0,0 +1,224 @@
1
+ const LANGUAGE_EXTENSIONS = {
2
+ '.js': 'javascript',
3
+ '.jsx': 'javascript',
4
+ '.mjs': 'javascript',
5
+ '.cjs': 'javascript',
6
+ '.ts': 'javascript',
7
+ '.tsx': 'javascript',
8
+ '.mts': 'javascript',
9
+ '.cts': 'javascript',
10
+ '.py': 'python',
11
+ '.pyi': 'python',
12
+ '.rs': 'rust',
13
+ '.go': 'go',
14
+ '.java': 'java',
15
+ '.kt': 'java',
16
+ '.c': 'c',
17
+ '.h': 'c',
18
+ '.cc': 'c',
19
+ '.cpp': 'c',
20
+ '.hpp': 'c',
21
+ '.sh': 'shell',
22
+ '.bash': 'shell',
23
+ '.zsh': 'shell',
24
+ '.rb': 'ruby',
25
+ };
26
+ const LINE_COMMENT = {
27
+ javascript: '//',
28
+ python: '#',
29
+ rust: '//',
30
+ go: '//',
31
+ java: '//',
32
+ c: '//',
33
+ shell: '#',
34
+ ruby: '#',
35
+ unknown: undefined,
36
+ };
37
+ const BLOCK_COMMENT = {
38
+ javascript: ['/*', '*/'],
39
+ rust: ['/*', '*/'],
40
+ go: ['/*', '*/'],
41
+ java: ['/*', '*/'],
42
+ c: ['/*', '*/'],
43
+ };
44
+ /** Signature/declaration lines worth keeping when lines must be dropped. */
45
+ const SIGNATURE_PATTERN = /^(?:export\s+)?(?:async\s+)?(?:function|class|interface|type|enum|struct|impl|trait|def|fn|const|let|var|public|private|protected|static|pub|package|import|from|use|mod)\b/;
46
+ const IMPORT_PATTERN = /^(?:import|from|use|require|#include|package|mod)\b/;
47
+ /** Infer a source language from a file extension. */
48
+ export function detectLanguage(filePath) {
49
+ const lastDot = filePath.lastIndexOf('.');
50
+ if (lastDot === -1)
51
+ return 'unknown';
52
+ return LANGUAGE_EXTENSIONS[filePath.slice(lastDot).toLowerCase()] ?? 'unknown';
53
+ }
54
+ /**
55
+ * Keep the most informative `maxLines` lines of a source read.
56
+ *
57
+ * The first half of the budget is kept verbatim, after which only structural
58
+ * lines survive — signatures, imports, and lone braces — with a marker where
59
+ * body lines were dropped. This preserves the shape of the file (what is
60
+ * defined where) rather than an arbitrary prefix, which is what makes the
61
+ * result still usable for orientation.
62
+ *
63
+ * @param content - file text.
64
+ * @param maxLines - line budget.
65
+ * @returns the reduced text.
66
+ */
67
+ export function smartTruncate(content, maxLines) {
68
+ const lines = content.split('\n');
69
+ if (lines.length <= maxLines)
70
+ return content;
71
+ const result = [];
72
+ let keptLines = 0;
73
+ let skippedSection = false;
74
+ for (const line of lines) {
75
+ const trimmed = line.trim();
76
+ const isImportant = SIGNATURE_PATTERN.test(trimmed) ||
77
+ IMPORT_PATTERN.test(trimmed) ||
78
+ trimmed.startsWith('pub ') ||
79
+ trimmed.startsWith('export ') ||
80
+ trimmed === '}' ||
81
+ trimmed === '{';
82
+ if (isImportant || keptLines < maxLines / 2) {
83
+ if (skippedSection) {
84
+ result.push(` // ... ${lines.length - keptLines} lines omitted`);
85
+ skippedSection = false;
86
+ }
87
+ result.push(line);
88
+ keptLines += 1;
89
+ }
90
+ else {
91
+ skippedSection = true;
92
+ }
93
+ if (keptLines >= maxLines - 1)
94
+ break;
95
+ }
96
+ if (skippedSection || keptLines < lines.length) {
97
+ result.push(`// ... ${lines.length - keptLines} more lines (total: ${lines.length})`);
98
+ }
99
+ return result.join('\n');
100
+ }
101
+ /**
102
+ * Remove non-documentation comments and collapse blank runs.
103
+ *
104
+ * Documentation comments — line docs and block docs alike — are kept: they
105
+ * carry the contract, which is the part a reader most often needs. A line
106
+ * whose comment marker appears inside a string literal is left alone, which is
107
+ * why the check is prefix-anchored rather than a plain substring search.
108
+ */
109
+ function filterMinimal(content, language) {
110
+ const lineComment = LINE_COMMENT[language];
111
+ const block = BLOCK_COMMENT[language];
112
+ const lines = content.split('\n');
113
+ const result = [];
114
+ let inBlockComment = false;
115
+ let inDocstring = false;
116
+ for (const line of lines) {
117
+ const trimmed = line.trim();
118
+ if (inBlockComment) {
119
+ if (block !== undefined && trimmed.includes(block[1]))
120
+ inBlockComment = false;
121
+ continue;
122
+ }
123
+ if (inDocstring) {
124
+ result.push(line);
125
+ if (trimmed.endsWith('"""') || trimmed.endsWith("'''"))
126
+ inDocstring = false;
127
+ continue;
128
+ }
129
+ if (language === 'python' && (trimmed.startsWith('"""') || trimmed.startsWith("'''"))) {
130
+ result.push(line);
131
+ const isSingleLine = trimmed.length > 3 && (trimmed.endsWith('"""') || trimmed.endsWith("'''"));
132
+ if (!isSingleLine)
133
+ inDocstring = true;
134
+ continue;
135
+ }
136
+ if (block !== undefined && trimmed.startsWith(block[0]) && !trimmed.includes(block[1], block[0].length)) {
137
+ // A doc block (an extra `*` after the opener) is kept verbatim; any other
138
+ // block comment opens and hides the lines that follow it.
139
+ const afterOpener = trimmed.charAt(block[0].length);
140
+ if (afterOpener === '*') {
141
+ result.push(line);
142
+ }
143
+ else {
144
+ inBlockComment = true;
145
+ }
146
+ continue;
147
+ }
148
+ if (lineComment !== undefined && trimmed.startsWith(lineComment)) {
149
+ // Doc comments stay; ordinary comments go. A doc marker is the comment
150
+ // prefix followed by `/` (`///`) or `!` (`//!`).
151
+ const afterMarker = trimmed.charAt(lineComment.length);
152
+ if (afterMarker === '/' || afterMarker === '!')
153
+ result.push(line);
154
+ continue;
155
+ }
156
+ result.push(line);
157
+ }
158
+ const collapsed = [];
159
+ let blankRun = 0;
160
+ for (const line of result) {
161
+ if (line.trim() === '') {
162
+ blankRun++;
163
+ if (blankRun > 1)
164
+ continue;
165
+ }
166
+ else {
167
+ blankRun = 0;
168
+ }
169
+ collapsed.push(line);
170
+ }
171
+ return collapsed.join('\n');
172
+ }
173
+ /**
174
+ * Keep imports, constants, and signatures while replacing bodies with a marker.
175
+ *
176
+ * Deliberately the most lossy level: it answers "what is in this file" without
177
+ * pretending to answer "how does it work".
178
+ */
179
+ function filterAggressive(content, language) {
180
+ const lines = content.split('\n');
181
+ const result = [];
182
+ let bodyDepth = 0;
183
+ let skipped = 0;
184
+ for (const line of lines) {
185
+ const trimmed = line.trim();
186
+ const isStructural = IMPORT_PATTERN.test(trimmed) ||
187
+ SIGNATURE_PATTERN.test(trimmed) ||
188
+ /^[A-Z_][A-Z0-9_]*\s*=/.test(trimmed) ||
189
+ trimmed === '}' ||
190
+ trimmed === '{' ||
191
+ trimmed === '';
192
+ if (isStructural) {
193
+ if (skipped > 0) {
194
+ result.push(` // ... ${skipped} implementation lines omitted`);
195
+ skipped = 0;
196
+ }
197
+ result.push(line);
198
+ bodyDepth = trimmed.endsWith('{') || trimmed.endsWith(':') ? bodyDepth + 1 : Math.max(0, bodyDepth - 1);
199
+ continue;
200
+ }
201
+ if (bodyDepth > 0) {
202
+ skipped++;
203
+ continue;
204
+ }
205
+ result.push(line);
206
+ }
207
+ if (skipped > 0)
208
+ result.push(` // ... ${skipped} implementation lines omitted`);
209
+ return result.join('\n');
210
+ }
211
+ /** Apply the configured source-filtering level. */
212
+ export function filterSourceCode(content, language, level) {
213
+ switch (level) {
214
+ case 'none':
215
+ return content;
216
+ case 'minimal':
217
+ return filterMinimal(content, language);
218
+ case 'aggressive':
219
+ return filterAggressive(content, language);
220
+ default:
221
+ return content;
222
+ }
223
+ }
224
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../../src/compact/source.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /** Whether the command is a test runner this module understands. */
2
+ export declare function isTestCommand(command: string | undefined | null): boolean;
3
+ /**
4
+ * Collapse test-runner output to a pass/fail/skip summary plus the first few
5
+ * failure excerpts.
6
+ *
7
+ * When no runner summary line can be parsed, per-line pass/fail markers are
8
+ * counted instead, so an unusual runner still yields a usable shape rather than
9
+ * a bare "0 passed".
10
+ */
11
+ export declare function aggregateTestOutput(output: string, command: string | undefined | null): string | null;
12
+ //# sourceMappingURL=test-output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-output.d.ts","sourceRoot":"","sources":["../../src/compact/test-output.ts"],"names":[],"mappings":"AAsFA,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAEzE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAoFrG"}
@@ -0,0 +1,168 @@
1
+ import { matchesCommandPatterns } from './detect.js';
2
+ const TEST_COMMAND_PATTERNS = [
3
+ /^npm\s+test\b/,
4
+ /^pnpm\s+test\b/,
5
+ /^yarn\s+test\b/,
6
+ /^bun\s+test\b/,
7
+ /^cargo\s+test\b/,
8
+ /^go\s+test\b/,
9
+ /^pytest\b/,
10
+ /^python\s+-m\s+pytest\b/,
11
+ /^(?:pnpm\s+)?(?:npx\s+)?vitest\b/,
12
+ /^(?:npx\s+)?jest\b/,
13
+ /^mocha\b/,
14
+ /^ava\b/,
15
+ /^tap\b/,
16
+ /^node\s+--test\b/,
17
+ ];
18
+ const TEST_RESULT_PATTERNS = [
19
+ /test result:\s*(\w+)\.\s*(\d+)\s*passed;\s*(\d+)\s*failed;/,
20
+ /#\s*tests\s+(\d+)\s*$/m,
21
+ /(\d+)\s*passed(?:,\s*(\d+)\s*failed)?(?:,\s*(\d+)\s*skipped)?/i,
22
+ /(\d+)\s*pass(?:,\s*(\d+)\s*fail)?(?:,\s*(\d+)\s*skip)?/i,
23
+ /tests?:\s*(\d+)\s*passed(?:,\s*(\d+)\s*failed)?(?:,\s*(\d+)\s*skipped)?/i,
24
+ ];
25
+ const FAILURE_START_PATTERNS = [
26
+ /^FAIL\s+/,
27
+ /^FAILED\s+/,
28
+ /^\s*●\s+/,
29
+ // U+2715 and U+2716 look alike and are both in the wild; `node --test` uses
30
+ // the heavy form, which a pattern written for the light one silently misses.
31
+ /^\s*[✕✖]\s+/,
32
+ /^\s*not ok\s+/,
33
+ /test\s+\w+\s+\.\.\.\s*FAILED/,
34
+ /thread\s+'\w+'\s+panicked/,
35
+ ];
36
+ const FALLBACK_PASS_PATTERN = /(?:\b(?:ok|PASS)\b|[✓✔])/;
37
+ const FALLBACK_FAIL_PATTERN = /(?:\b(?:FAIL|fail)\b|[✗✕✖])/;
38
+ const MAX_FAILURES = 5;
39
+ const MAX_FAILURE_LINES = 4;
40
+ const BLANKS_TO_CLOSE_BLOCK = 2;
41
+ /**
42
+ * Read `node --test`'s tallies, which it prints on separate lines:
43
+ * `ℹ tests 2` / `ℹ pass 1` / `ℹ fail 1`.
44
+ *
45
+ * These are authoritative — the runner counted them — so they are preferred
46
+ * over every scraped-marker fallback.
47
+ */
48
+ function extractNodeTestStats(output) {
49
+ const passed = output.match(/^\u2139\s*pass\s+(\d+)/m);
50
+ if (passed === null)
51
+ return undefined;
52
+ return {
53
+ passed: Number.parseInt(passed[1] ?? '0', 10) || 0,
54
+ failed: Number.parseInt(output.match(/^\u2139\s*fail\s+(\d+)/m)?.[1] ?? '0', 10) || 0,
55
+ skipped: Number.parseInt(output.match(/^\u2139\s*skipped\s+(\d+)/m)?.[1] ?? '0', 10) || 0,
56
+ };
57
+ }
58
+ function extractTestStats(output) {
59
+ const fromNodeTest = extractNodeTestStats(output);
60
+ if (fromNodeTest !== undefined)
61
+ return fromNodeTest;
62
+ for (const pattern of TEST_RESULT_PATTERNS) {
63
+ const match = output.match(pattern);
64
+ if (!match)
65
+ continue;
66
+ return {
67
+ passed: Number.parseInt(match[1] ?? '0', 10) || 0,
68
+ failed: Number.parseInt(match[2] ?? '0', 10) || 0,
69
+ skipped: Number.parseInt(match[3] ?? '0', 10) || 0,
70
+ };
71
+ }
72
+ return {};
73
+ }
74
+ /** Whether the command is a test runner this module understands. */
75
+ export function isTestCommand(command) {
76
+ return matchesCommandPatterns(command, TEST_COMMAND_PATTERNS);
77
+ }
78
+ /**
79
+ * Collapse test-runner output to a pass/fail/skip summary plus the first few
80
+ * failure excerpts.
81
+ *
82
+ * When no runner summary line can be parsed, per-line pass/fail markers are
83
+ * counted instead, so an unusual runner still yields a usable shape rather than
84
+ * a bare "0 passed".
85
+ */
86
+ export function aggregateTestOutput(output, command) {
87
+ if (!isTestCommand(command))
88
+ return null;
89
+ const lines = output.split('\n');
90
+ const summary = { passed: 0, failed: 0, skipped: 0, failures: [] };
91
+ const stats = extractTestStats(output);
92
+ summary.passed = stats.passed ?? 0;
93
+ summary.failed = stats.failed ?? 0;
94
+ summary.skipped = stats.skipped ?? 0;
95
+ if (summary.passed === 0 && summary.failed === 0) {
96
+ for (const line of lines) {
97
+ if (FALLBACK_PASS_PATTERN.test(line))
98
+ summary.passed++;
99
+ if (FALLBACK_FAIL_PATTERN.test(line))
100
+ summary.failed++;
101
+ }
102
+ }
103
+ if (summary.failed > 0) {
104
+ let inFailure = false;
105
+ let currentFailure = [];
106
+ let blankCount = 0;
107
+ for (const line of lines) {
108
+ if (FAILURE_START_PATTERNS.some((pattern) => pattern.test(line))) {
109
+ if (inFailure && currentFailure.length > 0)
110
+ summary.failures.push(currentFailure.join('\n'));
111
+ inFailure = true;
112
+ currentFailure = [line];
113
+ blankCount = 0;
114
+ continue;
115
+ }
116
+ if (!inFailure)
117
+ continue;
118
+ if (line.trim() === '') {
119
+ blankCount++;
120
+ if (blankCount >= BLANKS_TO_CLOSE_BLOCK && currentFailure.length > 3) {
121
+ summary.failures.push(currentFailure.join('\n'));
122
+ inFailure = false;
123
+ currentFailure = [];
124
+ }
125
+ else {
126
+ currentFailure.push(line);
127
+ }
128
+ continue;
129
+ }
130
+ if (line.match(/^\s/) || line.match(/^-/)) {
131
+ currentFailure.push(line);
132
+ blankCount = 0;
133
+ continue;
134
+ }
135
+ summary.failures.push(currentFailure.join('\n'));
136
+ inFailure = false;
137
+ currentFailure = [];
138
+ }
139
+ if (inFailure && currentFailure.length > 0)
140
+ summary.failures.push(currentFailure.join('\n'));
141
+ }
142
+ const result = ['Test Results:'];
143
+ result.push(` PASS: ${summary.passed} passed`);
144
+ if (summary.failed > 0)
145
+ result.push(` FAIL: ${summary.failed} failed`);
146
+ if (summary.skipped > 0)
147
+ result.push(` SKIP: ${summary.skipped} skipped`);
148
+ if (summary.failed > 0 && summary.failures.length > 0) {
149
+ result.push('\n Failures:');
150
+ for (const failure of summary.failures.slice(0, MAX_FAILURES)) {
151
+ const failureLines = failure.split('\n');
152
+ const firstLine = failureLines[0] ?? '';
153
+ result.push(` - ${firstLine.slice(0, 70)}${firstLine.length > 70 ? '...' : ''}`);
154
+ for (const detailLine of failureLines.slice(1, MAX_FAILURE_LINES)) {
155
+ if (detailLine.trim())
156
+ result.push(` ${detailLine.slice(0, 65)}${detailLine.length > 65 ? '...' : ''}`);
157
+ }
158
+ if (failureLines.length > MAX_FAILURE_LINES) {
159
+ result.push(` ... (${failureLines.length - MAX_FAILURE_LINES} more lines)`);
160
+ }
161
+ }
162
+ if (summary.failures.length > MAX_FAILURES) {
163
+ result.push(` ... and ${summary.failures.length - MAX_FAILURES} more failures`);
164
+ }
165
+ }
166
+ return result.join('\n');
167
+ }
168
+ //# sourceMappingURL=test-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-output.js","sourceRoot":"","sources":["../../src/compact/test-output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /** Text primitives shared by every compaction technique. */
2
+ /**
3
+ * Remove terminal color and formatting sequences.
4
+ *
5
+ * Covered: CSI (`ESC [ … letter`) and OSC (`ESC ] … BEL|ST`). The cheap guard
6
+ * matters because this runs on every text result and most have no escape byte
7
+ * at all.
8
+ */
9
+ export declare function stripAnsi(text: string): string;
10
+ /** Keep at most `maxLength` characters, marking elision with a trailing ellipsis. */
11
+ export declare function truncate(text: string, maxLength: number): string;
12
+ /** Number of lines, counting a trailing newline as a terminator rather than a new line. */
13
+ export declare function countLines(text: string): number;
14
+ /**
15
+ * Shorten a path to `maxLength` by eliding its middle segments.
16
+ *
17
+ * The last segment survives because it is the part a reader needs; earlier
18
+ * candidates keep one parent directory when the budget allows, which is what
19
+ * disambiguates two files with the same basename.
20
+ */
21
+ export declare function compactPath(path: string, maxLength: number): string;
22
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/compact/text.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAM5D;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG9C;AAED,qFAAqF;AACrF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAIhE;AAED,2FAA2F;AAC3F,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/C;AAiBD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CA8BnE"}
@@ -0,0 +1,87 @@
1
+ /** Text primitives shared by every compaction technique. */
2
+ const ANSI_CSI = /\u001b\[[0-9;]*[a-zA-Z]/g;
3
+ const ANSI_OSC_BEL = /\u001b\][0-9;]*(?:\u0007|\u001b\\)/g;
4
+ const ANSI_OSC_ST = /\u001b\][^\u0007\u001b]*(?:\u0007|\u001b\\)/g;
5
+ /**
6
+ * Remove terminal color and formatting sequences.
7
+ *
8
+ * Covered: CSI (`ESC [ … letter`) and OSC (`ESC ] … BEL|ST`). The cheap guard
9
+ * matters because this runs on every text result and most have no escape byte
10
+ * at all.
11
+ */
12
+ export function stripAnsi(text) {
13
+ if (!text.includes('\u001b'))
14
+ return text;
15
+ return text.replace(ANSI_CSI, '').replace(ANSI_OSC_BEL, '').replace(ANSI_OSC_ST, '');
16
+ }
17
+ /** Keep at most `maxLength` characters, marking elision with a trailing ellipsis. */
18
+ export function truncate(text, maxLength) {
19
+ if (text.length <= maxLength)
20
+ return text;
21
+ if (maxLength < 3)
22
+ return '...';
23
+ return `${text.slice(0, maxLength - 3)}...`;
24
+ }
25
+ /** Number of lines, counting a trailing newline as a terminator rather than a new line. */
26
+ export function countLines(text) {
27
+ if (!text)
28
+ return 0;
29
+ const normalized = text.endsWith('\n') ? text.slice(0, -1) : text;
30
+ if (!normalized)
31
+ return 1;
32
+ return normalized.split('\n').length;
33
+ }
34
+ function detectPathSeparator(path) {
35
+ return path.includes('\\') && !path.includes('/') ? '\\' : '/';
36
+ }
37
+ function detectPathPrefix(path, separator) {
38
+ if (/^[A-Za-z]:[\\/]/.test(path))
39
+ return `${path.slice(0, 2)}${separator}`;
40
+ if (path.startsWith('\\\\') || path.startsWith('//')) {
41
+ const parts = path.split(/[\\/]+/).filter((part) => part.length > 0);
42
+ if (parts.length >= 2)
43
+ return `${separator}${separator}${parts[0]}${separator}${parts[1]}${separator}`;
44
+ return `${separator}${separator}`;
45
+ }
46
+ if (path.startsWith('/') || path.startsWith('\\'))
47
+ return separator;
48
+ return '';
49
+ }
50
+ /**
51
+ * Shorten a path to `maxLength` by eliding its middle segments.
52
+ *
53
+ * The last segment survives because it is the part a reader needs; earlier
54
+ * candidates keep one parent directory when the budget allows, which is what
55
+ * disambiguates two files with the same basename.
56
+ */
57
+ export function compactPath(path, maxLength) {
58
+ if (path.length <= maxLength)
59
+ return path;
60
+ if (maxLength < 2)
61
+ return path.slice(0, maxLength);
62
+ const separator = detectPathSeparator(path);
63
+ const prefix = detectPathPrefix(path, separator);
64
+ const segments = path
65
+ .slice(prefix.length)
66
+ .split(/[\\/]+/)
67
+ .filter((segment) => segment.length > 0);
68
+ const lastSegment = segments[segments.length - 1] ?? path.slice(-(maxLength - 1));
69
+ const previousSegment = segments[segments.length - 2];
70
+ const tail = [previousSegment, lastSegment].filter((segment) => segment !== undefined);
71
+ const join = (head, parts) => {
72
+ const body = parts.join(separator);
73
+ return head ? `${head}${body}` : body;
74
+ };
75
+ const candidates = [
76
+ join(prefix, ['…', ...tail]),
77
+ join('', ['…', ...tail]),
78
+ join('', ['…', lastSegment]),
79
+ `…${path.slice(-(maxLength - 1))}`,
80
+ ];
81
+ for (const candidate of candidates) {
82
+ if (candidate.length <= maxLength)
83
+ return candidate;
84
+ }
85
+ return `…${lastSegment.slice(-(maxLength - 1))}`;
86
+ }
87
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/compact/text.ts"],"names":[],"mappings":"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"}