Skip to content

Commit 76dc715

Browse files
committed
refactor: streamline stdin handling in CLI and enhance file path resolution
- Updated CLI to always attempt conversion of stdin content, with error handling for empty input. - Resolved source directory paths to absolute in `convertDirectory` for consistent file handling. - Adjusted test cases to reflect changes in stdin processing and ensure accurate error reporting.
1 parent 952877e commit 76dc715

File tree

3 files changed

+53
-38
lines changed

3 files changed

+53
-38
lines changed

src/cli.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -130,19 +130,14 @@ program
130130
chunks.push(chunk);
131131
}
132132
const stdinContent = Buffer.concat(chunks).toString('utf-8');
133-
if (stdinContent) {
134-
// Call convertString with forceFormat as the 3rd argument
135-
const convertedContent = convertString(
136-
stdinContent,
137-
direction,
138-
forceFormat
139-
);
140-
process.stdout.write(convertedContent);
141-
} else {
142-
// Handle empty stdin case if necessary, maybe show help?
143-
program.help({ error: true }); // Show help if stdin is empty
144-
// NOTE: program.help({ error: true }) should exit, but we add else for clarity
145-
}
133+
// Always attempt conversion. convertString will throw E01 for empty string,
134+
// which will be caught below and handled by exitWithError.
135+
const convertedContent = convertString(
136+
stdinContent,
137+
direction,
138+
forceFormat
139+
);
140+
process.stdout.write(convertedContent);
146141
} catch (e) {
147142
// Handle errors during stdin read or conversion
148143
if (e instanceof ConversionError) {

src/index.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import { mkdir, readFile, stat, writeFile } from 'node:fs/promises';
2-
import { basename, dirname, extname, join, parse, relative } from 'node:path';
2+
import {
3+
basename,
4+
dirname,
5+
extname,
6+
join,
7+
parse,
8+
relative,
9+
resolve,
10+
} from 'node:path';
311
import fastGlob from 'fast-glob';
412
import { convertRuleContent, detectFormat } from './mapper';
513
import {
@@ -230,18 +238,21 @@ export async function convertDirectory(
230238
}
231239

232240
// Glob for both .md and .mdc files
233-
const globPattern = join(sourceDir, '**/*.{md,mdc}');
241+
const absoluteSourceDir = resolve(sourceDir); // Resolve to absolute path
242+
const globPattern = join(absoluteSourceDir, '**/*.{md,mdc}');
234243
const potentialFiles = await fastGlob(globPattern, {
235244
onlyFiles: true,
236245
dot: true,
246+
absolute: true, // Ensure fastGlob returns absolute paths
237247
});
238248

239249
if (potentialFiles.length === 0) {
240250
return [];
241251
}
242252

243253
for (const sourceFilePath of potentialFiles) {
244-
const relativePath = relative(sourceDir, sourceFilePath);
254+
// sourceFilePath is now absolute, ensure relativePath calculation is correct
255+
const relativePath = relative(absoluteSourceDir, sourceFilePath);
245256
const parsedSourcePath = parse(sourceFilePath);
246257

247258
let fileSpecificDirection: ConversionDirection | undefined =

test/index.test.ts

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -517,38 +517,42 @@ describe('CLI (cuws)', () => {
517517
});
518518

519519
it('should convert stdin to stdout', async () => {
520-
// Use exec directly for piping stdin
521-
const command = `echo "${windsurfManualContent.replace(/"/g, '\\"')}" | node "${path.resolve(cliPath)}" -r`;
522520
const { stdout, stderr, exitCode } = await new Promise<{
523521
stdout: string;
524522
stderr: string;
525523
exitCode: number | null;
526524
}>((resolve) => {
527-
const child = exec(command);
525+
const child = exec(`node "${path.resolve(cliPath)}" -r`, {
526+
env: { ...process.env },
527+
});
528528
let stdoutData = '';
529529
let stderrData = '';
530+
530531
child.stdout?.on('data', (data) => {
531532
stdoutData += data;
532533
});
533534
child.stderr?.on('data', (data) => {
534535
stderrData += data;
535536
});
536-
child.on('close', (code) =>
537-
resolve({ stdout: stdoutData, stderr: stderrData, exitCode: code })
538-
);
539-
child.on('error', (err) =>
537+
child.on('close', (code) => {
538+
resolve({ stdout: stdoutData, stderr: stderrData, exitCode: code });
539+
});
540+
child.on('error', (err) => {
540541
resolve({
541542
stdout: stdoutData,
542543
stderr: stderrData + err.message,
543544
exitCode: 1,
544-
})
545-
);
545+
});
546+
});
547+
548+
// Write to stdin
549+
child.stdin?.write(windsurfManualContent);
550+
child.stdin?.end();
546551
});
547552

548553
expect(stderr).toBe('');
549554
expect(exitCode).toBe(0);
550-
// Trim stdout because echo might add a newline
551-
expect(stdout.trim()).toEqual(expectedCursorManualContent.trim()); // Use expectedCursorManualContent
555+
expect(stdout.trim()).toEqual(expectedCursorManualContent.trim());
552556
});
553557

554558
it('should convert file input to stdout (using -i without -o)', async () => {
@@ -564,35 +568,40 @@ describe('CLI (cuws)', () => {
564568
});
565569

566570
it('should show help if stdin is empty', async () => {
567-
// Use exec directly for piping stdin
568-
const command = `echo "" | node "${path.resolve(cliPath)}" -r`;
569-
const { stderr, exitCode } = await new Promise<{
571+
const { stdout, stderr, exitCode } = await new Promise<{
570572
stdout: string;
571573
stderr: string;
572574
exitCode: number | null;
573575
}>((resolve) => {
574-
const child = exec(command);
576+
const child = exec(`node "${path.resolve(cliPath)}" -r`, {
577+
env: { ...process.env },
578+
});
575579
let stdoutData = '';
576580
let stderrData = '';
581+
577582
child.stdout?.on('data', (data) => {
578583
stdoutData += data;
579584
});
580585
child.stderr?.on('data', (data) => {
581586
stderrData += data;
582587
});
583-
child.on('close', (code) =>
584-
resolve({ stdout: stdoutData, stderr: stderrData, exitCode: code })
585-
);
586-
child.on('error', (err) =>
588+
child.on('close', (code) => {
589+
resolve({ stdout: stdoutData, stderr: stderrData, exitCode: code });
590+
});
591+
child.on('error', (err) => {
587592
resolve({
588593
stdout: stdoutData,
589594
stderr: stderrData + err.message,
590595
exitCode: 1,
591-
})
592-
);
596+
});
597+
});
598+
599+
// Write empty string to stdin and close it
600+
child.stdin?.write('');
601+
child.stdin?.end();
593602
});
594603

595-
// Expect the specific error message printed by program.help({ error: true })
604+
// Expect the specific error message
596605
expect(stderr).toContain(
597606
'Error (E01): Could not determine source format.'
598607
);

0 commit comments

Comments
 (0)