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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -39
app.py CHANGED
@@ -108,15 +108,19 @@ def apply_emoji_font(text: str, emoji_font_name: str) -> str:
108
  # --- PDF Generation & Handling ---
109
 
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)
116
  style_h3 = ParagraphStyle('h3', parent=styles['h3'], fontName=font_name, fontSize=14, leading=18, spaceBefore=8)
117
  style_code = ParagraphStyle('Code', fontName='Courier', backColor=colors.whitesmoke, textColor=colors.darkred, borderWidth=1, borderColor=colors.lightgrey, padding=8, leading=12, fontSize=9)
118
  style_table_header = ParagraphStyle('TableHeader', parent=style_normal, fontName=font_name + "-Bold" if font_name != 'Helvetica' else 'Helvetica-Bold')
119
-
120
  story = []
121
  lines = markdown_text.split('\n')
122
 
@@ -125,51 +129,70 @@ def markdown_to_story(markdown_text: str, font_name: str, emoji_font: str):
125
  first_heading = True
126
 
127
  for line in lines:
128
- if line.strip().startswith("```"):
 
 
129
  if in_code_block:
130
  story.append(Paragraph(code_block_text.replace('\n', '<br/>'), style_code)); story.append(Spacer(1, 0.1 * inch))
131
  in_code_block = False; code_block_text = ""
132
- else:
133
- in_code_block = True
134
  continue
135
  if in_code_block:
136
  code_block_text += line.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;') + '\n'
137
  continue
138
 
139
- if line.strip().startswith('|'):
140
  if not in_table: in_table = True
141
- if all(c in '-|: ' for c in line.strip()): continue
142
- cells = [apply_emoji_font(cell.strip(), emoji_font) for cell in line.strip().strip('|').split('|')]
143
  table_data.append(cells)
144
  continue
145
  if in_table:
146
  in_table = False
147
  if table_data:
148
- header = [Paragraph(cell, style_table_header) for cell in table_data[0]]
149
- formatted_rows = [[Paragraph(cell, style_normal) for cell in row] for row in table_data[1:]]
 
 
 
 
 
 
150
  table = Table([header] + formatted_rows, hAlign='LEFT', repeatRows=1)
151
  table.setStyle(TableStyle([('BACKGROUND', (0, 0), (-1, 0), colors.lightgrey), ('GRID', (0, 0), (-1, -1), 1, colors.darkgrey), ('VALIGN', (0,0), (-1,-1), 'MIDDLE')]))
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
 
 
173
  def create_pdf_preview(pdf_path: Path):
174
  preview_path = PREVIEW_DIR / f"{pdf_path.stem}.png"
175
  try:
@@ -247,27 +270,27 @@ SAMPLE_MARKDOWN = """# Deities Guide: Mythology and Moral Lessons
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
 
 
108
  # --- PDF Generation & Handling ---
109
 
110
  def markdown_to_story(markdown_text: str, font_name: str, emoji_font: str):
111
+ """
112
+ Converts markdown to a ReportLab story, with enhanced styling and page breaks.
113
+ This version correctly separates structural parsing from content formatting.
114
+ """
115
  styles = getSampleStyleSheet()
116
+ # Define styles for various markdown elements
117
  style_normal = ParagraphStyle('BodyText', fontName=font_name, spaceAfter=6, leading=14, fontSize=10)
118
  style_h1 = ParagraphStyle('h1', parent=styles['h1'], fontName=font_name, spaceBefore=12, fontSize=24, leading=28, textColor=colors.darkblue)
119
  style_h2 = ParagraphStyle('h2', parent=styles['h2'], fontName=font_name, fontSize=18, leading=22, spaceBefore=10)
120
  style_h3 = ParagraphStyle('h3', parent=styles['h3'], fontName=font_name, fontSize=14, leading=18, spaceBefore=8)
121
  style_code = ParagraphStyle('Code', fontName='Courier', backColor=colors.whitesmoke, textColor=colors.darkred, borderWidth=1, borderColor=colors.lightgrey, padding=8, leading=12, fontSize=9)
122
  style_table_header = ParagraphStyle('TableHeader', parent=style_normal, fontName=font_name + "-Bold" if font_name != 'Helvetica' else 'Helvetica-Bold')
123
+
124
  story = []
125
  lines = markdown_text.split('\n')
126
 
 
129
  first_heading = True
130
 
131
  for line in lines:
132
+ stripped_line = line.strip()
133
+
134
+ if stripped_line.startswith("```"):
135
  if in_code_block:
136
  story.append(Paragraph(code_block_text.replace('\n', '<br/>'), style_code)); story.append(Spacer(1, 0.1 * inch))
137
  in_code_block = False; code_block_text = ""
138
+ else: in_code_block = True
 
139
  continue
140
  if in_code_block:
141
  code_block_text += line.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;') + '\n'
142
  continue
143
 
144
+ if stripped_line.startswith('|'):
145
  if not in_table: in_table = True
146
+ if all(c in '-|: ' for c in stripped_line): continue
147
+ cells = [cell.strip() for cell in stripped_line.strip('|').split('|')]
148
  table_data.append(cells)
149
  continue
150
  if in_table:
151
  in_table = False
152
  if table_data:
153
+ header_content = [apply_emoji_font(re.sub(r'\*\*(.*?)\*\*', r'<b>\1</b>', cell), emoji_font) for cell in table_data[0]]
154
+ header = [Paragraph(cell, style_table_header) for cell in header_content]
155
+
156
+ formatted_rows = []
157
+ for row in table_data[1:]:
158
+ formatted_cells = [apply_emoji_font(re.sub(r'\*\*(.*?)\*\*', r'<b>\1</b>', cell), emoji_font) for cell in row]
159
+ formatted_rows.append([Paragraph(cell, style_normal) for cell in formatted_cells])
160
+
161
  table = Table([header] + formatted_rows, hAlign='LEFT', repeatRows=1)
162
  table.setStyle(TableStyle([('BACKGROUND', (0, 0), (-1, 0), colors.lightgrey), ('GRID', (0, 0), (-1, -1), 1, colors.darkgrey), ('VALIGN', (0,0), (-1,-1), 'MIDDLE')]))
163
  story.append(table); story.append(Spacer(1, 0.2 * inch))
164
+ table_data = []
 
 
 
 
 
165
 
166
+ if not stripped_line:
167
+ story.append(Spacer(1, 0.1 * inch))
168
+ continue
 
 
 
 
 
 
 
169
 
170
+ # Default content is the whole stripped line
171
+ content = stripped_line
172
+ style = style_normal
173
+ extra_args = {}
174
+
175
+ # Detect structural elements and extract the raw content
176
+ if stripped_line.startswith("# "):
177
+ if not first_heading: story.append(PageBreak())
178
+ content = stripped_line.lstrip('# '); style = style_h1; first_heading = False
179
+ elif stripped_line.startswith("## "):
180
+ content = stripped_line.lstrip('## '); style = style_h2
181
+ elif stripped_line.startswith("### "):
182
+ content = stripped_line.lstrip('### '); style = style_h3
183
+ elif stripped_line.startswith(("- ", "* ")):
184
+ content = stripped_line[2:]; extra_args['bulletText'] = 'β€’'
185
+
186
+ # Now, format the extracted content
187
+ # Apply markdown formatting for bold/italic
188
+ formatted_content = re.sub(r'_(.*?)_', r'<i>\1</i>', re.sub(r'\*\*(.*?)\*\*', r'<b>\1</b>', content))
189
+ # Then apply emoji font to the already formatted line
190
+ final_content = apply_emoji_font(formatted_content, emoji_font)
191
+
192
+ story.append(Paragraph(final_content, style, **extra_args))
193
  return story
194
 
195
+
196
  def create_pdf_preview(pdf_path: Path):
197
  preview_path = PREVIEW_DIR / f"{pdf_path.stem}.png"
198
  try:
 
270
  1. πŸ“œ **Introduction**
271
  - **Purpose**: Explore deities, spirits, saints, and beings with their epic stories and morals!
272
  - **Usage**: A guide for learning and storytelling across traditions. ️
273
+ - **Themes**: Justice βš–οΈ, faith πŸ™, hubris πŸ›οΈ, redemption ✨, cosmic order 🌌.
274
 
275
  2. πŸ› οΈ **Core Concepts of Divinity**
276
+ - **Powers**: Creation 🌍, omniscience πŸ‘οΈβ€πŸ—¨οΈ, shapeshifting πŸ¦‹ across entities.
277
+ - **Life Cycle**: Mortality ⏳, immortality ♾️, transitions like saints and avatars 🌟.
278
+ - **Communication**: Omens πŸ•ŠοΈ, visions πŸ‘οΈ, miracles ✨ from gods and spirits.
279
 
280
  # βš”οΈ Arthurian Legends
281
+ - **Merlin, Morgan le Fay, Arthur**: Mentor πŸ§™, rival πŸ§™β€β™€οΈ, son πŸ‘‘.
282
+ - **Relation**: Family tests loyalty 🀝.
283
+ - **Lesson**: Honor πŸŽ–οΈ vs. betrayal πŸ—‘οΈ.
284
 
285
  # πŸ›οΈ Greek Mythology
286
+ - **Zeus, Hera, Athena**: Father ⚑, mother πŸ‘‘, daughter πŸ¦‰.
287
+ - **Relation**: Family rules with tension 🌩️.
288
+ - **Lesson**: Hubris ΰ€…ΰ€Ήΰ€‚ΰ€•ΰ€Ύΰ€° meets wisdom 🧠.
289
 
290
  # πŸ•‰οΈ Hindu Trimurti
291
+ - **Brahma, Vishnu, Shiva**: Creator Brahma, preserver Vishnu, destroyer Shiva.
292
+ - **Relation**: Divine trio cycles existence πŸ”„.
293
+ - **Lesson**: Balance βš–οΈ sustains life πŸ’–.
294
  """
295
  with open(CWD / "sample.md", "w", encoding="utf-8") as f: f.write(SAMPLE_MARKDOWN)
296