legal-markdown-js
Version:
Node.js implementation of LegalMarkdown for processing legal documents with markdown and YAML - Complete feature parity with Ruby version
182 lines • 7.07 kB
TypeScript
/**
* Remark plugin for Legal Markdown template field processing
*
* This plugin processes template fields like {{field_name}} in Legal Markdown documents
* using AST-based processing. It handles:
* - Simple variables: {{client.name}}
* - Nested object access: {{client.contact.email}}
* - Helper functions: {{formatDate date "YYYY-MM-DD"}}
* - Parenthesized helper syntax: {{formatDate(@today, "YYYY-MM-DD")}}
* - Subexpressions: {{formatDate (addYears today 2) "YYYY-MM-DD"}}
* - Conditional expressions: {{active ? "Active" : "Inactive"}}
* - Field tracking integration for highlighting
*
* Syntax Support (Issue #142):
* - **Space-separated syntax** (standard): {{helper arg1 arg2}}
* - **Parenthesized syntax**: {{helper(arg1, arg2)}}
*
* Architecture:
* 1. Parse template field patterns in text nodes
* 2. Resolve field values from metadata
* 3. Replace patterns with resolved values
* 4. Track fields for highlighting support
*
* @example
* ```typescript
* import { unified } from 'unified';
* import remarkParse from 'remark-parse';
* import remarkTemplateFields from './template-fields.js';
*
* // Handlebars syntax (current)
* const processor = unified()
* .use(remarkParse)
* .use(remarkTemplateFields, {
* metadata: {
* client_name: 'ACME Corp',
* date: new Date('2025-01-15')
* }
* });
*
* const result = await processor.process('Hello {{client_name}}! Date: {{formatDate date "MMMM Do, YYYY"}}');
* // Output: Hello ACME Corp! Date: January 15th, 2025
* ```
*
* @module
*/
import type { Plugin } from 'unified';
import type { Root } from 'mdast';
import type { YamlValue } from '../../types/index.js';
/**
* Template field definition extracted from text
*/
interface TemplateField {
pattern: string;
fieldName: string;
expression: string;
startIndex: number;
endIndex: number;
}
/**
* Plugin options for template field processing
*/
interface TemplateFieldOptions {
/** Document metadata containing field values */
metadata: Record<string, YamlValue>;
/** Enable debug logging */
debug?: boolean;
/** Custom field patterns (defaults to {{field}} syntax) */
fieldPatterns?: string[];
/** Enable field tracking with highlighting during AST processing */
enableFieldTracking?: boolean;
/** Use AST-first field tracking tokens */
astFieldTracking?: boolean;
/** Highlight winner branches for conditionals */
logicBranchHighlighting?: boolean;
}
/**
* Check if a position is inside a loop or conditional block
*/
declare function isInsideLoopOrConditional(text: string, position: number): boolean;
/**
* Extract template fields from text content
*/
declare function extractTemplateFields(text: string, patterns: string[]): TemplateField[];
/**
* Resolve template field value from metadata
*/
declare function resolveFieldValue(fieldName: string, metadata: Record<string, YamlValue>): {
value: YamlValue | undefined;
hasLogic: boolean;
mixinType?: string;
isEmptyCondition?: boolean;
};
/**
* Resolve nested value from metadata using dot notation
*/
declare function resolveNestedValue(metadata: Record<string, YamlValue>, path: string): YamlValue | undefined;
/**
* Format value for display with optional field tracking
*/
declare function formatFieldValue(value: YamlValue | undefined, fieldName: string, enableFieldTracking?: boolean, hasLogic?: boolean, isEmptyField?: boolean): string;
/**
* Check if a text node is inside existing field tracking spans by examining sibling HTML nodes
*/
declare function isInsideFieldTrackingSpan(node: unknown, parent: unknown): boolean;
/**
* Smart split function that respects quoted strings and parentheses
*
* Splits a string on commas while preserving commas inside quoted strings
* and nested parentheses (for helper function calls).
* Handles both single and double quotes.
*
* @param str - String to split
* @returns Array of split parts
*
* @example
* ```typescript
* smartSplitArguments('arg1, "arg with, comma", arg3')
* // Returns: ['arg1', '"arg with, comma"', 'arg3']
*
* smartSplitArguments('addYears(@today, 5), "YYYY-MM-DD"')
* // Returns: ['addYears(@today, 5)', '"YYYY-MM-DD"']
* ```
*/
declare function smartSplitArguments(str: string): string[];
/**
* Parse comma-separated arguments from a helper function call with support for nested calls
*
* Parses helper function arguments, resolving metadata references, handling
* string literals, numbers, booleans, and nested helper function calls.
*
* @param argsString - Raw arguments string from helper call
* @param metadata - Metadata object for resolving references
* @returns Array of parsed argument values
*
* @example
* ```typescript
* parseHelperArguments("@today, 'YYYY-MM-DD'", { today: new Date() })
* // Returns: [Date, 'YYYY-MM-DD']
*
* parseHelperArguments("addYears(@today, 5), 'YYYY-MM-DD'", { '@today': new Date() })
* // Returns: [Date (5 years added), 'YYYY-MM-DD']
*
* parseHelperArguments("amount, 'USD'", { amount: 1500 })
* // Returns: [1500, 'USD']
* ```
*/
declare function parseHelperArguments(argsString: string, metadata: Record<string, YamlValue>): (YamlValue | undefined)[];
/**
* Parse Handlebars-style space-separated arguments from a helper function call
*
* Parses Handlebars helper arguments (space-separated instead of comma-separated),
* resolving metadata references, handling string literals, numbers, booleans,
* subexpressions, and nested helper function calls.
*
* @param argsString - Raw arguments string from Handlebars helper call
* @param metadata - Metadata object for resolving references
* @returns Array of parsed argument values
*
* @example
* ```typescript
* parseHandlebarsArguments('date "MMMM Do, YYYY"', { date: new Date() })
* // Returns: [Date, 'MMMM Do, YYYY']
*
* parseHandlebarsArguments('(addYears today 5) "YYYY-MM-DD"', { today: new Date() })
* // Returns: [Date (5 years added), 'YYYY-MM-DD']
*
* parseHandlebarsArguments('amount "USD"', { amount: 1500 })
* // Returns: [1500, 'USD']
*
* parseHandlebarsArguments('price quantity', { price: 10, quantity: 5 })
* // Returns: [10, 5]
* ```
*/
declare function parseHandlebarsArguments(argsString: string, metadata: Record<string, YamlValue>): (YamlValue | undefined)[];
/**
* Remark plugin for processing template fields in Legal Markdown documents
*/
declare const remarkTemplateFields: Plugin<[TemplateFieldOptions], Root>;
export default remarkTemplateFields;
export type { TemplateFieldOptions, TemplateField };
export { isInsideLoopOrConditional as _isInsideLoopOrConditional, extractTemplateFields as _extractTemplateFields, resolveFieldValue as _resolveFieldValue, resolveNestedValue as _resolveNestedValue, formatFieldValue as _formatFieldValue, isInsideFieldTrackingSpan as _isInsideFieldTrackingSpan, smartSplitArguments as _smartSplitArguments, parseHelperArguments as _parseHelperArguments, parseHandlebarsArguments as _parseHandlebarsArguments, };
//# sourceMappingURL=template-fields.d.ts.map