UNPKG

legal-markdown-js

Version:

Node.js implementation of LegalMarkdown for processing legal documents with markdown and YAML - Complete feature parity with Ruby version

232 lines 9.86 kB
/** * Legal Markdown Processor with Remark Pipeline (Phase 3: AST Processing) * * This module provides a comprehensive processor for Legal Markdown documents * using the remark ecosystem. It combines multiple remark plugins to provide * AST-based processing that avoids text contamination issues. * * Processing Flow: * - Phase 1: Context building (YAML parsing, metadata merging) - done in context-builder.ts * - Phase 2: String transformations (field normalization, clauses, loops) - done in string-transformations.ts * - Phase 3: AST processing (THIS MODULE - remark plugins) * - Phase 4: Format generation (HTML, PDF) - done in format-generator.ts * * Features: * - Complete remark pipeline with all Legal Markdown plugins * - Field tracking integration with automatic clearing * - Cross-reference processing with section numbering * - Metadata extraction and processing * - Comprehensive error handling and debugging * - Compatible with existing Legal Markdown API * * @example * ```typescript * import { processLegalMarkdownWithRemark } from './legal-markdown-processor.js'; * * const result = await processLegalMarkdownWithRemark(content, { * basePath: './documents', * enableFieldTracking: true, * debug: true * }); * * console.log(result.content); // Processed markdown * console.log(result.metadata); // Extracted metadata * console.log(result.fieldReport); // Field tracking report * ``` * * @see docs/architecture/03_processing_pipeline.md * @see docs/architecture/string-transformations.md * @module */ import type { Root } from 'mdast'; import type { MarkdownString } from '../../types/content-formats.js'; import type { YamlValue } from '../../types/index.js'; /** * Pre-process content to escape underscores inside {{}} to prevent * markdown parser from interpreting them as italic delimiters * * **Problem**: Field names with underscores like `{{counterparty.legal_name}}` * would be parsed by remark as `{{counterparty.legal*name}}` because markdown * treats `_text_` as emphasis (converted to `*text*` during parsing). * * **Solution**: Escape underscores to `\_` before markdown parsing. The escaped * underscores are later unescaped in: * - `remarkTemplateFields` (src/plugins/remark/template-fields.ts) * - `parseMarkdownInlineFormatting` (src/plugins/remark/legal-headers-parser.ts) * * @see https://github.com/petalo/legal-markdown-js/issues/139 * @see src/plugins/remark/template-fields.ts - Unescapes underscores during field extraction * @see src/plugins/remark/legal-headers-parser.ts - Excludes template fields from emphasis parsing * * @param content - Raw markdown content * @returns Content with underscores escaped for legacy syntax, unchanged for Handlebars * * @example * ```typescript * // Legacy syntax - escapes underscores * escapeTemplateUnderscores('{{legal_name}}') // => '{{legal\_name}}' * * // Handlebars syntax - no escaping needed * escapeTemplateUnderscores('{{titleCase section_name}}') // => '{{titleCase section_name}}' * escapeTemplateUnderscores('{{#if test}}') // => '{{#if test}}' (unchanged) * ``` */ declare function escapeTemplateUnderscores(content: string): string; /** * Configuration options for the Legal Markdown processor * @interface LegalMarkdownProcessorOptions */ export interface LegalMarkdownProcessorOptions { /** Base path for resolving relative imports */ basePath?: string; /** Enable field tracking and highlighting */ enableFieldTracking?: boolean; /** Use AST-first field tracking pipeline */ astFieldTracking?: boolean; /** Highlight winner branch content for conditional blocks */ logicBranchHighlighting?: boolean; /** Enable debug logging */ debug?: boolean; /** Validate plugin execution order and log warnings */ validatePluginOrder?: boolean; /** Additional metadata to merge with document metadata */ additionalMetadata?: Record<string, YamlValue>; /** Custom field patterns for field tracking */ fieldPatterns?: string[]; /** Disable specific processing steps */ disableCrossReferences?: boolean; disableFieldTracking?: boolean; /** Metadata export options */ exportMetadata?: boolean; exportFormat?: 'yaml' | 'json'; exportPath?: string; /** Processing flags (for compatibility with legacy processor) */ yamlOnly?: boolean; noHeaders?: boolean; noClauses?: boolean; noReferences?: boolean; noImports?: boolean; noMixins?: boolean; noReset?: boolean; noIndent?: boolean; throwOnYamlError?: boolean; /** Whether to add HTML comments showing import boundaries in output */ importTracing?: boolean; /** Whether to validate type compatibility during frontmatter merging */ validateImportTypes?: boolean; /** Whether to log detailed frontmatter merge operations */ logImportOperations?: boolean; /** Disable automatic frontmatter merging from imported files */ disableFrontmatterMerge?: boolean; } /** * Result from Legal Markdown processing * @interface LegalMarkdownProcessorResult */ export interface LegalMarkdownProcessorResult { /** Processed markdown content (always Markdown format, never HTML) */ content: MarkdownString; /** Extracted and processed metadata */ metadata: Record<string, YamlValue>; /** Cached AST for Phase 3 format generation (optional) */ ast?: Root; /** Array of exported metadata files */ exportedFiles?: string[]; /** Field tracking report (if enabled) */ fieldReport?: { totalFields: number; uniqueFields: number; fields: Map<string, import('../../extensions/tracking/field-tracker.js').TrackedField>; }; /** Processing statistics and debugging info */ stats: { processingTime: number; pluginsUsed: string[]; crossReferencesFound: number; fieldsTracked: number; }; /** Any warnings or non-fatal errors encountered */ warnings: string[]; } /** * Create a configured remark processor for Legal Markdown * * This function assembles a unified processor with all the necessary remark plugins * for Legal Markdown processing. Plugins are added in a specific order to ensure * proper processing dependencies: * * **CRITICAL PLUGIN ORDER:** * 1. Imports - MUST be first to load all content before any transformation * 2. Legal Headers Parser - MUST be after imports to convert headers in imported files * 3. Mixins - Content expansion before other processing * 4. Clauses - Conditional content * 5. Template fields - Field processing and tracking * 6. Cross-references - Reference resolution * 7. Headers - Final structure processing and numbering * * **WARNING:** Changing this order can break functionality: * - If Legal Headers Parser runs before Imports, headers in imported files won't be converted * - If Cross-references runs before Headers, section numbering won't be available * - If Mixins runs before Imports, variable expansion won't work for imported content * * @param metadata - Document metadata from YAML frontmatter and additional sources * @param options - Configuration options for processing * @returns Configured unified processor ready for content processing * @internal */ declare function createLegalMarkdownProcessor(metadata: Record<string, YamlValue>, options: LegalMarkdownProcessorOptions): import("unified").Processor<Root, undefined, undefined, undefined, undefined>; /** * Process Legal Markdown content using remark pipeline * * This is the main entry point for remark-based Legal Markdown processing. * It provides a complete AST-based processing pipeline with: * - YAML frontmatter parsing and metadata extraction * - Template field processing with nested helper support * - Cross-reference resolution and section numbering * - Field tracking for document highlighting * - Import processing for modular documents * - Comprehensive error handling and debugging * * @param content - Raw Legal Markdown content to process * @param options - Processing options and configuration * @returns Promise resolving to processed content, metadata, and statistics * * @example * ```typescript * const result = await processLegalMarkdownWithRemark(markdownContent, { * enableFieldTracking: true, * basePath: './templates', * debug: true * }); * * console.log(result.content); // Processed markdown * console.log(result.stats.fieldsTracked); // Number of tracked fields * ``` */ export declare function processLegalMarkdown(content: string, options?: LegalMarkdownProcessorOptions): Promise<LegalMarkdownProcessorResult>; /** * Create a pre-configured processor instance for reuse * * This factory function creates a reusable processor instance with pre-configured * options. Useful for batch processing multiple documents with the same settings. * * @param options - Base configuration options for all processing operations * @returns Object with async and sync processing methods * * @example * ```typescript * const processor = createReusableLegalMarkdownProcessor({ * enableFieldTracking: true, * basePath: './templates' * }); * * const result1 = await processor.process(content1); * const result2 = await processor.process(content2, { debug: true }); * ``` */ export declare function createReusableLegalMarkdownProcessor(options?: LegalMarkdownProcessorOptions): { process(content: string, additionalOptions?: Partial<LegalMarkdownProcessorOptions>): Promise<LegalMarkdownProcessorResult>; processSync(content: string, additionalOptions?: Partial<LegalMarkdownProcessorOptions>): never; }; export { escapeTemplateUnderscores as _escapeTemplateUnderscores, createLegalMarkdownProcessor as _createLegalMarkdownProcessor, }; //# sourceMappingURL=legal-markdown-processor.d.ts.map