awacke1 commited on
Commit
47ee42e
Β·
verified Β·
1 Parent(s): 2c16adb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +113 -100
app.py CHANGED
@@ -35,6 +35,9 @@ with st.sidebar:
35
  base_font_size = st.slider("Base Font Size (points)", min_value=6, max_value=16, value=10, step=1)
36
  if auto_size:
37
  st.info("Font size will adjust between 6-16 points based on content length, starting from your base size.")
 
 
 
38
 
39
  pdfmetrics.registerFont(TTFont(selected_font_name, selected_font_path))
40
 
@@ -52,7 +55,12 @@ def apply_emoji_font(text, emoji_font):
52
  r"\u2600-\u26FF"
53
  r"\u2700-\u27BF]+)"
54
  )
55
- return emoji_pattern.sub(r'<font face="{}">\1</font>'.format(emoji_font), text)
 
 
 
 
 
56
 
57
  default_markdown = """# 🌟 Deities Guide: Mythology and Moral Lessons 🌟
58
 
@@ -212,78 +220,93 @@ default_markdown = """# 🌟 Deities Guide: Mythology and Moral Lessons 🌟
212
  3. Saints/Prophets: Virtues (e.g., justice, prophecy).
213
  """
214
 
215
- def markdown_to_pdf_content(markdown_text):
216
  lines = markdown_text.strip().split('\n')
217
  pdf_content = []
218
- in_list = False
219
- current_item = None
220
- sub_items = []
221
 
222
- for line in lines:
223
- line = line.strip()
224
- if not line:
225
- continue
226
-
227
- if line.startswith('# '):
228
- continue
229
- elif line.startswith('## '):
230
- if current_item and sub_items:
231
- pdf_content.append([current_item, sub_items])
232
- sub_items = []
233
- current_item = None
234
- section = line.replace('## ', '').strip()
235
- pdf_content.append(f"<b>{section}</b>")
236
- in_list = False
237
- elif line.startswith('### '):
238
- if current_item and sub_items:
239
- pdf_content.append([current_item, sub_items])
240
- sub_items = []
241
- current_item = None
242
- subsection = line.replace('### ', '').strip()
243
- pdf_content.append(f"<b>{subsection}</b>")
244
- in_list = False
245
- elif re.match(r'^\d+\.', line):
246
- if current_item and sub_items:
247
- pdf_content.append([current_item, sub_items])
248
- sub_items = []
249
- current_item = line.strip()
250
- in_list = True
251
- elif re.match(r'^\d+\.\d+\.', line):
252
- sub_items.append(line.strip())
253
- elif line.startswith('*') and not in_list:
254
- pdf_content.append(line.strip())
255
- else:
256
- if in_list:
257
- sub_items.append(line.strip())
258
- else:
 
 
 
 
 
 
 
 
 
 
 
 
259
  pdf_content.append(line.strip())
 
 
 
 
 
 
 
 
260
 
261
- if current_item and sub_items:
262
- pdf_content.append([current_item, sub_items])
263
-
264
- total_weight = 0
265
- for item in pdf_content:
266
- if isinstance(item, list):
267
- total_weight += 1 + len(item[1])
268
- else:
269
- total_weight += 1
270
 
271
- target_weight = total_weight / 2
272
- left_column = []
273
- right_column = []
274
- current_weight = 0
275
 
276
  for item in pdf_content:
277
- item_weight = 1 + (len(item[1]) if isinstance(item, list) else 0)
278
- if current_weight < target_weight or not left_column:
279
- left_column.append(item)
280
- current_weight += item_weight
281
- else:
282
- right_column.append(item)
283
 
284
- return left_column, right_column
285
 
286
- def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
287
  buffer = io.BytesIO()
288
  doc = SimpleDocTemplate(
289
  buffer,
@@ -297,9 +320,8 @@ def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
297
  styles = getSampleStyleSheet()
298
  story = []
299
  spacer_height = 10
300
- left_column, right_column = markdown_to_pdf_content(markdown_text)
301
 
302
- total_lines = sum(1 + len(subs) if isinstance(item, list) else 1 for item in left_column + right_column)
303
  if auto_size:
304
  base_font_size = max(6, min(16, base_font_size * 300 / total_lines))
305
 
@@ -350,45 +372,36 @@ def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
350
  story.append(Paragraph(apply_emoji_font("Deities Guide: Mythology and Moral Lessons", selected_font_name), title_style))
351
  story.append(Spacer(1, spacer_height))
352
 
353
- left_cells = []
354
- for item in left_column:
355
- if isinstance(item, str) and item.startswith('<b>'):
356
- text = item.replace('<b>', '').replace('</b>', '')
357
- left_cells.append(Paragraph(apply_emoji_font(text, selected_font_name), section_style))
358
- elif isinstance(item, list):
359
- main_item, sub_items = item
360
- left_cells.append(Paragraph(apply_emoji_font(main_item, selected_font_name), item_style))
361
- for sub_item in sub_items:
362
- left_cells.append(Paragraph(apply_emoji_font(sub_item, selected_font_name), subitem_style))
363
- else:
364
- left_cells.append(Paragraph(apply_emoji_font(item, selected_font_name), item_style))
365
-
366
- right_cells = []
367
- for item in right_column:
368
- if isinstance(item, str) and item.startswith('<b>'):
369
- text = item.replace('<b>', '').replace('</b>', '')
370
- right_cells.append(Paragraph(apply_emoji_font(text, selected_font_name), section_style))
371
- elif isinstance(item, list):
372
- main_item, sub_items = item
373
- right_cells.append(Paragraph(apply_emoji_font(main_item, selected_font_name), item_style))
374
- for sub_item in sub_items:
375
- right_cells.append(Paragraph(apply_emoji_font(sub_item, selected_font_name), subitem_style))
376
- else:
377
- right_cells.append(Paragraph(apply_emoji_font(item, selected_font_name), item_style))
378
 
379
- max_cells = max(len(left_cells), len(right_cells))
380
- left_cells.extend([Paragraph("", item_style)] * (max_cells - len(left_cells)))
381
- right_cells.extend([Paragraph("", item_style)] * (max_cells - len(right_cells)))
382
 
383
- table_data = list(zip(left_cells, right_cells))
384
- col_width = (A4[1] - 36)
385
- table = Table(table_data, colWidths=[col_width, col_width], hAlign='CENTER')
386
  table.setStyle(TableStyle([
387
  ('VALIGN', (0, 0), (-1, -1), 'TOP'),
388
  ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
389
  ('BACKGROUND', (0, 0), (-1, -1), colors.white),
390
  ('GRID', (0, 0), (-1, -1), 0, colors.white),
391
- ('LINEAFTER', (0, 0), (0, -1), 0.5, colors.grey),
392
  ('LEFTPADDING', (0, 0), (-1, -1), 2),
393
  ('RIGHTPADDING', (0, 0), (-1, -1), 2),
394
  ('TOPPADDING', (0, 0), (-1, -1), 1),
@@ -418,20 +431,20 @@ if 'markdown_content' not in st.session_state:
418
  st.session_state.markdown_content = default_markdown
419
 
420
  with st.spinner("Generating PDF..."):
421
- pdf_bytes = create_main_pdf(st.session_state.markdown_content, base_font_size, auto_size)
422
 
423
  with st.container():
424
  pdf_images = pdf_to_image(pdf_bytes)
425
  if pdf_images:
426
  for i, img in enumerate(pdf_images):
427
- st.image(img, caption=f"Double-Page Spread", use_container_width=True)
428
  else:
429
  st.info("Download the PDF to view it locally.")
430
 
431
  st.download_button(
432
  label="Download PDF",
433
  data=pdf_bytes,
434
- file_name="deities_guide_double_page.pdf",
435
  mime="application/pdf"
436
  )
437
 
 
35
  base_font_size = st.slider("Base Font Size (points)", min_value=6, max_value=16, value=10, step=1)
36
  if auto_size:
37
  st.info("Font size will adjust between 6-16 points based on content length, starting from your base size.")
38
+
39
+ show_subitems = st.checkbox("Show Sub-items (e.g., 1.1, 2.1.3)", value=True)
40
+ plain_text_mode = st.checkbox("Render as Plain Text (Preserve Bold Only)", value=False)
41
 
42
  pdfmetrics.registerFont(TTFont(selected_font_name, selected_font_path))
43
 
 
55
  r"\u2600-\u26FF"
56
  r"\u2700-\u27BF]+)"
57
  )
58
+ def replace_emoji(match):
59
+ emoji = match.group(1)
60
+ if len(emoji) > 1:
61
+ emoji = emoji[0]
62
+ return f'<font face="{emoji_font}">{emoji}</font>'
63
+ return emoji_pattern.sub(replace_emoji, text)
64
 
65
  default_markdown = """# 🌟 Deities Guide: Mythology and Moral Lessons 🌟
66
 
 
220
  3. Saints/Prophets: Virtues (e.g., justice, prophecy).
221
  """
222
 
223
+ def markdown_to_pdf_content(markdown_text, show_subitems=True, plain_text_mode=False):
224
  lines = markdown_text.strip().split('\n')
225
  pdf_content = []
 
 
 
226
 
227
+ if plain_text_mode:
228
+ for line in lines:
229
+ line = line.strip()
230
+ if not line:
231
+ continue
232
+ if line.startswith('# '):
233
+ continue
234
+ bold_pattern = re.compile(r'\*\*(.*?)\*\*')
235
+ line = bold_pattern.sub(r'<b>\1</b>', line)
236
+ pdf_content.append(line)
237
+ else:
238
+ in_list = False
239
+ current_item = None
240
+ sub_items = []
241
+
242
+ for line in lines:
243
+ line = line.strip()
244
+ if not line:
245
+ continue
246
+
247
+ if line.startswith('# '):
248
+ continue
249
+ elif line.startswith('## '):
250
+ if current_item and sub_items:
251
+ pdf_content.append([current_item, sub_items])
252
+ sub_items = []
253
+ current_item = None
254
+ section = line.replace('## ', '').strip()
255
+ pdf_content.append(f"<b>{section}</b>")
256
+ in_list = False
257
+ elif line.startswith('### '):
258
+ if current_item and sub_items:
259
+ pdf_content.append([current_item, sub_items])
260
+ sub_items = []
261
+ current_item = None
262
+ if show_subitems:
263
+ subsection = line.replace('### ', '').strip()
264
+ pdf_content.append(f"<b>{subsection}</b>")
265
+ in_list = False
266
+ elif re.match(r'^\d+\.', line):
267
+ if current_item and sub_items:
268
+ pdf_content.append([current_item, sub_items])
269
+ sub_items = []
270
+ current_item = line.strip()
271
+ in_list = True
272
+ elif re.match(r'^\d+\.\d+\.', line):
273
+ if show_subitems:
274
+ sub_items.append(line.strip())
275
+ elif line.startswith('*') and not in_list:
276
  pdf_content.append(line.strip())
277
+ else:
278
+ if in_list:
279
+ sub_items.append(line.strip())
280
+ else:
281
+ pdf_content.append(line.strip())
282
+
283
+ if current_item and sub_items:
284
+ pdf_content.append([current_item, sub_items])
285
 
286
+ total_lines = sum(1 + len(subs) if isinstance(item, list) else 1 for item in pdf_content)
287
+ page_height = A4[0] - 72
288
+ lines_per_column = total_lines / 2
289
+ num_columns = max(2, int(total_lines / (page_height / (base_font_size * 1.15))))
290
+ num_columns = min(num_columns, 4)
291
+ if num_columns % 2 != 0:
292
+ num_columns += 1
 
 
293
 
294
+ lines_per_column = total_lines / num_columns
295
+ columns = [[] for _ in range(num_columns)]
296
+ current_line_count = 0
297
+ current_column = 0
298
 
299
  for item in pdf_content:
300
+ item_lines = 1 + (len(item[1]) if isinstance(item, list) else 0)
301
+ if current_line_count >= lines_per_column and current_column < num_columns - 1:
302
+ current_column += 1
303
+ current_line_count = 0
304
+ columns[current_column].append(item)
305
+ current_line_count += item_lines
306
 
307
+ return columns, total_lines, num_columns
308
 
309
+ def create_main_pdf(markdown_text, base_font_size=10, auto_size=False, show_subitems=True, plain_text_mode=False):
310
  buffer = io.BytesIO()
311
  doc = SimpleDocTemplate(
312
  buffer,
 
320
  styles = getSampleStyleSheet()
321
  story = []
322
  spacer_height = 10
323
+ columns, total_lines, num_columns = markdown_to_pdf_content(markdown_text, show_subitems, plain_text_mode)
324
 
 
325
  if auto_size:
326
  base_font_size = max(6, min(16, base_font_size * 300 / total_lines))
327
 
 
372
  story.append(Paragraph(apply_emoji_font("Deities Guide: Mythology and Moral Lessons", selected_font_name), title_style))
373
  story.append(Spacer(1, spacer_height))
374
 
375
+ column_cells = [[] for _ in range(num_columns)]
376
+ for col_idx, column in enumerate(columns):
377
+ for item in column:
378
+ if plain_text_mode:
379
+ column_cells[col_idx].append(Paragraph(apply_emoji_font(item, selected_font_name), item_style))
380
+ else:
381
+ if isinstance(item, str) and item.startswith('<b>'):
382
+ text = item.replace('<b>', '').replace('</b>', '')
383
+ column_cells[col_idx].append(Paragraph(apply_emoji_font(text, selected_font_name), section_style))
384
+ elif isinstance(item, list):
385
+ main_item, sub_items = item
386
+ column_cells[col_idx].append(Paragraph(apply_emoji_font(main_item, selected_font_name), item_style))
387
+ for sub_item in sub_items:
388
+ column_cells[col_idx].append(Paragraph(apply_emoji_font(sub_item, selected_font_name), subitem_style))
389
+ else:
390
+ column_cells[col_idx].append(Paragraph(apply_emoji_font(item, selected_font_name), item_style))
 
 
 
 
 
 
 
 
 
391
 
392
+ max_cells = max(len(cells) for cells in column_cells)
393
+ for cells in column_cells:
394
+ cells.extend([Paragraph("", item_style)] * (max_cells - len(cells)))
395
 
396
+ col_width = (A4[1] * 2 - 72) / num_columns
397
+ table_data = list(zip(*column_cells))
398
+ table = Table(table_data, colWidths=[col_width] * num_columns, hAlign='CENTER')
399
  table.setStyle(TableStyle([
400
  ('VALIGN', (0, 0), (-1, -1), 'TOP'),
401
  ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
402
  ('BACKGROUND', (0, 0), (-1, -1), colors.white),
403
  ('GRID', (0, 0), (-1, -1), 0, colors.white),
404
+ ('LINEAFTER', (0, 0), (num_columns-1, -1), 0.5, colors.grey),
405
  ('LEFTPADDING', (0, 0), (-1, -1), 2),
406
  ('RIGHTPADDING', (0, 0), (-1, -1), 2),
407
  ('TOPPADDING', (0, 0), (-1, -1), 1),
 
431
  st.session_state.markdown_content = default_markdown
432
 
433
  with st.spinner("Generating PDF..."):
434
+ pdf_bytes = create_main_pdf(st.session_state.markdown_content, base_font_size, auto_size, show_subitems, plain_text_mode)
435
 
436
  with st.container():
437
  pdf_images = pdf_to_image(pdf_bytes)
438
  if pdf_images:
439
  for i, img in enumerate(pdf_images):
440
+ st.image(img, caption=f"Multi-Column Spread", use_container_width=True)
441
  else:
442
  st.info("Download the PDF to view it locally.")
443
 
444
  st.download_button(
445
  label="Download PDF",
446
  data=pdf_bytes,
447
+ file_name="deities_guide_multi_column.pdf",
448
  mime="application/pdf"
449
  )
450