From 647a8d1c7bc1e4667fd1981e8c0644ee65ac1690 Mon Sep 17 00:00:00 2001 From: sergio Date: Mon, 15 Dec 2025 23:54:41 +0100 Subject: [PATCH] generation test --- .gitignore | 3 +- TFM_Sergio_Jimenez_OCR_Optimization.docx | Bin 106754 -> 0 bytes apply_content.py | 571 ++ generate_mermaid_figures.py | 110 + generate_thesis.py | 269 - generate_thesis_docx.py | 438 -- package-lock.json | 4127 +++++++++++++ package.json | 5 + thesis_output.htm | 751 --- thesis_output/figures/figura_1.png | Bin 0 -> 17100 bytes thesis_output/figures/figura_2.png | Bin 0 -> 55971 bytes thesis_output/figures/figura_3.png | Bin 0 -> 98404 bytes thesis_output/figures/figura_4.png | Bin 0 -> 32850 bytes thesis_output/figures/figura_5.png | Bin 0 -> 24564 bytes thesis_output/figures/figura_6.png | Bin 0 -> 16914 bytes thesis_output/figures/figura_7.png | Bin 0 -> 17910 bytes thesis_output/figures/figures_manifest.json | 37 + thesis_output/plantilla_individual.htm | 5321 +++++++++++++++++ .../colorschememapping.xml | 0 .../plantilla_individual_files}/filelist.xml | 0 .../plantilla_individual_files}/header.htm | 0 .../plantilla_individual_files}/image001.png | Bin .../plantilla_individual_files}/image002.gif | Bin .../plantilla_individual_files}/image003.png | Bin .../plantilla_individual_files}/image004.jpg | Bin .../plantilla_individual_files}/image005.png | Bin .../plantilla_individual_files}/image006.gif | Bin .../plantilla_individual_files}/item0001.xml | 0 .../plantilla_individual_files}/item0003.xml | 0 .../plantilla_individual_files}/item0005.xml | 0 .../plantilla_individual_files}/item0007.xml | 0 .../plantilla_individual_files}/props002.xml | 0 .../plantilla_individual_files}/props004.xml | 0 .../plantilla_individual_files}/props006.xml | 0 .../plantilla_individual_files}/props008.xml | 0 .../themedata.thmx | Bin 36 files changed, 10173 insertions(+), 1459 deletions(-) delete mode 100644 TFM_Sergio_Jimenez_OCR_Optimization.docx create mode 100644 apply_content.py create mode 100644 generate_mermaid_figures.py delete mode 100644 generate_thesis.py delete mode 100644 generate_thesis_docx.py create mode 100644 package-lock.json create mode 100644 package.json delete mode 100644 thesis_output.htm create mode 100644 thesis_output/figures/figura_1.png create mode 100644 thesis_output/figures/figura_2.png create mode 100644 thesis_output/figures/figura_3.png create mode 100644 thesis_output/figures/figura_4.png create mode 100644 thesis_output/figures/figura_5.png create mode 100644 thesis_output/figures/figura_6.png create mode 100644 thesis_output/figures/figura_7.png create mode 100644 thesis_output/figures/figures_manifest.json create mode 100644 thesis_output/plantilla_individual.htm rename {thesis_output_files => thesis_output/plantilla_individual_files}/colorschememapping.xml (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/filelist.xml (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/header.htm (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/image001.png (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/image002.gif (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/image003.png (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/image004.jpg (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/image005.png (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/image006.gif (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/item0001.xml (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/item0003.xml (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/item0005.xml (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/item0007.xml (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/props002.xml (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/props004.xml (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/props006.xml (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/props008.xml (100%) rename {thesis_output_files => thesis_output/plantilla_individual_files}/themedata.thmx (100%) diff --git a/.gitignore b/.gitignore index 1363bba..686d80f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ __pycache__/ dataset results .DS_Store -.claude \ No newline at end of file +.claude +node_modules diff --git a/TFM_Sergio_Jimenez_OCR_Optimization.docx b/TFM_Sergio_Jimenez_OCR_Optimization.docx deleted file mode 100644 index 9ca9e369851d214b160be031950caac25d88f98b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106754 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≻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 diff --git a/apply_content.py b/apply_content.py new file mode 100644 index 0000000..b5d332e --- /dev/null +++ b/apply_content.py @@ -0,0 +1,571 @@ +#!/usr/bin/env python3 +"""Replace template content with thesis content from docs/ folder using BeautifulSoup.""" + +import re +import os +from bs4 import BeautifulSoup, NavigableString + +BASE_DIR = '/Users/sergio/Desktop/MastersThesis' +TEMPLATE = os.path.join(BASE_DIR, 'thesis_output/plantilla_individual.htm') +DOCS_DIR = os.path.join(BASE_DIR, 'docs') + +# Global counters for tables and figures +table_counter = 0 +figure_counter = 0 + +def read_file(path): + try: + with open(path, 'r', encoding='utf-8') as f: + return f.read() + except UnicodeDecodeError: + with open(path, 'r', encoding='latin-1') as f: + return f.read() + +def write_file(path, content): + with open(path, 'w', encoding='utf-8') as f: + f.write(content) + +def md_to_html_para(text): + """Convert markdown inline formatting to HTML.""" + # Bold + text = re.sub(r'\*\*([^*]+)\*\*', r'\1', text) + # Italic + text = re.sub(r'\*([^*]+)\*', r'\1', text) + # Inline code + text = re.sub(r'`([^`]+)`', r'\1', text) + return text + +def extract_table_title(lines, current_index): + """Look for table title in preceding lines (e.g., **Tabla 1.** *Title*).""" + # Check previous non-empty lines for table title + for i in range(current_index - 1, max(0, current_index - 5), -1): + line = lines[i].strip() + if line.startswith('**Tabla') or line.startswith('*Tabla'): + return line + if line and not line.startswith('|'): + break + return None + +def extract_figure_title_from_mermaid(lines, current_index): + """Extract title from mermaid diagram or preceding text.""" + # Look for title in mermaid content + for i in range(current_index + 1, min(len(lines), current_index + 20)): + line = lines[i].strip() + if line.startswith('```'): + break + if 'title' in line.lower(): + # Extract title from: title "Some Title" + match = re.search(r'title\s+["\']([^"\']+)["\']', line) + if match: + return match.group(1) + + # Check preceding lines for figure reference + for i in range(current_index - 1, max(0, current_index - 3), -1): + line = lines[i].strip() + if line.startswith('**Figura') or 'Figura' in line: + return line + + return None + +def parse_md_to_html_blocks(md_content): + """Convert markdown content to HTML blocks with template styles.""" + global table_counter, figure_counter + + html_blocks = [] + lines = md_content.split('\n') + i = 0 + + while i < len(lines): + line = lines[i] + + # Skip empty lines + if not line.strip(): + i += 1 + continue + + # Mermaid diagram - convert to figure with actual image + if line.strip().startswith('```mermaid'): + figure_counter += 1 + mermaid_lines = [] + i += 1 + while i < len(lines) and not lines[i].strip() == '```': + mermaid_lines.append(lines[i]) + i += 1 + + # Try to extract title from mermaid content + mermaid_content = '\n'.join(mermaid_lines) + title_match = re.search(r'title\s+["\']?([^"\'"\n]+)["\']?', mermaid_content) + if title_match: + fig_title = title_match.group(1).strip() + else: + fig_title = f"Diagrama {figure_counter}" + + # Check if the generated PNG exists + fig_file = f'figures/figura_{figure_counter}.png' + fig_path = os.path.join(BASE_DIR, 'thesis_output', fig_file) + + # Create figure with proper template format (Piedefoto-tabla class) + html_blocks.append(f'''

Figura {figure_counter}. {fig_title}

''') + + if os.path.exists(fig_path): + # Use actual image with proper Word-compatible format + html_blocks.append(f'''

{fig_title}

''') + else: + # Fallback to placeholder + html_blocks.append(f'''

[Insertar diagrama Mermaid aquí]

''') + + html_blocks.append(f'''

Fuente: Elaboración propia.

''') + html_blocks.append('

 

') + i += 1 + continue + + # Code block (non-mermaid) + if line.strip().startswith('```'): + code_lang = line.strip()[3:] + code_lines = [] + i += 1 + while i < len(lines) and not lines[i].strip().startswith('```'): + code_lines.append(lines[i]) + i += 1 + code = '\n'.join(code_lines) + # Escape HTML entities in code + code = code.replace('&', '&').replace('<', '<').replace('>', '>') + html_blocks.append(f'

{code}

') + i += 1 + continue + + # Headers - ## becomes h2, ### becomes h3 + if line.startswith('####'): + text = line.lstrip('#').strip() + html_blocks.append(f'

{text}

') + i += 1 + continue + elif line.startswith('###'): + text = line.lstrip('#').strip() + html_blocks.append(f'

{text}

') + i += 1 + continue + elif line.startswith('##'): + text = line.lstrip('#').strip() + html_blocks.append(f'

{text}

') + i += 1 + continue + elif line.startswith('#'): + # Skip h1 - we keep the original + i += 1 + continue + + # Table - check for table title pattern first + if '|' in line and i + 1 < len(lines) and '---' in lines[i + 1]: + table_counter += 1 + + # Check if previous line has table title (e.g., **Tabla 1.** *Title*) + table_title = None + table_source = "Elaboración propia" + + # Look back for table title + for j in range(i - 1, max(0, i - 5), -1): + prev_line = lines[j].strip() + if prev_line.startswith('**Tabla') or prev_line.startswith('*Tabla'): + # Extract title text + table_title = re.sub(r'\*+', '', prev_line).strip() + break + elif prev_line and not prev_line.startswith('|'): + break + + # Parse table + table_lines = [] + while i < len(lines) and '|' in lines[i]: + if '---' not in lines[i]: + table_lines.append(lines[i]) + i += 1 + + # Look ahead for source + if i < len(lines) and 'Fuente:' in lines[i]: + table_source = lines[i].replace('*', '').replace('Fuente:', '').strip() + i += 1 + + # Add table title with proper template format (Piedefoto-tabla class) + if table_title: + clean_title = table_title.replace(f"Tabla {table_counter}.", "").strip() + html_blocks.append(f'

Tabla {table_counter}. {clean_title}

') + else: + html_blocks.append(f'

Tabla {table_counter}. Tabla de datos.

') + + # Build table HTML + table_html = '' + for j, tline in enumerate(table_lines): + cells = [c.strip() for c in tline.split('|')[1:-1]] + table_html += '' + for cell in cells: + if j == 0: + # Header row + table_html += f'' + else: + table_html += f'' + table_html += '' + table_html += '

{md_to_html_para(cell)}

{md_to_html_para(cell)}

' + html_blocks.append(table_html) + + # Add source with proper template format + html_blocks.append(f'

Fuente: {table_source}.

') + html_blocks.append('

 

') + continue + + # Blockquote + if line.startswith('>'): + quote_text = line[1:].strip() + i += 1 + while i < len(lines) and lines[i].startswith('>'): + quote_text += ' ' + lines[i][1:].strip() + i += 1 + html_blocks.append(f'

{md_to_html_para(quote_text)}

') + continue + + # Bullet list + if re.match(r'^[\-\*\+]\s', line): + while i < len(lines) and re.match(r'^[\-\*\+]\s', lines[i]): + item_text = lines[i][2:].strip() + html_blocks.append(f'

·     {md_to_html_para(item_text)}

') + i += 1 + continue + + # Numbered list + if re.match(r'^\d+\.\s', line): + num = 1 + while i < len(lines) and re.match(r'^\d+\.\s', lines[i]): + item_text = re.sub(r'^\d+\.\s*', '', lines[i]).strip() + html_blocks.append(f'

{num}.   {md_to_html_para(item_text)}

') + num += 1 + i += 1 + continue + + # Skip lines that are just table/figure titles (they'll be handled with the table/figure) + if line.strip().startswith('**Tabla') or line.strip().startswith('*Tabla'): + i += 1 + continue + if line.strip().startswith('**Figura') or line.strip().startswith('*Figura'): + i += 1 + continue + if line.strip().startswith('*Fuente:') or line.strip().startswith('Fuente:'): + i += 1 + continue + + # Regular paragraph + para_lines = [line] + i += 1 + while i < len(lines) and lines[i].strip() and not lines[i].startswith('#') and not lines[i].startswith('```') and not lines[i].startswith('>') and not re.match(r'^[\-\*\+]\s', lines[i]) and not re.match(r'^\d+\.\s', lines[i]) and '|' not in lines[i]: + para_lines.append(lines[i]) + i += 1 + + para_text = ' '.join(para_lines) + html_blocks.append(f'

{md_to_html_para(para_text)}

') + + return '\n\n'.join(html_blocks) + +def extract_section_content(md_content): + """Extract content from markdown, skipping the first # header.""" + md_content = re.sub(r'^#\s+[^\n]+\n+', '', md_content, count=1) + return parse_md_to_html_blocks(md_content) + +def find_section_element(soup, keyword): + """Find element containing keyword (h1 or special paragraph classes).""" + # First try h1 + for h1 in soup.find_all('h1'): + text = h1.get_text() + if keyword.lower() in text.lower(): + return h1 + + # Try special paragraph classes for unnumbered sections + for p in soup.find_all('p', class_=['Ttulo1sinnumerar', 'Anexo', 'MsoNormal']): + text = p.get_text() + if keyword.lower() in text.lower(): + classes = p.get('class', []) + if 'Ttulo1sinnumerar' in classes or 'Anexo' in classes: + return p + if re.match(r'^\d+\.?\s', text.strip()): + return p + return None + +def remove_elements_between(start_elem, end_elem): + """Remove all elements between start and end (exclusive).""" + current = start_elem.next_sibling + elements_to_remove = [] + while current and current != end_elem: + elements_to_remove.append(current) + current = current.next_sibling + for elem in elements_to_remove: + if hasattr(elem, 'decompose'): + elem.decompose() + elif isinstance(elem, NavigableString): + elem.extract() + +def format_references(refs_content): + """Format references with proper MsoBibliography style.""" + refs_content = refs_content.replace('# Referencias bibliográficas {.unnumbered}', '').strip() + refs_html = '' + + for line in refs_content.split('\n\n'): + line = line.strip() + if not line: + continue + + # Apply markdown formatting + formatted = md_to_html_para(line) + + # Use MsoBibliography style with hanging indent (36pt indent, -36pt text-indent) + refs_html += f'''

{formatted}

\n''' + + return refs_html + +def extract_resumen_parts(resumen_content): + """Extract Spanish resumen and English abstract from 00_resumen.md""" + parts = resumen_content.split('---') + + spanish_part = parts[0] if len(parts) > 0 else '' + english_part = parts[1] if len(parts) > 1 else '' + + # Extract Spanish content + spanish_text = '' + spanish_keywords = '' + if '**Palabras clave:**' in spanish_part: + text_part, kw_part = spanish_part.split('**Palabras clave:**') + spanish_text = text_part.replace('# Resumen', '').strip() + spanish_keywords = kw_part.strip() + else: + spanish_text = spanish_part.replace('# Resumen', '').strip() + + # Extract English content + english_text = '' + english_keywords = '' + if '**Keywords:**' in english_part: + text_part, kw_part = english_part.split('**Keywords:**') + english_text = text_part.replace('# Abstract', '').strip() + english_keywords = kw_part.strip() + else: + english_text = english_part.replace('# Abstract', '').strip() + + return spanish_text, spanish_keywords, english_text, english_keywords + +def main(): + global table_counter, figure_counter + + print("Reading template...") + html_content = read_file(TEMPLATE) + soup = BeautifulSoup(html_content, 'html.parser') + + print("Reading docs content...") + docs = { + 'resumen': read_file(os.path.join(DOCS_DIR, '00_resumen.md')), + 'intro': read_file(os.path.join(DOCS_DIR, '01_introduccion.md')), + 'contexto': read_file(os.path.join(DOCS_DIR, '02_contexto_estado_arte.md')), + 'objetivos': read_file(os.path.join(DOCS_DIR, '03_objetivos_metodologia.md')), + 'desarrollo': read_file(os.path.join(DOCS_DIR, '04_desarrollo_especifico.md')), + 'conclusiones': read_file(os.path.join(DOCS_DIR, '05_conclusiones_trabajo_futuro.md')), + 'referencias': read_file(os.path.join(DOCS_DIR, '06_referencias_bibliograficas.md')), + 'anexo': read_file(os.path.join(DOCS_DIR, '07_anexo_a.md')), + } + + # Extract resumen and abstract + spanish_text, spanish_kw, english_text, english_kw = extract_resumen_parts(docs['resumen']) + + # Replace title + print("Replacing title...") + for elem in soup.find_all(string=re.compile(r'Título del TFE', re.IGNORECASE)): + elem.replace_with(elem.replace('Título del TFE', 'Optimización de Hiperparámetros OCR con Ray Tune para Documentos Académicos en Español')) + + # Replace Resumen section + print("Replacing Resumen...") + resumen_title = soup.find('p', class_='Ttulondices', string=re.compile(r'Resumen')) + if resumen_title: + # Find and replace content after Resumen title until Abstract + current = resumen_title.find_next_sibling() + elements_to_remove = [] + while current: + text = current.get_text() if hasattr(current, 'get_text') else str(current) + if 'Abstract' in text and current.name == 'p' and 'Ttulondices' in str(current.get('class', [])): + break + elements_to_remove.append(current) + current = current.find_next_sibling() + + for elem in elements_to_remove: + if hasattr(elem, 'decompose'): + elem.decompose() + + # Insert new resumen content + resumen_html = f'''

{spanish_text}

+

 

+

Palabras clave: {spanish_kw}

+

 

''' + resumen_soup = BeautifulSoup(resumen_html, 'html.parser') + insert_point = resumen_title + for new_elem in reversed(list(resumen_soup.children)): + insert_point.insert_after(new_elem) + print(" ✓ Replaced Resumen") + + # Replace Abstract section + print("Replacing Abstract...") + abstract_title = soup.find('p', class_='Ttulondices', string=re.compile(r'Abstract')) + if abstract_title: + # Find and replace content after Abstract title until next major section + current = abstract_title.find_next_sibling() + elements_to_remove = [] + while current: + # Stop at page break or next title + if current.name == 'span' and 'page-break' in str(current): + break + text = current.get_text() if hasattr(current, 'get_text') else str(current) + if current.name == 'p' and ('Ttulondices' in str(current.get('class', [])) or 'MsoToc' in str(current.get('class', []))): + break + elements_to_remove.append(current) + current = current.find_next_sibling() + + for elem in elements_to_remove: + if hasattr(elem, 'decompose'): + elem.decompose() + + # Insert new abstract content + abstract_html = f'''

{english_text}

+

 

+

Keywords: {english_kw}

+

 

''' + abstract_soup = BeautifulSoup(abstract_html, 'html.parser') + insert_point = abstract_title + for new_elem in reversed(list(abstract_soup.children)): + insert_point.insert_after(new_elem) + print(" ✓ Replaced Abstract") + + # Remove "Importante" callout boxes (template instructions) + print("Removing template instructions...") + for div in soup.find_all('div'): + text = div.get_text() + if 'Importante:' in text and 'extensión mínima' in text: + div.decompose() + print(" ✓ Removed 'Importante' box") + + # Remove "Ejemplo de nota al pie" footnote + for elem in soup.find_all(string=re.compile(r'Ejemplo de nota al pie')): + parent = elem.parent + if parent: + # Find the footnote container and remove it + while parent and parent.name != 'p': + parent = parent.parent + if parent: + parent.decompose() + print(" ✓ Removed footnote example") + + # Clear old figure/table index entries (they need to be regenerated in Word) + print("Clearing old index entries...") + # Remove old figure index entries that reference template examples + for p in soup.find_all('p', class_='MsoToc3'): + text = p.get_text() + if 'Figura 1. Ejemplo' in text or 'Tabla 1. Ejemplo' in text: + p.decompose() + print(" ✓ Removed template index entry") + + # Also clear the specific figure/table from template + for p in soup.find_all('p', class_='Imagencentrada'): + p.decompose() + print(" ✓ Removed template figure placeholder") + + # Remove template table example + for table in soup.find_all('table', class_='MsoTableGrid'): + # Check if this is the template example table + text = table.get_text() + if 'Celda 1' in text or 'Encabezado 1' in text: + # Also remove surrounding caption and source + prev_sib = table.find_previous_sibling() + next_sib = table.find_next_sibling() + if prev_sib and 'Tabla 1. Ejemplo' in prev_sib.get_text(): + prev_sib.decompose() + if next_sib and 'Fuente:' in next_sib.get_text(): + next_sib.decompose() + table.decompose() + print(" ✓ Removed template table example") + break + + # Define chapters with their keywords and next chapter keywords + chapters = [ + ('Introducción', 'intro', 'Contexto'), + ('Contexto', 'contexto', 'Objetivos'), + ('Objetivos', 'objetivos', 'Desarrollo'), + ('Desarrollo', 'desarrollo', 'Conclusiones'), + ('Conclusiones', 'conclusiones', 'Referencias'), + ] + + print("Replacing chapter contents...") + for chapter_keyword, doc_key, next_keyword in chapters: + print(f" Processing: {chapter_keyword}") + + # Reset counters for consistent numbering per chapter (optional - remove if you want global numbering) + # table_counter = 0 + # figure_counter = 0 + + start_elem = find_section_element(soup, chapter_keyword) + end_elem = find_section_element(soup, next_keyword) + + if start_elem and end_elem: + remove_elements_between(start_elem, end_elem) + new_content_html = extract_section_content(docs[doc_key]) + new_soup = BeautifulSoup(new_content_html, 'html.parser') + insert_point = start_elem + for new_elem in reversed(list(new_soup.children)): + insert_point.insert_after(new_elem) + print(f" ✓ Replaced content") + else: + if not start_elem: + print(f" Warning: Could not find start element for {chapter_keyword}") + if not end_elem: + print(f" Warning: Could not find end element for {next_keyword}") + + # Handle Referencias + print(" Processing: Referencias bibliográficas") + refs_start = find_section_element(soup, 'Referencias') + anexo_elem = find_section_element(soup, 'Anexo') + + if refs_start and anexo_elem: + remove_elements_between(refs_start, anexo_elem) + refs_html = format_references(docs['referencias']) + refs_soup = BeautifulSoup(refs_html, 'html.parser') + insert_point = refs_start + for new_elem in reversed(list(refs_soup.children)): + insert_point.insert_after(new_elem) + print(f" ✓ Replaced content") + + # Handle Anexo (last section) + print(" Processing: Anexo") + if anexo_elem: + body = soup.find('body') + if body: + current = anexo_elem.next_sibling + while current: + next_elem = current.next_sibling + if hasattr(current, 'decompose'): + current.decompose() + elif isinstance(current, NavigableString): + current.extract() + current = next_elem + + anexo_content = extract_section_content(docs['anexo']) + anexo_soup = BeautifulSoup(anexo_content, 'html.parser') + insert_point = anexo_elem + for new_elem in reversed(list(anexo_soup.children)): + insert_point.insert_after(new_elem) + print(f" ✓ Replaced content") + + print(f"\nSummary: {table_counter} tables, {figure_counter} figures processed") + + print("Saving modified template...") + output_html = str(soup) + write_file(TEMPLATE, output_html) + + print(f"✓ Done! Modified: {TEMPLATE}") + print("\nTo convert to DOCX:") + print("1. Open the .htm file in Microsoft Word") + print("2. Replace [Insertar diagrama Mermaid aquí] placeholders with actual diagrams") + print("3. Update indices: Select all (Ctrl+A) then press F9 to update fields") + print(" - This will regenerate: Índice de contenidos, Índice de figuras, Índice de tablas") + print("4. Save as .docx") + +if __name__ == '__main__': + main() diff --git a/generate_mermaid_figures.py b/generate_mermaid_figures.py new file mode 100644 index 0000000..a2e5ce7 --- /dev/null +++ b/generate_mermaid_figures.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +"""Extract Mermaid diagrams from markdown files and convert to PNG images.""" + +import os +import re +import subprocess +import json + +BASE_DIR = '/Users/sergio/Desktop/MastersThesis' +DOCS_DIR = os.path.join(BASE_DIR, 'docs') +OUTPUT_DIR = os.path.join(BASE_DIR, 'thesis_output/figures') +MMDC = os.path.join(BASE_DIR, 'node_modules/.bin/mmdc') + +def extract_mermaid_diagrams(): + """Extract all mermaid diagrams from markdown files.""" + diagrams = [] + + md_files = [ + '02_contexto_estado_arte.md', + '03_objetivos_metodologia.md', + '04_desarrollo_especifico.md', + ] + + for md_file in md_files: + filepath = os.path.join(DOCS_DIR, md_file) + if not os.path.exists(filepath): + continue + + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + + # Find all mermaid blocks + pattern = r'```mermaid\n(.*?)```' + matches = re.findall(pattern, content, re.DOTALL) + + for i, mermaid_code in enumerate(matches): + # Try to extract title + title_match = re.search(r'title\s+["\']?([^"\'"\n]+)["\']?', mermaid_code) + title = title_match.group(1).strip() if title_match else f"Diagrama de {md_file}" + + diagrams.append({ + 'source': md_file, + 'code': mermaid_code.strip(), + 'title': title, + 'index': len(diagrams) + 1 + }) + + return diagrams + +def convert_to_png(diagrams): + """Convert mermaid diagrams to PNG using mmdc.""" + os.makedirs(OUTPUT_DIR, exist_ok=True) + + generated = [] + + for diagram in diagrams: + # Write mermaid code to temp file + temp_file = os.path.join(OUTPUT_DIR, f'temp_{diagram["index"]}.mmd') + output_file = os.path.join(OUTPUT_DIR, f'figura_{diagram["index"]}.png') + + with open(temp_file, 'w', encoding='utf-8') as f: + f.write(diagram['code']) + + # Convert using mmdc + try: + result = subprocess.run( + [MMDC, '-i', temp_file, '-o', output_file, '-b', 'white', '-w', '800'], + capture_output=True, + text=True, + timeout=60 + ) + + if os.path.exists(output_file): + print(f"✓ Generated: figura_{diagram['index']}.png - {diagram['title']}") + generated.append({ + 'file': f'figura_{diagram["index"]}.png', + 'title': diagram['title'], + 'index': diagram['index'] + }) + else: + print(f"✗ Failed: figura_{diagram['index']}.png - {result.stderr}") + except subprocess.TimeoutExpired: + print(f"✗ Timeout: figura_{diagram['index']}.png") + except Exception as e: + print(f"✗ Error: figura_{diagram['index']}.png - {e}") + + # Clean up temp file + if os.path.exists(temp_file): + os.remove(temp_file) + + return generated + +def main(): + print("Extracting Mermaid diagrams from markdown files...") + diagrams = extract_mermaid_diagrams() + print(f"Found {len(diagrams)} diagrams\n") + + print("Converting to PNG images...") + generated = convert_to_png(diagrams) + + print(f"\n✓ Generated {len(generated)} figures in {OUTPUT_DIR}") + + # Save manifest for apply_content.py to use + manifest_file = os.path.join(OUTPUT_DIR, 'figures_manifest.json') + with open(manifest_file, 'w', encoding='utf-8') as f: + json.dump(generated, f, indent=2, ensure_ascii=False) + print(f"✓ Saved manifest to {manifest_file}") + +if __name__ == '__main__': + main() diff --git a/generate_thesis.py b/generate_thesis.py deleted file mode 100644 index bf9103c..0000000 --- a/generate_thesis.py +++ /dev/null @@ -1,269 +0,0 @@ -#!/usr/bin/env python3 -"""Generate thesis DOCX from HTML template and markdown content.""" - -import os -import re -import shutil -import subprocess -from bs4 import BeautifulSoup - -BASE_DIR = '/Users/sergio/Desktop/MastersThesis' -TEMPLATE_HTM = os.path.join(BASE_DIR, 'instructions/plantilla_individual.htm') -TEMPLATE_FILES = os.path.join(BASE_DIR, 'instructions/plantilla_individual_files') -OUTPUT_HTM = os.path.join(BASE_DIR, 'thesis_output.htm') -OUTPUT_FILES = os.path.join(BASE_DIR, 'thesis_output_files') -OUTPUT_DOCX = os.path.join(BASE_DIR, 'TFM_Sergio_Jimenez_OCR_Optimization.docx') -DOCS_DIR = os.path.join(BASE_DIR, 'docs') - -def read_md(filename): - with open(os.path.join(DOCS_DIR, filename), 'r', encoding='utf-8') as f: - return f.read() - -def md_to_html(md_text): - """Convert markdown to simple HTML.""" - html = md_text - - # Headers - html = re.sub(r'^#### (.+)$', r'

\1

', html, flags=re.MULTILINE) - html = re.sub(r'^### (.+)$', r'

\1

', html, flags=re.MULTILINE) - html = re.sub(r'^## (.+)$', r'

\1

', html, flags=re.MULTILINE) - html = re.sub(r'^# (.+)$', r'

\1

', html, flags=re.MULTILINE) - - # Bold and italic - html = re.sub(r'\*\*([^*]+)\*\*', r'\1', html) - html = re.sub(r'\*([^*]+)\*', r'\1', html) - - # Inline code - html = re.sub(r'`([^`]+)`', r'\1', html) - - # Code blocks - def code_block_replace(match): - lang = match.group(1) - code = match.group(2) - return f'
{code}
' - html = re.sub(r'```(\w*)\n(.*?)```', code_block_replace, html, flags=re.DOTALL) - - # Blockquotes - html = re.sub(r'^>\s*(.+)$', r'
\1
', html, flags=re.MULTILINE) - - # Tables - def table_replace(match): - lines = match.group(0).strip().split('\n') - rows = [] - for line in lines: - if '---' in line: - continue - cells = [c.strip() for c in line.split('|')[1:-1]] - rows.append(cells) - - table_html = '' - for i, row in enumerate(rows): - table_html += '' - tag = 'th' if i == 0 else 'td' - for cell in row: - table_html += f'<{tag} style="padding:5px;border:1px solid #ccc">{cell}' - table_html += '' - table_html += '
' - return table_html - - html = re.sub(r'(\|[^\n]+\|\n)+', table_replace, html) - - # Bullet lists - def bullet_list_replace(match): - items = match.group(0).strip().split('\n') - list_html = '
    ' - for item in items: - item_text = re.sub(r'^[\-\*\+]\s*', '', item) - list_html += f'
  • {item_text}
  • ' - list_html += '
' - return list_html - html = re.sub(r'(^[\-\*\+]\s+.+\n?)+', bullet_list_replace, html, flags=re.MULTILINE) - - # Numbered lists - def num_list_replace(match): - items = match.group(0).strip().split('\n') - list_html = '
    ' - for item in items: - item_text = re.sub(r'^\d+\.\s*', '', item) - list_html += f'
  1. {item_text}
  2. ' - list_html += '
' - return list_html - html = re.sub(r'(^\d+\.\s+.+\n?)+', num_list_replace, html, flags=re.MULTILINE) - - # Paragraphs (lines not already in tags) - lines = html.split('\n') - result = [] - for line in lines: - line = line.strip() - if not line: - continue - if line.startswith('<') or line.startswith('{'): - result.append(line) - else: - result.append(f'

{line}

') - - return '\n'.join(result) - -def main(): - print("Reading template...") - with open(TEMPLATE_HTM, 'r', encoding='utf-8', errors='ignore') as f: - html = f.read() - - soup = BeautifulSoup(html, 'html.parser') - - # Read markdown files - print("Reading markdown content...") - md_files = { - 'resumen': read_md('00_resumen.md'), - 'intro': read_md('01_introduccion.md'), - 'contexto': read_md('02_contexto_estado_arte.md'), - 'objetivos': read_md('03_objetivos_metodologia.md'), - 'desarrollo': read_md('04_desarrollo_especifico.md'), - 'conclusiones': read_md('05_conclusiones_trabajo_futuro.md'), - 'referencias': read_md('06_referencias_bibliograficas.md'), - 'anexo': read_md('07_anexo_a.md'), - } - - # Convert markdown to HTML - print("Converting markdown to HTML...") - html_content = {} - for key, md in md_files.items(): - html_content[key] = md_to_html(md) - - # Find and replace content sections - print("Replacing template content...") - - # Find all WordSection divs and main content areas - sections = soup.find_all('div', class_=lambda x: x and 'WordSection' in x) - - # Strategy: Find chapter headings and replace following content - # The template has placeholders we need to replace - - # Simple approach: Create new HTML with template structure but our content - new_html = ''' - - - -TFM - Optimización de Hiperparámetros OCR - - - -''' - - # Title page - new_html += ''' -
-

UNIR Logo

-

Universidad Internacional de La Rioja
Escuela Superior de Ingeniería y Tecnología

-

Máster Universitario en Inteligencia Artificial

-

Optimización de Hiperparámetros OCR con Ray Tune para Documentos Académicos en Español

-

Trabajo Fin de Estudio presentado por: Sergio Jiménez Jiménez

-

Tipo de trabajo: Comparativa de soluciones / Piloto experimental

-

Director: [Nombre del Director]

-

Fecha: 2025

-
-''' - - # Resumen - new_html += '
\n' - new_html += html_content['resumen'] - new_html += '
\n' - - # Table of contents placeholder - new_html += ''' -
-

Índice de contenidos

-

[El índice se generará automáticamente en Word]

-
-''' - - # Chapters - chapters = [ - ('intro', 'introduccion'), - ('contexto', 'contexto'), - ('objetivos', 'objetivos'), - ('desarrollo', 'desarrollo'), - ('conclusiones', 'conclusiones'), - ] - - for key, _ in chapters: - new_html += '
\n' - new_html += html_content[key] - new_html += '
\n' - - # Referencias - new_html += '
\n' - new_html += html_content['referencias'] - new_html += '
\n' - - # Anexo - new_html += '
\n' - new_html += html_content['anexo'] - new_html += '
\n' - - new_html += '' - - # Save HTML - print(f"Saving HTML to {OUTPUT_HTM}...") - with open(OUTPUT_HTM, 'w', encoding='utf-8') as f: - f.write(new_html) - - # Copy template files folder - if os.path.exists(OUTPUT_FILES): - shutil.rmtree(OUTPUT_FILES) - if os.path.exists(TEMPLATE_FILES): - shutil.copytree(TEMPLATE_FILES, OUTPUT_FILES) - - # Create UNIR logo placeholder if not exists - os.makedirs(OUTPUT_FILES, exist_ok=True) - - # Convert to DOCX using pandoc - print(f"Converting to DOCX with pandoc...") - result = subprocess.run([ - 'pandoc', - OUTPUT_HTM, - '-o', OUTPUT_DOCX, - '--reference-doc', os.path.join(BASE_DIR, 'instructions/plantilla_individual.docx'), - '--toc', - '--toc-depth=3' - ], capture_output=True, text=True) - - if result.returncode != 0: - print(f"Pandoc error: {result.stderr}") - # Try without reference doc - print("Retrying without reference doc...") - result = subprocess.run([ - 'pandoc', - OUTPUT_HTM, - '-o', OUTPUT_DOCX, - '--toc', - '--toc-depth=3' - ], capture_output=True, text=True) - - if result.returncode == 0: - print(f"✓ Document saved to {OUTPUT_DOCX}") - print(f"✓ HTML version saved to {OUTPUT_HTM}") - else: - print(f"Error: {result.stderr}") - -if __name__ == '__main__': - main() diff --git a/generate_thesis_docx.py b/generate_thesis_docx.py deleted file mode 100644 index 32194f0..0000000 --- a/generate_thesis_docx.py +++ /dev/null @@ -1,438 +0,0 @@ -#!/usr/bin/env python3 -""" -Generate thesis.docx from markdown files using UNIR template. -""" - -import re -import os -from docx import Document -from docx.shared import Pt, Cm, RGBColor, Inches -from docx.enum.text import WD_ALIGN_PARAGRAPH -from docx.enum.style import WD_STYLE_TYPE -from docx.oxml.ns import qn -from docx.oxml import OxmlElement - -# Paths -TEMPLATE_PATH = 'instructions/plantilla_individual.docx' -OUTPUT_PATH = 'TFM_Sergio_Jimenez_OCR_Optimization.docx' -DOCS_PATH = 'docs' - -# Thesis metadata -THESIS_TITLE = "Optimización de Hiperparámetros OCR con Ray Tune para Documentos Académicos en Español" -AUTHOR = "Sergio Jiménez Jiménez" -DIRECTOR = "[Nombre del Director]" -DATE = "2025" - - -def read_markdown_file(filepath): - """Read markdown file and return content.""" - with open(filepath, 'r', encoding='utf-8') as f: - return f.read() - - -def parse_markdown_blocks(md_content): - """Parse markdown content into blocks (headers, paragraphs, code, tables, lists).""" - blocks = [] - lines = md_content.split('\n') - i = 0 - - while i < len(lines): - line = lines[i] - - # Skip empty lines - if not line.strip(): - i += 1 - continue - - # Code block - if line.strip().startswith('```'): - lang = line.strip()[3:] - code_lines = [] - i += 1 - while i < len(lines) and not lines[i].strip().startswith('```'): - code_lines.append(lines[i]) - i += 1 - blocks.append({'type': 'code', 'lang': lang, 'content': '\n'.join(code_lines)}) - i += 1 - continue - - # Headers - if line.startswith('#'): - level = len(line) - len(line.lstrip('#')) - text = line.lstrip('#').strip() - # Remove {.unnumbered} suffix - text = re.sub(r'\s*\{\.unnumbered\}\s*$', '', text) - blocks.append({'type': 'header', 'level': level, 'content': text}) - i += 1 - continue - - # Table - if '|' in line and i + 1 < len(lines) and '---' in lines[i + 1]: - table_lines = [line] - i += 1 - while i < len(lines) and '|' in lines[i]: - table_lines.append(lines[i]) - i += 1 - blocks.append({'type': 'table', 'content': table_lines}) - continue - - # Blockquote - if line.startswith('>'): - quote_text = line[1:].strip() - i += 1 - while i < len(lines) and lines[i].startswith('>'): - quote_text += ' ' + lines[i][1:].strip() - i += 1 - blocks.append({'type': 'quote', 'content': quote_text}) - continue - - # List item (bullet or numbered) - if re.match(r'^[\-\*\+]\s', line) or re.match(r'^\d+\.\s', line): - list_items = [] - list_type = 'numbered' if re.match(r'^\d+\.', line) else 'bullet' - while i < len(lines): - current = lines[i] - if re.match(r'^[\-\*\+]\s', current): - list_items.append(current[2:].strip()) - i += 1 - elif re.match(r'^\d+\.\s', current): - list_items.append(re.sub(r'^\d+\.\s*', '', current).strip()) - i += 1 - elif current.strip() == '': - break - else: - break - blocks.append({'type': 'list', 'list_type': list_type, 'items': list_items}) - continue - - # Figure caption (italic text starting with *Figura or Figura) - if line.strip().startswith('*Figura') or line.strip().startswith('Figura'): - blocks.append({'type': 'caption', 'content': line.strip().strip('*')}) - i += 1 - continue - - # Regular paragraph - para_lines = [line] - i += 1 - while i < len(lines) and lines[i].strip() and not lines[i].startswith('#') and not lines[i].startswith('```') and not lines[i].startswith('>') and not re.match(r'^[\-\*\+]\s', lines[i]) and not re.match(r'^\d+\.\s', lines[i]) and '|' not in lines[i]: - para_lines.append(lines[i]) - i += 1 - - para_text = ' '.join(para_lines) - blocks.append({'type': 'paragraph', 'content': para_text}) - - return blocks - - -def add_formatted_text(paragraph, text): - """Add text with inline formatting (bold, italic, code) to a paragraph.""" - # Pattern for inline formatting - parts = re.split(r'(\*\*[^*]+\*\*|\*[^*]+\*|`[^`]+`)', text) - - for part in parts: - if not part: - continue - if part.startswith('**') and part.endswith('**'): - run = paragraph.add_run(part[2:-2]) - run.bold = True - elif part.startswith('*') and part.endswith('*'): - run = paragraph.add_run(part[1:-1]) - run.italic = True - elif part.startswith('`') and part.endswith('`'): - run = paragraph.add_run(part[1:-1]) - run.font.name = 'Consolas' - run.font.size = Pt(10) - else: - paragraph.add_run(part) - - -def add_table_to_doc(doc, table_lines): - """Add a markdown table to the document.""" - # Parse table - rows = [] - for line in table_lines: - if '---' in line: - continue - cells = [c.strip() for c in line.split('|')[1:-1]] - if cells: - rows.append(cells) - - if not rows: - return - - # Create table - num_cols = len(rows[0]) - table = doc.add_table(rows=len(rows), cols=num_cols) - table.style = 'Table Grid' - - for i, row_data in enumerate(rows): - row = table.rows[i] - for j, cell_text in enumerate(row_data): - if j < len(row.cells): - cell = row.cells[j] - cell.text = '' - para = cell.paragraphs[0] - add_formatted_text(para, cell_text) - if i == 0: # Header row - for run in para.runs: - run.bold = True - - # Add spacing after table - doc.add_paragraph() - - -def add_code_block(doc, code, lang=''): - """Add a code block to the document.""" - para = doc.add_paragraph() - para.paragraph_format.left_indent = Cm(0.5) - para.paragraph_format.space_before = Pt(6) - para.paragraph_format.space_after = Pt(6) - - run = para.add_run(code) - run.font.name = 'Consolas' - run.font.size = Pt(9) - - # Add background shading - shading = OxmlElement('w:shd') - shading.set(qn('w:fill'), 'F5F5F5') - para._p.get_or_add_pPr().append(shading) - - -def get_header_style(level, is_numbered=True): - """Get the appropriate style for a header level.""" - if level == 1: - return 'Heading 1' - elif level == 2: - return 'Heading 2' - elif level == 3: - return 'Heading 3' - elif level == 4: - return 'Heading 4' - else: - return 'Normal' - - -def add_section_content(doc, md_content, start_numbered=True): - """Add markdown content to the document with proper formatting.""" - blocks = parse_markdown_blocks(md_content) - - for block in blocks: - if block['type'] == 'header': - level = block['level'] - text = block['content'] - - # Map markdown header levels to document styles - # ## (level 2) -> Heading 2 (subsection like 1.1. Motivación) - # ### (level 3) -> Heading 3 (sub-subsection like 1.1.1. xxx) - # #### (level 4) -> Heading 4 - - if level == 1: - # Skip level 1 headers - they're added separately as chapter titles - continue - elif level == 2: - para = doc.add_paragraph(text, style='Heading 2') - elif level == 3: - para = doc.add_paragraph(text, style='Heading 3') - elif level == 4: - para = doc.add_paragraph(text, style='Heading 4') - else: - para = doc.add_paragraph(text) - if para.runs: - para.runs[0].bold = True - - elif block['type'] == 'paragraph': - para = doc.add_paragraph() - add_formatted_text(para, block['content']) - - elif block['type'] == 'code': - add_code_block(doc, block['content'], block.get('lang', '')) - - elif block['type'] == 'table': - add_table_to_doc(doc, block['content']) - - elif block['type'] == 'quote': - para = doc.add_paragraph() - para.paragraph_format.left_indent = Cm(1) - para.paragraph_format.right_indent = Cm(1) - add_formatted_text(para, block['content']) - for run in para.runs: - run.italic = True - - elif block['type'] == 'list': - for item in block['items']: - if block['list_type'] == 'bullet': - para = doc.add_paragraph(style='List Paragraph') - para.paragraph_format.left_indent = Cm(1) - add_formatted_text(para, '• ' + item) - else: - para = doc.add_paragraph(style='List Paragraph') - para.paragraph_format.left_indent = Cm(1) - add_formatted_text(para, item) - - elif block['type'] == 'caption': - para = doc.add_paragraph() - para.alignment = WD_ALIGN_PARAGRAPH.CENTER - run = para.add_run(block['content']) - run.italic = True - run.font.size = Pt(10) - - -def create_thesis_document(): - """Create the thesis document from template and markdown files.""" - print("Loading template...") - doc = Document(TEMPLATE_PATH) - - # Find and update title on cover page - for para in doc.paragraphs[:20]: - if 'Título del TFE' in para.text or 'titulo del TFE' in para.text.lower(): - para.clear() - run = para.add_run(THESIS_TITLE) - run.bold = True - - # Clear template content after indices (keep cover, resumen structure) - # We'll find where actual content starts and replace it - - # Read all markdown files - print("Reading markdown files...") - md_files = { - 'resumen': read_markdown_file(os.path.join(DOCS_PATH, '00_resumen.md')), - 'introduccion': read_markdown_file(os.path.join(DOCS_PATH, '01_introduccion.md')), - 'contexto': read_markdown_file(os.path.join(DOCS_PATH, '02_contexto_estado_arte.md')), - 'objetivos': read_markdown_file(os.path.join(DOCS_PATH, '03_objetivos_metodologia.md')), - 'desarrollo': read_markdown_file(os.path.join(DOCS_PATH, '04_desarrollo_especifico.md')), - 'conclusiones': read_markdown_file(os.path.join(DOCS_PATH, '05_conclusiones_trabajo_futuro.md')), - 'referencias': read_markdown_file(os.path.join(DOCS_PATH, '06_referencias_bibliograficas.md')), - 'anexo': read_markdown_file(os.path.join(DOCS_PATH, '07_anexo_a.md')), - } - - # Create new document based on template but with our content - print("Creating new document with thesis content...") - - # Start fresh document with template styles - new_doc = Document(TEMPLATE_PATH) - - # Clear all content after a certain point - # Keep first ~70 paragraphs (cover + resumen structure + indices) - paras_to_remove = [] - found_intro = False - for i, para in enumerate(new_doc.paragraphs): - if 'Introducción' in para.text and para.style and 'Heading 1' in para.style.name: - found_intro = True - if found_intro: - paras_to_remove.append(para) - - # Remove old content - for para in paras_to_remove: - p = para._element - p.getparent().remove(p) - - # Now add our content - print("Adding thesis content...") - - # Add each chapter - chapters = [ - ('introduccion', '1. Introducción'), - ('contexto', '2. Contexto y estado del arte'), - ('objetivos', '3. Objetivos concretos y metodología de trabajo'), - ('desarrollo', '4. Desarrollo específico de la contribución'), - ('conclusiones', '5. Conclusiones y trabajo futuro'), - ] - - for key, title in chapters: - print(f" Adding chapter: {title}") - # Add chapter heading with Heading 1 style - new_doc.add_paragraph(title, style='Heading 1') - - # Remove the top-level header from content (we added it separately with proper style) - content = md_files[key] - # Remove the first # header line and intro paragraph that follows - content = re.sub(r'^#\s+\d+\.\s+[^\n]+\n+', '', content) - add_section_content(new_doc, content) - new_doc.add_page_break() - - # Add Referencias - print(" Adding Referencias bibliográficas") - para = new_doc.add_paragraph('Referencias bibliográficas', style='Título 1 sin numerar') - refs_content = md_files['referencias'] - refs_content = re.sub(r'^#[^\n]+\n+', '', refs_content) # Remove header - - # Parse references (each reference is a paragraph) - for line in refs_content.split('\n\n'): - if line.strip(): - para = new_doc.add_paragraph() - para.paragraph_format.left_indent = Cm(1.27) - para.paragraph_format.first_line_indent = Cm(-1.27) - add_formatted_text(para, line.strip()) - - new_doc.add_page_break() - - # Add Anexo - print(" Adding Anexo A") - para = new_doc.add_paragraph('Anexo A. Código fuente y datos analizados', style='Título 1 sin numerar') - anexo_content = md_files['anexo'] - anexo_content = re.sub(r'^#[^\n]+\n+', '', anexo_content) - add_section_content(new_doc, anexo_content) - - # Update Resumen/Abstract sections (find them in the document and update) - print("Updating Resumen and Abstract...") - resumen_content = md_files['resumen'] - - # Parse resumen file to extract Spanish and English parts - resumen_blocks = parse_markdown_blocks(resumen_content) - spanish_paragraphs = [] - english_paragraphs = [] - keywords_es = "" - keywords_en = "" - current_section = None - - for block in resumen_blocks: - if block['type'] == 'header': - if 'Resumen' in block['content']: - current_section = 'es' - elif 'Abstract' in block['content']: - current_section = 'en' - elif block['type'] == 'paragraph': - text = block['content'] - if 'Palabras clave:' in text: - keywords_es = text - elif 'Keywords:' in text: - keywords_en = text - elif current_section == 'es' and text.strip(): - spanish_paragraphs.append(text) - elif current_section == 'en' and text.strip(): - english_paragraphs.append(text) - - # Find and update Resumen section in doc - found_resumen = False - found_abstract = False - for i, para in enumerate(new_doc.paragraphs): - text = para.text.strip() - - if 'Resumen' in text and para.style and 'Título' in para.style.name: - found_resumen = True - # Update following paragraphs - for j, sp in enumerate(spanish_paragraphs[:3]): # Limit to first 3 paragraphs - if i + j + 1 < len(new_doc.paragraphs): - target_para = new_doc.paragraphs[i + j + 1] - if target_para.style and target_para.style.name == 'Normal': - target_para.clear() - add_formatted_text(target_para, sp) - - elif 'Abstract' in text and para.style and 'Título' in para.style.name: - found_abstract = True - for j, ep in enumerate(english_paragraphs[:3]): - if i + j + 1 < len(new_doc.paragraphs): - target_para = new_doc.paragraphs[i + j + 1] - if target_para.style and target_para.style.name == 'Normal': - target_para.clear() - add_formatted_text(target_para, ep) - - # Save document - print(f"Saving document to {OUTPUT_PATH}...") - new_doc.save(OUTPUT_PATH) - print(f"Done! Document saved as {OUTPUT_PATH}") - - -if __name__ == '__main__': - os.chdir('/Users/sergio/Desktop/MastersThesis') - create_thesis_document() diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c4ec9ca --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4127 @@ +{ + "name": "MastersThesis", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@mermaid-js/mermaid-cli": "^11.12.0" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "license": "MIT", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz", + "integrity": "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==", + "license": "MIT" + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "license": "Apache-2.0", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==", + "license": "Apache-2.0" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", + "license": "Apache-2.0" + }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.27.16", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.16.tgz", + "integrity": "sha512-9O8N4SeG2z++TSM8QA/KTeKFBVCNEz/AGS7gWPJf6KFRzmRWixFRnCnkPHRDwSVZW6QPDO6uT0P2SpWNKCc9/g==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.6", + "@floating-ui/utils": "^0.2.10", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", + "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.4" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@headlessui/react": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.9.tgz", + "integrity": "sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "^0.26.16", + "@react-aria/focus": "^3.20.2", + "@react-aria/interactions": "^3.25.0", + "@tanstack/react-virtual": "^3.13.9", + "use-sync-external-store": "^1.5.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/@headlessui/react/node_modules/@floating-ui/react": { + "version": "0.26.28", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", + "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.8", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@headlessui/tailwindcss": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@headlessui/tailwindcss/-/tailwindcss-0.2.2.tgz", + "integrity": "sha512-xNe42KjdyA4kfUKLLPGzME9zkH7Q3rOZ5huFihWNWOQFxnItxPB3/67yBI8/qBfY8nwBRx5GHn4VprsoluVMGw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "tailwindcss": "^3.0 || ^4.0" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz", + "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==", + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^1.1.0", + "@iconify/types": "^2.0.0", + "mlly": "^1.8.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mermaid-js/mermaid-cli": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@mermaid-js/mermaid-cli/-/mermaid-cli-11.12.0.tgz", + "integrity": "sha512-a0swOS6PByXKi0dZnLQQIhbtUEu7ubc6bojmIqXqvUPq7mIJukCNEvVBTv6IAbuEWqB3Ti8QntupoGdz3ej+kg==", + "license": "MIT", + "dependencies": { + "@mermaid-js/mermaid-zenuml": "^0.2.0", + "chalk": "^5.0.1", + "commander": "^14.0.0", + "import-meta-resolve": "^4.1.0", + "mermaid": "^11.0.2" + }, + "bin": { + "mmdc": "src/cli.js" + }, + "engines": { + "node": "^18.19 || >=20.0" + }, + "peerDependencies": { + "puppeteer": "^23" + } + }, + "node_modules/@mermaid-js/mermaid-zenuml": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@mermaid-js/mermaid-zenuml/-/mermaid-zenuml-0.2.2.tgz", + "integrity": "sha512-sUjwk4NWUpy9uaHypYSIGJDks10ZaZo5CHH9lx9xcmyqv9w7yvd4vecUmlUQxmlHStYO+aqSkYKX5/gFjDfypw==", + "license": "MIT", + "dependencies": { + "@zenuml/core": "^3.35.2" + }, + "peerDependencies": { + "mermaid": "^10 || ^11" + } + }, + "node_modules/@mermaid-js/parser": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.3.tgz", + "integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==", + "license": "MIT", + "dependencies": { + "langium": "3.3.1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@puppeteer/browsers": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.6.1.tgz", + "integrity": "sha512-aBSREisdsGH890S2rQqK82qmQYU3uFpSH8wcZWHgHzl3LfzsxAKbLNiAG9mO8v1Y0UICBeClICxPJvyr0rcuxg==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.4.0", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.5.0", + "semver": "^7.6.3", + "tar-fs": "^3.0.6", + "unbzip2-stream": "^1.4.3", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-aria/focus": { + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.21.2.tgz", + "integrity": "sha512-JWaCR7wJVggj+ldmM/cb/DXFg47CXR55lznJhZBh4XVqJjMKwaOOqpT5vNN7kpC1wUpXicGNuDnJDN1S/+6dhQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.25.6", + "@react-aria/utils": "^3.31.0", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/interactions": { + "version": "3.25.6", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.6.tgz", + "integrity": "sha512-5UgwZmohpixwNMVkMvn9K1ceJe6TzlRlAfuYoQDUuOkk62/JVJNDLAPKIf5YMRc7d2B0rmfgaZLMtbREb0Zvkw==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-aria/utils": "^3.31.0", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.10.tgz", + "integrity": "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/utils": { + "version": "3.31.0", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.31.0.tgz", + "integrity": "sha512-ABOzCsZrWzf78ysswmguJbx3McQUja7yeGj6/vZo4JVsZNlxAN+E9rs381ExBRI0KzVo6iBTeX5De8eMZPJXig==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/ssr": "^3.9.10", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.10.8", + "@react-types/shared": "^3.32.1", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/flags": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.2.tgz", + "integrity": "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@react-stately/utils": { + "version": "3.10.8", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.8.tgz", + "integrity": "sha512-SN3/h7SzRsusVQjQ4v10LaVsDc81jyyR0DD5HnsQitm/I5WDpaSr2nRHtyloPFU48jlql1XX/S04T2DLQM7Y3g==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/shared": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.32.1.tgz", + "integrity": "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", + "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tanstack/react-virtual": { + "version": "3.13.13", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.13.tgz", + "integrity": "sha512-4o6oPMDvQv+9gMi8rE6gWmsOjtUZUYIJHv7EB+GblyYdi8U6OqLl8rhHWIUZSL1dUU2dPwTdTgybCKf9EjIrQg==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.13.13" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.13.13", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.13.tgz", + "integrity": "sha512-uQFoSdKKf5S8k51W5t7b2qpfkyIbdHMzAn+AMQvHPxKUPeo1SsGaA4JRISQT87jm28b7z8OEqPcg1IOZagQHcA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "license": "MIT" + }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "license": "MIT", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==", + "license": "MIT" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==", + "license": "MIT" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "license": "MIT", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==", + "license": "MIT" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==", + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==", + "license": "MIT" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==", + "license": "MIT" + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", + "license": "MIT" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.0.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.2.tgz", + "integrity": "sha512-gWEkeiyYE4vqjON/+Obqcoeffmk0NF15WSBwSs7zwVA2bAbTaE0SJ7P0WNGoJn8uE7fiaV5a7dKYIJriEqOrmA==", + "license": "MIT", + "optional": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@zenuml/core": { + "version": "3.43.2", + "resolved": "https://registry.npmjs.org/@zenuml/core/-/core-3.43.2.tgz", + "integrity": "sha512-p08Wu7wlTb2sHNjE7NrUhlEA9c/TLhi9T13lysHhEwxa1VFsdkwJr5x4wK622VtH2Lq3t7TDNXELvcjWp2kp0Q==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "^0.27.8", + "@headlessui/react": "^2.2.1", + "@headlessui/tailwindcss": "^0.2.2", + "antlr4": "~4.11.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "color-string": "^2.0.1", + "dompurify": "^3.2.5", + "highlight.js": "^10.7.3", + "html-to-image": "^1.11.13", + "immer": "^10.1.1", + "jotai": "^2.12.2", + "lodash": "^4.17.21", + "marked": "^4.3.0", + "pako": "^2.1.0", + "pino": "^8.8.0", + "radash": "^12.1.0", + "ramda": "^0.28.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^3.1.0", + "tailwindcss": "^3.4.17" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/antlr4": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.11.0.tgz", + "integrity": "sha512-GUGlpE2JUjAN+G8G5vY+nOoeyNhHsXoIJwP1XF1oRw89vifA1K46T6SEkwLwr7drihN7I/lf0DIjKc4OZvBX8w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=14" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/b4a": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/bare-fs": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.2.tgz", + "integrity": "sha512-veTnRzkb6aPHOvSKIOy60KzURfBdUflr5VReI+NSaPL6xf+XLdONQgZgpYvUuZLVQ8dCqxpBAudaOM1+KpAUxw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" + }, + "engines": { + "bare": ">=1.16.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-os": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz", + "integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "bare": ">=1.14.0" + } + }, + "node_modules/bare-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", + "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-os": "^3.0.1" + } + }, + "node_modules/bare-stream": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz", + "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "streamx": "^2.21.0" + }, + "peerDependencies": { + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, + "node_modules/bare-url": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.3.2.tgz", + "integrity": "sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-path": "^3.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chromium-bidi": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.11.0.tgz", + "integrity": "sha512-6CJWHkNRoyZyjV9Rwv2lYONZf1Xm0IuDyNq97nwSsxxP3wf5Bwy15K5rOvVKMtJ127jJBmxFUanSAOjgFRxgrA==", + "license": "Apache-2.0", + "dependencies": { + "mitt": "3.0.1", + "zod": "3.23.8" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-convert/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/color-string": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", + "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/commander": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", + "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "license": "MIT" + }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "license": "MIT", + "dependencies": { + "layout-base": "^1.0.0" + } + }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cytoscape": { + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", + "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "license": "MIT", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "license": "MIT", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==", + "license": "MIT" + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "license": "BSD-3-Clause", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", + "license": "ISC" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre-d3-es": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.13.tgz", + "integrity": "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==", + "license": "MIT", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "license": "MIT", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, + "node_modules/devtools-protocol": { + "version": "0.0.1367902", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1367902.tgz", + "integrity": "sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==", + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" + }, + "node_modules/dompurify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", + "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", + "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", + "license": "MIT", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==", + "license": "MIT" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/html-to-image": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz", + "integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==", + "license": "MIT" + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/immer": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz", + "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/ip-address": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", + "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "license": "MIT", + "peer": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/jotai": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.16.0.tgz", + "integrity": "sha512-NmkwPBet0SHQ28GBfEb10sqnbVOYyn6DL4iazZgGRDUKxSWL0iqcm+IK4TqTSFC2ixGk+XX2e46Wbv364a3cKg==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0", + "@babel/template": ">=7.0.0", + "@types/react": ">=17.0.0", + "react": ">=17.0.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@babel/template": { + "optional": true + }, + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/katex": { + "version": "0.16.27", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.27.tgz", + "integrity": "sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" + }, + "node_modules/langium": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", + "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "license": "MIT", + "dependencies": { + "chevrotain": "~11.0.3", + "chevrotain-allstar": "~0.3.0", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.0.8" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", + "license": "MIT" + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/mermaid": { + "version": "11.12.2", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.2.tgz", + "integrity": "sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==", + "license": "MIT", + "peer": true, + "dependencies": { + "@braintree/sanitize-url": "^7.1.1", + "@iconify/utils": "^3.0.1", + "@mermaid-js/parser": "^0.6.3", + "@types/d3": "^7.4.3", + "cytoscape": "^3.29.3", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.13", + "dayjs": "^1.11.18", + "dompurify": "^3.2.5", + "katex": "^0.16.22", + "khroma": "^2.1.0", + "lodash-es": "^4.17.21", + "marked": "^16.2.1", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0" + } + }, + "node_modules/mermaid/node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", + "license": "MIT", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "license": "MIT", + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "license": "MIT" + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==", + "license": "MIT" + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pino": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-8.21.0.tgz", + "integrity": "sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^6.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^3.7.0", + "thread-stream": "^2.6.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "license": "MIT", + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", + "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==", + "license": "MIT" + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==", + "license": "MIT" + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "license": "MIT", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/puppeteer": { + "version": "23.11.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.11.1.tgz", + "integrity": "sha512-53uIX3KR5en8l7Vd8n5DUv90Ae9QDQsyIthaUFVzwV6yU750RjqRznEtNMBT20VthqAdemnJN+hxVdmMHKt7Zw==", + "deprecated": "< 24.15.0 is no longer supported", + "hasInstallScript": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@puppeteer/browsers": "2.6.1", + "chromium-bidi": "0.11.0", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1367902", + "puppeteer-core": "23.11.1", + "typed-query-selector": "^2.12.0" + }, + "bin": { + "puppeteer": "lib/cjs/puppeteer/node/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/puppeteer-core": { + "version": "23.11.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.11.1.tgz", + "integrity": "sha512-3HZ2/7hdDKZvZQ7dhhITOUg4/wOrDRjyK2ZBllRB0ZCOi9u0cwq1ACHDjBB+nX+7+kltHjQvBRdeY7+W0T+7Gg==", + "license": "Apache-2.0", + "dependencies": { + "@puppeteer/browsers": "2.6.1", + "chromium-bidi": "0.11.0", + "debug": "^4.4.0", + "devtools-protocol": "0.0.1367902", + "typed-query-selector": "^2.12.0", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, + "node_modules/radash": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/radash/-/radash-12.1.1.tgz", + "integrity": "sha512-h36JMxKRqrAxVD8201FrCpyeNuUY9Y5zZwujr20fFO77tpUtGa6EZzfKw/3WaiBX95fq7+MpsuMLNdSnORAwSA==", + "license": "MIT", + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/ramda": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.28.0.tgz", + "integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/react": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", + "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.3" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", + "license": "Unlicense" + }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "license": "MIT", + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "license": "MIT", + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/sonic-boom": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", + "integrity": "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "license": "MIT" + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tabbable": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.3.0.tgz", + "integrity": "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ==", + "license": "MIT" + }, + "node_modules/tailwind-merge": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz", + "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tar-fs": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", + "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/thread-stream": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.7.0.tgz", + "integrity": "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "license": "Apache-2.0" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typed-query-selector": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", + "license": "MIT" + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "license": "MIT" + }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "license": "MIT", + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/unbzip2-stream/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT", + "optional": true + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8fff7f3 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@mermaid-js/mermaid-cli": "^11.12.0" + } +} diff --git a/thesis_output.htm b/thesis_output.htm deleted file mode 100644 index 0845de9..0000000 --- a/thesis_output.htm +++ /dev/null @@ -1,751 +0,0 @@ - - - - -TFM - Optimización de Hiperparámetros OCR - - - - -
-

UNIR Logo

-

Universidad Internacional de La Rioja
Escuela Superior de Ingeniería y Tecnología

-

Máster Universitario en Inteligencia Artificial

-

Optimización de Hiperparámetros OCR con Ray Tune para Documentos Académicos en Español

-

Trabajo Fin de Estudio presentado por: Sergio Jiménez Jiménez

-

Tipo de trabajo: Comparativa de soluciones / Piloto experimental

-

Director: [Nombre del Director]

-

Fecha: 2025

-
-
-

Resumen

-

El presente Trabajo Fin de Máster aborda la optimización de sistemas de Reconocimiento Óptico de Caracteres (OCR) basados en inteligencia artificial para documentos en español, específicamente en un entorno con recursos computacionales limitados donde el fine-tuning de modelos no es viable. El objetivo principal es identificar la configuración óptima de hiperparámetros que maximice la precisión del reconocimiento de texto sin requerir entrenamiento adicional de los modelos.

-

Se realizó un estudio comparativo de tres soluciones OCR de código abierto: EasyOCR, PaddleOCR (PP-OCRv5) y DocTR, evaluando su rendimiento mediante las métricas estándar CER (Character Error Rate) y WER (Word Error Rate) sobre un corpus de documentos académicos en español. Tras identificar PaddleOCR como la solución más prometedora, se procedió a una optimización sistemática de hiperparámetros utilizando Ray Tune con el algoritmo de búsqueda Optuna, ejecutando 64 configuraciones diferentes.

-

Los resultados demuestran que la optimización de hiperparámetros logró una mejora significativa del rendimiento: el CER se redujo de 7.78% a 1.49% (mejora del 80.9% en reducción de errores), alcanzando una precisión de caracteres del 98.51%. El hallazgo más relevante fue que el parámetro textline_orientation (clasificación de orientación de línea de texto) tiene un impacto crítico, reduciendo el CER en un 69.7% cuando está habilitado. Adicionalmente, se identificó que el umbral de detección de píxeles (text_det_thresh) presenta una correlación negativa fuerte (-0.52) con el error, siendo el parámetro continuo más influyente.

-

Este trabajo demuestra que es posible obtener mejoras sustanciales en sistemas OCR mediante optimización de hiperparámetros, ofreciendo una alternativa práctica al fine-tuning cuando los recursos computacionales son limitados.

-Palabras clave: OCR, Reconocimiento Óptico de Caracteres, PaddleOCR, Optimización de Hiperparámetros, Ray Tune, Procesamiento de Documentos, Inteligencia Artificial -

---

-

Abstract

-

This Master's Thesis addresses the optimization of Artificial Intelligence-based Optical Character Recognition (OCR) systems for Spanish documents, specifically in a resource-constrained environment where model fine-tuning is not feasible. The main objective is to identify the optimal hyperparameter configuration that maximizes text recognition accuracy without requiring additional model training.

-

A comparative study of three open-source OCR solutions was conducted: EasyOCR, PaddleOCR (PP-OCRv5), and DocTR, evaluating their performance using standard CER (Character Error Rate) and WER (Word Error Rate) metrics on a corpus of academic documents in Spanish. After identifying PaddleOCR as the most promising solution, systematic hyperparameter optimization was performed using Ray Tune with the Optuna search algorithm, executing 64 different configurations.

-

Results demonstrate that hyperparameter optimization achieved significant performance improvement: CER was reduced from 7.78% to 1.49% (80.9% error reduction), achieving 98.51% character accuracy. The most relevant finding was that the textline_orientation parameter (text line orientation classification) has a critical impact, reducing CER by 69.7% when enabled. Additionally, the pixel detection threshold (text_det_thresh) was found to have a strong negative correlation (-0.52) with error, being the most influential continuous parameter.

-

This work demonstrates that substantial improvements in OCR systems can be obtained through hyperparameter optimization, offering a practical alternative to fine-tuning when computational resources are limited.

-Keywords: OCR, Optical Character Recognition, PaddleOCR, Hyperparameter Optimization, Ray Tune, Document Processing, Artificial Intelligence
- -
-

Índice de contenidos

-

[El índice se generará automáticamente en Word]

-
-
-

1. Introducción

-

Este capítulo presenta la motivación del trabajo, identificando el problema a resolver y justificando su relevancia. Se plantea la pregunta de investigación central y se describe la estructura del documento.

-

1.1. Motivación

-

El Reconocimiento Óptico de Caracteres (OCR) es una tecnología fundamental en la era de la digitalización documental. Su capacidad para convertir imágenes de texto en datos editables y procesables ha transformado sectores como la administración pública, el ámbito legal, la banca y la educación. Sin embargo, a pesar de los avances significativos impulsados por el aprendizaje profundo, la implementación práctica de sistemas OCR de alta precisión sigue presentando desafíos considerables.

-

El procesamiento de documentos en español presenta particularidades que complican el reconocimiento automático de texto. Los caracteres especiales (ñ, acentos), las variaciones tipográficas en documentos académicos y administrativos, y la presencia de elementos gráficos como tablas, encabezados y marcas de agua generan errores que pueden propagarse en aplicaciones downstream como la extracción de entidades nombradas o el análisis semántico.

-

Los modelos OCR basados en redes neuronales profundas, como los empleados en PaddleOCR, EasyOCR o DocTR, ofrecen un rendimiento impresionante en benchmarks estándar. No obstante, su adaptación a dominios específicos típicamente requiere fine-tuning con datos etiquetados del dominio objetivo y recursos computacionales significativos (GPUs de alta capacidad). Esta barrera técnica y económica excluye a muchos investigadores y organizaciones de beneficiarse plenamente de estas tecnologías.

-

La presente investigación surge de una necesidad práctica: optimizar un sistema OCR para documentos académicos en español sin disponer de recursos GPU para realizar fine-tuning. Esta restricción, lejos de ser una limitación excepcional, representa la realidad de muchos entornos académicos y empresariales donde el acceso a infraestructura de cómputo avanzada es limitado.

-

1.2. Planteamiento del trabajo

-

El problema central que aborda este trabajo puede formularse de la siguiente manera:

-
¿Es posible mejorar significativamente el rendimiento de modelos OCR preentrenados para documentos en español mediante la optimización sistemática de hiperparámetros, sin requerir fine-tuning ni recursos GPU?
-

Este planteamiento se descompone en las siguientes cuestiones específicas:

-
  1. Selección de modelo base: ¿Cuál de las soluciones OCR de código abierto disponibles (EasyOCR, PaddleOCR, DocTR) ofrece el mejor rendimiento base para documentos en español?
-
  1. Impacto de hiperparámetros: ¿Qué hiperparámetros del pipeline OCR tienen mayor influencia en las métricas de error (CER, WER)?
-
  1. Optimización automatizada: ¿Puede un proceso de búsqueda automatizada de hiperparámetros (mediante Ray Tune/Optuna) encontrar configuraciones que superen significativamente los valores por defecto?
-
  1. Viabilidad práctica: ¿Son los tiempos de inferencia y los recursos requeridos compatibles con un despliegue en entornos con recursos limitados?
-

La relevancia de este problema radica en su aplicabilidad inmediata. Una metodología reproducible para optimizar OCR sin fine-tuning beneficiaría a:

-
  • Investigadores que procesan grandes volúmenes de documentos académicos
  • Instituciones educativas que digitalizan archivos históricos
  • Pequeñas y medianas empresas que automatizan flujos documentales
  • Desarrolladores que integran OCR en aplicaciones con restricciones de recursos
-

1.3. Estructura del trabajo

-

El presente documento se organiza en los siguientes capítulos:

-Capítulo 2 - Contexto y Estado del Arte: Se presenta una revisión de las tecnologías OCR basadas en aprendizaje profundo, incluyendo las arquitecturas de detección y reconocimiento de texto, así como los trabajos previos en optimización de estos sistemas. -Capítulo 3 - Objetivos y Metodología: Se definen los objetivos SMART del trabajo y se describe la metodología experimental seguida, incluyendo la preparación del dataset, las métricas de evaluación y el proceso de optimización con Ray Tune. -Capítulo 4 - Desarrollo Específico de la Contribución: Este capítulo presenta el desarrollo completo del estudio comparativo y la optimización de hiperparámetros de sistemas OCR, estructurado en tres secciones: (4.1) planteamiento de la comparativa con la evaluación de EasyOCR, PaddleOCR y DocTR; (4.2) desarrollo de la comparativa con la optimización de hiperparámetros mediante Ray Tune; y (4.3) discusión y análisis de resultados. -Capítulo 5 - Conclusiones y Trabajo Futuro: Se resumen las contribuciones del trabajo, se discute el grado de cumplimiento de los objetivos y se proponen líneas de trabajo futuro. -Anexos: Se incluye el enlace al repositorio de código fuente y datos, así como tablas completas de resultados experimentales.
-
-

2. Contexto y estado del arte

-

Este capítulo presenta el marco teórico y tecnológico en el que se desarrolla el presente trabajo. Se revisan los fundamentos del Reconocimiento Óptico de Caracteres (OCR), la evolución de las técnicas basadas en aprendizaje profundo, las principales soluciones de código abierto disponibles y los trabajos previos relacionados con la optimización de sistemas OCR.

-

2.1. Contexto del problema

-

Definición y Evolución Histórica del OCR

-

El Reconocimiento Óptico de Caracteres (OCR) es el proceso de conversión de imágenes de texto manuscrito, mecanografiado o impreso en texto codificado digitalmente. La tecnología OCR ha evolucionado significativamente desde sus orígenes en la década de 1950:

-
  • Primera generación (1950-1970): Sistemas basados en plantillas que requerían fuentes específicas.
  • Segunda generación (1970-1990): Introducción de técnicas de extracción de características y clasificadores estadísticos.
  • Tercera generación (1990-2010): Modelos basados en Redes Neuronales Artificiales y Modelos Ocultos de Markov (HMM).
  • Cuarta generación (2010-presente): Arquitecturas de aprendizaje profundo que dominan el estado del arte.
-

Pipeline Moderno de OCR

-

Los sistemas OCR modernos siguen típicamente un pipeline de dos etapas:

-

``mermaid

-

flowchart LR

-

subgraph Input

-

A["Imagen de
documento"]

-

end

-

subgraph "Etapa 1: Detección"

-

B["Text Detection
(DB, EAST, CRAFT)"]

-

end

-

subgraph "Etapa 2: Reconocimiento"

-

C["Text Recognition
(CRNN, SVTR, Transformer)"]

-

end

-

subgraph Output

-

D["Texto
extraído"]

-

end

-

A --> B

-

B -->|"Regiones de texto
(bounding boxes)"| C

-

C --> D

-

style A fill:#e1f5fe

-

style D fill:#c8e6c9

-
` -Figura 1. Pipeline típico de un sistema OCR moderno con etapas de detección y reconocimiento. -
  1. Detección de texto (Text Detection): Localización de regiones que contienen texto en la imagen. Las arquitecturas más utilizadas incluyen:
- EAST (Efficient and Accurate Scene Text Detector) -

- CRAFT (Character Region Awareness for Text Detection)

-

- DB (Differentiable Binarization)

-
  1. Reconocimiento de texto (Text Recognition): Transcripción del contenido textual de las regiones detectadas. Las arquitecturas predominantes son:
- CRNN (Convolutional Recurrent Neural Network) con CTC loss -

- Arquitecturas encoder-decoder con atención

-

- Transformers (ViTSTR, TrOCR)

-

Métricas de Evaluación

-

Las métricas estándar para evaluar sistemas OCR son:

-Character Error Rate (CER): Se calcula como CER = (S + D + I) / N, donde S = sustituciones, D = eliminaciones, I = inserciones, N = caracteres de referencia. -Word Error Rate (WER): Se calcula de forma análoga pero a nivel de palabras en lugar de caracteres. -

Un CER del 1% significa que 1 de cada 100 caracteres es erróneo. Para aplicaciones críticas como extracción de datos financieros o médicos, se requieren CER inferiores al 1%.

-

Particularidades del OCR para el Idioma Español

-

El español presenta características específicas que impactan el OCR:

-
  • Caracteres especiales: ñ, á, é, í, ó, ú, ü, ¿, ¡
  • Diacríticos: Los acentos pueden confundirse con ruido o artefactos
  • Longitud de palabras: Palabras generalmente más largas que en inglés
  • Puntuación: Signos de interrogación y exclamación invertidos
-

2.2. Estado del arte

-

Soluciones OCR de Código Abierto

-

EasyOCR

-

EasyOCR es una biblioteca de OCR desarrollada por Jaided AI (2020) que soporta más de 80 idiomas. Sus características principales incluyen:

-
  • Arquitectura: Detector CRAFT + Reconocedor CRNN/Transformer
  • Fortalezas: Facilidad de uso, soporte multilingüe amplio, bajo consumo de memoria
  • Limitaciones: Menor precisión en documentos complejos, opciones de configuración limitadas
  • Caso de uso ideal: Prototipado rápido y aplicaciones con restricciones de memoria
-

PaddleOCR

-

PaddleOCR es el sistema OCR desarrollado por Baidu como parte del ecosistema PaddlePaddle (2024). La versión PP-OCRv5, utilizada en este trabajo, representa el estado del arte en OCR industrial:

-
  • Arquitectura:
- Detector: DB (Differentiable Binarization) con backbone ResNet (Liao et al., 2020) -

- Reconocedor: SVTR (Scene-Text Visual Transformer Recognition)

-

- Clasificador de orientación opcional

-
  • Hiperparámetros configurables:
-Tabla 1. Hiperparámetros configurables de PaddleOCR. -
ParámetroDescripciónValor por defecto
text_det_threshUmbral de detección de píxeles0.3
text_det_box_threshUmbral de caja de detección0.6
text_det_unclip_ratioCoeficiente de expansión1.5
text_rec_score_threshUmbral de confianza de reconocimiento0.5
use_textline_orientationClasificación de orientaciónFalse
use_doc_orientation_classifyClasificación de orientación de documentoFalse
use_doc_unwarpingCorrección de deformaciónFalse
-Fuente: Documentación oficial de PaddleOCR (PaddlePaddle, 2024). -
  • Fortalezas: Alta precisión, pipeline altamente configurable, modelos específicos para servidor
  • Limitaciones: Mayor complejidad de configuración, dependencia del framework PaddlePaddle
-

DocTR

-

DocTR (Document Text Recognition) es una biblioteca desarrollada por Mindee (2021) orientada a la investigación:

-
  • Arquitectura:
- Detectores: DB, LinkNet -

- Reconocedores: CRNN, SAR, ViTSTR

-
  • Fortalezas: API limpia, orientación académica, salida estructurada de alto nivel
  • Limitaciones: Menor rendimiento en español comparado con PaddleOCR
-

Comparativa de Arquitecturas

-Tabla 2. Comparativa de soluciones OCR de código abierto. -
ModeloTipoComponentesFortalezas Clave
EasyOCREnd-to-end (det + rec)CRAFT + CRNN/TransformerLigero, fácil de usar, multilingüe
PaddleOCREnd-to-end (det + rec + cls)DB + SVTR/CRNNSoporte multilingüe robusto, configurable
DocTREnd-to-end (det + rec)DB/LinkNet + CRNN/SAR/ViTSTROrientado a investigación, API limpia
-Fuente: Documentación oficial de cada herramienta (JaidedAI, 2020; PaddlePaddle, 2024; Mindee, 2021). -

Optimización de Hiperparámetros

-

Fundamentos

-

La optimización de hiperparámetros (HPO) busca encontrar la configuración de parámetros que maximiza (o minimiza) una métrica objetivo (Feurer & Hutter, 2019). A diferencia de los parámetros del modelo (pesos), los hiperparámetros no se aprenden durante el entrenamiento.

-

Los métodos de HPO incluyen:

-
  • Grid Search: Búsqueda exhaustiva en una rejilla predefinida
  • Random Search: Muestreo aleatorio del espacio de búsqueda (Bergstra & Bengio, 2012)
  • Bayesian Optimization: Modelado probabilístico de la función objetivo (Bergstra et al., 2011)
  • Algoritmos evolutivos: Optimización inspirada en evolución biológica
-

Ray Tune y Optuna

-Ray Tune es un framework de optimización de hiperparámetros escalable (Liaw et al., 2018) que permite: -
  • Ejecución paralela de experimentos
  • Early stopping de configuraciones poco prometedoras
  • Integración con múltiples algoritmos de búsqueda
-Optuna es una biblioteca de optimización bayesiana (Akiba et al., 2019) que implementa: -
  • Tree-structured Parzen Estimator (TPE)
  • Pruning de trials no prometedores
  • Visualización de resultados
-

La combinación Ray Tune + Optuna permite búsquedas eficientes en espacios de alta dimensionalidad.

-
`mermaid -

flowchart TD

-

subgraph "Ray Tune"

-

A["Espacio de
búsqueda"]

-

B["Scheduler
(gestión de trials)"]

-

C["Trial 1"]

-

D["Trial 2"]

-

E["Trial N"]

-

end

-

subgraph "Optuna (TPE)"

-

F["Modelo probabilístico
de la función objetivo"]

-

G["Sugiere nueva
configuración"]

-

end

-

subgraph "Evaluación"

-

H["Ejecuta modelo OCR
con config"]

-

I["Calcula métricas
(CER, WER)"]

-

end

-

A --> B

-

B --> C & D & E

-

C & D & E --> H

-

H --> I

-

I -->|"Resultados"| F

-

F --> G

-

G -->|"Nueva config"| B

-

style A fill:#fff3e0

-

style I fill:#e8f5e9

-
`` -Figura 2. Arquitectura de optimización de hiperparámetros con Ray Tune y Optuna. -

HPO en Sistemas OCR

-

La aplicación de HPO a sistemas OCR ha sido explorada principalmente en el contexto de:

-
  1. Preprocesamiento de imagen: Optimización de parámetros de binarización, filtrado y escalado (Liang et al., 2005)
-
  1. Arquitecturas de detección: Ajuste de umbrales de confianza y NMS (Non-Maximum Suppression)
-
  1. Post-procesamiento: Optimización de corrección ortográfica y modelos de lenguaje
-

Sin embargo, existe un vacío en la literatura respecto a la optimización sistemática de los hiperparámetros de inferencia en pipelines OCR modernos como PaddleOCR, especialmente para idiomas diferentes del inglés y chino.

-

Datasets y Benchmarks para Español

-

Los principales recursos para evaluación de OCR en español incluyen:

-
  • FUNSD-ES: Versión en español del dataset de formularios
  • MLT (ICDAR): Multi-Language Text dataset con muestras en español
  • Documentos académicos: Utilizados en este trabajo (instrucciones TFE de UNIR)
-

Los trabajos previos en OCR para español se han centrado principalmente en:

-
  1. Digitalización de archivos históricos (manuscritos coloniales)
  2. Procesamiento de documentos de identidad
  3. Reconocimiento de texto en escenas naturales
-

La optimización de hiperparámetros para documentos académicos en español representa una contribución original de este trabajo.

-

2.3. Conclusiones

-

Este capítulo ha presentado:

-
  1. Los fundamentos del OCR moderno y su pipeline de detección-reconocimiento
  2. Las tres principales soluciones de código abierto: EasyOCR, PaddleOCR y DocTR
  3. Los métodos de optimización de hiperparámetros, con énfasis en Ray Tune y Optuna
  4. Las particularidades del OCR para el idioma español
-

El estado del arte revela que, si bien existen soluciones OCR de alta calidad, su optimización para dominios específicos mediante ajuste de hiperparámetros (sin fine-tuning) ha recibido poca atención. Este trabajo contribuye a llenar ese vacío proponiendo una metodología reproducible para la optimización de PaddleOCR en documentos académicos en español.

-
-

3. Objetivos concretos y metodología de trabajo

-

Este capítulo establece los objetivos del trabajo siguiendo la metodología SMART (Doran, 1981) y describe la metodología experimental empleada para alcanzarlos. Se define un objetivo general y cinco objetivos específicos, todos ellos medibles y verificables.

-

3.1. Objetivo general

-
Optimizar el rendimiento de PaddleOCR para documentos académicos en español mediante ajuste de hiperparámetros, alcanzando un CER inferior al 2% sin requerir fine-tuning del modelo ni recursos GPU dedicados.
-

Justificación SMART del Objetivo General

-
CriterioCumplimiento
Específico (S)Se define claramente qué se quiere lograr: optimizar PaddleOCR mediante ajuste de hiperparámetros para documentos en español
Medible (M)Se establece una métrica cuantificable: CER < 2%
Alcanzable (A)Es viable dado que: (1) PaddleOCR permite configuración de hiperparámetros, (2) Ray Tune posibilita búsqueda automatizada, (3) No se requiere GPU
Relevante (R)El impacto es demostrable: mejora la extracción de texto en documentos académicos sin costes adicionales de infraestructura
Temporal (T)El plazo es un cuatrimestre, correspondiente al TFM
-

3.2. Objetivos específicos

-

OE1: Comparar soluciones OCR de código abierto

-
Evaluar el rendimiento base de EasyOCR, PaddleOCR y DocTR en documentos académicos en español, utilizando CER y WER como métricas, para seleccionar el modelo más prometedor.
-

OE2: Preparar un dataset de evaluación

-
Construir un dataset estructurado de imágenes de documentos académicos en español con su texto de referencia (ground truth) extraído del PDF original.
-

OE3: Identificar hiperparámetros críticos

-
Analizar la correlación entre los hiperparámetros de PaddleOCR y las métricas de error para identificar los parámetros con mayor impacto en el rendimiento.
-

OE4: Optimizar hiperparámetros con Ray Tune

-
Ejecutar una búsqueda automatizada de hiperparámetros utilizando Ray Tune con Optuna, evaluando al menos 50 configuraciones diferentes.
-

OE5: Validar la configuración optimizada

-
Comparar el rendimiento de la configuración baseline versus la configuración optimizada sobre el dataset completo, documentando la mejora obtenida.
-

3.3. Metodología del trabajo

-

3.3.1. Visión General

-

``mermaid

-

flowchart TD

-

A["Fase 1: Preparación del Dataset

-

• Conversión PDF → Imágenes (300 DPI)

-

• Extracción de texto de referencia (PyMuPDF)

-

• Estructura: carpetas img/ y txt/ pareadas"]

-

B["Fase 2: Benchmark Comparativo

-

• Evaluación de EasyOCR, PaddleOCR, DocTR

-

• Métricas: CER, WER

-

• Selección del modelo base"]

-

C["Fase 3: Definición del Espacio de Búsqueda

-

• Identificación de hiperparámetros configurables

-

• Definición de rangos y distribuciones

-

• Configuración de Ray Tune + Optuna"]

-

D["Fase 4: Optimización de Hiperparámetros

-

• Ejecución de 64 trials con Ray Tune

-

• Paralelización (2 trials concurrentes)

-

• Registro de métricas y configuraciones"]

-

E["Fase 5: Validación y Análisis

-

• Comparación baseline vs optimizado

-

• Análisis de correlaciones

-

• Documentación de resultados"]

-

A --> B --> C --> D --> E

-
` -

3.3.2. Fase 1: Preparación del Dataset

-

Fuente de Datos

-

Se utilizaron documentos PDF académicos de UNIR (Universidad Internacional de La Rioja), específicamente las instrucciones para la elaboración del TFE del Máster en Inteligencia Artificial.

-

Proceso de Conversión

-

El script prepare_dataset.ipynb implementa:

-
  1. Conversión PDF a imágenes:
- Biblioteca: PyMuPDF (fitz) -

- Resolución: 300 DPI

-

- Formato de salida: PNG

-
  1. Extracción de texto de referencia:
- Método:
page.get_text("dict") de PyMuPDF -

- Preservación de estructura de líneas

-

- Tratamiento de texto vertical/marginal

-

- Normalización de espacios y saltos de línea

-

Estructura del Dataset

-
`mermaid -

flowchart LR

-

dataset["dataset/"] --> d0["0/"]

-

d0 --> pdf["instrucciones.pdf"]

-

d0 --> img["img/"]

-

img --> img1["page_0001.png"]

-

img --> img2["page_0002.png"]

-

img --> imgN["..."]

-

d0 --> txt["txt/"]

-

txt --> txt1["page_0001.txt"]

-

txt --> txt2["page_0002.txt"]

-

txt --> txtN["..."]

-

dataset --> dots["..."]

-
` -

Clase ImageTextDataset

-

Se implementó una clase Python para cargar pares imagen-texto:

-
`python -

class ImageTextDataset:

-

def __init__(self, root):

-

# Carga pares (imagen, texto) de carpetas pareadas

-

def __getitem__(self, idx):

-

# Retorna (PIL.Image, str)

-
` -

3.3.3. Fase 2: Benchmark Comparativo

-

Modelos Evaluados

-
ModeloVersiónConfiguración
EasyOCR-Idiomas: ['es', 'en']
PaddleOCRPP-OCRv5Modelos server_det + server_rec
DocTR-db_resnet50 + sar_resnet31
-

Métricas de Evaluación

-

Se utilizó la biblioteca jiwer para calcular:

-`python -

from jiwer import wer, cer

-

def evaluate_text(reference, prediction):

-

return {

-

'WER': wer(reference, prediction),

-

'CER': cer(reference, prediction)

-

}

-
` -

3.3.4. Fase 3: Espacio de Búsqueda

-

Hiperparámetros Seleccionados

-
ParámetroTipoRango/ValoresDescripción
use_doc_orientation_classifyBooleano[True, False]Clasificación de orientación del documento
use_doc_unwarpingBooleano[True, False]Corrección de deformación del documento
textline_orientationBooleano[True, False]Clasificación de orientación de línea de texto
text_det_threshContinuo[0.0, 0.7]Umbral de detección de píxeles de texto
text_det_box_threshContinuo[0.0, 0.7]Umbral de caja de detección
text_det_unclip_ratioFijo0.0Coeficiente de expansión (fijado)
text_rec_score_threshContinuo[0.0, 0.7]Umbral de confianza de reconocimiento
-

Configuración de Ray Tune

-
`python -

from ray import tune

-

from ray.tune.search.optuna import OptunaSearch

-

search_space = {

-

"use_doc_orientation_classify": tune.choice([True, False]),

-

"use_doc_unwarping": tune.choice([True, False]),

-

"textline_orientation": tune.choice([True, False]),

-

"text_det_thresh": tune.uniform(0.0, 0.7),

-

"text_det_box_thresh": tune.uniform(0.0, 0.7),

-

"text_det_unclip_ratio": tune.choice([0.0]),

-

"text_rec_score_thresh": tune.uniform(0.0, 0.7),

-

}

-

tuner = tune.Tuner(

-

trainable_paddle_ocr,

-

tune_config=tune.TuneConfig(

-

metric="CER",

-

mode="min",

-

search_alg=OptunaSearch(),

-

num_samples=64,

-

max_concurrent_trials=2

-

)

-

)

-
` -

3.3.5. Fase 4: Ejecución de Optimización

-

Arquitectura de Ejecución

-

Debido a incompatibilidades entre Ray y PaddleOCR en el mismo proceso, se implementó una arquitectura basada en subprocesos:

-
`mermaid -

flowchart LR

-

A["Ray Tune (proceso principal)"]

-

A --> B["Subprocess 1: paddle_ocr_tuning.py --config"]

-

B --> B_out["Retorna JSON con métricas"]

-

A --> C["Subprocess 2: paddle_ocr_tuning.py --config"]

-

C --> C_out["Retorna JSON con métricas"]

-
` -

Script de Evaluación (paddle_ocr_tuning.py)

-

El script recibe hiperparámetros por línea de comandos:

-
`bash -

python paddle_ocr_tuning.py \

-

--pdf-folder ./dataset \

-

--textline-orientation True \

-

--text-det-box-thresh 0.5 \

-

--text-det-thresh 0.4 \

-

--text-rec-score-thresh 0.6

-
` -

Y retorna métricas en formato JSON:

-
`json -{ -

"CER": 0.0125,

-

"WER": 0.1040,

-

"TIME": 331.09,

-

"PAGES": 5,

-

"TIME_PER_PAGE": 66.12

-

}

-
` -

3.3.6. Fase 5: Validación

-

Protocolo de Validación

-
  1. Baseline: Ejecución con configuración por defecto de PaddleOCR
  2. Optimizado: Ejecución con mejor configuración encontrada
  3. Comparación: Evaluación sobre las 24 páginas del dataset completo
  4. Métricas reportadas: CER, WER, tiempo de procesamiento
-

3.3.7. Entorno de Ejecución

-

Hardware

-
ComponenteEspecificación
CPUIntel Core (especificar modelo)
RAM16 GB
GPUNo disponible (ejecución en CPU)
AlmacenamientoSSD
-

Software

-
ComponenteVersión
Sistema OperativoWindows 10/11
Python3.11.9
PaddleOCR3.3.2
PaddlePaddle3.2.2
Ray2.52.1
Optuna4.6.0
-

3.3.8. Limitaciones Metodológicas

-
  1. Tamaño del dataset: El dataset contiene 24 páginas de un único tipo de documento. Resultados pueden no generalizar a otros formatos.
-
  1. Ejecución en CPU: Los tiempos de procesamiento (~70s/página) serían significativamente menores con GPU.
-
  1. Ground truth imperfecto: El texto de referencia extraído de PDF puede contener errores en documentos con layouts complejos.
-
  1. Parámetro fijo: text_det_unclip_ratio` quedó fijado en 0.0 durante todo el experimento por decisión de diseño inicial.
-

3.4. Resumen del capítulo

-

Este capítulo ha establecido:

-
  1. Un objetivo general SMART: alcanzar CER < 2% mediante optimización de hiperparámetros
  2. Cinco objetivos específicos medibles y alcanzables
  3. Una metodología experimental en cinco fases claramente definidas
  4. El espacio de búsqueda de hiperparámetros y la configuración de Ray Tune
  5. Las limitaciones reconocidas del enfoque
-

El siguiente capítulo presenta el desarrollo específico de la contribución, incluyendo el benchmark comparativo de soluciones OCR, la optimización de hiperparámetros y el análisis de resultados.

-
-

4. Desarrollo específico de la contribución

-

Este capítulo presenta el desarrollo completo del estudio comparativo y la optimización de hiperparámetros de sistemas OCR. Se estructura según el tipo de trabajo "Comparativa de soluciones" establecido por las instrucciones de UNIR: planteamiento de la comparativa, desarrollo de la comparativa, y discusión y análisis de resultados.

-

4.1. Planteamiento de la comparativa

-

4.1.1. Introducción

-

Esta sección presenta los resultados del estudio comparativo realizado entre tres soluciones OCR de código abierto: EasyOCR, PaddleOCR y DocTR. Los experimentos fueron documentados en el notebook ocr_benchmark_notebook.ipynb del repositorio. El objetivo es identificar el modelo base más prometedor para la posterior fase de optimización de hiperparámetros.

-

4.1.2. Configuración del Experimento

-

Dataset de Evaluación

-

Se utilizó el documento "Instrucciones para la redacción y elaboración del TFE" del Máster Universitario en Inteligencia Artificial de UNIR, ubicado en la carpeta instructions/.

-Tabla 3. Características del dataset de evaluación. -
CaracterísticaValor
Número de páginas evaluadas5 (páginas 1-5 en benchmark inicial)
FormatoPDF digital (no escaneado)
IdiomaEspañol
Resolución de conversión300 DPI
-Fuente: Elaboración propia. -

Configuración de los Modelos

-

Según el código en ocr_benchmark_notebook.ipynb:

-EasyOCR: -

``python

-

easyocr_reader = easyocr.Reader(['es', 'en']) # Spanish and English

-
` -PaddleOCR (PP-OCRv5): -`python -

paddleocr_model = PaddleOCR(

-

text_detection_model_name="PP-OCRv5_server_det",

-

text_recognition_model_name="PP-OCRv5_server_rec",

-

use_doc_orientation_classify=False,

-

use_doc_unwarping=False,

-

use_textline_orientation=True,

-

)

-
` -

Versión utilizada: PaddleOCR 3.2.0 (según output del notebook)

-DocTR: -
`python -

doctr_model = ocr_predictor(det_arch="db_resnet50", reco_arch="sar_resnet31", pretrained=True)

-
` -

Métricas de Evaluación

-

Se utilizó la biblioteca jiwer para calcular CER y WER:

-`python -

from jiwer import wer, cer

-

def evaluate_text(reference, prediction):

-

return {'WER': wer(reference, prediction), 'CER': cer(reference, prediction)}

-
` -

4.1.3. Resultados del Benchmark

-

Resultados de PaddleOCR (Datos del CSV)

-

Del archivo results/ai_ocr_benchmark_finetune_results_20251206_113206.csv, se obtienen los siguientes resultados de PaddleOCR para las páginas 5-9 del documento:

-Tabla 4. Resultados de PaddleOCR por página (benchmark inicial). -
PáginaWERCER
512.16%6.33%
612.81%6.40%
711.06%6.24%
88.13%1.54%
910.61%5.58%
-Fuente:
results/ai_ocr_benchmark_finetune_results_20251206_113206.csv. -Promedio PaddleOCR (páginas 5-9): -
  • CER medio: ~5.22%
  • WER medio: ~10.95%
-

Comparativa de Modelos

-

Según la documentación del notebook ocr_benchmark_notebook.ipynb, los tres modelos evaluados representan diferentes paradigmas de OCR:

-Tabla 5. Comparativa de arquitecturas OCR evaluadas. -
ModeloTipoComponentesFortalezas Clave
EasyOCREnd-to-end (det + rec)DB + CRNN/TransformerLigero, fácil de usar, multilingüe
PaddleOCR (PP-OCR)End-to-end (det + rec + cls)DB + SRN/CRNNSoporte multilingüe robusto, pipeline configurable
DocTREnd-to-end (det + rec)DB/LinkNet + CRNN/SAR/VitSTROrientado a investigación, API limpia
-Fuente: Documentación oficial de cada herramienta (JaidedAI, 2020; PaddlePaddle, 2024; Mindee, 2021). -

Ejemplo de Salida OCR

-

Del archivo CSV, un ejemplo de predicción de PaddleOCR para la página 8:

-
"Escribe siempre al menos un párrafo de introducción en cada capítulo o apartado, explicando de qué vas a tratar en esa sección. Evita que aparezcan dos encabezados de nivel consecutivos sin ningún texto entre medias. [...] En esta titulacióon se cita de acuerdo con la normativa Apa."
-Errores observados en este ejemplo: -
  • titulacióon en lugar de titulación (carácter duplicado)
  • Apa en lugar de APA (capitalización)
-

4.1.4. Justificación de la Selección de PaddleOCR

-

Criterios de Selección

-

Basándose en los resultados obtenidos y la documentación del benchmark:

-
  1. Rendimiento: PaddleOCR obtuvo CER entre 1.54% y 6.40% en las páginas evaluadas
  2. Configurabilidad: PaddleOCR ofrece múltiples hiperparámetros ajustables:
- Umbrales de detección (
text_det_thresh, text_det_box_thresh) -

- Umbral de reconocimiento (text_rec_score_thresh)

-

- Componentes opcionales (use_textline_orientation, use_doc_orientation_classify, use_doc_unwarping)

-
  1. Documentación oficial: [PaddleOCR Documentation](https://www.paddleocr.ai/v3.0.0/en/version3.x/pipeline_usage/OCR.html)
-

Decisión

-Se selecciona PaddleOCR (PP-OCRv5) para la fase de optimización debido a: -
  • Resultados iniciales prometedores (CER ~5%)
  • Alta configurabilidad de hiperparámetros de inferencia
  • Pipeline modular que permite experimentación
-

4.1.5. Limitaciones del Benchmark

-
  1. Tamaño reducido: Solo 5 páginas evaluadas en el benchmark comparativo inicial
  2. Único tipo de documento: Documentos académicos de UNIR únicamente
  3. Ground truth: El texto de referencia se extrajo automáticamente del PDF, lo cual puede introducir errores en layouts complejos
-

4.1.6. Resumen de la Sección

-

Esta sección ha presentado:

-
  1. La configuración del benchmark según ocr_benchmark_notebook.ipynb
  2. Los resultados cuantitativos de PaddleOCR del archivo CSV de resultados
  3. La justificación de la selección de PaddleOCR para optimización
-Fuentes de datos utilizadas: -
  • ocr_benchmark_notebook.ipynb: Código del benchmark
  • results/ai_ocr_benchmark_finetune_results_20251206_113206.csv: Resultados numéricos
  • Documentación oficial de PaddleOCR
-

4.2. Desarrollo de la comparativa: Optimización de hiperparámetros

-

4.2.1. Introducción

-

Esta sección describe el proceso de optimización de hiperparámetros de PaddleOCR utilizando Ray Tune con el algoritmo de búsqueda Optuna. Los experimentos fueron implementados en el notebook src/paddle_ocr_fine_tune_unir_raytune.ipynb y los resultados se almacenaron en src/raytune_paddle_subproc_results_20251207_192320.csv.

-

4.2.2. Configuración del Experimento

-

Entorno de Ejecución

-

Según los outputs del notebook:

-Tabla 6. Entorno de ejecución del experimento. -
ComponenteVersión/Especificación
Python3.11.9
PaddlePaddle3.2.2
PaddleOCR3.3.2
Ray2.52.1
GPUNo disponible (CPU only)
-Fuente: Outputs del notebook
src/paddle_ocr_fine_tune_unir_raytune.ipynb. -

Dataset

-

Se utilizó un dataset estructurado en src/dataset/ creado mediante el notebook src/prepare_dataset.ipynb:

-
  • Estructura: Carpetas con subcarpetas img/ y txt/ pareadas
  • Páginas evaluadas por trial: 5 (páginas 5-10 del documento)
  • Gestión de datos: Clase ImageTextDataset en src/dataset_manager.py
-

Espacio de Búsqueda

-

Según el código del notebook, se definió el siguiente espacio de búsqueda:

-
`python -

search_space = {

-

"use_doc_orientation_classify": tune.choice([True, False]),

-

"use_doc_unwarping": tune.choice([True, False]),

-

"textline_orientation": tune.choice([True, False]),

-

"text_det_thresh": tune.uniform(0.0, 0.7),

-

"text_det_box_thresh": tune.uniform(0.0, 0.7),

-

"text_det_unclip_ratio": tune.choice([0.0]), # Fijado

-

"text_rec_score_thresh": tune.uniform(0.0, 0.7),

-

}

-
` -Descripción de parámetros (según documentación de PaddleOCR): -
ParámetroDescripción
use_doc_orientation_classifyClasificación de orientación del documento
use_doc_unwarpingCorrección de deformación del documento
textline_orientationClasificación de orientación de línea de texto
text_det_threshUmbral de detección de píxeles de texto
text_det_box_threshUmbral de caja de detección
text_det_unclip_ratioCoeficiente de expansión (fijado en 0.0)
text_rec_score_threshUmbral de confianza de reconocimiento
-

Configuración de Ray Tune

-
`python -

tuner = tune.Tuner(

-

trainable_paddle_ocr,

-

tune_config=tune.TuneConfig(

-

metric="CER",

-

mode="min",

-

search_alg=OptunaSearch(),

-

num_samples=64,

-

max_concurrent_trials=2

-

),

-

run_config=air.RunConfig(verbose=2, log_to_file=False),

-

param_space=search_space

-

)

-
` -
  • Métrica objetivo: CER (minimizar)
  • Algoritmo de búsqueda: Optuna (TPE - Tree-structured Parzen Estimator)
  • Número de trials: 64
  • Trials concurrentes: 2
-

4.2.3. Resultados de la Optimización

-

Estadísticas Descriptivas

-

Del archivo CSV de resultados (raytune_paddle_subproc_results_20251207_192320.csv):

-Tabla 7. Estadísticas descriptivas de los 64 trials de Ray Tune. -
EstadísticaCERWERTiempo (s)Tiempo/Página (s)
count64646464
mean5.25%14.28%347.6169.42
std11.03%10.75%7.881.57
min1.15%9.89%320.9764.10
25%1.20%10.04%344.2468.76
50%1.23%10.20%346.4269.19
75%4.03%13.20%350.1469.93
max51.61%59.45%368.5773.63
-Fuente:
src/raytune_paddle_subproc_results_20251207_192320.csv. -

Mejor Configuración Encontrada

-

Según el análisis del notebook:

-
` -

Best CER: 0.011535 (1.15%)

-

Best WER: 0.098902 (9.89%)

-

Configuración óptima:

-

textline_orientation: True

-

use_doc_orientation_classify: False

-

use_doc_unwarping: False

-

text_det_thresh: 0.4690

-

text_det_box_thresh: 0.5412

-

text_det_unclip_ratio: 0.0

-

text_rec_score_thresh: 0.6350

-
` -

Análisis de Correlación

-

Correlación de Pearson entre parámetros y métricas de error (del notebook):

-Correlación con CER: -
ParámetroCorrelación
CER1.000
config/text_det_box_thresh0.226
config/text_rec_score_thresh-0.161
config/text_det_thresh-0.523
config/text_det_unclip_ratioNaN
-Correlación con WER: -
ParámetroCorrelación
WER1.000
config/text_det_box_thresh0.227
config/text_rec_score_thresh-0.173
config/text_det_thresh-0.521
config/text_det_unclip_ratioNaN
-Hallazgo clave: El parámetro
text_det_thresh muestra la correlación más fuerte (-0.52), indicando que valores más altos de este umbral tienden a reducir el error. -

Impacto del Parámetro textline_orientation

-

Según el análisis del notebook, este parámetro booleano tiene el mayor impacto:

-Tabla 8. Impacto del parámetro textline_orientation en las métricas de error. -
textline_orientationCER MedioWER Medio
True~3.76%~12.73%
False~12.40%~21.71%
-Fuente: Análisis del notebook
src/paddle_ocr_fine_tune_unir_raytune.ipynb. -Interpretación: -

El CER medio es ~3.3x menor con textline_orientation=True (3.76% vs 12.40%). Además, la varianza es mucho menor, lo que indica resultados más consistentes. Para documentos en español con layouts mixtos (tablas, encabezados, direcciones), la clasificación de orientación ayuda a PaddleOCR a ordenar correctamente las líneas de texto.

-`mermaid -

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#0098CD'}}}%%

-

xychart-beta

-

title "Impacto de textline_orientation en CER"

-

x-axis ["textline_orientation=False", "textline_orientation=True"]

-

y-axis "CER (%)" 0 --> 15

-

bar [12.40, 3.76]

-
` -Figura 3. Comparación del CER medio según el valor del parámetro textline_orientation. -

Análisis de Fallos

-

Los trials con CER muy alto (>40%) se produjeron cuando:

-
  • text_det_thresh < 0.1 (valores muy bajos)
  • textline_orientation = False
-

Ejemplo de trial con fallo catastrófico:

-
  • CER: 51.61%
  • WER: 59.45%
  • Configuración: text_det_thresh=0.017, textline_orientation=True
-

4.2.4. Comparación Baseline vs Optimizado

-

Resultados sobre Dataset Completo (24 páginas)

-

Del análisis final del notebook ejecutando sobre las 24 páginas:

-Tabla 9. Comparación baseline vs configuración optimizada (24 páginas). -
ModeloCERWER
PaddleOCR (Baseline)7.78%14.94%
PaddleOCR-HyperAdjust1.49%7.62%
-Fuente: Ejecución final en notebook
src/paddle_ocr_fine_tune_unir_raytune.ipynb. -

Métricas de Mejora

-Tabla 10. Análisis de la mejora obtenida. -
MétricaBaselineOptimizadoMejora AbsolutaReducción Error
CER7.78%1.49%-6.29 pp80.9%
WER14.94%7.62%-7.32 pp49.0%
-Fuente: Elaboración propia a partir de los resultados experimentales. -

Interpretación (del notebook)

-
"La optimización de hiperparámetros mejoró la precisión de caracteres de 92.2% a 98.5%, una ganancia de 6.3 puntos porcentuales. Aunque el baseline ya ofrecía resultados aceptables, la configuración optimizada reduce los errores residuales en un 80.9%."
-
`mermaid -

%%{init: {'theme': 'base'}}%%

-

xychart-beta

-

title "Comparación Baseline vs Optimizado (24 páginas)"

-

x-axis ["CER", "WER"]

-

y-axis "Tasa de error (%)" 0 --> 16

-

bar "Baseline" [7.78, 14.94]

-

bar "Optimizado" [1.49, 7.62]

-
` -Figura 4. Comparación de métricas de error entre configuración baseline y optimizada. -Impacto práctico: En un documento de 10,000 caracteres: -
  • Baseline: ~778 caracteres con error
  • Optimizado: ~149 caracteres con error
  • Diferencia: ~629 caracteres menos con errores
-

4.2.5. Tiempo de Ejecución

-
MétricaValor
Tiempo total del experimento~6 horas (64 trials × ~6 min/trial)
Tiempo medio por trial367.72 segundos
Tiempo medio por página69.42 segundos
Total páginas procesadas64 trials × 5 páginas = 320 evaluaciones
-

4.2.6. Resumen de la Sección

-

Esta sección ha presentado:

-
  1. Configuración del experimento: 64 trials con Ray Tune + Optuna sobre 7 hiperparámetros
  2. Resultados estadísticos: CER medio 5.25%, CER mínimo 1.15%
  3. Hallazgos clave:
-
textline_orientation=True es crítico (reduce CER ~70%) -

- text_det_thresh tiene correlación -0.52 con CER

-

- Valores bajos de text_det_thresh (<0.1) causan fallos catastróficos

-
  1. Mejora final: CER reducido de 7.78% a 1.49% (reducción del 80.9%)
-Fuentes de datos: -
  • src/paddle_ocr_fine_tune_unir_raytune.ipynb: Código del experimento
  • src/raytune_paddle_subproc_results_20251207_192320.csv: Resultados de 64 trials
  • src/paddle_ocr_tuning.py: Script de evaluación
-

4.3. Discusión y análisis de resultados

-

4.3.1. Introducción

-

Esta sección presenta un análisis consolidado de los resultados obtenidos en las fases de benchmark comparativo y optimización de hiperparámetros. Se discuten las implicaciones prácticas y se evalúa el cumplimiento de los objetivos planteados.

-

4.3.2. Resumen de Resultados

-

Resultados del Benchmark Comparativo

-

Del archivo results/ai_ocr_benchmark_finetune_results_20251206_113206.csv, PaddleOCR con configuración inicial (use_textline_orientation=True) obtuvo los siguientes resultados en las páginas 5-9:

-
PáginaWERCER
512.16%6.33%
612.81%6.40%
711.06%6.24%
88.13%1.54%
910.61%5.58%
Promedio10.95%5.22%
-

Resultados de la Optimización con Ray Tune

-

Del archivo src/raytune_paddle_subproc_results_20251207_192320.csv (64 trials):

-
MétricaValor
CER mínimo1.15%
CER medio5.25%
CER máximo51.61%
WER mínimo9.89%
WER medio14.28%
WER máximo59.45%
-

Comparación Final (Dataset Completo - 24 páginas)

-

Resultados del notebook src/paddle_ocr_fine_tune_unir_raytune.ipynb:

-
ModeloCERPrecisión CaracteresWERPrecisión Palabras
PaddleOCR (Baseline)7.78%92.22%14.94%85.06%
PaddleOCR-HyperAdjust1.49%98.51%7.62%92.38%
-

4.3.3. Análisis de Resultados

-

Mejora Obtenida

-
Forma de MediciónValor
Mejora en precisión de caracteres (absoluta)+6.29 puntos porcentuales
Reducción del CER (relativa)80.9%
Mejora en precisión de palabras (absoluta)+7.32 puntos porcentuales
Reducción del WER (relativa)49.0%
Precisión final de caracteres98.51%
-

Impacto de Hiperparámetros Individuales

-Parámetro
textline_orientation -

Este parámetro booleano demostró ser el más influyente:

-
ValorCER MedioImpacto
True~3.76%Rendimiento óptimo
False~12.40%3.3x peor
-Reducción del CER: 69.7% cuando se habilita la clasificación de orientación de línea. -Parámetro
text_det_thresh -

Correlación con CER: -0.523 (la más fuerte de los parámetros continuos)

-
RangoComportamiento
< 0.1Fallos catastróficos (CER 40-50%)
0.3 - 0.6Rendimiento óptimo
Valor óptimo0.4690
-Parámetros con menor impacto -
ParámetroCorrelación con CERValor óptimo
text_det_box_thresh+0.2260.5412
text_rec_score_thresh-0.1610.6350
use_doc_orientation_classify-False
use_doc_unwarping-False
-

Configuración Óptima Final

-
`python -

config_optimizada = {

-

"textline_orientation": True, # CRÍTICO

-

"use_doc_orientation_classify": False,

-

"use_doc_unwarping": False,

-

"text_det_thresh": 0.4690, # Correlación -0.52

-

"text_det_box_thresh": 0.5412,

-

"text_det_unclip_ratio": 0.0,

-

"text_rec_score_thresh": 0.6350,

-

}

-
` -

4.3.4. Discusión

-

Hallazgos Principales

-
  1. Importancia de la clasificación de orientación de línea: El parámetro textline_orientation=True es el factor más determinante. Esto tiene sentido para documentos con layouts mixtos (tablas, encabezados, direcciones) donde el orden correcto de las líneas de texto es crucial.
-
  1. Umbral de detección crítico: El parámetro text_det_thresh presenta un umbral mínimo efectivo (~0.1). Valores inferiores generan demasiados falsos positivos en la detección, corrompiendo el reconocimiento posterior.
-
  1. Componentes opcionales innecesarios: Para documentos académicos digitales (no escaneados), los módulos de corrección de orientación de documento (use_doc_orientation_classify) y corrección de deformación (use_doc_unwarping) no aportan mejora e incluso pueden introducir overhead.
-

Interpretación de la Correlación Negativa

-

La correlación negativa de text_det_thresh (-0.52) con el CER indica que:

-
  • Umbrales más altos filtran detecciones de baja confianza
  • Esto reduce falsos positivos que generan texto erróneo
  • El reconocimiento es más preciso con menos regiones pero más confiables
-

Limitaciones de los Resultados

-
  1. Generalización: Los resultados se obtuvieron sobre documentos de un único tipo (instrucciones académicas UNIR). La configuración óptima puede variar para otros tipos de documentos.
-
  1. Ground truth automático: El texto de referencia se extrajo programáticamente del PDF. En layouts complejos, esto puede introducir errores en la evaluación.
-
  1. Ejecución en CPU: Los tiempos reportados (~69s/página) corresponden a ejecución en CPU. Con GPU, los tiempos serían significativamente menores.
-
  1. Parámetro fijo: text_det_unclip_ratio permaneció fijo en 0.0 durante todo el experimento por decisión de diseño.
-

Comparación con Objetivos

-
ObjetivoMetaResultadoCumplimiento
OE1: Comparar soluciones OCREvaluar EasyOCR, PaddleOCR, DocTRPaddleOCR seleccionado
OE2: Preparar datasetConstruir dataset estructuradoDataset de 24 páginas
OE3: Identificar hiperparámetros críticosAnalizar correlacionestextline_orientation y text_det_thresh identificados
OE4: Optimizar con Ray TuneMínimo 50 configuraciones64 trials ejecutados
OE5: Validar configuraciónDocumentar mejoraCER 7.78% → 1.49%
Objetivo GeneralCER < 2%CER = 1.49%
-

4.3.5. Implicaciones Prácticas

-

Recomendaciones de Configuración

-

Para documentos académicos en español similares a los evaluados:

-
  1. Obligatorio: use_textline_orientation=True
  2. Recomendado: text_det_thresh entre 0.4 y 0.5
  3. Opcional: text_det_box_thresh ~0.5, text_rec_score_thresh >0.6
  4. No recomendado: Habilitar use_doc_orientation_classify o use_doc_unwarping para documentos digitales
-

Impacto Cuantitativo

-

En un documento típico de 10,000 caracteres:

-
ConfiguraciónErrores estimados
Baseline~778 caracteres
Optimizada~149 caracteres
Reducción629 caracteres menos con errores
-

Aplicabilidad

-

Esta metodología de optimización es aplicable cuando:

-
  • No se dispone de recursos GPU para fine-tuning
  • El modelo preentrenado ya tiene soporte para el idioma objetivo
  • Se busca mejorar rendimiento sin reentrenar
-

4.3.6. Resumen de la Sección

-

Esta sección ha presentado:

-
  1. Los resultados consolidados del benchmark y la optimización
  2. El análisis del impacto de cada hiperparámetro
  3. La configuración óptima identificada
  4. La discusión de limitaciones y aplicabilidad
  5. El cumplimiento de los objetivos planteados
-Resultado principal: Se logró reducir el CER del 7.78% al 1.49% (mejora del 80.9%) mediante optimización de hiperparámetros, cumpliendo el objetivo de alcanzar CER < 2%. -Fuentes de datos: -
  • results/ai_ocr_benchmark_finetune_results_20251206_113206.csv
  • src/raytune_paddle_subproc_results_20251207_192320.csv
  • src/paddle_ocr_fine_tune_unir_raytune.ipynb`
-
-

5. Conclusiones y trabajo futuro

-

Este capítulo resume las principales conclusiones del trabajo, evalúa el grado de cumplimiento de los objetivos planteados y propone líneas de trabajo futuro que permitirían ampliar y profundizar los resultados obtenidos.

-

5.1. Conclusiones

-

5.1.1. Conclusiones Generales

-

Este Trabajo Fin de Máster ha demostrado que es posible mejorar significativamente el rendimiento de sistemas OCR preentrenados mediante optimización sistemática de hiperparámetros, sin requerir fine-tuning ni recursos GPU dedicados.

-

El objetivo principal del trabajo era alcanzar un CER inferior al 2% en documentos académicos en español. Los resultados obtenidos confirman el cumplimiento de este objetivo:

-
MétricaObjetivoResultado
CER< 2%1.49%
-

5.1.2. Conclusiones Específicas

-Respecto a OE1 (Comparativa de soluciones OCR): -
  • Se evaluaron tres soluciones OCR de código abierto: EasyOCR, PaddleOCR (PP-OCRv5) y DocTR
  • PaddleOCR demostró el mejor rendimiento base para documentos en español
  • La configurabilidad del pipeline de PaddleOCR lo hace idóneo para optimización
-Respecto a OE2 (Preparación del dataset): -
  • Se construyó un dataset estructurado con 24 páginas de documentos académicos
  • La clase ImageTextDataset facilita la carga de pares imagen-texto
  • El ground truth se extrajo automáticamente del PDF mediante PyMuPDF
-Respecto a OE3 (Identificación de hiperparámetros críticos): -
  • El parámetro textline_orientation es el más influyente: reduce el CER en un 69.7% cuando está habilitado
  • El umbral text_det_thresh presenta la correlación más fuerte (-0.52) con el CER
  • Los parámetros de corrección de documento (use_doc_orientation_classify, use_doc_unwarping) no aportan mejora en documentos digitales
-Respecto a OE4 (Optimización con Ray Tune): -
  • Se ejecutaron 64 trials con el algoritmo OptunaSearch
  • El tiempo total del experimento fue aproximadamente 6 horas (en CPU)
  • La arquitectura basada en subprocesos permitió superar incompatibilidades entre Ray y PaddleOCR
-Respecto a OE5 (Validación de la configuración): -
  • Se validó la configuración óptima sobre el dataset completo de 24 páginas
  • La mejora obtenida fue del 80.9% en reducción del CER (7.78% → 1.49%)
  • La precisión de caracteres alcanzó el 98.51%
-

5.1.3. Hallazgos Clave

-
  1. Arquitectura sobre umbrales: Un único parámetro booleano (textline_orientation) tiene más impacto que todos los umbrales continuos combinados.
-
  1. Umbrales mínimos efectivos: Valores de text_det_thresh < 0.1 causan fallos catastróficos (CER >40%).
-
  1. Simplicidad para documentos digitales: Para documentos PDF digitales (no escaneados), los módulos de corrección de orientación y deformación son innecesarios.
-
  1. Optimización sin fine-tuning: Se puede mejorar significativamente el rendimiento de modelos preentrenados mediante ajuste de hiperparámetros de inferencia.
-

5.1.4. Contribuciones del Trabajo

-
  1. Metodología reproducible: Se documenta un proceso completo de optimización de hiperparámetros OCR con Ray Tune + Optuna.
-
  1. Análisis de hiperparámetros de PaddleOCR: Se cuantifica el impacto de cada parámetro configurable mediante correlaciones y análisis comparativo.
-
  1. Configuración óptima para español: Se proporciona una configuración validada para documentos académicos en español.
-
  1. Código fuente: Todo el código está disponible en el repositorio GitHub para reproducción y extensión.
-

5.1.5. Limitaciones del Trabajo

-
  1. Tipo de documento único: Los experimentos se realizaron únicamente sobre documentos académicos de UNIR. La generalización a otros tipos de documentos requiere validación adicional.
-
  1. Tamaño del dataset: 24 páginas es un corpus limitado para conclusiones estadísticamente robustas.
-
  1. Ground truth automático: La extracción automática del texto de referencia puede introducir errores en layouts complejos.
-
  1. Ejecución en CPU: Los tiempos de procesamiento (~69s/página) limitan la aplicabilidad en escenarios de alto volumen.
-
  1. Parámetro no explorado: text_det_unclip_ratio permaneció fijo en 0.0 durante todo el experimento.
-

5.2. Líneas de trabajo futuro

-

5.2.1. Extensiones Inmediatas

-
  1. Validación cruzada: Evaluar la configuración óptima en otros tipos de documentos en español (facturas, formularios, textos manuscritos).
-
  1. Exploración de text_det_unclip_ratio: Incluir este parámetro en el espacio de búsqueda.
-
  1. Dataset ampliado: Construir un corpus más amplio y diverso de documentos en español.
-
  1. Evaluación con GPU: Medir tiempos de inferencia con aceleración GPU.
-

5.2.2. Líneas de Investigación

-
  1. Transfer learning de hiperparámetros: Investigar si las configuraciones óptimas para un tipo de documento transfieren a otros dominios.
-
  1. Optimización multi-objetivo: Considerar simultáneamente CER, WER y tiempo de inferencia como objetivos.
-
  1. AutoML para OCR: Aplicar técnicas de AutoML más avanzadas (Neural Architecture Search, meta-learning).
-
  1. Comparación con fine-tuning: Cuantificar la brecha de rendimiento entre optimización de hiperparámetros y fine-tuning real.
-

5.2.3. Aplicaciones Prácticas

-
  1. Herramienta de configuración automática: Desarrollar una herramienta que determine automáticamente la configuración óptima para un nuevo tipo de documento.
-
  1. Integración en pipelines de producción: Implementar la configuración optimizada en sistemas reales de procesamiento documental.
-
  1. Benchmark público: Publicar un benchmark de OCR para documentos en español que facilite la comparación de soluciones.
-

5.2.4. Reflexión Final

-

Este trabajo demuestra que, en un contexto de recursos limitados donde el fine-tuning de modelos de deep learning no es viable, la optimización de hiperparámetros representa una alternativa práctica y efectiva para mejorar sistemas OCR.

-

La metodología propuesta es reproducible, los resultados son cuantificables, y las conclusiones son aplicables a escenarios reales de procesamiento documental. La reducción del CER del 7.78% al 1.49% representa una mejora sustancial que puede tener impacto directo en aplicaciones downstream como extracción de información, análisis semántico y búsqueda de documentos.

-

El código fuente y los datos experimentales están disponibles públicamente para facilitar la reproducción y extensión de este trabajo.

-
-

Referencias bibliográficas {.unnumbered}

-

Akiba, T., Sano, S., Yanase, T., Ohta, T., & Koyama, M. (2019). Optuna: A next-generation hyperparameter optimization framework. Proceedings of the 25th ACM SIGKDD International Conference on Knowledge Discovery & Data Mining, 2623-2631. https://doi.org/10.1145/3292500.3330701

-

Baek, Y., Lee, B., Han, D., Yun, S., & Lee, H. (2019). Character region awareness for text detection. Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition, 9365-9374. https://doi.org/10.1109/CVPR.2019.00959

-

Bergstra, J., & Bengio, Y. (2012). Random search for hyper-parameter optimization. Journal of Machine Learning Research, 13(1), 281-305. https://jmlr.org/papers/v13/bergstra12a.html

-

Bergstra, J., Bardenet, R., Bengio, Y., & Kégl, B. (2011). Algorithms for hyper-parameter optimization. Advances in Neural Information Processing Systems, 24, 2546-2554. https://papers.nips.cc/paper/2011/hash/86e8f7ab32cfd12577bc2619bc635690-Abstract.html

-

Cohen, J. (1988). Statistical power analysis for the behavioral sciences (2nd ed.). Lawrence Erlbaum Associates.

-

Doran, G. T. (1981). There's a S.M.A.R.T. way to write management's goals and objectives. Management Review, 70(11), 35-36.

-

Du, Y., Li, C., Guo, R., Yin, X., Liu, W., Zhou, J., Bai, Y., Yu, Z., Yang, Y., Dang, Q., & Wang, H. (2020). PP-OCR: A practical ultra lightweight OCR system. arXiv preprint arXiv:2009.09941. https://arxiv.org/abs/2009.09941

-

Du, Y., Li, C., Guo, R., Cui, C., Liu, W., Zhou, J., Lu, B., Yang, Y., Liu, Q., Hu, X., Yu, D., & Wang, H. (2023). PP-OCRv4: Mobile scene text detection and recognition. arXiv preprint arXiv:2310.05930. https://arxiv.org/abs/2310.05930

-

Feurer, M., & Hutter, F. (2019). Hyperparameter optimization. In F. Hutter, L. Kotthoff, & J. Vanschoren (Eds.), Automated machine learning: Methods, systems, challenges (pp. 3-33). Springer. https://doi.org/10.1007/978-3-030-05318-5_1

-

He, P., Huang, W., Qiao, Y., Loy, C. C., & Tang, X. (2016). Reading scene text in deep convolutional sequences. Proceedings of the AAAI Conference on Artificial Intelligence, 30(1), 3501-3508. https://doi.org/10.1609/aaai.v30i1.10291

-

JaidedAI. (2020). EasyOCR: Ready-to-use OCR with 80+ supported languages. GitHub. https://github.com/JaidedAI/EasyOCR

-

Liang, J., Doermann, D., & Li, H. (2005). Camera-based analysis of text and documents: A survey. International Journal of Document Analysis and Recognition, 7(2), 84-104. https://doi.org/10.1007/s10032-004-0138-z

-

Liao, M., Wan, Z., Yao, C., Chen, K., & Bai, X. (2020). Real-time scene text detection with differentiable binarization. Proceedings of the AAAI Conference on Artificial Intelligence, 34(07), 11474-11481. https://doi.org/10.1609/aaai.v34i07.6812

-

Liaw, R., Liang, E., Nishihara, R., Moritz, P., Gonzalez, J. E., & Stoica, I. (2018). Tune: A research platform for distributed model selection and training. arXiv preprint arXiv:1807.05118. https://arxiv.org/abs/1807.05118

-

Mindee. (2021). DocTR: Document Text Recognition. GitHub. https://github.com/mindee/doctr

-

Moritz, P., Nishihara, R., Wang, S., Tumanov, A., Liaw, R., Liang, E., Elibol, M., Yang, Z., Paul, W., Jordan, M. I., & Stoica, I. (2018). Ray: A distributed framework for emerging AI applications. 13th USENIX Symposium on Operating Systems Design and Implementation (OSDI 18), 561-577. https://www.usenix.org/conference/osdi18/presentation/moritz

-

Morris, A. C., Maier, V., & Green, P. D. (2004). From WER and RIL to MER and WIL: Improved evaluation measures for connected speech recognition. Eighth International Conference on Spoken Language Processing. https://doi.org/10.21437/Interspeech.2004-668

-

PaddlePaddle. (2024). PaddleOCR: Awesome multilingual OCR toolkits based on PaddlePaddle. GitHub. https://github.com/PaddlePaddle/PaddleOCR

-

Pearson, K. (1895). Notes on regression and inheritance in the case of two parents. Proceedings of the Royal Society of London, 58, 240-242. https://doi.org/10.1098/rspl.1895.0041

-

PyMuPDF. (2024). PyMuPDF documentation. https://pymupdf.readthedocs.io/

-

Shi, B., Bai, X., & Yao, C. (2016). An end-to-end trainable neural network for image-based sequence recognition and its application to scene text recognition. IEEE Transactions on Pattern Analysis and Machine Intelligence, 39(11), 2298-2304. https://doi.org/10.1109/TPAMI.2016.2646371

-

Smith, R. (2007). An overview of the Tesseract OCR engine. Ninth International Conference on Document Analysis and Recognition (ICDAR 2007), 2, 629-633. https://doi.org/10.1109/ICDAR.2007.4376991

-

Zhou, X., Yao, C., Wen, H., Wang, Y., Zhou, S., He, W., & Liang, J. (2017). EAST: An efficient and accurate scene text detector. Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition, 5551-5560. https://doi.org/10.1109/CVPR.2017.283

-

Zoph, B., & Le, Q. V. (2017). Neural architecture search with reinforcement learning. International Conference on Learning Representations (ICLR). https://arxiv.org/abs/1611.01578

-
-

Anexo A. Código fuente y datos analizados {.unnumbered}

-

A.1 Repositorio del Proyecto

-

El código fuente completo y los datos utilizados en este trabajo están disponibles en el siguiente repositorio:

-URL del repositorio: https://github.com/seryus/MastersThesis -

El repositorio incluye:

-
  • Notebooks de experimentación: Código completo de los experimentos realizados
  • Scripts de evaluación: Herramientas para evaluar modelos OCR
  • Dataset: Imágenes y textos de referencia utilizados
  • Resultados: Archivos CSV con los resultados de los 64 trials de Ray Tune
-

A.2 Estructura del Repositorio

-

``

-

MastersThesis/

-

├── docs/ # Capítulos de la tesis en Markdown

-

├── src/

-

│ ├── paddle_ocr_fine_tune_unir_raytune.ipynb # Experimento principal

-

│ ├── paddle_ocr_tuning.py # Script de evaluación CLI

-

│ ├── dataset_manager.py # Clase ImageTextDataset

-

│ ├── prepare_dataset.ipynb # Preparación del dataset

-

│ └── raytune_paddle_subproc_results_*.csv # Resultados de 64 trials

-

├── results/ # Resultados de benchmarks

-

├── instructions/ # Instrucciones y plantilla UNIR

-

└── README.md

-
` -

A.3 Requisitos de Software

-

Para reproducir los experimentos se requieren las siguientes dependencias:

-
ComponenteVersión
Python3.11.9
PaddlePaddle3.2.2
PaddleOCR3.3.2
Ray2.52.1
Optuna4.6.0
jiwer(última versión)
PyMuPDF(última versión)
-

A.4 Instrucciones de Ejecución

-
  1. Clonar el repositorio
  2. Instalar dependencias: pip install -r requirements.txt
  3. Ejecutar el notebook src/paddle_ocr_fine_tune_unir_raytune.ipynb`
-

A.5 Licencia

-

El código se distribuye bajo licencia MIT.

- \ No newline at end of file diff --git a/thesis_output/figures/figura_1.png b/thesis_output/figures/figura_1.png new file mode 100644 index 0000000000000000000000000000000000000000..ee9271b2c9b5d628ae70921e3e02deb357b5df13 GIT binary patch literal 17100 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 X-3`kXE%(34@Jm8ehLCvu-qZgDjQb9w literal 0 HcmV?d00001 diff --git a/thesis_output/figures/figura_3.png b/thesis_output/figures/figura_3.png new file mode 100644 index 0000000000000000000000000000000000000000..1c4c2547a924a56423bebe1a170ad99f92c3c8b5 GIT binary patch literal 98404 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 XO1X)x5Ie*Ax1%Vhdh)f5f%pFcyxGLK literal 0 HcmV?d00001 diff --git a/thesis_output/figures/figura_4.png b/thesis_output/figures/figura_4.png new file mode 100644 index 0000000000000000000000000000000000000000..f6aa146e39a58d514fe2c03755da6882d26c6eeb GIT binary patch literal 32850 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 literal 0 HcmV?d00001 diff --git a/thesis_output/figures/figura_5.png b/thesis_output/figures/figura_5.png new file mode 100644 index 0000000000000000000000000000000000000000..b83b7fc90cebaab001c820b111924e8c63605901 GIT binary patch literal 24564 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

lAptCeN?9JjzKe|HVPl)B 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 K&L$io+V|- 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 literal 0 HcmV?d00001 diff --git a/thesis_output/figures/figures_manifest.json b/thesis_output/figures/figures_manifest.json new file mode 100644 index 0000000..2d19865 --- /dev/null +++ b/thesis_output/figures/figures_manifest.json @@ -0,0 +1,37 @@ +[ + { + "file": "figura_1.png", + "title": "Diagrama de 02_contexto_estado_arte.md", + "index": 1 + }, + { + "file": "figura_2.png", + "title": "Diagrama de 02_contexto_estado_arte.md", + "index": 2 + }, + { + "file": "figura_3.png", + "title": "Diagrama de 03_objetivos_metodologia.md", + "index": 3 + }, + { + "file": "figura_4.png", + "title": "Diagrama de 03_objetivos_metodologia.md", + "index": 4 + }, + { + "file": "figura_5.png", + "title": "Diagrama de 03_objetivos_metodologia.md", + "index": 5 + }, + { + "file": "figura_6.png", + "title": "Impacto de textline_orientation en CER", + "index": 6 + }, + { + "file": "figura_7.png", + "title": "Comparación Baseline vs Optimizado (24 páginas)", + "index": 7 + } +] \ No newline at end of file diff --git a/thesis_output/plantilla_individual.htm b/thesis_output/plantilla_individual.htm new file mode 100644 index 0000000..cdf2b41 --- /dev/null +++ b/thesis_output/plantilla_individual.htm @@ -0,0 +1,5321 @@ + + + + + + + + + + + + + + + + + + + + +

+

 

+

Texto
+
+Descripción generada automáticamente

+

Universidad +Internacional de La Rioja

+

Escuela +Superior de Ingeniería y

+

Tecnología

+

 

+

 

+

 

+

 

+

Máster Universitario +en Inteligencia artificial

+

Optimización de Hiperparámetros OCR +con Ray Tune para Documentos Académicos en Español

+ +

 

+

           

+ + + + + + + + + + + + + + + + + +
+

Trabajo fin de + estudio presentado por:

+
+

Sergio Jiménez Jiménez

+
+

Tipo de + trabajo:

+
+

Desarrollo + Software

+
+

Director/a:

+
+

Javier Rodrigo + Villazón Terrazas

+
+

Fecha:

+
+

06.10.2025

+
+

 

+
+
+

Resumen

El presente Trabajo Fin de Máster aborda la optimización de sistemas de Reconocimiento Óptico de Caracteres (OCR) basados en inteligencia artificial para documentos en español, específicamente en un entorno con recursos computacionales limitados donde el fine-tuning de modelos no es viable. El objetivo principal es identificar la configuración óptima de hiperparámetros que maximice la precisión del reconocimiento de texto sin requerir entrenamiento adicional de los modelos. + +Se realizó un estudio comparativo de tres soluciones OCR de código abierto: EasyOCR, PaddleOCR (PP-OCRv5) y DocTR, evaluando su rendimiento mediante las métricas estándar CER (Character Error Rate) y WER (Word Error Rate) sobre un corpus de documentos académicos en español. Tras identificar PaddleOCR como la solución más prometedora, se procedió a una optimización sistemática de hiperparámetros utilizando Ray Tune con el algoritmo de búsqueda Optuna, ejecutando 64 configuraciones diferentes. + +Los resultados demuestran que la optimización de hiperparámetros logró una mejora significativa del rendimiento: el CER se redujo de 7.78% a 1.49% (mejora del 80.9% en reducción de errores), alcanzando una precisión de caracteres del 98.51%. El hallazgo más relevante fue que el parámetro `textline_orientation` (clasificación de orientación de línea de texto) tiene un impacto crítico, reduciendo el CER en un 69.7% cuando está habilitado. Adicionalmente, se identificó que el umbral de detección de píxeles (`text_det_thresh`) presenta una correlación negativa fuerte (-0.52) con el error, siendo el parámetro continuo más influyente. + +Este trabajo demuestra que es posible obtener mejoras sustanciales en sistemas OCR mediante optimización de hiperparámetros, ofreciendo una alternativa práctica al fine-tuning cuando los recursos computacionales son limitados.

+

 

+

Palabras clave: OCR, Reconocimiento Óptico de Caracteres, PaddleOCR, Optimización de Hiperparámetros, Ray Tune, Procesamiento de Documentos, Inteligencia Artificial

+

 

+ + + + + + + + + + +

Abstract

This Master's Thesis addresses the optimization of Artificial Intelligence-based Optical Character Recognition (OCR) systems for Spanish documents, specifically in a resource-constrained environment where model fine-tuning is not feasible. The main objective is to identify the optimal hyperparameter configuration that maximizes text recognition accuracy without requiring additional model training. + +A comparative study of three open-source OCR solutions was conducted: EasyOCR, PaddleOCR (PP-OCRv5), and DocTR, evaluating their performance using standard CER (Character Error Rate) and WER (Word Error Rate) metrics on a corpus of academic documents in Spanish. After identifying PaddleOCR as the most promising solution, systematic hyperparameter optimization was performed using Ray Tune with the Optuna search algorithm, executing 64 different configurations. + +Results demonstrate that hyperparameter optimization achieved significant performance improvement: CER was reduced from 7.78% to 1.49% (80.9% error reduction), achieving 98.51% character accuracy. The most relevant finding was that the `textline_orientation` parameter (text line orientation classification) has a critical impact, reducing CER by 69.7% when enabled. Additionally, the pixel detection threshold (`text_det_thresh`) was found to have a strong negative correlation (-0.52) with error, being the most influential continuous parameter. + +This work demonstrates that substantial improvements in OCR systems can be obtained through hyperparameter optimization, offering a practical alternative to fine-tuning when computational resources are limited.

+

 

+

Keywords: OCR, Optical Character Recognition, PaddleOCR, Hyperparameter Optimization, Ray Tune, Document Processing, Artificial Intelligence

+

 

+ + + + + +
+
+

 

+ +

Índice de contenidos

+

1.    Introducción. 1

+

1.1.      Motivación. 1

+

1.2.      Planteamiento +del trabajo. 3

+

1.3.      Estructura +del trabajo. 3

+

2.    Contexto +y estado del arte. 4

+

2.1.      Contexto +del problema. 4

+

2.2.      Estado +del arte. 4

+

2.3.      Conclusiones. 5

+

3.    Objetivos +concretos y metodología de trabajo. 6

+

3.1.      Objetivo +general 6

+

3.2.      Objetivos +específicos. 7

+

3.3.      Metodología +del trabajo. 8

+

4.    Desarrollo específico de la contribución. 9

+

5.    Conclusiones +y trabajo futuro. 13

+

5.1.      Conclusiones. 13

+

5.2.      Líneas +de trabajo futuro. 13

+

Referencias bibliográficas. 14

+

Anexo A.     Código +fuente y datos analizados 15

+


+Índice de figuras

+

Figura 1. Ejemplo +de figura realizada para nuestro trabajo. 2

+


+Índice de tablas

+

Tabla 1. Ejemplo +de tabla con sus principales elementos. 2

+

 

+

 

+

 

+

 

+

 

+

 

+

 

+

 

+

 

+

 

+

 

+

 

+

 

+

 

+

 

+

 

+
+
+
+
+

1.   +Introducción

Este capítulo presenta la motivación del trabajo, identificando el problema a resolver y justificando su relevancia. Se plantea la pregunta de investigación central y se describe la estructura del documento.

+

1.1. Motivación

+

El Reconocimiento Óptico de Caracteres (OCR) es una tecnología fundamental en la era de la digitalización documental. Su capacidad para convertir imágenes de texto en datos editables y procesables ha transformado sectores como la administración pública, el ámbito legal, la banca y la educación. Sin embargo, a pesar de los avances significativos impulsados por el aprendizaje profundo, la implementación práctica de sistemas OCR de alta precisión sigue presentando desafíos considerables.

+

El procesamiento de documentos en español presenta particularidades que complican el reconocimiento automático de texto. Los caracteres especiales (ñ, acentos), las variaciones tipográficas en documentos académicos y administrativos, y la presencia de elementos gráficos como tablas, encabezados y marcas de agua generan errores que pueden propagarse en aplicaciones downstream como la extracción de entidades nombradas o el análisis semántico.

+

Los modelos OCR basados en redes neuronales profundas, como los empleados en PaddleOCR, EasyOCR o DocTR, ofrecen un rendimiento impresionante en benchmarks estándar. No obstante, su adaptación a dominios específicos típicamente requiere fine-tuning con datos etiquetados del dominio objetivo y recursos computacionales significativos (GPUs de alta capacidad). Esta barrera técnica y económica excluye a muchos investigadores y organizaciones de beneficiarse plenamente de estas tecnologías.

+

La presente investigación surge de una necesidad práctica: optimizar un sistema OCR para documentos académicos en español sin disponer de recursos GPU para realizar fine-tuning. Esta restricción, lejos de ser una limitación excepcional, representa la realidad de muchos entornos académicos y empresariales donde el acceso a infraestructura de cómputo avanzada es limitado.

+

1.2. Planteamiento del trabajo

+

El problema central que aborda este trabajo puede formularse de la siguiente manera:

+

¿Es posible mejorar significativamente el rendimiento de modelos OCR preentrenados para documentos en español mediante la optimización sistemática de hiperparámetros, sin requerir fine-tuning ni recursos GPU?

+

Este planteamiento se descompone en las siguientes cuestiones específicas:

+

1.   Selección de modelo base: ¿Cuál de las soluciones OCR de código abierto disponibles (EasyOCR, PaddleOCR, DocTR) ofrece el mejor rendimiento base para documentos en español?

+

1.   Impacto de hiperparámetros: ¿Qué hiperparámetros del pipeline OCR tienen mayor influencia en las métricas de error (CER, WER)?

+

1.   Optimización automatizada: ¿Puede un proceso de búsqueda automatizada de hiperparámetros (mediante Ray Tune/Optuna) encontrar configuraciones que superen significativamente los valores por defecto?

+

1.   Viabilidad práctica: ¿Son los tiempos de inferencia y los recursos requeridos compatibles con un despliegue en entornos con recursos limitados?

+

La relevancia de este problema radica en su aplicabilidad inmediata. Una metodología reproducible para optimizar OCR sin fine-tuning beneficiaría a:

+

·     Investigadores que procesan grandes volúmenes de documentos académicos

+

·     Instituciones educativas que digitalizan archivos históricos

+

·     Pequeñas y medianas empresas que automatizan flujos documentales

+

·     Desarrolladores que integran OCR en aplicaciones con restricciones de recursos

+

1.3. Estructura del trabajo

+

El presente documento se organiza en los siguientes capítulos:

+

Capítulo 2 - Contexto y Estado del Arte: Se presenta una revisión de las tecnologías OCR basadas en aprendizaje profundo, incluyendo las arquitecturas de detección y reconocimiento de texto, así como los trabajos previos en optimización de estos sistemas.

+

Capítulo 3 - Objetivos y Metodología: Se definen los objetivos SMART del trabajo y se describe la metodología experimental seguida, incluyendo la preparación del dataset, las métricas de evaluación y el proceso de optimización con Ray Tune.

+

Capítulo 4 - Desarrollo Específico de la Contribución: Este capítulo presenta el desarrollo completo del estudio comparativo y la optimización de hiperparámetros de sistemas OCR, estructurado en tres secciones: (4.1) planteamiento de la comparativa con la evaluación de EasyOCR, PaddleOCR y DocTR; (4.2) desarrollo de la comparativa con la optimización de hiperparámetros mediante Ray Tune; y (4.3) discusión y análisis de resultados.

+

Capítulo 5 - Conclusiones y Trabajo Futuro: Se resumen las contribuciones del trabajo, se discute el grado de cumplimiento de los objetivos y se proponen líneas de trabajo futuro.

+

Anexos: Se incluye el enlace al repositorio de código fuente y datos, así como tablas completas de resultados experimentales.

2.   +Contexto +y estado del arte

Este capítulo presenta el marco teórico y tecnológico en el que se desarrolla el presente trabajo. Se revisan los fundamentos del Reconocimiento Óptico de Caracteres (OCR), la evolución de las técnicas basadas en aprendizaje profundo, las principales soluciones de código abierto disponibles y los trabajos previos relacionados con la optimización de sistemas OCR.

+

2.1. Contexto del problema

+

Definición y Evolución Histórica del OCR

+

El Reconocimiento Óptico de Caracteres (OCR) es el proceso de conversión de imágenes de texto manuscrito, mecanografiado o impreso en texto codificado digitalmente. La tecnología OCR ha evolucionado significativamente desde sus orígenes en la década de 1950:

+

·     Primera generación (1950-1970): Sistemas basados en plantillas que requerían fuentes específicas.

+

·     Segunda generación (1970-1990): Introducción de técnicas de extracción de características y clasificadores estadísticos.

+

·     Tercera generación (1990-2010): Modelos basados en Redes Neuronales Artificiales y Modelos Ocultos de Markov (HMM).

+

·     Cuarta generación (2010-presente): Arquitecturas de aprendizaje profundo que dominan el estado del arte.

+

Pipeline Moderno de OCR

+

Los sistemas OCR modernos siguen típicamente un pipeline de dos etapas:

+

Figura 1. Diagrama 1

+

Diagrama 1

+

Fuente: Elaboración propia.

+

 

+

1.   Detección de texto (Text Detection): Localización de regiones que contienen texto en la imagen. Las arquitecturas más utilizadas incluyen:

+

- EAST (Efficient and Accurate Scene Text Detector) - CRAFT (Character Region Awareness for Text Detection) - DB (Differentiable Binarization)

+

1.   Reconocimiento de texto (Text Recognition): Transcripción del contenido textual de las regiones detectadas. Las arquitecturas predominantes son:

+

- CRNN (Convolutional Recurrent Neural Network) con CTC loss - Arquitecturas encoder-decoder con atención - Transformers (ViTSTR, TrOCR)

+

Métricas de Evaluación

+

Las métricas estándar para evaluar sistemas OCR son:

+

Character Error Rate (CER): Se calcula como CER = (S + D + I) / N, donde S = sustituciones, D = eliminaciones, I = inserciones, N = caracteres de referencia.

+

Word Error Rate (WER): Se calcula de forma análoga pero a nivel de palabras en lugar de caracteres.

+

Un CER del 1% significa que 1 de cada 100 caracteres es erróneo. Para aplicaciones críticas como extracción de datos financieros o médicos, se requieren CER inferiores al 1%.

+

Particularidades del OCR para el Idioma Español

+

El español presenta características específicas que impactan el OCR:

+

·     Caracteres especiales: ñ, á, é, í, ó, ú, ü, ¿, ¡

+

·     Diacríticos: Los acentos pueden confundirse con ruido o artefactos

+

·     Longitud de palabras: Palabras generalmente más largas que en inglés

+

·     Puntuación: Signos de interrogación y exclamación invertidos

+

2.2. Estado del arte

+

Soluciones OCR de Código Abierto

+

EasyOCR

+

EasyOCR es una biblioteca de OCR desarrollada por Jaided AI (2020) que soporta más de 80 idiomas. Sus características principales incluyen:

+

·     Arquitectura: Detector CRAFT + Reconocedor CRNN/Transformer

+

·     Fortalezas: Facilidad de uso, soporte multilingüe amplio, bajo consumo de memoria

+

·     Limitaciones: Menor precisión en documentos complejos, opciones de configuración limitadas

+

·     Caso de uso ideal: Prototipado rápido y aplicaciones con restricciones de memoria

+

PaddleOCR

+

PaddleOCR es el sistema OCR desarrollado por Baidu como parte del ecosistema PaddlePaddle (2024). La versión PP-OCRv5, utilizada en este trabajo, representa el estado del arte en OCR industrial:

+

·     Arquitectura:

+

- Detector: DB (Differentiable Binarization) con backbone ResNet (Liao et al., 2020) - Reconocedor: SVTR (Scene-Text Visual Transformer Recognition) - Clasificador de orientación opcional

+

·     Hiperparámetros configurables:

+

Tabla 1. Hiperparámetros configurables de PaddleOCR.

+

Parámetro

Descripción

Valor por defecto

text_det_thresh

Umbral de detección de píxeles

0.3

text_det_box_thresh

Umbral de caja de detección

0.6

text_det_unclip_ratio

Coeficiente de expansión

1.5

text_rec_score_thresh

Umbral de confianza de reconocimiento

0.5

use_textline_orientation

Clasificación de orientación

False

use_doc_orientation_classify

Clasificación de orientación de documento

False

use_doc_unwarping

Corrección de deformación

False

+

Fuente: Elaboración propia.

+

 

+

·     Fortalezas: Alta precisión, pipeline altamente configurable, modelos específicos para servidor

+

·     Limitaciones: Mayor complejidad de configuración, dependencia del framework PaddlePaddle

+

DocTR

+

DocTR (Document Text Recognition) es una biblioteca desarrollada por Mindee (2021) orientada a la investigación:

+

·     Arquitectura:

+

- Detectores: DB, LinkNet - Reconocedores: CRNN, SAR, ViTSTR

+

·     Fortalezas: API limpia, orientación académica, salida estructurada de alto nivel

+

·     Limitaciones: Menor rendimiento en español comparado con PaddleOCR

+

Comparativa de Arquitecturas

+

Tabla 2. Comparativa de soluciones OCR de código abierto.

+

Modelo

Tipo

Componentes

Fortalezas Clave

EasyOCR

End-to-end (det + rec)

CRAFT + CRNN/Transformer

Ligero, fácil de usar, multilingüe

PaddleOCR

End-to-end (det + rec + cls)

DB + SVTR/CRNN

Soporte multilingüe robusto, configurable

DocTR

End-to-end (det + rec)

DB/LinkNet + CRNN/SAR/ViTSTR

Orientado a investigación, API limpia

+

Fuente: Elaboración propia.

+

 

+

Optimización de Hiperparámetros

+

Fundamentos

+

La optimización de hiperparámetros (HPO) busca encontrar la configuración de parámetros que maximiza (o minimiza) una métrica objetivo (Feurer & Hutter, 2019). A diferencia de los parámetros del modelo (pesos), los hiperparámetros no se aprenden durante el entrenamiento.

+

Los métodos de HPO incluyen:

+

·     Grid Search: Búsqueda exhaustiva en una rejilla predefinida

+

·     Random Search: Muestreo aleatorio del espacio de búsqueda (Bergstra & Bengio, 2012)

+

·     Bayesian Optimization: Modelado probabilístico de la función objetivo (Bergstra et al., 2011)

+

·     Algoritmos evolutivos: Optimización inspirada en evolución biológica

+

Ray Tune y Optuna

+

Ray Tune es un framework de optimización de hiperparámetros escalable (Liaw et al., 2018) que permite:

+

·     Ejecución paralela de experimentos

+

·     Early stopping de configuraciones poco prometedoras

+

·     Integración con múltiples algoritmos de búsqueda

+

Optuna es una biblioteca de optimización bayesiana (Akiba et al., 2019) que implementa:

+

·     Tree-structured Parzen Estimator (TPE)

+

·     Pruning de trials no prometedores

+

·     Visualización de resultados

+

La combinación Ray Tune + Optuna permite búsquedas eficientes en espacios de alta dimensionalidad.

+

Figura 2. Diagrama 2

+

Diagrama 2

+

Fuente: Elaboración propia.

+

 

+

HPO en Sistemas OCR

+

La aplicación de HPO a sistemas OCR ha sido explorada principalmente en el contexto de:

+

1.   Preprocesamiento de imagen: Optimización de parámetros de binarización, filtrado y escalado (Liang et al., 2005)

+

1.   Arquitecturas de detección: Ajuste de umbrales de confianza y NMS (Non-Maximum Suppression)

+

1.   Post-procesamiento: Optimización de corrección ortográfica y modelos de lenguaje

+

Sin embargo, existe un vacío en la literatura respecto a la optimización sistemática de los hiperparámetros de inferencia en pipelines OCR modernos como PaddleOCR, especialmente para idiomas diferentes del inglés y chino.

+

Datasets y Benchmarks para Español

+

Los principales recursos para evaluación de OCR en español incluyen:

+

·     FUNSD-ES: Versión en español del dataset de formularios

+

·     MLT (ICDAR): Multi-Language Text dataset con muestras en español

+

·     Documentos académicos: Utilizados en este trabajo (instrucciones TFE de UNIR)

+

Los trabajos previos en OCR para español se han centrado principalmente en:

+

1.   Digitalización de archivos históricos (manuscritos coloniales)

+

2.   Procesamiento de documentos de identidad

+

3.   Reconocimiento de texto en escenas naturales

+

La optimización de hiperparámetros para documentos académicos en español representa una contribución original de este trabajo.

+

2.3. Conclusiones

+

Este capítulo ha presentado:

+

1.   Los fundamentos del OCR moderno y su pipeline de detección-reconocimiento

+

2.   Las tres principales soluciones de código abierto: EasyOCR, PaddleOCR y DocTR

+

3.   Los métodos de optimización de hiperparámetros, con énfasis en Ray Tune y Optuna

+

4.   Las particularidades del OCR para el idioma español

+

El estado del arte revela que, si bien existen soluciones OCR de alta calidad, su optimización para dominios específicos mediante ajuste de hiperparámetros (sin fine-tuning) ha recibido poca atención. Este trabajo contribuye a llenar ese vacío proponiendo una metodología reproducible para la optimización de PaddleOCR en documentos académicos en español.

3.   +Objetivos +concretos y metodología de trabajo

Este capítulo establece los objetivos del trabajo siguiendo la metodología SMART (Doran, 1981) y describe la metodología experimental empleada para alcanzarlos. Se define un objetivo general y cinco objetivos específicos, todos ellos medibles y verificables.

+

3.1. Objetivo general

+

Optimizar el rendimiento de PaddleOCR para documentos académicos en español mediante ajuste de hiperparámetros, alcanzando un CER inferior al 2% sin requerir fine-tuning del modelo ni recursos GPU dedicados.

+

Justificación SMART del Objetivo General

+

Tabla 3. Tabla de datos.

+

Criterio

Cumplimiento

Específico (S)

Se define claramente qué se quiere lograr: optimizar PaddleOCR mediante ajuste de hiperparámetros para documentos en español

Medible (M)

Se establece una métrica cuantificable: CER < 2%

Alcanzable (A)

Es viable dado que: (1) PaddleOCR permite configuración de hiperparámetros, (2) Ray Tune posibilita búsqueda automatizada, (3) No se requiere GPU

Relevante (R)

El impacto es demostrable: mejora la extracción de texto en documentos académicos sin costes adicionales de infraestructura

Temporal (T)

El plazo es un cuatrimestre, correspondiente al TFM

+

Fuente: Elaboración propia.

+

 

+

3.2. Objetivos específicos

+

OE1: Comparar soluciones OCR de código abierto

+

Evaluar el rendimiento base de EasyOCR, PaddleOCR y DocTR en documentos académicos en español, utilizando CER y WER como métricas, para seleccionar el modelo más prometedor.

+

OE2: Preparar un dataset de evaluación

+

Construir un dataset estructurado de imágenes de documentos académicos en español con su texto de referencia (ground truth) extraído del PDF original.

+

OE3: Identificar hiperparámetros críticos

+

Analizar la correlación entre los hiperparámetros de PaddleOCR y las métricas de error para identificar los parámetros con mayor impacto en el rendimiento.

+

OE4: Optimizar hiperparámetros con Ray Tune

+

Ejecutar una búsqueda automatizada de hiperparámetros utilizando Ray Tune con Optuna, evaluando al menos 50 configuraciones diferentes.

+

OE5: Validar la configuración optimizada

+

Comparar el rendimiento de la configuración baseline versus la configuración optimizada sobre el dataset completo, documentando la mejora obtenida.

+

3.3. Metodología del trabajo

+

3.3.1. Visión General

+

Figura 3. Diagrama 3

+

Diagrama 3

+

Fuente: Elaboración propia.

+

 

+

3.3.2. Fase 1: Preparación del Dataset

+

Fuente de Datos

+

Se utilizaron documentos PDF académicos de UNIR (Universidad Internacional de La Rioja), específicamente las instrucciones para la elaboración del TFE del Máster en Inteligencia Artificial.

+

Proceso de Conversión

+

El script prepare_dataset.ipynb implementa:

+

1.   Conversión PDF a imágenes:

+

- Biblioteca: PyMuPDF (fitz) - Resolución: 300 DPI - Formato de salida: PNG

+

1.   Extracción de texto de referencia:

+

- Método: page.get_text("dict") de PyMuPDF - Preservación de estructura de líneas - Tratamiento de texto vertical/marginal - Normalización de espacios y saltos de línea

+

Estructura del Dataset

+

Figura 4. Diagrama 4

+

Diagrama 4

+

Fuente: Elaboración propia.

+

 

+

Clase ImageTextDataset

+

Se implementó una clase Python para cargar pares imagen-texto:

+

class ImageTextDataset:
+    def __init__(self, root):
+        # Carga pares (imagen, texto) de carpetas pareadas
+
+    def __getitem__(self, idx):
+        # Retorna (PIL.Image, str)

+

3.3.3. Fase 2: Benchmark Comparativo

+

Modelos Evaluados

+

Tabla 4. Tabla de datos.

+

Modelo

Versión

Configuración

EasyOCR

-

Idiomas: ['es', 'en']

PaddleOCR

PP-OCRv5

Modelos server_det + server_rec

DocTR

-

db_resnet50 + sar_resnet31

+

Fuente: Elaboración propia.

+

 

+

Métricas de Evaluación

+

Se utilizó la biblioteca jiwer para calcular:

+

from jiwer import wer, cer
+
+def evaluate_text(reference, prediction):
+    return {
+        'WER': wer(reference, prediction),
+        'CER': cer(reference, prediction)
+    }

+

3.3.4. Fase 3: Espacio de Búsqueda

+

Hiperparámetros Seleccionados

+

Tabla 5. Tabla de datos.

+

Parámetro

Tipo

Rango/Valores

Descripción

use_doc_orientation_classify

Booleano

[True, False]

Clasificación de orientación del documento

use_doc_unwarping

Booleano

[True, False]

Corrección de deformación del documento

textline_orientation

Booleano

[True, False]

Clasificación de orientación de línea de texto

text_det_thresh

Continuo

[0.0, 0.7]

Umbral de detección de píxeles de texto

text_det_box_thresh

Continuo

[0.0, 0.7]

Umbral de caja de detección

text_det_unclip_ratio

Fijo

0.0

Coeficiente de expansión (fijado)

text_rec_score_thresh

Continuo

[0.0, 0.7]

Umbral de confianza de reconocimiento

+

Fuente: Elaboración propia.

+

 

+

Configuración de Ray Tune

+

from ray import tune
+from ray.tune.search.optuna import OptunaSearch
+
+search_space = {
+    "use_doc_orientation_classify": tune.choice([True, False]),
+    "use_doc_unwarping": tune.choice([True, False]),
+    "textline_orientation": tune.choice([True, False]),
+    "text_det_thresh": tune.uniform(0.0, 0.7),
+    "text_det_box_thresh": tune.uniform(0.0, 0.7),
+    "text_det_unclip_ratio": tune.choice([0.0]),
+    "text_rec_score_thresh": tune.uniform(0.0, 0.7),
+}
+
+tuner = tune.Tuner(
+    trainable_paddle_ocr,
+    tune_config=tune.TuneConfig(
+        metric="CER",
+        mode="min",
+        search_alg=OptunaSearch(),
+        num_samples=64,
+        max_concurrent_trials=2
+    )
+)

+

3.3.5. Fase 4: Ejecución de Optimización

+

Arquitectura de Ejecución

+

Debido a incompatibilidades entre Ray y PaddleOCR en el mismo proceso, se implementó una arquitectura basada en subprocesos:

+

Figura 5. Diagrama 5

+

Diagrama 5

+

Fuente: Elaboración propia.

+

 

+

Script de Evaluación (paddle_ocr_tuning.py)

+

El script recibe hiperparámetros por línea de comandos:

+

python paddle_ocr_tuning.py \
+    --pdf-folder ./dataset \
+    --textline-orientation True \
+    --text-det-box-thresh 0.5 \
+    --text-det-thresh 0.4 \
+    --text-rec-score-thresh 0.6

+

Y retorna métricas en formato JSON:

+

{
+    "CER": 0.0125,
+    "WER": 0.1040,
+    "TIME": 331.09,
+    "PAGES": 5,
+    "TIME_PER_PAGE": 66.12
+}

+

3.3.6. Fase 5: Validación

+

Protocolo de Validación

+

1.   Baseline: Ejecución con configuración por defecto de PaddleOCR

+

2.   Optimizado: Ejecución con mejor configuración encontrada

+

3.   Comparación: Evaluación sobre las 24 páginas del dataset completo

+

4.   Métricas reportadas: CER, WER, tiempo de procesamiento

+

3.3.7. Entorno de Ejecución

+

Hardware

+

Tabla 6. Tabla de datos.

+

Componente

Especificación

CPU

Intel Core (especificar modelo)

RAM

16 GB

GPU

No disponible (ejecución en CPU)

Almacenamiento

SSD

+

Fuente: Elaboración propia.

+

 

+

Software

+

Tabla 7. Tabla de datos.

+

Componente

Versión

Sistema Operativo

Windows 10/11

Python

3.11.9

PaddleOCR

3.3.2

PaddlePaddle

3.2.2

Ray

2.52.1

Optuna

4.6.0

+

Fuente: Elaboración propia.

+

 

+

3.3.8. Limitaciones Metodológicas

+

1.   Tamaño del dataset: El dataset contiene 24 páginas de un único tipo de documento. Resultados pueden no generalizar a otros formatos.

+

1.   Ejecución en CPU: Los tiempos de procesamiento (~70s/página) serían significativamente menores con GPU.

+

1.   Ground truth imperfecto: El texto de referencia extraído de PDF puede contener errores en documentos con layouts complejos.

+

1.   Parámetro fijo: text_det_unclip_ratio quedó fijado en 0.0 durante todo el experimento por decisión de diseño inicial.

+

3.4. Resumen del capítulo

+

Este capítulo ha establecido:

+

1.   Un objetivo general SMART: alcanzar CER < 2% mediante optimización de hiperparámetros

+

2.   Cinco objetivos específicos medibles y alcanzables

+

3.   Una metodología experimental en cinco fases claramente definidas

+

4.   El espacio de búsqueda de hiperparámetros y la configuración de Ray Tune

+

5.   Las limitaciones reconocidas del enfoque

+

El siguiente capítulo presenta el desarrollo específico de la contribución, incluyendo el benchmark comparativo de soluciones OCR, la optimización de hiperparámetros y el análisis de resultados.

4.   Desarrollo +específico de la contribución

Este capítulo presenta el desarrollo completo del estudio comparativo y la optimización de hiperparámetros de sistemas OCR. Se estructura según el tipo de trabajo "Comparativa de soluciones" establecido por las instrucciones de UNIR: planteamiento de la comparativa, desarrollo de la comparativa, y discusión y análisis de resultados.

+

4.1. Planteamiento de la comparativa

+

4.1.1. Introducción

+

Esta sección presenta los resultados del estudio comparativo realizado entre tres soluciones OCR de código abierto: EasyOCR, PaddleOCR y DocTR. Los experimentos fueron documentados en el notebook ocr_benchmark_notebook.ipynb del repositorio. El objetivo es identificar el modelo base más prometedor para la posterior fase de optimización de hiperparámetros.

+

4.1.2. Configuración del Experimento

+

Dataset de Evaluación

+

Se utilizó el documento "Instrucciones para la redacción y elaboración del TFE" del Máster Universitario en Inteligencia Artificial de UNIR, ubicado en la carpeta instructions/.

+

Tabla 8. Tabla 3. Características del dataset de evaluación.

+

Característica

Valor

Número de páginas evaluadas

5 (páginas 1-5 en benchmark inicial)

Formato

PDF digital (no escaneado)

Idioma

Español

Resolución de conversión

300 DPI

+

Fuente: Elaboración propia.

+

 

+

Configuración de los Modelos

+

Según el código en ocr_benchmark_notebook.ipynb:

+

EasyOCR:

+

easyocr_reader = easyocr.Reader(['es', 'en'])  # Spanish and English

+

PaddleOCR (PP-OCRv5):

+

paddleocr_model = PaddleOCR(
+    text_detection_model_name="PP-OCRv5_server_det",
+    text_recognition_model_name="PP-OCRv5_server_rec",
+    use_doc_orientation_classify=False,
+    use_doc_unwarping=False,
+    use_textline_orientation=True,
+)

+

Versión utilizada: PaddleOCR 3.2.0 (según output del notebook)

+

DocTR:

+

doctr_model = ocr_predictor(det_arch="db_resnet50", reco_arch="sar_resnet31", pretrained=True)

+

Métricas de Evaluación

+

Se utilizó la biblioteca jiwer para calcular CER y WER:

+

from jiwer import wer, cer
+
+def evaluate_text(reference, prediction):
+    return {'WER': wer(reference, prediction), 'CER': cer(reference, prediction)}

+

4.1.3. Resultados del Benchmark

+

Resultados de PaddleOCR (Datos del CSV)

+

Del archivo results/ai_ocr_benchmark_finetune_results_20251206_113206.csv, se obtienen los siguientes resultados de PaddleOCR para las páginas 5-9 del documento:

+

Tabla 9. Tabla 4. Resultados de PaddleOCR por página (benchmark inicial).

+

Página

WER

CER

5

12.16%

6.33%

6

12.81%

6.40%

7

11.06%

6.24%

8

8.13%

1.54%

9

10.61%

5.58%

+

Fuente: Elaboración propia.

+

 

+

Promedio PaddleOCR (páginas 5-9):

+

·     CER medio: ~5.22%

+

·     WER medio: ~10.95%

+

Comparativa de Modelos

+

Según la documentación del notebook ocr_benchmark_notebook.ipynb, los tres modelos evaluados representan diferentes paradigmas de OCR:

+

Tabla 10. Tabla 5. Comparativa de arquitecturas OCR evaluadas.

+

Modelo

Tipo

Componentes

Fortalezas Clave

EasyOCR

End-to-end (det + rec)

DB + CRNN/Transformer

Ligero, fácil de usar, multilingüe

PaddleOCR (PP-OCR)

End-to-end (det + rec + cls)

DB + SRN/CRNN

Soporte multilingüe robusto, pipeline configurable

DocTR

End-to-end (det + rec)

DB/LinkNet + CRNN/SAR/VitSTR

Orientado a investigación, API limpia

+

Fuente: Elaboración propia.

+

 

+

Ejemplo de Salida OCR

+

Del archivo CSV, un ejemplo de predicción de PaddleOCR para la página 8:

+

"Escribe siempre al menos un párrafo de introducción en cada capítulo o apartado, explicando de qué vas a tratar en esa sección. Evita que aparezcan dos encabezados de nivel consecutivos sin ningún texto entre medias. [...] En esta titulacióon se cita de acuerdo con la normativa Apa."

+

Errores observados en este ejemplo:

+

·     titulacióon en lugar de titulación (carácter duplicado)

+

·     Apa en lugar de APA (capitalización)

+

4.1.4. Justificación de la Selección de PaddleOCR

+

Criterios de Selección

+

Basándose en los resultados obtenidos y la documentación del benchmark:

+

1.   Rendimiento: PaddleOCR obtuvo CER entre 1.54% y 6.40% en las páginas evaluadas

+

2.   Configurabilidad: PaddleOCR ofrece múltiples hiperparámetros ajustables:

+

- Umbrales de detección (text_det_thresh, text_det_box_thresh) - Umbral de reconocimiento (text_rec_score_thresh) - Componentes opcionales (use_textline_orientation, use_doc_orientation_classify, use_doc_unwarping)

+

1.   Documentación oficial: [PaddleOCR Documentation](https://www.paddleocr.ai/v3.0.0/en/version3.x/pipeline_usage/OCR.html)

+

Decisión

+

Se selecciona PaddleOCR (PP-OCRv5) para la fase de optimización debido a:

+

·     Resultados iniciales prometedores (CER ~5%)

+

·     Alta configurabilidad de hiperparámetros de inferencia

+

·     Pipeline modular que permite experimentación

+

4.1.5. Limitaciones del Benchmark

+

1.   Tamaño reducido: Solo 5 páginas evaluadas en el benchmark comparativo inicial

+

2.   Único tipo de documento: Documentos académicos de UNIR únicamente

+

3.   Ground truth: El texto de referencia se extrajo automáticamente del PDF, lo cual puede introducir errores en layouts complejos

+

4.1.6. Resumen de la Sección

+

Esta sección ha presentado:

+

1.   La configuración del benchmark según ocr_benchmark_notebook.ipynb

+

2.   Los resultados cuantitativos de PaddleOCR del archivo CSV de resultados

+

3.   La justificación de la selección de PaddleOCR para optimización

+

Fuentes de datos utilizadas:

+

·     ocr_benchmark_notebook.ipynb: Código del benchmark

+

·     results/ai_ocr_benchmark_finetune_results_20251206_113206.csv: Resultados numéricos

+

·     Documentación oficial de PaddleOCR

+

4.2. Desarrollo de la comparativa: Optimización de hiperparámetros

+

4.2.1. Introducción

+

Esta sección describe el proceso de optimización de hiperparámetros de PaddleOCR utilizando Ray Tune con el algoritmo de búsqueda Optuna. Los experimentos fueron implementados en el notebook src/paddle_ocr_fine_tune_unir_raytune.ipynb y los resultados se almacenaron en src/raytune_paddle_subproc_results_20251207_192320.csv.

+

4.2.2. Configuración del Experimento

+

Entorno de Ejecución

+

Según los outputs del notebook:

+

Tabla 11. Tabla 6. Entorno de ejecución del experimento.

+

Componente

Versión/Especificación

Python

3.11.9

PaddlePaddle

3.2.2

PaddleOCR

3.3.2

Ray

2.52.1

GPU

No disponible (CPU only)

+

Fuente: Elaboración propia.

+

 

+

Dataset

+

Se utilizó un dataset estructurado en src/dataset/ creado mediante el notebook src/prepare_dataset.ipynb:

+

·     Estructura: Carpetas con subcarpetas img/ y txt/ pareadas

+

·     Páginas evaluadas por trial: 5 (páginas 5-10 del documento)

+

·     Gestión de datos: Clase ImageTextDataset en src/dataset_manager.py

+

Espacio de Búsqueda

+

Según el código del notebook, se definió el siguiente espacio de búsqueda:

+

search_space = {
+    "use_doc_orientation_classify": tune.choice([True, False]),
+    "use_doc_unwarping": tune.choice([True, False]),
+    "textline_orientation": tune.choice([True, False]),
+    "text_det_thresh": tune.uniform(0.0, 0.7),
+    "text_det_box_thresh": tune.uniform(0.0, 0.7),
+    "text_det_unclip_ratio": tune.choice([0.0]),  # Fijado
+    "text_rec_score_thresh": tune.uniform(0.0, 0.7),
+}

+

Descripción de parámetros (según documentación de PaddleOCR):

+

Tabla 12. Tabla de datos.

+

Parámetro

Descripción

use_doc_orientation_classify

Clasificación de orientación del documento

use_doc_unwarping

Corrección de deformación del documento

textline_orientation

Clasificación de orientación de línea de texto

text_det_thresh

Umbral de detección de píxeles de texto

text_det_box_thresh

Umbral de caja de detección

text_det_unclip_ratio

Coeficiente de expansión (fijado en 0.0)

text_rec_score_thresh

Umbral de confianza de reconocimiento

+

Fuente: Elaboración propia.

+

 

+

Configuración de Ray Tune

+

tuner = tune.Tuner(
+    trainable_paddle_ocr,
+    tune_config=tune.TuneConfig(
+        metric="CER",
+        mode="min",
+        search_alg=OptunaSearch(),
+        num_samples=64,
+        max_concurrent_trials=2
+    ),
+    run_config=air.RunConfig(verbose=2, log_to_file=False),
+    param_space=search_space
+)

+

·     Métrica objetivo: CER (minimizar)

+

·     Algoritmo de búsqueda: Optuna (TPE - Tree-structured Parzen Estimator)

+

·     Número de trials: 64

+

·     Trials concurrentes: 2

+

4.2.3. Resultados de la Optimización

+

Estadísticas Descriptivas

+

Del archivo CSV de resultados (raytune_paddle_subproc_results_20251207_192320.csv):

+

Tabla 13. Tabla 7. Estadísticas descriptivas de los 64 trials de Ray Tune.

+

Estadística

CER

WER

Tiempo (s)

Tiempo/Página (s)

count

64

64

64

64

mean

5.25%

14.28%

347.61

69.42

std

11.03%

10.75%

7.88

1.57

min

1.15%

9.89%

320.97

64.10

25%

1.20%

10.04%

344.24

68.76

50%

1.23%

10.20%

346.42

69.19

75%

4.03%

13.20%

350.14

69.93

max

51.61%

59.45%

368.57

73.63

+

Fuente: Elaboración propia.

+

 

+

Mejor Configuración Encontrada

+

Según el análisis del notebook:

+

Best CER: 0.011535 (1.15%)
+Best WER: 0.098902 (9.89%)
+
+Configuración óptima:
+  textline_orientation: True
+  use_doc_orientation_classify: False
+  use_doc_unwarping: False
+  text_det_thresh: 0.4690
+  text_det_box_thresh: 0.5412
+  text_det_unclip_ratio: 0.0
+  text_rec_score_thresh: 0.6350

+

Análisis de Correlación

+

Correlación de Pearson entre parámetros y métricas de error (del notebook):

+

Correlación con CER:

+

Tabla 14. Tabla de datos.

+

Parámetro

Correlación

CER

1.000

config/text_det_box_thresh

0.226

config/text_rec_score_thresh

-0.161

config/text_det_thresh

-0.523

config/text_det_unclip_ratio

NaN

+

Fuente: Elaboración propia.

+

 

+

Correlación con WER:

+

Tabla 15. Tabla de datos.

+

Parámetro

Correlación

WER

1.000

config/text_det_box_thresh

0.227

config/text_rec_score_thresh

-0.173

config/text_det_thresh

-0.521

config/text_det_unclip_ratio

NaN

+

Fuente: Elaboración propia.

+

 

+

Hallazgo clave: El parámetro text_det_thresh muestra la correlación más fuerte (-0.52), indicando que valores más altos de este umbral tienden a reducir el error.

+

Impacto del Parámetro textline_orientation

+

Según el análisis del notebook, este parámetro booleano tiene el mayor impacto:

+

Tabla 16. Tabla 8. Impacto del parámetro textline_orientation en las métricas de error.

+

textline_orientation

CER Medio

WER Medio

True

~3.76%

~12.73%

False

~12.40%

~21.71%

+

Fuente: Elaboración propia.

+

 

+

Interpretación: El CER medio es ~3.3x menor con textline_orientation=True (3.76% vs 12.40%). Además, la varianza es mucho menor, lo que indica resultados más consistentes. Para documentos en español con layouts mixtos (tablas, encabezados, direcciones), la clasificación de orientación ayuda a PaddleOCR a ordenar correctamente las líneas de texto.

+

Figura 6. Impacto de textline_orientation en CER

+

Impacto de textline_orientation en CER

+

Fuente: Elaboración propia.

+

 

+

Análisis de Fallos

+

Los trials con CER muy alto (>40%) se produjeron cuando:

+

·     text_det_thresh < 0.1 (valores muy bajos)

+

·     textline_orientation = False

+

Ejemplo de trial con fallo catastrófico:

+

·     CER: 51.61%

+

·     WER: 59.45%

+

·     Configuración: text_det_thresh=0.017, textline_orientation=True

+

4.2.4. Comparación Baseline vs Optimizado

+

Resultados sobre Dataset Completo (24 páginas)

+

Del análisis final del notebook ejecutando sobre las 24 páginas:

+

Tabla 17. Tabla 9. Comparación baseline vs configuración optimizada (24 páginas).

+

Modelo

CER

WER

PaddleOCR (Baseline)

7.78%

14.94%

PaddleOCR-HyperAdjust

1.49%

7.62%

+

Fuente: Elaboración propia.

+

 

+

Métricas de Mejora

+

Tabla 18. Tabla 10. Análisis de la mejora obtenida.

+

Métrica

Baseline

Optimizado

Mejora Absoluta

Reducción Error

CER

7.78%

1.49%

-6.29 pp

80.9%

WER

14.94%

7.62%

-7.32 pp

49.0%

+

Fuente: Elaboración propia.

+

 

+

Interpretación (del notebook)

+

"La optimización de hiperparámetros mejoró la precisión de caracteres de 92.2% a 98.5%, una ganancia de 6.3 puntos porcentuales. Aunque el baseline ya ofrecía resultados aceptables, la configuración optimizada reduce los errores residuales en un 80.9%."

+

Figura 7. Comparación Baseline vs Optimizado (24 páginas)

+

Comparación Baseline vs Optimizado (24 páginas)

+

Fuente: Elaboración propia.

+

 

+

Impacto práctico: En un documento de 10,000 caracteres:

+

·     Baseline: ~778 caracteres con error

+

·     Optimizado: ~149 caracteres con error

+

·     Diferencia: ~629 caracteres menos con errores

+

4.2.5. Tiempo de Ejecución

+

Tabla 19. Tabla de datos.

+

Métrica

Valor

Tiempo total del experimento

~6 horas (64 trials × ~6 min/trial)

Tiempo medio por trial

367.72 segundos

Tiempo medio por página

69.42 segundos

Total páginas procesadas

64 trials × 5 páginas = 320 evaluaciones

+

Fuente: Elaboración propia.

+

 

+

4.2.6. Resumen de la Sección

+

Esta sección ha presentado:

+

1.   Configuración del experimento: 64 trials con Ray Tune + Optuna sobre 7 hiperparámetros

+

2.   Resultados estadísticos: CER medio 5.25%, CER mínimo 1.15%

+

3.   Hallazgos clave:

+

- textline_orientation=True es crítico (reduce CER ~70%) - text_det_thresh tiene correlación -0.52 con CER - Valores bajos de text_det_thresh (<0.1) causan fallos catastróficos

+

1.   Mejora final: CER reducido de 7.78% a 1.49% (reducción del 80.9%)

+

Fuentes de datos:

+

·     src/paddle_ocr_fine_tune_unir_raytune.ipynb: Código del experimento

+

·     src/raytune_paddle_subproc_results_20251207_192320.csv: Resultados de 64 trials

+

·     src/paddle_ocr_tuning.py: Script de evaluación

+

4.3. Discusión y análisis de resultados

+

4.3.1. Introducción

+

Esta sección presenta un análisis consolidado de los resultados obtenidos en las fases de benchmark comparativo y optimización de hiperparámetros. Se discuten las implicaciones prácticas y se evalúa el cumplimiento de los objetivos planteados.

+

4.3.2. Resumen de Resultados

+

Resultados del Benchmark Comparativo

+

Del archivo results/ai_ocr_benchmark_finetune_results_20251206_113206.csv, PaddleOCR con configuración inicial (use_textline_orientation=True) obtuvo los siguientes resultados en las páginas 5-9:

+

Tabla 20. Tabla de datos.

+

Página

WER

CER

5

12.16%

6.33%

6

12.81%

6.40%

7

11.06%

6.24%

8

8.13%

1.54%

9

10.61%

5.58%

Promedio

10.95%

5.22%

+

Fuente: Elaboración propia.

+

 

+

Resultados de la Optimización con Ray Tune

+

Del archivo src/raytune_paddle_subproc_results_20251207_192320.csv (64 trials):

+

Tabla 21. Tabla de datos.

+

Métrica

Valor

CER mínimo

1.15%

CER medio

5.25%

CER máximo

51.61%

WER mínimo

9.89%

WER medio

14.28%

WER máximo

59.45%

+

Fuente: Elaboración propia.

+

 

+

Comparación Final (Dataset Completo - 24 páginas)

+

Resultados del notebook src/paddle_ocr_fine_tune_unir_raytune.ipynb:

+

Tabla 22. Tabla de datos.

+

Modelo

CER

Precisión Caracteres

WER

Precisión Palabras

PaddleOCR (Baseline)

7.78%

92.22%

14.94%

85.06%

PaddleOCR-HyperAdjust

1.49%

98.51%

7.62%

92.38%

+

Fuente: Elaboración propia.

+

 

+

4.3.3. Análisis de Resultados

+

Mejora Obtenida

+

Tabla 23. Tabla de datos.

+

Forma de Medición

Valor

Mejora en precisión de caracteres (absoluta)

+6.29 puntos porcentuales

Reducción del CER (relativa)

80.9%

Mejora en precisión de palabras (absoluta)

+7.32 puntos porcentuales

Reducción del WER (relativa)

49.0%

Precisión final de caracteres

98.51%

+

Fuente: Elaboración propia.

+

 

+

Impacto de Hiperparámetros Individuales

+

Parámetro textline_orientation

+

Este parámetro booleano demostró ser el más influyente:

+

Tabla 24. Tabla de datos.

+

Valor

CER Medio

Impacto

True

~3.76%

Rendimiento óptimo

False

~12.40%

3.3x peor

+

Fuente: Elaboración propia.

+

 

+

Reducción del CER: 69.7% cuando se habilita la clasificación de orientación de línea.

+

Parámetro text_det_thresh

+

Correlación con CER: -0.523 (la más fuerte de los parámetros continuos)

+

Tabla 25. Tabla de datos.

+

Rango

Comportamiento

< 0.1

Fallos catastróficos (CER 40-50%)

0.3 - 0.6

Rendimiento óptimo

Valor óptimo

0.4690

+

Fuente: Elaboración propia.

+

 

+

Parámetros con menor impacto

+

Tabla 26. Tabla de datos.

+

Parámetro

Correlación con CER

Valor óptimo

text_det_box_thresh

+0.226

0.5412

text_rec_score_thresh

-0.161

0.6350

use_doc_orientation_classify

-

False

use_doc_unwarping

-

False

+

Fuente: Elaboración propia.

+

 

+

Configuración Óptima Final

+

config_optimizada = {
+    "textline_orientation": True,           # CRÍTICO
+    "use_doc_orientation_classify": False,
+    "use_doc_unwarping": False,
+    "text_det_thresh": 0.4690,              # Correlación -0.52
+    "text_det_box_thresh": 0.5412,
+    "text_det_unclip_ratio": 0.0,
+    "text_rec_score_thresh": 0.6350,
+}

+

4.3.4. Discusión

+

Hallazgos Principales

+

1.   Importancia de la clasificación de orientación de línea: El parámetro textline_orientation=True es el factor más determinante. Esto tiene sentido para documentos con layouts mixtos (tablas, encabezados, direcciones) donde el orden correcto de las líneas de texto es crucial.

+

1.   Umbral de detección crítico: El parámetro text_det_thresh presenta un umbral mínimo efectivo (~0.1). Valores inferiores generan demasiados falsos positivos en la detección, corrompiendo el reconocimiento posterior.

+

1.   Componentes opcionales innecesarios: Para documentos académicos digitales (no escaneados), los módulos de corrección de orientación de documento (use_doc_orientation_classify) y corrección de deformación (use_doc_unwarping) no aportan mejora e incluso pueden introducir overhead.

+

Interpretación de la Correlación Negativa

+

La correlación negativa de text_det_thresh (-0.52) con el CER indica que:

+

·     Umbrales más altos filtran detecciones de baja confianza

+

·     Esto reduce falsos positivos que generan texto erróneo

+

·     El reconocimiento es más preciso con menos regiones pero más confiables

+

Limitaciones de los Resultados

+

1.   Generalización: Los resultados se obtuvieron sobre documentos de un único tipo (instrucciones académicas UNIR). La configuración óptima puede variar para otros tipos de documentos.

+

1.   Ground truth automático: El texto de referencia se extrajo programáticamente del PDF. En layouts complejos, esto puede introducir errores en la evaluación.

+

1.   Ejecución en CPU: Los tiempos reportados (~69s/página) corresponden a ejecución en CPU. Con GPU, los tiempos serían significativamente menores.

+

1.   Parámetro fijo: text_det_unclip_ratio permaneció fijo en 0.0 durante todo el experimento por decisión de diseño.

+

Comparación con Objetivos

+

Tabla 27. Tabla de datos.

+

Objetivo

Meta

Resultado

Cumplimiento

OE1: Comparar soluciones OCR

Evaluar EasyOCR, PaddleOCR, DocTR

PaddleOCR seleccionado

OE2: Preparar dataset

Construir dataset estructurado

Dataset de 24 páginas

OE3: Identificar hiperparámetros críticos

Analizar correlaciones

textline_orientation y text_det_thresh identificados

OE4: Optimizar con Ray Tune

Mínimo 50 configuraciones

64 trials ejecutados

OE5: Validar configuración

Documentar mejora

CER 7.78% → 1.49%

Objetivo General

CER < 2%

CER = 1.49%

+

Fuente: Elaboración propia.

+

 

+

4.3.5. Implicaciones Prácticas

+

Recomendaciones de Configuración

+

Para documentos académicos en español similares a los evaluados:

+

1.   Obligatorio: use_textline_orientation=True

+

2.   Recomendado: text_det_thresh entre 0.4 y 0.5

+

3.   Opcional: text_det_box_thresh ~0.5, text_rec_score_thresh >0.6

+

4.   No recomendado: Habilitar use_doc_orientation_classify o use_doc_unwarping para documentos digitales

+

Impacto Cuantitativo

+

En un documento típico de 10,000 caracteres:

+

Tabla 28. Tabla de datos.

+

Configuración

Errores estimados

Baseline

~778 caracteres

Optimizada

~149 caracteres

Reducción

629 caracteres menos con errores

+

Fuente: Elaboración propia.

+

 

+

Aplicabilidad

+

Esta metodología de optimización es aplicable cuando:

+

·     No se dispone de recursos GPU para fine-tuning

+

·     El modelo preentrenado ya tiene soporte para el idioma objetivo

+

·     Se busca mejorar rendimiento sin reentrenar

+

4.3.6. Resumen de la Sección

+

Esta sección ha presentado:

+

1.   Los resultados consolidados del benchmark y la optimización

+

2.   El análisis del impacto de cada hiperparámetro

+

3.   La configuración óptima identificada

+

4.   La discusión de limitaciones y aplicabilidad

+

5.   El cumplimiento de los objetivos planteados

+

Resultado principal: Se logró reducir el CER del 7.78% al 1.49% (mejora del 80.9%) mediante optimización de hiperparámetros, cumpliendo el objetivo de alcanzar CER < 2%.

+

Fuentes de datos:

+

·     results/ai_ocr_benchmark_finetune_results_20251206_113206.csv

+

·     src/raytune_paddle_subproc_results_20251207_192320.csv

+

·     src/paddle_ocr_fine_tune_unir_raytune.ipynb

5.   +Conclusiones +y trabajo futuro

Este capítulo resume las principales conclusiones del trabajo, evalúa el grado de cumplimiento de los objetivos planteados y propone líneas de trabajo futuro que permitirían ampliar y profundizar los resultados obtenidos.

+

5.1. Conclusiones

+

5.1.1. Conclusiones Generales

+

Este Trabajo Fin de Máster ha demostrado que es posible mejorar significativamente el rendimiento de sistemas OCR preentrenados mediante optimización sistemática de hiperparámetros, sin requerir fine-tuning ni recursos GPU dedicados.

+

El objetivo principal del trabajo era alcanzar un CER inferior al 2% en documentos académicos en español. Los resultados obtenidos confirman el cumplimiento de este objetivo:

+

Tabla 29. Tabla de datos.

+

Métrica

Objetivo

Resultado

CER

< 2%

1.49%

+

Fuente: Elaboración propia.

+

 

+

5.1.2. Conclusiones Específicas

+

Respecto a OE1 (Comparativa de soluciones OCR):

+

·     Se evaluaron tres soluciones OCR de código abierto: EasyOCR, PaddleOCR (PP-OCRv5) y DocTR

+

·     PaddleOCR demostró el mejor rendimiento base para documentos en español

+

·     La configurabilidad del pipeline de PaddleOCR lo hace idóneo para optimización

+

Respecto a OE2 (Preparación del dataset):

+

·     Se construyó un dataset estructurado con 24 páginas de documentos académicos

+

·     La clase ImageTextDataset facilita la carga de pares imagen-texto

+

·     El ground truth se extrajo automáticamente del PDF mediante PyMuPDF

+

Respecto a OE3 (Identificación de hiperparámetros críticos):

+

·     El parámetro textline_orientation es el más influyente: reduce el CER en un 69.7% cuando está habilitado

+

·     El umbral text_det_thresh presenta la correlación más fuerte (-0.52) con el CER

+

·     Los parámetros de corrección de documento (use_doc_orientation_classify, use_doc_unwarping) no aportan mejora en documentos digitales

+

Respecto a OE4 (Optimización con Ray Tune):

+

·     Se ejecutaron 64 trials con el algoritmo OptunaSearch

+

·     El tiempo total del experimento fue aproximadamente 6 horas (en CPU)

+

·     La arquitectura basada en subprocesos permitió superar incompatibilidades entre Ray y PaddleOCR

+

Respecto a OE5 (Validación de la configuración):

+

·     Se validó la configuración óptima sobre el dataset completo de 24 páginas

+

·     La mejora obtenida fue del 80.9% en reducción del CER (7.78% → 1.49%)

+

·     La precisión de caracteres alcanzó el 98.51%

+

5.1.3. Hallazgos Clave

+

1.   Arquitectura sobre umbrales: Un único parámetro booleano (textline_orientation) tiene más impacto que todos los umbrales continuos combinados.

+

1.   Umbrales mínimos efectivos: Valores de text_det_thresh < 0.1 causan fallos catastróficos (CER >40%).

+

1.   Simplicidad para documentos digitales: Para documentos PDF digitales (no escaneados), los módulos de corrección de orientación y deformación son innecesarios.

+

1.   Optimización sin fine-tuning: Se puede mejorar significativamente el rendimiento de modelos preentrenados mediante ajuste de hiperparámetros de inferencia.

+

5.1.4. Contribuciones del Trabajo

+

1.   Metodología reproducible: Se documenta un proceso completo de optimización de hiperparámetros OCR con Ray Tune + Optuna.

+

1.   Análisis de hiperparámetros de PaddleOCR: Se cuantifica el impacto de cada parámetro configurable mediante correlaciones y análisis comparativo.

+

1.   Configuración óptima para español: Se proporciona una configuración validada para documentos académicos en español.

+

1.   Código fuente: Todo el código está disponible en el repositorio GitHub para reproducción y extensión.

+

5.1.5. Limitaciones del Trabajo

+

1.   Tipo de documento único: Los experimentos se realizaron únicamente sobre documentos académicos de UNIR. La generalización a otros tipos de documentos requiere validación adicional.

+

1.   Tamaño del dataset: 24 páginas es un corpus limitado para conclusiones estadísticamente robustas.

+

1.   Ground truth automático: La extracción automática del texto de referencia puede introducir errores en layouts complejos.

+

1.   Ejecución en CPU: Los tiempos de procesamiento (~69s/página) limitan la aplicabilidad en escenarios de alto volumen.

+

1.   Parámetro no explorado: text_det_unclip_ratio permaneció fijo en 0.0 durante todo el experimento.

+

5.2. Líneas de trabajo futuro

+

5.2.1. Extensiones Inmediatas

+

1.   Validación cruzada: Evaluar la configuración óptima en otros tipos de documentos en español (facturas, formularios, textos manuscritos).

+

1.   Exploración de text_det_unclip_ratio: Incluir este parámetro en el espacio de búsqueda.

+

1.   Dataset ampliado: Construir un corpus más amplio y diverso de documentos en español.

+

1.   Evaluación con GPU: Medir tiempos de inferencia con aceleración GPU.

+

5.2.2. Líneas de Investigación

+

1.   Transfer learning de hiperparámetros: Investigar si las configuraciones óptimas para un tipo de documento transfieren a otros dominios.

+

1.   Optimización multi-objetivo: Considerar simultáneamente CER, WER y tiempo de inferencia como objetivos.

+

1.   AutoML para OCR: Aplicar técnicas de AutoML más avanzadas (Neural Architecture Search, meta-learning).

+

1.   Comparación con fine-tuning: Cuantificar la brecha de rendimiento entre optimización de hiperparámetros y fine-tuning real.

+

5.2.3. Aplicaciones Prácticas

+

1.   Herramienta de configuración automática: Desarrollar una herramienta que determine automáticamente la configuración óptima para un nuevo tipo de documento.

+

1.   Integración en pipelines de producción: Implementar la configuración optimizada en sistemas reales de procesamiento documental.

+

1.   Benchmark público: Publicar un benchmark de OCR para documentos en español que facilite la comparación de soluciones.

+

5.2.4. Reflexión Final

+

Este trabajo demuestra que, en un contexto de recursos limitados donde el fine-tuning de modelos de deep learning no es viable, la optimización de hiperparámetros representa una alternativa práctica y efectiva para mejorar sistemas OCR.

+

La metodología propuesta es reproducible, los resultados son cuantificables, y las conclusiones son aplicables a escenarios reales de procesamiento documental. La reducción del CER del 7.78% al 1.49% representa una mejora sustancial que puede tener impacto directo en aplicaciones downstream como extracción de información, análisis semántico y búsqueda de documentos.

+

El código fuente y los datos experimentales están disponibles públicamente para facilitar la reproducción y extensión de este trabajo.

Referencias +bibliográficas

Akiba, T., Sano, S., Yanase, T., Ohta, T., & Koyama, M. (2019). Optuna: A next-generation hyperparameter optimization framework. Proceedings of the 25th ACM SIGKDD International Conference on Knowledge Discovery & Data Mining, 2623-2631. https://doi.org/10.1145/3292500.3330701

+

Baek, Y., Lee, B., Han, D., Yun, S., & Lee, H. (2019). Character region awareness for text detection. Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition, 9365-9374. https://doi.org/10.1109/CVPR.2019.00959

+

Bergstra, J., & Bengio, Y. (2012). Random search for hyper-parameter optimization. Journal of Machine Learning Research, 13(1), 281-305. https://jmlr.org/papers/v13/bergstra12a.html

+

Bergstra, J., Bardenet, R., Bengio, Y., & Kégl, B. (2011). Algorithms for hyper-parameter optimization. Advances in Neural Information Processing Systems, 24, 2546-2554. https://papers.nips.cc/paper/2011/hash/86e8f7ab32cfd12577bc2619bc635690-Abstract.html

+

Cohen, J. (1988). Statistical power analysis for the behavioral sciences (2nd ed.). Lawrence Erlbaum Associates.

+

Doran, G. T. (1981). There's a S.M.A.R.T. way to write management's goals and objectives. Management Review, 70(11), 35-36.

+

Du, Y., Li, C., Guo, R., Yin, X., Liu, W., Zhou, J., Bai, Y., Yu, Z., Yang, Y., Dang, Q., & Wang, H. (2020). PP-OCR: A practical ultra lightweight OCR system. arXiv preprint arXiv:2009.09941. https://arxiv.org/abs/2009.09941

+

Du, Y., Li, C., Guo, R., Cui, C., Liu, W., Zhou, J., Lu, B., Yang, Y., Liu, Q., Hu, X., Yu, D., & Wang, H. (2023). PP-OCRv4: Mobile scene text detection and recognition. arXiv preprint arXiv:2310.05930. https://arxiv.org/abs/2310.05930

+

Feurer, M., & Hutter, F. (2019). Hyperparameter optimization. In F. Hutter, L. Kotthoff, & J. Vanschoren (Eds.), Automated machine learning: Methods, systems, challenges (pp. 3-33). Springer. https://doi.org/10.1007/978-3-030-05318-5_1

+

He, P., Huang, W., Qiao, Y., Loy, C. C., & Tang, X. (2016). Reading scene text in deep convolutional sequences. Proceedings of the AAAI Conference on Artificial Intelligence, 30(1), 3501-3508. https://doi.org/10.1609/aaai.v30i1.10291

+

JaidedAI. (2020). EasyOCR: Ready-to-use OCR with 80+ supported languages. GitHub. https://github.com/JaidedAI/EasyOCR

+

Liang, J., Doermann, D., & Li, H. (2005). Camera-based analysis of text and documents: A survey. International Journal of Document Analysis and Recognition, 7(2), 84-104. https://doi.org/10.1007/s10032-004-0138-z

+

Liao, M., Wan, Z., Yao, C., Chen, K., & Bai, X. (2020). Real-time scene text detection with differentiable binarization. Proceedings of the AAAI Conference on Artificial Intelligence, 34(07), 11474-11481. https://doi.org/10.1609/aaai.v34i07.6812

+

Liaw, R., Liang, E., Nishihara, R., Moritz, P., Gonzalez, J. E., & Stoica, I. (2018). Tune: A research platform for distributed model selection and training. arXiv preprint arXiv:1807.05118. https://arxiv.org/abs/1807.05118

+

Mindee. (2021). DocTR: Document Text Recognition. GitHub. https://github.com/mindee/doctr

+

Moritz, P., Nishihara, R., Wang, S., Tumanov, A., Liaw, R., Liang, E., Elibol, M., Yang, Z., Paul, W., Jordan, M. I., & Stoica, I. (2018). Ray: A distributed framework for emerging AI applications. 13th USENIX Symposium on Operating Systems Design and Implementation (OSDI 18), 561-577. https://www.usenix.org/conference/osdi18/presentation/moritz

+

Morris, A. C., Maier, V., & Green, P. D. (2004). From WER and RIL to MER and WIL: Improved evaluation measures for connected speech recognition. Eighth International Conference on Spoken Language Processing. https://doi.org/10.21437/Interspeech.2004-668

+

PaddlePaddle. (2024). PaddleOCR: Awesome multilingual OCR toolkits based on PaddlePaddle. GitHub. https://github.com/PaddlePaddle/PaddleOCR

+

Pearson, K. (1895). Notes on regression and inheritance in the case of two parents. Proceedings of the Royal Society of London, 58, 240-242. https://doi.org/10.1098/rspl.1895.0041

+

PyMuPDF. (2024). PyMuPDF documentation. https://pymupdf.readthedocs.io/

+

Shi, B., Bai, X., & Yao, C. (2016). An end-to-end trainable neural network for image-based sequence recognition and its application to scene text recognition. IEEE Transactions on Pattern Analysis and Machine Intelligence, 39(11), 2298-2304. https://doi.org/10.1109/TPAMI.2016.2646371

+

Smith, R. (2007). An overview of the Tesseract OCR engine. Ninth International Conference on Document Analysis and Recognition (ICDAR 2007), 2, 629-633. https://doi.org/10.1109/ICDAR.2007.4376991

+

Zhou, X., Yao, C., Wen, H., Wang, Y., Zhou, S., He, W., & Liang, J. (2017). EAST: An efficient and accurate scene text detector. Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition, 5551-5560. https://doi.org/10.1109/CVPR.2017.283

+

Zoph, B., & Le, Q. V. (2017). Neural architecture search with reinforcement learning. International Conference on Learning Representations (ICLR). https://arxiv.org/abs/1611.01578

+

Anexo A.    +Código fuente y datos analizados

A.1 Repositorio del Proyecto

+

El código fuente completo y los datos utilizados en este trabajo están disponibles en el siguiente repositorio:

+

URL del repositorio: https://github.com/seryus/MastersThesis

+

El repositorio incluye:

+

·     Notebooks de experimentación: Código completo de los experimentos realizados

+

·     Scripts de evaluación: Herramientas para evaluar modelos OCR

+

·     Dataset: Imágenes y textos de referencia utilizados

+

·     Resultados: Archivos CSV con los resultados de los 64 trials de Ray Tune

+

A.2 Estructura del Repositorio

+

MastersThesis/
+├── docs/                    # Capítulos de la tesis en Markdown
+├── src/
+│   ├── paddle_ocr_fine_tune_unir_raytune.ipynb  # Experimento principal
+│   ├── paddle_ocr_tuning.py                      # Script de evaluación CLI
+│   ├── dataset_manager.py                        # Clase ImageTextDataset
+│   ├── prepare_dataset.ipynb                     # Preparación del dataset
+│   └── raytune_paddle_subproc_results_*.csv      # Resultados de 64 trials
+├── results/                 # Resultados de benchmarks
+├── instructions/            # Instrucciones y plantilla UNIR
+└── README.md

+

A.3 Requisitos de Software

+

Para reproducir los experimentos se requieren las siguientes dependencias:

+

Tabla 30. Tabla de datos.

+

Componente

Versión

Python

3.11.9

PaddlePaddle

3.2.2

PaddleOCR

3.3.2

Ray

2.52.1

Optuna

4.6.0

jiwer

(última versión)

PyMuPDF

(última versión)

+

Fuente: Elaboración propia.

+

 

+

A.4 Instrucciones de Ejecución

+

1.   Clonar el repositorio

+

2.   Instalar dependencias: pip install -r requirements.txt

+

3.   Ejecutar el notebook src/paddle_ocr_fine_tune_unir_raytune.ipynb

+

A.5 Licencia

+

El código se distribuye bajo licencia MIT.

+

+
+ +
+ +
+
+ + diff --git a/thesis_output_files/colorschememapping.xml b/thesis_output/plantilla_individual_files/colorschememapping.xml similarity index 100% rename from thesis_output_files/colorschememapping.xml rename to thesis_output/plantilla_individual_files/colorschememapping.xml diff --git a/thesis_output_files/filelist.xml b/thesis_output/plantilla_individual_files/filelist.xml similarity index 100% rename from thesis_output_files/filelist.xml rename to thesis_output/plantilla_individual_files/filelist.xml diff --git a/thesis_output_files/header.htm b/thesis_output/plantilla_individual_files/header.htm similarity index 100% rename from thesis_output_files/header.htm rename to thesis_output/plantilla_individual_files/header.htm diff --git a/thesis_output_files/image001.png b/thesis_output/plantilla_individual_files/image001.png similarity index 100% rename from thesis_output_files/image001.png rename to thesis_output/plantilla_individual_files/image001.png diff --git a/thesis_output_files/image002.gif b/thesis_output/plantilla_individual_files/image002.gif similarity index 100% rename from thesis_output_files/image002.gif rename to thesis_output/plantilla_individual_files/image002.gif diff --git a/thesis_output_files/image003.png b/thesis_output/plantilla_individual_files/image003.png similarity index 100% rename from thesis_output_files/image003.png rename to thesis_output/plantilla_individual_files/image003.png diff --git a/thesis_output_files/image004.jpg b/thesis_output/plantilla_individual_files/image004.jpg similarity index 100% rename from thesis_output_files/image004.jpg rename to thesis_output/plantilla_individual_files/image004.jpg diff --git a/thesis_output_files/image005.png b/thesis_output/plantilla_individual_files/image005.png similarity index 100% rename from thesis_output_files/image005.png rename to thesis_output/plantilla_individual_files/image005.png diff --git a/thesis_output_files/image006.gif b/thesis_output/plantilla_individual_files/image006.gif similarity index 100% rename from thesis_output_files/image006.gif rename to thesis_output/plantilla_individual_files/image006.gif diff --git a/thesis_output_files/item0001.xml b/thesis_output/plantilla_individual_files/item0001.xml similarity index 100% rename from thesis_output_files/item0001.xml rename to thesis_output/plantilla_individual_files/item0001.xml diff --git a/thesis_output_files/item0003.xml b/thesis_output/plantilla_individual_files/item0003.xml similarity index 100% rename from thesis_output_files/item0003.xml rename to thesis_output/plantilla_individual_files/item0003.xml diff --git a/thesis_output_files/item0005.xml b/thesis_output/plantilla_individual_files/item0005.xml similarity index 100% rename from thesis_output_files/item0005.xml rename to thesis_output/plantilla_individual_files/item0005.xml diff --git a/thesis_output_files/item0007.xml b/thesis_output/plantilla_individual_files/item0007.xml similarity index 100% rename from thesis_output_files/item0007.xml rename to thesis_output/plantilla_individual_files/item0007.xml diff --git a/thesis_output_files/props002.xml b/thesis_output/plantilla_individual_files/props002.xml similarity index 100% rename from thesis_output_files/props002.xml rename to thesis_output/plantilla_individual_files/props002.xml diff --git a/thesis_output_files/props004.xml b/thesis_output/plantilla_individual_files/props004.xml similarity index 100% rename from thesis_output_files/props004.xml rename to thesis_output/plantilla_individual_files/props004.xml diff --git a/thesis_output_files/props006.xml b/thesis_output/plantilla_individual_files/props006.xml similarity index 100% rename from thesis_output_files/props006.xml rename to thesis_output/plantilla_individual_files/props006.xml diff --git a/thesis_output_files/props008.xml b/thesis_output/plantilla_individual_files/props008.xml similarity index 100% rename from thesis_output_files/props008.xml rename to thesis_output/plantilla_individual_files/props008.xml diff --git a/thesis_output_files/themedata.thmx b/thesis_output/plantilla_individual_files/themedata.thmx similarity index 100% rename from thesis_output_files/themedata.thmx rename to thesis_output/plantilla_individual_files/themedata.thmx