From 1eb255b879ad737e3c9839846139b86f003a178b Mon Sep 17 00:00:00 2001 From: TheMaddax Date: Thu, 20 Mar 2025 10:21:19 -0500 Subject: [PATCH] Remove TxtToPDF function --- Dockerfile | 3 +- backend/app.py | 18 +---- backend/utils.py | 152 +----------------------------------- cline_docs/activeContext.md | 6 ++ cline_docs/progress.md | 3 + frontend/src/App.js | 8 -- 6 files changed, 12 insertions(+), 178 deletions(-) diff --git a/Dockerfile b/Dockerfile index fa849da..d44d5a4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,8 +47,7 @@ RUN pip install --no-cache-dir ocrmypdf==14.4.0 pdf2image==1.16.3 RUN pip install --no-cache-dir \ google-generativeai==0.3.1 \ openai==1.3.0 \ - mistralai==0.0.7 \ - beautifulsoup4==4.12.2 + mistralai==0.0.7 # Copy backend code COPY backend/ /app/backend/ diff --git a/backend/app.py b/backend/app.py index 8448b5b..d86dc90 100644 --- a/backend/app.py +++ b/backend/app.py @@ -9,7 +9,7 @@ from flask_login import LoginManager, login_user, logout_user, login_required, c from auth import User, verify_user, init_default_users from werkzeug.utils import secure_filename from models import get_models, add_model, get_languages, update_prompt, get_prompt, add_language, delete_prompt, custom_prompts, default_prompts -from utils import process_file, translate_file_by_pages, convert_txt_to_pdf +from utils import process_file, translate_file_by_pages import time app = Flask(__name__, static_folder="static", static_url_path="") @@ -386,22 +386,6 @@ def upload_config(): except Exception as e: return jsonify({"error": str(e)}), 400 -@app.route('/api/txttopdf', methods=['POST']) -@login_required -def txt_to_pdf_endpoint(): - data = request.get_json() - filename = data.get("filename") - if not filename: - return jsonify({"error": "Missing filename parameter"}), 400 - txt_path = os.path.join(OUTPUT_FOLDER, filename) - if not os.path.exists(txt_path): - return jsonify({"error": "File not found"}), 404 - try: - pdf_path = convert_txt_to_pdf(txt_path) - return jsonify({"message": "TXT to PDF conversion completed", "pdf_file": os.path.basename(pdf_path)}) - except Exception as e: - return jsonify({"error": str(e)}), 500 - @app.route('/', defaults={'path': ''}) @app.route('/') def serve(path): diff --git a/backend/utils.py b/backend/utils.py index 45d73b2..8807105 100644 --- a/backend/utils.py +++ b/backend/utils.py @@ -12,13 +12,7 @@ import base64 import re from models import get_prompt -from reportlab.lib.pagesizes import A4 -from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak -from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle -from reportlab.lib.enums import TA_JUSTIFY, TA_CENTER - -# Se agrega BeautifulSoup para procesar HTML -from bs4 import BeautifulSoup +# These imports were only used by TxtToPdf functionality and have been removed UPLOAD_FOLDER = "uploads" OUTPUT_FOLDER = "outputs" @@ -607,147 +601,3 @@ def process_file(file_path, api, model, mode, prompt_key, update_progress, is_ca update_progress(100, "🎉 Process completed") return processed_text - -def organize_paragraphs(text): - """ - Organiza el texto plano en párrafos de forma más flexible. - Si se detecta doble salto de línea se usa como separador; - si no, se procesa línea a línea para unirlas en párrafos, creando uno nuevo cuando: - - Se encuentra una línea vacía, o - - La línea actual termina en punto. - Dentro de cada párrafo se unen las líneas; se inserta un
si la lĂ­nea termina en punto. - """ - text = text.strip() - paragraphs = [] - if "\n\n" in text: - blocks = re.split(r'\n\s*\n', text) - else: - lines = text.splitlines() - blocks = [] - buffer = "" - for line in lines: - stripped = line.strip() - if not stripped: - if buffer: - blocks.append(buffer) - buffer = "" - else: - if buffer and buffer.endswith("."): - blocks.append(buffer) - buffer = stripped - else: - if buffer: - buffer += " " + stripped - else: - buffer = stripped - if buffer: - blocks.append(buffer) - for block in blocks: - line_list = block.splitlines() - if len(line_list) == 1: - paragraphs.append(line_list[0].strip()) - else: - new_block = "" - for i, line in enumerate(line_list): - line = line.strip() - if not line: - continue - if i < len(line_list) - 1: - if line.endswith("."): - new_block += line + "
" - else: - new_block += line + " " - else: - new_block += line - paragraphs.append(new_block.strip()) - return paragraphs - -def convert_txt_to_pdf(txt_file_path): - """ - Convierte un archivo TXT a PDF siguiendo estas reglas: - - Se detecta el patrón [Page XXXX] para separar páginas (solo al inicio). - - Este marcador se convierte en un encabezado (h1). - - Si el contenido proviene de un bloque markdown con ```html se elimina ese marcador y - se parsea con BeautifulSoup para generar párrafos independientes. - - Para contenido en texto plano se organiza en párrafos con organize_paragraphs. - - Se inserta un PageBreak después de cada bloque de página. - """ - with open(txt_file_path, "r", encoding="utf-8") as f: - content = f.read() - - base_name = os.path.splitext(os.path.basename(txt_file_path))[0] - output_pdf = os.path.join(OUTPUT_FOLDER, base_name + "_txt.pdf") - doc = SimpleDocTemplate( - output_pdf, - pagesize=A4, - rightMargin=40, leftMargin=40, - topMargin=40, bottomMargin=40 - ) - styles = getSampleStyleSheet() - header_styles = { - "h1": ParagraphStyle('Heading1', parent=styles['Heading1'], alignment=TA_CENTER), - "h2": ParagraphStyle('Heading2', parent=styles['Heading2'], alignment=TA_CENTER), - "h3": ParagraphStyle('Heading3', parent=styles['Heading3'], alignment=TA_CENTER), - "h4": ParagraphStyle('Heading4', parent=styles['Heading4'], alignment=TA_CENTER), - "h5": ParagraphStyle('Heading5', parent=styles['Heading5'], alignment=TA_CENTER), - "h6": ParagraphStyle('Heading6', parent=styles['Heading6'], alignment=TA_CENTER), - } - normal_style = ParagraphStyle( - 'Normal', - parent=styles['Normal'], - alignment=TA_JUSTIFY, - leading=15, - leftIndent=20 - ) - - flowables = [] - # Patrón para detectar el marcador [Page XXXX] - page_pattern = re.compile(r'\[Page\s+\d{4}\]') - parts = re.split(r'(\[Page\s+\d{4}\])', content) - first_page_encountered = False - - for part in parts: - part = part.strip() - if not part: - continue - - if page_pattern.fullmatch(part): - if first_page_encountered: - flowables.append(PageBreak()) - else: - first_page_encountered = True - header_para = Paragraph(part, styles['Heading1']) - flowables.append(header_para) - flowables.append(Spacer(1, 12)) - else: - if part.startswith("```"): - lines = part.splitlines() - if lines and lines[0].startswith("```"): - lines = lines[1:] - if lines and lines[-1].strip() == "```": - lines = lines[:-1] - part = "\n".join(lines) - # Si parece HTML, se procesa para separar cada etiqueta de interés - if re.search(r'<\s*html', part, re.IGNORECASE) or re.search(r'<\s*(p|h[1-6])', part, re.IGNORECASE): - if not part.lower().startswith("" - soup = BeautifulSoup(part, "html.parser") - for element in soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p']): - if element.name.lower() in ["h1", "h2", "h3", "h4", "h5", "h6"]: - style = header_styles.get(element.name.lower(), styles['Heading1']) - else: - style = normal_style - text_content = element.get_text().strip() - if text_content: - flowables.append(Paragraph(text_content, style)) - flowables.append(Spacer(1, 12)) - else: - # Texto plano -> organizar en párrafos - paragraphs = organize_paragraphs(part) - for para_text in paragraphs: - if para_text: - flowables.append(Paragraph(para_text, normal_style)) - flowables.append(Spacer(1, 12)) - - doc.build(flowables) - return output_pdf diff --git a/cline_docs/activeContext.md b/cline_docs/activeContext.md index 86de6bc..f8df014 100644 --- a/cline_docs/activeContext.md +++ b/cline_docs/activeContext.md @@ -7,6 +7,12 @@ - Finalizing image description functionality ## Recent Changes +- Removed TxtToPdf functionality: + - Removed TxtToPdf component from frontend + - Removed TxtToPdf route from App.js navigation + - Removed txttopdf endpoint from backend API + - Removed convert_txt_to_pdf and organize_paragraphs functions from utils.py + - Removed beautifulsoup4 dependency from Dockerfile - Added Flask-Login for backend authentication - Created auth.py for user management - Added Login component to frontend diff --git a/cline_docs/progress.md b/cline_docs/progress.md index 283cdc3..9dceca6 100644 --- a/cline_docs/progress.md +++ b/cline_docs/progress.md @@ -86,6 +86,9 @@ - Testing: 40% complete - Overall Progress: ~85% complete +## Recent Changes +- ✅ Removed: TxtToPdf functionality has been completely removed from the application as it's no longer needed + ## Known Issues - ✅ Fixed: 'Files' object has no attribute 'upload_blob' error in image description functionality - ✅ Fixed: '504 Deadline Exceeded' error in Gemini API calls with large images diff --git a/frontend/src/App.js b/frontend/src/App.js index 74098e5..1f2a9c3 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -5,7 +5,6 @@ import FileUpload from './components/FileUpload'; import Login from './components/Login'; import FileList from './components/FileList'; import Configurations from './components/Configurations'; -import TxtToPdf from './components/TxtToPdf'; import Notifications from './components/Notifications'; import ChangePassword from './components/ChangePassword'; import ImageDescription from './components/ImageDescription'; @@ -108,19 +107,12 @@ function App() { > ⚙️ Configurations -
{activeTab === 'DocuLens' && } {activeTab === 'image-description' && } {activeTab === 'files' && } {activeTab === 'configurations' && } - {activeTab === 'txttopdf' && }
{showChangePassword && (