awacke1 commited on
Commit
f82d603
·
verified ·
1 Parent(s): e1e5118

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -14
app.py CHANGED
@@ -75,16 +75,34 @@ def register_local_fonts():
75
  return sorted(text_font_names), emoji_font_name
76
 
77
  def apply_emoji_font(text: str, emoji_font_name: str) -> str:
78
- """Wraps emoji characters in a <font> tag to use the dedicated emoji font."""
 
 
 
79
  if not emoji_font_name:
80
  return text
81
 
 
82
  emoji_pattern = re.compile(f"([{re.escape(''.join(map(chr, range(0x1f600, 0x1f650))))}"
83
  f"{re.escape(''.join(map(chr, range(0x1f300, 0x1f5ff))))}"
84
  f"{re.escape(''.join(map(chr, range(0x1f900, 0x1f9ff))))}"
85
  f"{re.escape(''.join(map(chr, range(0x2600, 0x26ff))))}"
86
  f"{re.escape(''.join(map(chr, range(0x2700, 0x27bf))))}]+)")
87
- return emoji_pattern.sub(fr'<font name="{emoji_font_name}">\1</font>', text)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
 
90
  # --- PDF Generation & Handling ---
@@ -92,7 +110,6 @@ def apply_emoji_font(text: str, emoji_font_name: str) -> str:
92
  def markdown_to_story(markdown_text: str, font_name: str, emoji_font: str):
93
  """Converts markdown to a ReportLab story, with enhanced styling and page breaks."""
94
  styles = getSampleStyleSheet()
95
- # Define styles for various markdown elements
96
  style_normal = ParagraphStyle('BodyText', fontName=font_name, spaceAfter=6, leading=14, fontSize=10)
97
  style_h1 = ParagraphStyle('h1', parent=styles['h1'], fontName=font_name, spaceBefore=12, fontSize=24, leading=28, textColor=colors.darkblue)
98
  style_h2 = ParagraphStyle('h2', parent=styles['h2'], fontName=font_name, fontSize=18, leading=22, spaceBefore=10)
@@ -135,18 +152,21 @@ def markdown_to_story(markdown_text: str, font_name: str, emoji_font: str):
135
  story.append(table); story.append(Spacer(1, 0.2 * inch))
136
  table_data = []
137
 
138
- line_with_emoji = apply_emoji_font(line, emoji_font)
139
- formatted_line = re.sub(r'_(.*?)_', r'<i>\1</i>', re.sub(r'\*\*(.*?)\*\*', r'<b>\1</b>', line_with_emoji))
140
-
 
 
141
  if line.startswith("# "):
142
  if not first_heading: story.append(PageBreak())
143
- story.append(Paragraph(formatted_line[2:], style_h1)); first_heading = False
144
- elif line.startswith("## "): story.append(Paragraph(formatted_line[3:], style_h2))
145
- elif line.startswith("### "): story.append(Paragraph(formatted_line[4:], style_h3))
146
- elif line.strip().startswith(("* ", "- ")): story.append(Paragraph(formatted_line.strip()[2:], style_normal, bulletText='•'))
147
- elif re.match(r'^\d+\.\s', line.strip()): story.append(Paragraph(formatted_line.strip(), style_normal))
 
148
  elif line.strip() == "": story.append(Spacer(1, 0.1 * inch))
149
- else: story.append(Paragraph(formatted_line, style_normal))
150
 
151
  return story
152
 
@@ -222,8 +242,34 @@ def generate_pdfs_api(files, layouts, fonts, num_columns, page_w_mult, page_h_mu
222
 
223
  # --- Gradio UI Definition ---
224
  AVAILABLE_FONTS, EMOJI_FONT_NAME = register_local_fonts()
225
- SAMPLE_MARKDOWN = "# Document Title 🚀\n\nThis is the first section.\n\n## Subsection 1.1\n\nHere is some text with **bold** and _italic_ elements. And an emoji: 😊\n\n# Chapter Two\n\nThis new chapter starts on a new page automatically.\n\n### A Table of Data\n| Item | Category | Status |\n|---|---|---|\n| Chocolate 🍫| Food | Delicious |\n| Computer 💻| Tech | Necessary |\n\n```python\n# This is a code block.\ndef main():\n print(\"Hello, PDF World!\")\n```"
226
- with open(CWD / "sample.md", "w") as f: f.write(SAMPLE_MARKDOWN)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
 
228
  with gr.Blocks(theme=gr.themes.Soft(), title="Advanced PDF Generator") as demo:
229
  gr.Markdown("# 📄 Advanced PDF Layout Engine")
 
75
  return sorted(text_font_names), emoji_font_name
76
 
77
  def apply_emoji_font(text: str, emoji_font_name: str) -> str:
78
+ """
79
+ Intelligently wraps emoji characters in a <font> tag, preserving existing HTML-like tags.
80
+ This prevents invalid nested tags like <b><font>...</font></b> which ReportLab handles poorly.
81
+ """
82
  if not emoji_font_name:
83
  return text
84
 
85
+ # Regex to find emojis
86
  emoji_pattern = re.compile(f"([{re.escape(''.join(map(chr, range(0x1f600, 0x1f650))))}"
87
  f"{re.escape(''.join(map(chr, range(0x1f300, 0x1f5ff))))}"
88
  f"{re.escape(''.join(map(chr, range(0x1f900, 0x1f9ff))))}"
89
  f"{re.escape(''.join(map(chr, range(0x2600, 0x26ff))))}"
90
  f"{re.escape(''.join(map(chr, range(0x2700, 0x27bf))))}]+)")
91
+
92
+ # Regex to split the string by existing tags (<b>, <i>)
93
+ tag_pattern = re.compile(r"(<[^>]+>)")
94
+ parts = tag_pattern.split(text)
95
+
96
+ result = []
97
+ for part in parts:
98
+ if tag_pattern.match(part):
99
+ # It's a tag, append it as is
100
+ result.append(part)
101
+ else:
102
+ # It's text, apply emoji font to any emojis within this segment
103
+ result.append(emoji_pattern.sub(fr'<font name="{emoji_font_name}">\1</font>', part))
104
+
105
+ return "".join(result)
106
 
107
 
108
  # --- PDF Generation & Handling ---
 
110
  def markdown_to_story(markdown_text: str, font_name: str, emoji_font: str):
111
  """Converts markdown to a ReportLab story, with enhanced styling and page breaks."""
112
  styles = getSampleStyleSheet()
 
113
  style_normal = ParagraphStyle('BodyText', fontName=font_name, spaceAfter=6, leading=14, fontSize=10)
114
  style_h1 = ParagraphStyle('h1', parent=styles['h1'], fontName=font_name, spaceBefore=12, fontSize=24, leading=28, textColor=colors.darkblue)
115
  style_h2 = ParagraphStyle('h2', parent=styles['h2'], fontName=font_name, fontSize=18, leading=22, spaceBefore=10)
 
152
  story.append(table); story.append(Spacer(1, 0.2 * inch))
153
  table_data = []
154
 
155
+ # Apply base formatting first
156
+ formatted_line = re.sub(r'_(.*?)_', r'<i>\1</i>', re.sub(r'\*\*(.*?)\*\*', r'<b>\1</b>', line))
157
+ # Then apply emoji font to the already formatted line
158
+ line_with_emoji = apply_emoji_font(formatted_line, emoji_font)
159
+
160
  if line.startswith("# "):
161
  if not first_heading: story.append(PageBreak())
162
+ # Strip markdown characters from the original line before applying style
163
+ story.append(Paragraph(apply_emoji_font(re.sub(r'\*\*(.*?)\*\*', r'<b>\1</b>', line[2:]), emoji_font), style_h1)); first_heading = False
164
+ elif line.startswith("## "): story.append(Paragraph(apply_emoji_font(re.sub(r'\*\*(.*?)\*\*', r'<b>\1</b>', line[3:]), emoji_font), style_h2))
165
+ elif line.startswith("### "): story.append(Paragraph(apply_emoji_font(re.sub(r'\*\*(.*?)\*\*', r'<b>\1</b>', line[4:]), emoji_font), style_h3))
166
+ elif line.strip().startswith(("- ", "* ")): story.append(Paragraph(line_with_emoji.strip()[2:], style_normal, bulletText='•'))
167
+ elif re.match(r'^\d+\.\s', line.strip()): story.append(Paragraph(line_with_emoji.strip(), style_normal))
168
  elif line.strip() == "": story.append(Spacer(1, 0.1 * inch))
169
+ else: story.append(Paragraph(line_with_emoji, style_normal))
170
 
171
  return story
172
 
 
242
 
243
  # --- Gradio UI Definition ---
244
  AVAILABLE_FONTS, EMOJI_FONT_NAME = register_local_fonts()
245
+ SAMPLE_MARKDOWN = """# Deities Guide: Mythology and Moral Lessons
246
+
247
+ 1. 📜 **Introduction**
248
+ - **Purpose**: Explore deities, spirits, saints, and beings with their epic stories and morals!
249
+ - **Usage**: A guide for learning and storytelling across traditions. ️
250
+ - **Themes**: Justice ️, faith , hubris , redemption , cosmic order .
251
+
252
+ 2. 🛠️ **Core Concepts of Divinity**
253
+ - **Powers**: Creation , omniscience ️‍️, shapeshifting across entities.
254
+ - **Life Cycle**: Mortality , immortality , transitions like saints and avatars .
255
+ - **Communication**: Omens ️, visions ️, miracles from gods and spirits.
256
+
257
+ # ⚔️ Arthurian Legends
258
+ - **Merlin, Morgan le Fay, Arthur**: Mentor , rival ‍️, son .
259
+ - **Relation**: Family tests loyalty .
260
+ - **Lesson**: Honor ️ vs. betrayal ️.
261
+
262
+ # 🏛️ Greek Mythology
263
+ - **Zeus, Hera, Athena**: Father , mother , daughter .
264
+ - **Relation**: Family rules with tension ️.
265
+ - **Lesson**: Hubris  meets wisdom .
266
+
267
+ # 🕉️ Hindu Trimurti
268
+ - **Brahma, Vishnu, Shiva**: Creator , preserver ️, destroyer .
269
+ - **Relation**: Divine trio cycles existence .
270
+ - **Lesson**: Balance ️ sustains life .
271
+ """
272
+ with open(CWD / "sample.md", "w", encoding="utf-8") as f: f.write(SAMPLE_MARKDOWN)
273
 
274
  with gr.Blocks(theme=gr.themes.Soft(), title="Advanced PDF Generator") as demo:
275
  gr.Markdown("# 📄 Advanced PDF Layout Engine")