markmv
Version:
TypeScript CLI for markdown file operations with intelligent link refactoring
236 lines • 7.89 kB
TypeScript
/**
* Represents a section of content to be joined from a markdown file.
*
* Contains all necessary information for intelligent joining including content, metadata,
* dependencies, and ordering information.
*
* @category Strategies
*/
export interface JoinSection {
/** Original file path */
filePath: string;
/** Content of the file */
content: string;
/** Frontmatter extracted from the file */
frontmatter: string | undefined;
/** Title extracted from the file (from frontmatter or first header) */
title: string | undefined;
/** Dependencies (files this content links to) */
dependencies: string[];
/** Order priority for this section */
order: number;
}
/**
* Result of a join operation containing combined content and metadata.
*
* Provides comprehensive information about the joining process including success status, conflicts,
* and any issues encountered.
*
* @category Strategies
*/
export interface JoinResult {
/** Whether the join was successful */
success: boolean;
/** Combined content */
content: string;
/** Combined frontmatter */
frontmatter: string | undefined;
/** List of files that were joined */
sourceFiles: string[];
/** Conflicts that need resolution */
conflicts: JoinConflict[];
/** Warnings */
warnings: string[];
/** Errors */
errors: string[];
/** Duplicate links that were removed */
deduplicatedLinks: string[];
}
/**
* Represents a conflict detected during the join operation.
*
* Conflicts can arise from duplicate headers, frontmatter merging issues, or content overlaps that
* require resolution.
*
* @category Strategies
*/
export interface JoinConflict {
/** Type of conflict */
type: 'frontmatter-merge' | 'duplicate-headers' | 'link-collision' | 'content-overlap';
/** Description of the conflict */
description: string;
/** Files involved in the conflict */
files: string[];
/** Suggested resolution */
resolution?: string;
/** Line numbers where conflict occurs */
lines?: number[];
}
/**
* Configuration options for join strategy operations.
*
* Controls various aspects of the joining process including ordering, content formatting, and
* conflict resolution behavior.
*
* @category Strategies
*/
export interface JoinStrategyOptions {
/** Output file path */
outputPath?: string;
/** Strategy for ordering content */
orderStrategy?: 'alphabetical' | 'manual' | 'dependency' | 'chronological';
/** Custom section separator */
separator?: string;
/** Whether to merge frontmatter */
mergeFrontmatter?: boolean;
/** Whether to deduplicate links */
deduplicateLinks?: boolean;
/** Whether to resolve header conflicts automatically */
resolveHeaderConflicts?: boolean;
/** Custom ordering for manual strategy */
customOrder?: string[];
/** Whether to preserve original file structure */
preserveStructure?: boolean;
}
/**
* Abstract base class for all join strategies.
*
* Provides common functionality for joining markdown files including frontmatter merging, conflict
* detection, and link deduplication. Concrete strategies implement specific ordering algorithms.
*
* @category Strategies
*
* @example
* Implementing a custom join strategy
* ```typescript
* class CustomJoinStrategy extends BaseJoinStrategy {
* async join(sections: JoinSection[]): Promise<JoinResult> {
* // Custom ordering logic
* const orderedSections = this.customSort(sections);
* return this.buildResult(orderedSections);
* }
* }
* ```
*/
export declare abstract class BaseJoinStrategy {
protected options: JoinStrategyOptions;
constructor(options?: JoinStrategyOptions);
abstract join(sections: JoinSection[]): Promise<JoinResult>;
/** Extract title from content (frontmatter or first header) */
protected extractTitle(content: string, frontmatter?: string): string | undefined;
/** Merge multiple frontmatter blocks */
protected mergeFrontmatter(sections: JoinSection[]): string;
/** Detect conflicts between sections */
protected detectConflicts(sections: JoinSection[]): JoinConflict[];
/** Extract all headers from content */
protected extractHeaders(content: string): string[];
/** Deduplicate links in combined content */
protected deduplicateLinks(content: string): {
content: string;
removedLinks: string[];
};
}
/**
* Join strategy that orders content based on dependency relationships.
*
* Uses topological sorting to arrange sections so that files are ordered according to their
* cross-reference dependencies. Files with no dependencies come first, followed by files that
* depend on them.
*
* @category Strategies
*
* @example
* Dependency-based joining
* ```typescript
* const strategy = new DependencyOrderJoinStrategy({
* mergeFrontmatter: true,
* deduplicateLinks: true
* });
*
* const result = await strategy.join(sections);
* if (result.success) {
* console.log(`Joined ${result.sourceFiles.length} files in dependency order`);
* }
* ```
*/
export declare class DependencyOrderJoinStrategy extends BaseJoinStrategy {
join(sections: JoinSection[]): Promise<JoinResult>;
private topologicalSort;
private buildResult;
}
/**
* Join strategy that orders content alphabetically by title or filename.
*
* Provides simple, predictable ordering by sorting files alphabetically based on their extracted
* title (from frontmatter or first header) or falling back to the filename if no title is
* available.
*
* @category Strategies
*
* @example
* Alphabetical joining
* ```typescript
* const strategy = new AlphabeticalJoinStrategy({
* separator: '\n\n<!-- Next Section -->\n\n'
* });
*
* const result = await strategy.join(sections);
* console.log(`Files ordered: ${result.sourceFiles.join(', ')}`);
* ```
*/
export declare class AlphabeticalJoinStrategy extends BaseJoinStrategy {
join(sections: JoinSection[]): Promise<JoinResult>;
private buildResult;
}
/**
* Join strategy that uses a custom manual ordering with alphabetical fallback.
*
* Allows explicit specification of file order through the customOrder option. Files not specified
* in the custom order are appended in alphabetical order. This provides maximum control over the
* final document structure.
*
* @category Strategies
*
* @example
* Manual ordering with fallback
* ```typescript
* const strategy = new ManualOrderJoinStrategy({
* customOrder: ['intro.md', 'main-content.md', 'conclusion.md'],
* mergeFrontmatter: true
* });
*
* // Files will be ordered as specified, with any others alphabetically
* const result = await strategy.join(sections);
* ```
*/
export declare class ManualOrderJoinStrategy extends BaseJoinStrategy {
join(sections: JoinSection[]): Promise<JoinResult>;
private buildResult;
}
/**
* Join strategy that orders content chronologically by date.
*
* Extracts dates from frontmatter (date, created, modified fields) or attempts to parse dates from
* filenames. Orders content from oldest to newest, providing a timeline-based organization for
* content.
*
* @category Strategies
*
* @example
* Chronological joining
* ```typescript
* const strategy = new ChronologicalJoinStrategy({
* separator: '\n\n---\n\n'
* });
*
* // Files will be ordered by date (oldest first)
* const result = await strategy.join(sections);
* console.log(`Chronological order: ${result.sourceFiles.join(' → ')}`);
* ```
*/
export declare class ChronologicalJoinStrategy extends BaseJoinStrategy {
join(sections: JoinSection[]): Promise<JoinResult>;
private extractDate;
private buildResult;
}
//# sourceMappingURL=join-strategies.d.ts.map