Skip to content

Commit 0cf0cdd

Browse files
committed
feat: add configurable preview length and character filtering
- Add previewLength config option (default: 80) - Strip non-alphanumeric chars except spaces, dots, hyphens - Pass config.previewLength to getReadmePreview function - Add previewLength to default config creation - Add 2 tests for character filtering and custom length Example config: { "previewLength": 50 // Shorter previews } All 31 tests passing ✅
1 parent 408f9b7 commit 0cf0cdd

File tree

3 files changed

+40
-4
lines changed

3 files changed

+40
-4
lines changed

index.mjs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ if (process.argv.includes('--init')) {
5555
execute: 'code .',
5656
execute2: 'zsh',
5757
execute3: '[ -f .nvmrc ] && . ~/.nvm/nvm.sh && nvm use; code .',
58+
previewLength: 80
5859
};
5960
try {
6061
fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
@@ -195,7 +196,7 @@ const main = async () => {
195196
if (process.argv.includes('--list')) {
196197
gitRepos.forEach((repo, index) => {
197198
const relativePath = path.relative(BASE_DIR, repo) || path.basename(repo);
198-
const preview = getReadmePreview(repo);
199+
const preview = getReadmePreview(repo, config.previewLength || 80);
199200
const display = preview ? `${relativePath} - ${preview}` : relativePath;
200201
console.log(`${index}: ${display}`);
201202
});
@@ -225,7 +226,7 @@ const main = async () => {
225226
// Interactive mode
226227
const choices = gitRepos.map((repo) => {
227228
const name = path.relative(BASE_DIR, repo) || path.basename(repo);
228-
const preview = getReadmePreview(repo);
229+
const preview = getReadmePreview(repo, config.previewLength || 80);
229230
return {
230231
name: preview ? `${name} - ${preview}` : name,
231232
value: repo,

src/utils.mjs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const getExecuteCommand = (args, config) => {
4141
};
4242

4343
// Get README preview for repository
44-
export const getReadmePreview = (repoPath) => {
44+
export const getReadmePreview = (repoPath, maxLength = 80) => {
4545
const readmeFiles = ['README.md', 'readme.md', 'README.txt', 'readme.txt'];
4646

4747
for (const filename of readmeFiles) {
@@ -73,7 +73,10 @@ export const getReadmePreview = (repoPath) => {
7373
// Strip markdown links: [text](url) -> text
7474
firstLine = firstLine.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1');
7575

76-
return firstLine.length > 80 ? firstLine.substring(0, 77) + '...' : firstLine;
76+
// Strip non-alphanumeric chars except spaces, dots, hyphens
77+
firstLine = firstLine.replace(/[^a-zA-Z0-9\s.-]/g, '');
78+
79+
return firstLine.length > maxLength ? firstLine.substring(0, maxLength - 3) + '...' : firstLine;
7780
}
7881
} catch {
7982
// Ignore errors and continue

test/utils.test.mjs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,35 @@ test('getReadmePreview - strips markdown links', () => {
162162
if (fs.existsSync(tempDir)) fs.rmSync(tempDir, { recursive: true });
163163
}
164164
});
165+
test('getReadmePreview - strips non-alphanumeric characters', () => {
166+
const tempDir = path.join(process.cwd(), 'temp-chars-readme');
167+
const readmePath = path.join(tempDir, 'README.md');
168+
169+
try {
170+
fs.mkdirSync(tempDir, { recursive: true });
171+
fs.writeFileSync(readmePath, 'A tool with @#$%^&*()+={}[]|\\:";\'<>?,/ special chars!');
172+
173+
const preview = getReadmePreview(tempDir);
174+
assert.strictEqual(preview, 'A tool with special chars');
175+
} finally {
176+
if (fs.existsSync(readmePath)) fs.unlinkSync(readmePath);
177+
if (fs.existsSync(tempDir)) fs.rmSync(tempDir, { recursive: true });
178+
}
179+
});
180+
181+
test('getReadmePreview - respects custom maxLength', () => {
182+
const tempDir = path.join(process.cwd(), 'temp-length-readme');
183+
const readmePath = path.join(tempDir, 'README.md');
184+
185+
try {
186+
fs.mkdirSync(tempDir, { recursive: true });
187+
fs.writeFileSync(readmePath, 'This is a very long description that should be truncated');
188+
189+
const preview = getReadmePreview(tempDir, 20);
190+
assert(preview.length <= 20);
191+
assert(preview.endsWith('...'));
192+
} finally {
193+
if (fs.existsSync(readmePath)) fs.unlinkSync(readmePath);
194+
if (fs.existsSync(tempDir)) fs.rmSync(tempDir, { recursive: true });
195+
}
196+
});

0 commit comments

Comments
 (0)