File size: 8,807 Bytes
6b0f2e2
 
 
 
 
419f149
6b0f2e2
 
 
419f149
6b0f2e2
 
419f149
 
6b0f2e2
 
 
419f149
6b0f2e2
 
 
 
 
 
 
 
 
 
9ee8b55
419f149
 
 
6b0f2e2
 
9ee8b55
 
 
 
419f149
9ee8b55
 
 
 
 
 
 
 
 
 
 
 
6b0f2e2
 
419f149
 
 
 
 
 
 
0b4df0b
419f149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0b4df0b
419f149
 
 
 
 
 
 
9ee8b55
6b0f2e2
 
0b4df0b
9ee8b55
6b0f2e2
 
 
 
419f149
9ee8b55
 
 
 
 
 
419f149
 
 
9ee8b55
 
 
 
 
419f149
6b0f2e2
 
 
 
 
 
419f149
 
 
 
6b0f2e2
 
 
 
 
 
 
0b4df0b
6b0f2e2
 
 
9ee8b55
 
 
 
419f149
 
9ee8b55
 
 
 
 
6b0f2e2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
419f149
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import os
import io
import traceback
import re
from flask import Flask, request, send_file, render_template
from flask_cors import CORS

from docx import Document
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.shared import Pt
from weasyprint import HTML, CSS
import arabic_reshaper
from bidi.algorithm import get_display # برای راست‌چین و ترکیب حروف فارسی
import markdown
from htmldocx import HtmlToDocx

app = Flask(__name__)
CORS(app)

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
FONT_FILE_NAME = "Vazirmatn-Regular.ttf"
FOOTER_TEXT = "هوش مصنوعی آلفا دانلود از گوگل پلی"

def get_line_direction(line):
    if not line or line.isspace(): return 'ltr'
    rtl_pattern = re.compile(r'[\u0600-\u06FF\u0750-\u077F]')
    return 'rtl' if rtl_pattern.search(line) else 'ltr'

def reshape_rtl_text(text):
    # ترکیب reshaper و bidi برای خروجی بی‌نقص در فایل‌ها
    reshaped_text = arabic_reshaper.reshape(text)
    return get_display(reshaped_text)

def get_base_html_for_conversion(text_content):
    raw_html = markdown.markdown(
        text_content, 
        extensions=['extra', 'tables', 'nl2br', 'sane_lists']
    )
    reshaped_html = arabic_reshaper.reshape(raw_html)
    
    tags_to_rtl =['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li', 'table', 'th', 'td']
    for tag in tags_to_rtl:
        pattern = re.compile(rf'<{tag}(?P<attrs>\s[^>]*)?>', re.IGNORECASE)
        def replacer(match):
            attrs = match.group('attrs') or ''
            if 'dir="ltr"' in attrs.lower() or 'style="text-align: left' in attrs.lower():
                return match.group(0)
            return f'<{tag}{attrs} style="text-align: right; direction: rtl; font-family: Vazir, sans-serif;">'
        reshaped_html = pattern.sub(replacer, reshaped_html)
        
    return reshaped_html

def create_docx(text_content):
    try:
        document = Document()
        parser = HtmlToDocx()
        html_content = get_base_html_for_conversion(text_content)
        parser.add_html_to_document(html_content, document)
        
        document.add_paragraph("")
        footer_p = document.add_paragraph(FOOTER_TEXT)
        footer_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
        for run in footer_p.runs:
            run.bold = True
            
        buffer = io.BytesIO()
        document.save(buffer)
        buffer.seek(0)
        return buffer
    except Exception as e:
        print(f"⚠️ HTML to DOCX Failed: {e}")
        # سیستم Fallback: اگر مارک‌داون هوش مصنوعی خراب بود، فایل Word ساده می‌سازد
        document = Document()
        document.styles['Normal'].font.name = 'Arial'
        
        for line in text_content.split('\n'):
            if line.strip():
                p = document.add_paragraph(reshape_rtl_text(line))
                p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
                
        document.add_paragraph("\n")
        footer_p = document.add_paragraph(FOOTER_TEXT)
        footer_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
        for run in footer_p.runs: run.bold = True

        buffer = io.BytesIO()
        document.save(buffer)
        buffer.seek(0)
        return buffer

def create_pdf_with_weasyprint(text_content):
    html_body = get_base_html_for_conversion(text_content)
    reshaped_footer = FOOTER_TEXT
    
    full_html = f"""
    <!DOCTYPE html><html lang="fa"><head><meta charset="UTF-8"><title>Exported PDF</title>
    <style>
        @font-face {{ font-family: 'Vazir'; src: url('{FONT_FILE_NAME}'); }}
        body {{ font-family: 'Vazir', sans-serif; font-size: 12pt; line-height: 1.8; color: #111; }}
        h1 {{ font-size: 24pt; color: #0d5c75; border-bottom: 2px solid #0d5c75; padding-bottom: 5px; margin-top: 30px; margin-bottom: 15px; }}
        h2 {{ font-size: 20pt; color: #1a7b9c; margin-top: 25px; margin-bottom: 10px; }}
        h3 {{ font-size: 16pt; color: #222; margin-top: 20px; }}
        h4, h5, h6 {{ font-size: 14pt; color: #333; font-weight: bold; }}
        strong, b {{ font-weight: bold; color: #000; }}
        em, i {{ font-style: italic; color: #444; }}
        blockquote {{ border-right: 4px solid #1095c1; margin: 15px 0; padding: 10px 15px 10px 0; color: #555; background-color: #f7fbff; border-radius: 4px; }}
        code {{ font-family: monospace; background-color: #f1f1f1; padding: 2px 6px; border-radius: 4px; font-size: 11pt; direction: ltr; display: inline-block; color: #c7254e; word-wrap: break-word; }}
        pre {{ background-color: #f8f9fa; padding: 15px; border-radius: 6px; border: 1px solid #e1e1e8; direction: ltr; text-align: left; overflow-x: auto; white-space: pre-wrap; }}
        pre code {{ background-color: transparent; padding: 0; color: #333; }}
        table {{ border-collapse: collapse; width: 100%; margin-top: 20px; margin-bottom: 20px; }}
        th, td {{ border: 1px solid #ccc; padding: 10px; text-align: right; }}
        th {{ background-color: #e9ecef; font-weight: bold; }}
        p {{ margin: 0 0 12px 0; padding: 0; text-align: justify; }}
        .footer {{ margin-top: 50px; padding-top: 15px; border-top: 2px solid #1095c1; text-align: center; color: #1095c1; font-size: 11pt; font-weight: bold; font-family: 'Vazir', sans-serif; page-break-inside: avoid; }}
    </style></head><body>{html_body}
    <div class="footer">{reshaped_footer}</div></body></html>
    """
    try:
        html = HTML(string=full_html, base_url=BASE_DIR)
        return io.BytesIO(html.write_pdf())
    except Exception as e:
        print(f"🔥🔥🔥 WEASYPRINT FAILED! 🔥🔥🔥\n{e}")
        # در صورت شکست، به جای ارور دادن، یک خروجی ساده برمی‌گرداند
        return create_txt("خطا در ساخت PDF به دلیل پیچیدگی متن. لطفا از فایل DOCX استفاده کنید.\n\n" + text_content)

def create_txt(text_content):
    full_content = f"{text_content}\n\n\n---\n{FOOTER_TEXT}"
    return io.BytesIO(full_content.encode('utf-8'))

def create_html(text_content):
    html_body = get_base_html_for_conversion(text_content)
    reshaped_footer = FOOTER_TEXT
    full_html = f"""
    <!DOCTYPE html><html lang="fa"><head><meta charset="UTF-8"><title>Exported File</title>
    <style>
        body {{ font-size: 12pt; line-height: 1.8; max-width: 800px; margin: 2rem auto; padding: 2rem; border: 1px solid #ddd; font-family: sans-serif; direction: rtl; color: #222; }}
        h1 {{ color: #0d5c75; border-bottom: 2px solid #ddd; padding-bottom: 5px; }}
        h2 {{ color: #1a7b9c; }}
        blockquote {{ border-right: 4px solid #1095c1; margin: 0; padding-right: 15px; background: #f9f9f9; padding: 10px; }}
        code {{ font-family: monospace; background-color: #f4f4f4; padding: 2px 5px; border-radius: 4px; direction: ltr; display: inline-block; color: #c7254e; word-wrap: break-word; }}
        pre {{ background-color: #f4f4f4; padding: 15px; border-radius: 5px; direction: ltr; text-align: left; overflow-x: auto; white-space: pre-wrap; }}
        table {{ border-collapse: collapse; width: 100%; }}
        th, td {{ border: 1px solid #ddd; padding: 8px; }}
        th {{ background-color: #f2f2f2; }}
        p {{ margin: 0 0 10px 0; text-align: justify; }}
        .footer {{ margin-top: 3rem; padding-top: 1rem; border-top: 2px solid #1095c1; text-align: center; color: #1095c1; font-weight: bold; font-size: 11pt; }}
    </style></head><body>{html_body}
    <div class="footer">{reshaped_footer}</div></body></html>
    """
    return io.BytesIO(full_html.encode('utf-8'))

def process_request(content, file_format):
    actions = {'pdf': create_pdf_with_weasyprint, 'docx': create_docx, 'html': create_html, 'txt': create_txt}
    buffer_func = actions.get(file_format, create_txt)
    buffer = buffer_func(content)
    mimetypes = {'pdf': 'application/pdf', 'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'html': 'text/html', 'txt': 'text/plain'}
    mimetype = mimetypes.get(file_format, 'text/plain')
    filename = f'export.{file_format}'
    return send_file(buffer, as_attachment=True, download_name=filename, mimetype=mimetype)

@app.route('/', methods=['GET', 'POST', 'HEAD'])
def index():
    if request.method == 'HEAD':
        return '', 200

    if request.method == 'POST':
        content = request.form.get('content')
        file_format = request.form.get('format', 'txt').lower()
        if not content:
            return "لطفا متنی برای تبدیل وارد کنید.", 400
        return process_request(content, file_format)
    
    return render_template('index.html')

if __name__ == '__main__':
    app.run(debug=False, host='0.0.0.0', port=7860)