legal-markdown-js
Version:
Node.js implementation of LegalMarkdown for processing legal documents with markdown and YAML - Complete feature parity with Ruby version
213 lines • 8.07 kB
JavaScript
/**
* @fileoverview Content Detection Module for Legal Markdown Processing
*
* This module provides intelligent content type detection for various document
* formats including reStructuredText (RST) and LaTeX. It uses pattern matching
* and heuristics to determine if content requires specific parsers for conversion
* to Legal Markdown format.
*
* Features:
* - reStructuredText format detection with pattern-based analysis
* - LaTeX document format detection with command recognition
* - YAML frontmatter awareness to avoid false positives
* - Robust pattern matching with configurable thresholds
* - Support for various RST directives and syntax elements
* - LaTeX command and environment detection
*
* @example
* ```typescript
* import { ContentDetector } from './content-detector.js';
*
* // Detect RST content
* const isRst = ContentDetector.needsRstParser(content);
* if (isRst) {
* content = await convertRstToLegalMarkdown(content);
* }
*
* // Detect LaTeX content
* const isLatex = ContentDetector.needsLatexParser(content);
* if (isLatex) {
* content = await convertLatexToLegalMarkdown(content);
* }
* ```
*/
/**
* Content detection utility class for identifying document formats
*
* Provides static methods to detect different document formats using pattern
* matching and content analysis. Designed to prevent unnecessary processing
* of content that doesn't require specific parsers.
*
* @class ContentDetector
* @example
* ```typescript
* import { ContentDetector } from './content-detector.js';
*
* // Check if content needs RST processing
* if (ContentDetector.needsRstParser(content)) {
* content = await processRstContent(content);
* }
*
* // Check if content needs LaTeX processing
* if (ContentDetector.needsLatexParser(content)) {
* content = await processLatexContent(content);
* }
* ```
*/
export class ContentDetector {
/**
* Detects if content requires reStructuredText parsing
*
* Uses pattern matching to identify RST-specific syntax elements including
* directives, header underlines, reference links, code blocks, and other
* RST constructs. Avoids false positives with YAML frontmatter content.
*
* @param {string} content - The content to analyze for RST patterns
* @returns {boolean} True if content appears to be reStructuredText, false otherwise
* @example
* ```typescript
* const rstContent = `
* Introduction
* ============
*
* This is a sample RST document.
*
* .. note::
* This is an RST directive.
* `;
*
* const isRst = ContentDetector.needsRstParser(rstContent);
* console.log(isRst); // true
* ```
*/
static needsRstParser(content) {
// No tratar como RST si empieza con YAML frontmatter
if (content.startsWith('---')) {
return false;
}
// Patrones específicos para RST
const rstPatterns = [
/^\.\.[ \t]+\w+::/m, // Directives
/^[=~^"'`#*+<>-]{4,}[ \t]*$/m, // Header underlines (4+ chars)
/`[^`]+`__?/, // Reference links
/`[^<]+[ \t]*<[^>]+>`_/, // External links
/::[ \t]*$/m, // Code blocks
/^\.\.[ \t]+(note|warning|important)::/m, // Admonitions
/^\*[ \t]+\S/m, // Bullet lists with content
/^\d+\.[ \t]+\S/m, // Numbered lists with content
];
// Patrones fuertemente indicativos de RST (solo uno necesario)
const strongRstPatterns = [
/^\.\.[ \t]+\w+::/m, // Directives
/`[^<]+[ \t]*<[^>]+>`_/, // External links with RST syntax
/^\.\.[ \t]+(note|warning|important)::/m, // Admonitions
/::[ \t]*$/m, // Code blocks
];
// Patrones de header con underline (específico de RST)
const headerPattern = /^.+\n[=~^"'`#*+<>-]{4,}[ \t]*$/m;
// Si hay patrones fuertes, es RST
const strongMatches = strongRstPatterns.filter(pattern => pattern.test(content));
if (strongMatches.length >= 1) {
return true;
}
// Si hay header underline, es muy probable que sea RST
if (headerPattern.test(content)) {
return true;
}
// Requiere al menos 2 patrones para confirmar RST
const matches = rstPatterns.filter(pattern => pattern.test(content));
return matches.length >= 2;
}
/**
* Detects if content requires LaTeX parsing
*
* Uses pattern matching to identify LaTeX-specific commands, environments,
* and syntax elements including document classes, sections, text formatting
* commands, and environments. Requires multiple pattern matches to avoid
* false positives.
*
* @param {string} content - The content to analyze for LaTeX patterns
* @returns {boolean} True if content appears to be LaTeX, false otherwise
* @example
* ```typescript
* const latexContent = `
* \\documentclass{article}
* \\begin{document}
* \\section{Introduction}
* This is \\textbf{bold} text in LaTeX.
* \\end{document}
* `;
*
* const isLatex = ContentDetector.needsLatexParser(latexContent);
* console.log(isLatex); // true
* ```
*/
static needsLatexParser(content) {
// No tratar como LaTeX si empieza con YAML frontmatter
if (content.startsWith('---')) {
return false;
}
// Patrones específicos para LaTeX
const latexPatterns = [
/\\documentclass\{/, // Document class
/\\begin\{document\}/, // Begin document
/\\section\*?\{/, // Sections
/\\subsection\*?\{/, // Subsections
/\\begin\{[^}]+\}/, // Environments
/\\[a-zA-Z]+\{[^}]*\}/, // Commands with arguments
/\\textbf\{/, // Bold text
/\\textit\{/, // Italic text
/\\emph\{/, // Emphasis
/\\usepackage\{/, // Package imports
/\\href\{[^}]*\}\{[^}]*\}/, // Links
/\\item\b/, // List items
/\\cite\{/, // Citations
/\\ref\{/, // References
/\\label\{/, // Labels
];
// Patrones fuertemente indicativos de LaTeX (solo uno necesario)
const strongLatexPatterns = [
/\\documentclass\{/, // Document class
/\\begin\{document\}/, // Begin document
/\\section\*?\{/, // Sections
/\\subsection\*?\{/, // Subsections
/\\usepackage\{/, // Package imports
/\\textbf\{/, // Bold text
/\\textit\{/, // Italic text
/\\emph\{/, // Emphasis
/\\item\b/, // List items
/\\cite\{/, // Citations
/\\ref\{/, // References
/\\label\{/, // Labels
];
// Si hay patrones fuertes, es LaTeX
const strongMatches = strongLatexPatterns.filter(pattern => pattern.test(content));
if (strongMatches.length >= 1) {
return true;
}
// Requiere al menos 2 patrones para confirmar LaTeX
const matches = latexPatterns.filter(pattern => pattern.test(content));
return matches.length >= 2;
}
/**
* Detects if content requires Pandoc processing
*
* This is a convenience method that combines RST and LaTeX detection to
* determine if content needs any form of Pandoc processing for conversion
* to Legal Markdown format.
*
* @param {string} content - The content to analyze for format patterns
* @returns {boolean} True if content needs Pandoc processing, false otherwise
* @example
* ```typescript
* const needsProcessing = ContentDetector.needsPandoc(content);
* if (needsProcessing) {
* content = await processThroughPandoc(content);
* }
* ```
*/
static needsPandoc(content) {
return this.needsRstParser(content) || this.needsLatexParser(content);
}
}
//# sourceMappingURL=content-detector.js.map