UNPKG

legal-markdown-js

Version:

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

178 lines 5.91 kB
/** * Branded types for differentiating content formats * * This module provides type-safe wrappers for string content to prevent * accidentally mixing Markdown, HTML, and plain text formats. Using branded * types allows TypeScript to catch format mismatches at compile time. * * @example * ```typescript * // Type-safe conversion * const markdown = asMarkdown('# Title\n\nContent'); * const html = await generateHtml(markdown); // ✅ Type-safe * * // This will cause a TypeScript error: * const html = '<h1>Title</h1>'; * await generateHtml(html); // ❌ Type error: HTML cannot be passed as Markdown * ``` * * @module types/content-formats */ /** * Type guard to check if content appears to be HTML * * Performs a heuristic check for HTML tags in the content. * This is not foolproof but catches most common cases. * * @param content - The content to check * @returns true if content appears to contain HTML tags * * @example * ```typescript * isHtml('<h1>Title</h1>'); // true * isHtml('# Title'); // false * isHtml('Plain text'); // false * ``` */ export function isHtml(content) { // Simple heuristic: detect complete HTML documents vs Markdown with embedded HTML // // Note: This is NOT a perfect detector. It only catches obvious cases where // someone passed a complete HTML document instead of Markdown. It will NOT // detect all HTML content, and that's intentional - Markdown can contain // embedded HTML tags (like <div>, <span>, etc.) which is perfectly valid. // // We only check for structural tags that should never appear in Markdown: // - DOCTYPE declarations // - <html>, <head>, <body> tags // // This is sufficient to catch the bug where generateHtml output was // accidentally passed to generatePdf/generateHtml again. const structuralHtmlPattern = /<!DOCTYPE|<\/?html[\s>]|<\/?head[\s>]|<\/?body[\s>]/i; return structuralHtmlPattern.test(content); } /** * Type guard to check if content appears to be Markdown * * A simple heuristic: if it's not HTML, we assume it's Markdown or plain text. * More sophisticated detection could check for Markdown syntax patterns. * * @param content - The content to check * @returns true if content does not appear to be HTML * * @example * ```typescript * isMarkdown('# Title'); // true * isMarkdown('Plain text'); // true * isMarkdown('<h1>Title</h1>'); // false * ``` */ export function isMarkdown(content) { return !isHtml(content); } /** * Converts a string to MarkdownString type * * This is a type assertion that should be used when you know the content * is Markdown. For safety, consider validating with isMarkdown() first. * * @param content - The content to convert * @returns The same content typed as MarkdownString * * @example * ```typescript * const markdown = asMarkdown('# Title\n\nContent'); * await generateHtml(markdown); // Type-safe * ``` */ export function asMarkdown(content) { return content; } /** * Converts a string to HtmlString type * * This is a type assertion that should be used when you know the content * is HTML. For safety, consider validating with isHtml() first. * * @param content - The content to convert * @returns The same content typed as HtmlString * * @example * ```typescript * const html = asHtml('<h1>Title</h1>'); * await renderHtml(html); // Type-safe * ``` */ export function asHtml(content) { return content; } /** * Converts a string to PlainTextString type * * This is a type assertion that should be used when you know the content * is plain text without formatting. * * @param content - The content to convert * @returns The same content typed as PlainTextString * * @example * ```typescript * const plain = asPlainText('Just plain text'); * console.log(plain); * ``` */ export function asPlainText(content) { return content; } /** * Safely converts any string to MarkdownString after validation * * Throws an error if the content appears to be HTML instead of Markdown. * Use this when you want runtime validation in addition to type safety. * * @param content - The content to validate and convert * @param source - Optional description of where this content came from (for error messages) * @returns The content typed as MarkdownString * @throws {Error} If content appears to be HTML * * @example * ```typescript * const markdown = toMarkdown('# Title'); // ✅ OK * const invalid = toMarkdown('<h1>Title</h1>'); // ❌ Throws error * ``` */ export function toMarkdown(content, source) { if (isHtml(content)) { const sourceInfo = source ? ` from ${source}` : ''; throw new Error(`Expected Markdown content${sourceInfo}, but received HTML. ` + 'This indicates a bug where HTML was passed instead of Markdown. ' + `Content preview: ${content.substring(0, 100)}...`); } return content; } /** * Safely converts any string to HtmlString after validation * * Validates that the content appears to contain HTML markup. * Use this when you want runtime validation in addition to type safety. * * @param content - The content to validate and convert * @param source - Optional description of where this content came from (for error messages) * @returns The content typed as HtmlString * @throws {Error} If content does not appear to be HTML * * @example * ```typescript * const html = toHtml('<h1>Title</h1>'); // ✅ OK * const invalid = toHtml('# Title'); // ❌ Throws error * ``` */ export function toHtml(content, source) { if (!isHtml(content)) { const sourceInfo = source ? ` from ${source}` : ''; throw new Error(`Expected HTML content${sourceInfo}, but received non-HTML text. ` + `Content preview: ${content.substring(0, 100)}...`); } return content; } //# sourceMappingURL=content-formats.js.map