Remove TxtToPDF function

This commit is contained in:
TheMaddax 2025-03-20 10:21:19 -05:00
parent f067f527c6
commit 1eb255b879
6 changed files with 12 additions and 178 deletions

View file

@ -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/

View file

@ -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('/<path:path>')
def serve(path):

View file

@ -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 <br/> 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 + "<br/>"
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("<html"):
part = "<html>" + part + "</html>"
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

View file

@ -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

View file

@ -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

View file

@ -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
</button>
<button
onClick={() => setActiveTab('txttopdf')}
className={activeTab === 'txttopdf' ? 'active tab-txttopdf' : 'tab-txttopdf'}
>
📝 TXT to PDF
</button>
</nav>
<main>
{activeTab === 'DocuLens' && <FileUpload onJobCompleted={handleJobCompleted} />}
{activeTab === 'image-description' && <ImageDescription onJobCompleted={handleJobCompleted} />}
{activeTab === 'files' && <FileList />}
{activeTab === 'configurations' && <Configurations />}
{activeTab === 'txttopdf' && <TxtToPdf />}
</main>
<Notifications notifications={notifications} onClear={clearNotifications} />
{showChangePassword && (