markmv
Version:
TypeScript CLI for markdown file operations with intelligent link refactoring
184 lines ⢠7.07 kB
JavaScript
import { ContentSplitter } from '../core/content-splitter.js';
/**
* Execute the split command to divide a single markdown file into multiple files.
*
* This command provides intelligent splitting of markdown files using various strategies and
* automatic link refactoring. It supports:
*
* - Header-based splitting (by heading levels)
* - Size-based splitting (by file size limits)
* - Line-based splitting (at specific line numbers)
* - Manual splitting (with user guidance)
* - Automatic link updates and integrity validation
* - Custom output directory specification
*
* The split operation automatically updates all cross-references to reflect the new file structure
* and maintains link integrity throughout the project.
*
* @category Commands
*
* @example
* Header-based splitting
* ```typescript
* await splitCommand('large-document.md', {
* strategy: 'headers',
* headerLevel: 2,
* output: './sections/'
* });
* ```
*
* @example
* Size-based splitting with dry run
* ```typescript
* await splitCommand('big-file.md', {
* strategy: 'size',
* maxSize: 50, // 50KB per file
* dryRun: true,
* verbose: true
* });
* ```
*
* @example
* Line-based splitting
* ```typescript
* await splitCommand('content.md', {
* strategy: 'lines',
* splitLines: '100,250,400',
* output: './parts/'
* });
* ```
*
* @param source - Path to the markdown file to split
* @param options - Configuration options for the split operation
*
* @throws Will exit the process with code 1 if the operation fails
*/
export async function splitCommand(source, options) {
const splitter = new ContentSplitter();
// Parse split lines if provided
let splitLines;
if (options.splitLines) {
try {
splitLines = options.splitLines
.split(',')
.map((line) => Number.parseInt(line.trim(), 10))
.filter((line) => !Number.isNaN(line));
if (splitLines.length === 0) {
console.error('ā Invalid split lines format. Use comma-separated numbers like: 10,25,50');
process.exit(1);
}
}
catch (error) {
console.error('ā Failed to parse split lines:', error);
process.exit(1);
}
}
const splitOptions = {
strategy: options.strategy || 'headers',
outputDir: options.output || '.',
dryRun: options.dryRun || false,
verbose: options.verbose || false,
headerLevel: options.headerLevel || 2,
maxSize: options.maxSize || 100,
splitLines: splitLines || undefined,
};
if (options.verbose) {
console.log(`šŖ Splitting ${source} using ${splitOptions.strategy} strategy`);
if (options.dryRun) {
console.log('š Dry run mode - no changes will be made');
}
if (splitOptions.strategy === 'headers') {
console.log(`š Split on header level: ${splitOptions.headerLevel}`);
}
if (splitOptions.strategy === 'size') {
console.log(`š Maximum size per section: ${splitOptions.maxSize}KB`);
}
if (splitOptions.strategy === 'lines' && splitOptions.splitLines) {
console.log(`š Split at lines: ${splitOptions.splitLines.join(', ')}`);
}
}
try {
const result = await splitter.splitFile(source, splitOptions);
if (!result.success) {
console.error('ā Split operation failed:');
for (const error of result.errors) {
console.error(` ${error}`);
}
process.exit(1);
}
// Display results
if (options.dryRun) {
console.log('\nš Changes that would be made:');
if (result.createdFiles.length > 0) {
console.log('\nš Files that would be created:');
for (const file of result.createdFiles) {
console.log(` + ${file}`);
}
}
if (result.modifiedFiles.length > 0) {
console.log('\nš Files that would be modified:');
for (const file of result.modifiedFiles) {
console.log(` ~ ${file}`);
}
}
if (result.changes.length > 0 && options.verbose) {
console.log('\nš Changes:');
for (const change of result.changes) {
if (change.type === 'file-created') {
console.log(` + Created: ${change.filePath}`);
}
else if (change.type === 'link-updated') {
console.log(` ~ Updated links in: ${change.filePath}`);
}
}
}
console.log(`\nš Summary: Would create ${result.createdFiles.length} file(s) and modify ${result.modifiedFiles.length} file(s)`);
}
else {
console.log('ā
Split operation completed successfully!');
console.log(`š Created ${result.createdFiles.length} new file(s):`);
for (const file of result.createdFiles) {
console.log(` + ${file}`);
}
if (result.modifiedFiles.length > 0) {
console.log(`\nš Modified ${result.modifiedFiles.length} file(s):`);
for (const file of result.modifiedFiles) {
console.log(` ~ ${file}`);
}
}
if (options.verbose && result.changes.length > 0) {
const linkUpdates = result.changes.filter((c) => c.type === 'link-updated').length;
if (linkUpdates > 0) {
console.log(`\nš Updated links in ${linkUpdates} file(s)`);
}
}
}
// Display warnings
if (result.warnings.length > 0) {
console.log('\nā ļø Warnings:');
for (const warning of result.warnings) {
console.log(` ${warning}`);
}
}
// Show helpful tips
if (!options.dryRun && result.success) {
console.log('\nš” Tips:');
console.log(' ⢠Use --dry-run to preview changes before splitting');
console.log(' ⢠Use --verbose for detailed operation logs');
if (splitOptions.strategy === 'headers') {
console.log(' ⢠Use --header-level to control which headers trigger splits');
}
if (splitOptions.strategy === 'size') {
console.log(' ⢠Use --max-size to adjust the maximum file size (in KB)');
}
if (splitOptions.strategy === 'lines') {
console.log(' ⢠Use --split-lines with comma-separated line numbers (e.g., --split-lines 10,25,50)');
}
}
}
catch (error) {
console.error(`ā Unexpected error: ${error}`);
process.exit(1);
}
}
//# sourceMappingURL=split.js.map