Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -82,7 +82,11 @@ async def generate_audio(text, voice, filename):
|
|
| 82 |
def detect_and_convert_links(text):
|
| 83 |
# Convert Markdown links [text](url) to HTML <a> tags
|
| 84 |
md_link_pattern = re.compile(r'\[(.*?)\]\((https?://[^\s\[\]()<>{}]+)\)')
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
|
| 87 |
# Convert plain URLs to HTML <a> tags, avoiding already tagged links
|
| 88 |
url_pattern = re.compile(
|
|
@@ -91,14 +95,14 @@ def detect_and_convert_links(text):
|
|
| 91 |
)
|
| 92 |
def replace_url(match):
|
| 93 |
url = match.group(1)
|
| 94 |
-
return f'<a href="{url}">{url}</a>'
|
| 95 |
|
| 96 |
text = url_pattern.sub(replace_url, text)
|
| 97 |
return text
|
| 98 |
|
| 99 |
def apply_emoji_font(text, emoji_font):
|
| 100 |
# Preserve links and bold tags
|
| 101 |
-
link_pattern = re.compile(r'(<a\s+href="[^"]+"
|
| 102 |
bold_pattern = re.compile(r'(<b>.*?</b>)')
|
| 103 |
|
| 104 |
# Split text around links and bold tags
|
|
@@ -149,11 +153,11 @@ def apply_emoji_font(text, emoji_font):
|
|
| 149 |
for match in emoji_pattern.finditer(content):
|
| 150 |
start, end = match.span()
|
| 151 |
if last_pos < start:
|
| 152 |
-
parts.append(f'<font face="
|
| 153 |
parts.append(replace_emoji(match))
|
| 154 |
last_pos = end
|
| 155 |
if last_pos < len(content):
|
| 156 |
-
parts.append(f'<font face="
|
| 157 |
result.append(''.join(parts))
|
| 158 |
else:
|
| 159 |
# Keep links and bold tags unchanged
|
|
@@ -224,9 +228,7 @@ def create_pdf(markdown_text, base_font_size, render_with_bold, auto_bold_number
|
|
| 224 |
selected_font_path = next((f for f in available_font_files if "NotoEmoji-Bold" in f), None)
|
| 225 |
if selected_font_path:
|
| 226 |
pdfmetrics.registerFont(TTFont("NotoEmoji-Bold", selected_font_path))
|
| 227 |
-
|
| 228 |
-
st.error("NotoEmoji-Bold font not found.")
|
| 229 |
-
return
|
| 230 |
except Exception as e:
|
| 231 |
st.error(f"Font registration error: {e}")
|
| 232 |
return
|
|
@@ -250,7 +252,7 @@ def create_pdf(markdown_text, base_font_size, render_with_bold, auto_bold_number
|
|
| 250 |
adjusted_font_size = int(col_width / (avg_line_chars / 10))
|
| 251 |
adjusted_font_size = max(min_font_size, adjusted_font_size)
|
| 252 |
item_style = ParagraphStyle(
|
| 253 |
-
'ItemStyle', parent=styles['Normal'], fontName="
|
| 254 |
fontSize=adjusted_font_size, leading=adjusted_font_size * 1.15, spaceAfter=1,
|
| 255 |
linkUnderline=True
|
| 256 |
)
|
|
@@ -261,7 +263,7 @@ def create_pdf(markdown_text, base_font_size, render_with_bold, auto_bold_number
|
|
| 261 |
linkUnderline=True
|
| 262 |
)
|
| 263 |
section_style = ParagraphStyle(
|
| 264 |
-
'SectionStyle', parent=styles['Heading2'], fontName="
|
| 265 |
textColor=colors.darkblue, fontSize=adjusted_font_size * 1.1, leading=adjusted_font_size * 1.32, spaceAfter=2,
|
| 266 |
linkUnderline=True
|
| 267 |
)
|
|
@@ -287,7 +289,7 @@ def create_pdf(markdown_text, base_font_size, render_with_bold, auto_bold_number
|
|
| 287 |
heading_style = ParagraphStyle(
|
| 288 |
f'Heading{level}Style',
|
| 289 |
parent=styles['Heading1'],
|
| 290 |
-
fontName="
|
| 291 |
textColor=colors.darkblue if level == 1 else (colors.black if level > 2 else colors.blue),
|
| 292 |
fontSize=adjusted_font_size * (1.6 - (level-1)*0.15),
|
| 293 |
leading=adjusted_font_size * (1.8 - (level-1)*0.15),
|
|
@@ -303,9 +305,9 @@ def create_pdf(markdown_text, base_font_size, render_with_bold, auto_bold_number
|
|
| 303 |
else:
|
| 304 |
column_cells[col_idx].append(Paragraph(apply_emoji_font(content, "NotoEmoji-Bold"), section_style))
|
| 305 |
else:
|
| 306 |
-
column_cells[col_idx].append(Paragraph(apply_emoji_font(item, "
|
| 307 |
else:
|
| 308 |
-
column_cells[col_idx].append(Paragraph(apply_emoji_font(str(item), "
|
| 309 |
max_cells = max(len(cells) for cells in column_cells) if column_cells else 0
|
| 310 |
for cells in column_cells:
|
| 311 |
cells.extend([Paragraph("", item_style)] * (max_cells - len(cells)))
|
|
|
|
| 82 |
def detect_and_convert_links(text):
|
| 83 |
# Convert Markdown links [text](url) to HTML <a> tags
|
| 84 |
md_link_pattern = re.compile(r'\[(.*?)\]\((https?://[^\s\[\]()<>{}]+)\)')
|
| 85 |
+
def replace_md_link(match):
|
| 86 |
+
text = match.group(1)
|
| 87 |
+
url = match.group(2)
|
| 88 |
+
return f'<a href="{url}" color="blue">{text}</a>'
|
| 89 |
+
text = md_link_pattern.sub(replace_md_link, text)
|
| 90 |
|
| 91 |
# Convert plain URLs to HTML <a> tags, avoiding already tagged links
|
| 92 |
url_pattern = re.compile(
|
|
|
|
| 95 |
)
|
| 96 |
def replace_url(match):
|
| 97 |
url = match.group(1)
|
| 98 |
+
return f'<a href="{url}" color="blue">{url}</a>'
|
| 99 |
|
| 100 |
text = url_pattern.sub(replace_url, text)
|
| 101 |
return text
|
| 102 |
|
| 103 |
def apply_emoji_font(text, emoji_font):
|
| 104 |
# Preserve links and bold tags
|
| 105 |
+
link_pattern = re.compile(r'(<a\s+href="[^"]+"[^>]*>.*?</a>)')
|
| 106 |
bold_pattern = re.compile(r'(<b>.*?</b>)')
|
| 107 |
|
| 108 |
# Split text around links and bold tags
|
|
|
|
| 153 |
for match in emoji_pattern.finditer(content):
|
| 154 |
start, end = match.span()
|
| 155 |
if last_pos < start:
|
| 156 |
+
parts.append(f'<font face="DejaVuSans">{content[last_pos:start]}</font>')
|
| 157 |
parts.append(replace_emoji(match))
|
| 158 |
last_pos = end
|
| 159 |
if last_pos < len(content):
|
| 160 |
+
parts.append(f'<font face="DejaVuSans">{content[last_pos:]}</font>')
|
| 161 |
result.append(''.join(parts))
|
| 162 |
else:
|
| 163 |
# Keep links and bold tags unchanged
|
|
|
|
| 228 |
selected_font_path = next((f for f in available_font_files if "NotoEmoji-Bold" in f), None)
|
| 229 |
if selected_font_path:
|
| 230 |
pdfmetrics.registerFont(TTFont("NotoEmoji-Bold", selected_font_path))
|
| 231 |
+
pdfmetrics.registerFont(TTFont("DejaVuSans", "DejaVuSans.ttf"))
|
|
|
|
|
|
|
| 232 |
except Exception as e:
|
| 233 |
st.error(f"Font registration error: {e}")
|
| 234 |
return
|
|
|
|
| 252 |
adjusted_font_size = int(col_width / (avg_line_chars / 10))
|
| 253 |
adjusted_font_size = max(min_font_size, adjusted_font_size)
|
| 254 |
item_style = ParagraphStyle(
|
| 255 |
+
'ItemStyle', parent=styles['Normal'], fontName="DejaVuSans",
|
| 256 |
fontSize=adjusted_font_size, leading=adjusted_font_size * 1.15, spaceAfter=1,
|
| 257 |
linkUnderline=True
|
| 258 |
)
|
|
|
|
| 263 |
linkUnderline=True
|
| 264 |
)
|
| 265 |
section_style = ParagraphStyle(
|
| 266 |
+
'SectionStyle', parent=styles['Heading2'], fontName="DejaVuSans",
|
| 267 |
textColor=colors.darkblue, fontSize=adjusted_font_size * 1.1, leading=adjusted_font_size * 1.32, spaceAfter=2,
|
| 268 |
linkUnderline=True
|
| 269 |
)
|
|
|
|
| 289 |
heading_style = ParagraphStyle(
|
| 290 |
f'Heading{level}Style',
|
| 291 |
parent=styles['Heading1'],
|
| 292 |
+
fontName="DejaVuSans",
|
| 293 |
textColor=colors.darkblue if level == 1 else (colors.black if level > 2 else colors.blue),
|
| 294 |
fontSize=adjusted_font_size * (1.6 - (level-1)*0.15),
|
| 295 |
leading=adjusted_font_size * (1.8 - (level-1)*0.15),
|
|
|
|
| 305 |
else:
|
| 306 |
column_cells[col_idx].append(Paragraph(apply_emoji_font(content, "NotoEmoji-Bold"), section_style))
|
| 307 |
else:
|
| 308 |
+
column_cells[col_idx].append(Paragraph(apply_emoji_font(item, "DejaVuSans"), item_style))
|
| 309 |
else:
|
| 310 |
+
column_cells[col_idx].append(Paragraph(apply_emoji_font(str(item), "DejaVuSans"), item_style))
|
| 311 |
max_cells = max(len(cells) for cells in column_cells) if column_cells else 0
|
| 312 |
for cells in column_cells:
|
| 313 |
cells.extend([Paragraph("", item_style)] * (max_cells - len(cells)))
|