awacke1 commited on
Commit
4a870b7
Β·
verified Β·
1 Parent(s): ee9c24d

Update backup11.app.py

Browse files
Files changed (1) hide show
  1. backup11.app.py +81 -57
backup11.app.py CHANGED
@@ -22,7 +22,7 @@ from pypdf import PdfReader, PdfWriter
22
  from pypdf.annotations import Link
23
  from pypdf.generic import Fit
24
 
25
- st.set_page_config(layout="wide", initial_sidebar_state="collapsed")
26
 
27
  # Existing functions (unchanged)
28
  def get_timestamp_prefix():
@@ -139,7 +139,7 @@ def apply_emoji_font(text, emoji_font):
139
 
140
  return ''.join(result)
141
 
142
- def markdown_to_pdf_content(markdown_text, render_with_bold, auto_bold_numbers, add_space_before_numbered, headings_to_fonts):
143
  lines = markdown_text.strip().split('\n')
144
  pdf_content = []
145
  number_pattern = re.compile(r'^\d+(\.\d+)*\.\s')
@@ -174,16 +174,11 @@ def markdown_to_pdf_content(markdown_text, render_with_bold, auto_bold_numbers,
174
  line = re.sub(r'\*\*(.+?)\*\*', r'<b>\1</b>', line)
175
  line = re.sub(r'\*([^*]+?)\*', r'<b>\1</b>', line)
176
 
177
- if auto_bold_numbers and is_numbered_line:
178
- if not (line.startswith("<b>") and line.endswith("</b>")):
179
- if "<b>" in line and "</b>" in line:
180
- line = re.sub(r'</?b>', '', line)
181
- line = f"<b>{line}</b>"
182
  pdf_content.append(line)
183
  total_lines = len(pdf_content)
184
  return pdf_content, total_lines
185
 
186
- def create_pdf(markdown_text, base_font_size, render_with_bold, auto_bold_numbers, enlarge_numbered, num_columns, add_space_before_numbered, headings_to_fonts, doc_title):
187
  buffer = io.BytesIO()
188
  page_width = A4[0] * 2
189
  page_height = A4[1]
@@ -198,7 +193,7 @@ def create_pdf(markdown_text, base_font_size, render_with_bold, auto_bold_number
198
  )
199
  styles = getSampleStyleSheet()
200
  spacer_height = 10
201
- pdf_content, total_lines = markdown_to_pdf_content(markdown_text, render_with_bold, auto_bold_numbers, add_space_before_numbered, headings_to_fonts)
202
  try:
203
  available_font_files = glob.glob("*.ttf")
204
  if not available_font_files:
@@ -218,7 +213,7 @@ def create_pdf(markdown_text, base_font_size, render_with_bold, auto_bold_number
218
  usable_width = page_width - 72
219
  avg_line_chars = total_chars / total_lines if total_lines > 0 else 50
220
  ideal_lines_per_col = 20
221
- suggested_columns = max(1, min(6, int(total_lines / ideal_lines_per_col) + 1))
222
  num_columns = num_columns if num_columns != 0 else suggested_columns
223
  col_width = usable_width / num_columns
224
  min_font_size = 6
@@ -230,6 +225,12 @@ def create_pdf(markdown_text, base_font_size, render_with_bold, auto_bold_number
230
  if avg_line_chars > col_width / adjusted_font_size * 10:
231
  adjusted_font_size = int(col_width / (avg_line_chars / 10))
232
  adjusted_font_size = max(min_font_size, adjusted_font_size)
 
 
 
 
 
 
233
  item_style = ParagraphStyle(
234
  'ItemStyle', parent=styles['Normal'], fontName="DejaVuSans",
235
  fontSize=adjusted_font_size, leading=adjusted_font_size * 1.15, spaceAfter=1,
@@ -237,8 +238,7 @@ def create_pdf(markdown_text, base_font_size, render_with_bold, auto_bold_number
237
  )
238
  numbered_bold_style = ParagraphStyle(
239
  'NumberedBoldStyle', parent=styles['Normal'], fontName="NotoEmoji-Bold",
240
- fontSize=adjusted_font_size + 1 if enlarge_numbered else adjusted_font_size,
241
- leading=(adjusted_font_size + 1) * 1.15 if enlarge_numbered else adjusted_font_size * 1.15, spaceAfter=1,
242
  linkUnderline=True
243
  )
244
  section_style = ParagraphStyle(
@@ -323,9 +323,9 @@ def pdf_to_image(pdf_bytes):
323
  return None
324
 
325
  # PDF creation and linking functions
326
- WORDS_10 = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]
327
- WORDS_20 = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
328
- "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty"]
329
 
330
  def create_crossfile_pdfs(source_pdf="TestSource.pdf", target_pdf="TestTarget.pdf"):
331
  """Create two PDFs with cross-file linking."""
@@ -333,7 +333,7 @@ def create_crossfile_pdfs(source_pdf="TestSource.pdf", target_pdf="TestTarget.pd
333
  buffer = io.BytesIO()
334
  c = canvas.Canvas(buffer)
335
  c.setFont("Helvetica", 12)
336
- for i, word in enumerate(WORDS_10, 1):
337
  y = 800 - (i * 20)
338
  c.drawString(50, y, f"{i}. {word}")
339
  c.showPage()
@@ -414,7 +414,7 @@ def create_selflinking_pdf(pdf_file="SelfLinking.pdf"):
414
  c.drawString(50, 800, "Table of Contents")
415
  c.setFont("Helvetica", 12)
416
  toc_y_positions = []
417
- for i, word in enumerate(WORDS_10, 1):
418
  y = 760 - (i * 20)
419
  c.drawString(50, y, f"{word}")
420
  toc_y_positions.append(y)
@@ -423,7 +423,7 @@ def create_selflinking_pdf(pdf_file="SelfLinking.pdf"):
423
  # Page 2: Numbered list 1-20
424
  c.setFont("Helvetica", 12)
425
  list_y_positions = []
426
- for i, word in enumerate(WORDS_20, 1):
427
  y = 800 - (i * 20)
428
  c.drawString(50, y, f"{i}. {word}")
429
  list_y_positions.append(y)
@@ -446,12 +446,12 @@ def create_selflinking_pdf(pdf_file="SelfLinking.pdf"):
446
  toc_page = writer.pages[0]
447
  list_page = writer.pages[1]
448
  writer.add_outline_item("Table of Contents", 0, fit=Fit(fit_type="/Fit"))
449
- for i, word in enumerate(WORDS_10, 1):
450
  y = list_y_positions[i-1]
451
  writer.add_outline_item(word, 1, fit=Fit(fit_type="/XYZ", fit_args=[50, y, 0]))
452
 
453
  # Add TOC links from page 1 to page 2
454
- for i, word in enumerate(WORDS_10):
455
  toc_y = toc_y_positions[i]
456
  list_y = list_y_positions[i]
457
  link = Link(
@@ -472,7 +472,7 @@ md_files = [f for f in glob.glob("*.md") if os.path.basename(f) != "README.md"]
472
  md_options = [os.path.splitext(os.path.basename(f))[0] for f in md_files]
473
 
474
  with st.sidebar:
475
- st.markdown("### PDF Options")
476
  if md_options:
477
  selected_md = st.selectbox("Select Markdown File", options=md_options, index=0)
478
  with open(f"{selected_md}.md", "r", encoding="utf-8") as f:
@@ -481,51 +481,74 @@ with st.sidebar:
481
  st.warning("No markdown file found. Please add one to your folder.")
482
  selected_md = None
483
  st.session_state.markdown_content = ""
 
484
  available_font_files = {os.path.splitext(os.path.basename(f))[0]: f for f in glob.glob("*.ttf")}
485
- selected_font_name = st.selectbox("Select Emoji Font", options=list(available_font_files.keys()),
486
- index=list(available_font_files.keys()).index("NotoEmoji-Bold") if "NotoEmoji-Bold" in available_font_files else 0)
 
 
 
487
  base_font_size = st.slider("Font Size (points)", min_value=6, max_value=16, value=8, step=1)
488
- render_with_bold = st.checkbox("Render with Bold Formatting (remove ** markers)", value=True, key="render_with_bold")
489
- auto_bold_numbers = st.checkbox("Auto Bold Numbered Lines", value=True, key="auto_bold_numbers")
490
- enlarge_numbered = st.checkbox("Enlarge Font Size for Numbered Lines", value=True, key="enlarge_numbered")
491
- add_space_before_numbered = st.checkbox("Add Space Ahead of Numbered Lines", value=False, key="add_space_before_numbered")
492
-
493
- headings_to_fonts = st.checkbox("Headings to Fonts", value=False, key="headings_to_fonts",
494
- help="Convert Markdown headings (# Heading) and emphasis (*word*) to appropriate font styles")
495
 
496
- auto_columns = st.checkbox("AutoColumns", value=False, key="auto_columns")
 
 
 
 
 
 
497
 
498
- if auto_columns and 'markdown_content' in st.session_state:
 
 
 
 
499
  current_markdown = st.session_state.markdown_content
500
  lines = current_markdown.strip().split('\n')
501
- longest_line_words = 0
502
  for line in lines:
503
  if line.strip():
504
  word_count = len(line.split())
505
  longest_line_words = max(longest_line_words, word_count)
506
- if longest_line_words > 25:
507
- recommended_columns = 1
508
- elif longest_line_words >= 18:
509
- recommended_columns = 2
510
- elif longest_line_words >= 11:
511
- recommended_columns = 3
 
512
  else:
513
- recommended_columns = "Auto"
514
- st.info(f"Longest line has {longest_line_words} words. Recommending {recommended_columns} columns.")
515
- else:
516
- recommended_columns = "Auto"
 
 
 
 
 
 
517
 
518
- column_options = ["Auto"] + list(range(1, 7))
519
- num_columns = st.selectbox("Number of Columns", options=column_options,
520
- index=0 if recommended_columns == "Auto" else column_options.index(recommended_columns))
521
- num_columns = 0 if num_columns == "Auto" else int(num_columns)
 
 
522
  st.info("Font size and columns adjust to fit one page.")
523
 
524
- edited_markdown = st.text_area("Input Markdown", value=st.session_state.markdown_content, height=300, key=f"markdown_{selected_md}_{selected_font_name}_{num_columns}")
 
 
 
 
 
 
525
 
 
526
  col1, col2 = st.columns(2)
527
  with col1:
528
- if st.button("πŸ”„πŸ“„ Update PDF"):
529
  st.session_state.markdown_content = edited_markdown
530
  if selected_md:
531
  with open(f"{selected_md}.md", "w", encoding="utf-8") as f:
@@ -543,12 +566,13 @@ with st.sidebar:
543
 
544
  prefix = get_timestamp_prefix()
545
  st.download_button(
546
- label="πŸ’ΎπŸ“ Save Markdown",
547
  data=st.session_state.markdown_content,
548
  file_name=f"{prefix} {selected_md}.md" if selected_md else f"{prefix} default.md",
549
  mime="text/markdown"
550
  )
551
- st.markdown("### Text-to-Speech")
 
552
  VOICES = ["en-US-AriaNeural", "en-US-JennyNeural", "en-GB-SoniaNeural", "en-US-GuyNeural", "en-US-AnaNeural"]
553
  selected_voice = st.selectbox("Select Voice for TTS", options=VOICES, index=0)
554
  if st.button("Generate Audio"):
@@ -559,7 +583,7 @@ with st.sidebar:
559
  with open(audio_file, "rb") as f:
560
  audio_bytes = f.read()
561
  st.download_button(
562
- label="πŸ’ΎπŸ”Š Save Audio",
563
  data=audio_bytes,
564
  file_name=audio_filename,
565
  mime="audio/mpeg"
@@ -601,16 +625,16 @@ with st.spinner("Generating PDF..."):
601
  pdf_bytes = create_pdf(
602
  st.session_state.markdown_content,
603
  base_font_size,
604
- render_with_bold,
605
- auto_bold_numbers,
606
- enlarge_numbered,
607
  num_columns,
608
  add_space_before_numbered,
609
  headings_to_fonts,
610
- doc_title=selected_md if selected_md else "Untitled"
 
 
611
  )
612
 
613
  with st.container():
 
614
  pdf_images = pdf_to_image(pdf_bytes)
615
  if pdf_images:
616
  for img in pdf_images:
@@ -620,7 +644,7 @@ with st.container():
620
 
621
  with st.sidebar:
622
  st.download_button(
623
- label="πŸ’ΎπŸ“„ Save PDF",
624
  data=pdf_bytes,
625
  file_name=f"{prefix} {selected_md}.pdf" if selected_md else f"{prefix} output.pdf",
626
  mime="application/pdf"
 
22
  from pypdf.annotations import Link
23
  from pypdf.generic import Fit
24
 
25
+ st.set_page_config(layout="wide", initial_sidebar_state="expanded")
26
 
27
  # Existing functions (unchanged)
28
  def get_timestamp_prefix():
 
139
 
140
  return ''.join(result)
141
 
142
+ def markdown_to_pdf_content(markdown_text, add_space_before_numbered, headings_to_fonts):
143
  lines = markdown_text.strip().split('\n')
144
  pdf_content = []
145
  number_pattern = re.compile(r'^\d+(\.\d+)*\.\s')
 
174
  line = re.sub(r'\*\*(.+?)\*\*', r'<b>\1</b>', line)
175
  line = re.sub(r'\*([^*]+?)\*', r'<b>\1</b>', line)
176
 
 
 
 
 
 
177
  pdf_content.append(line)
178
  total_lines = len(pdf_content)
179
  return pdf_content, total_lines
180
 
181
+ def create_pdf(markdown_text, base_font_size, num_columns, add_space_before_numbered, headings_to_fonts, doc_title, longest_line_words, total_lines):
182
  buffer = io.BytesIO()
183
  page_width = A4[0] * 2
184
  page_height = A4[1]
 
193
  )
194
  styles = getSampleStyleSheet()
195
  spacer_height = 10
196
+ pdf_content, total_lines = markdown_to_pdf_content(markdown_text, add_space_before_numbered, headings_to_fonts)
197
  try:
198
  available_font_files = glob.glob("*.ttf")
199
  if not available_font_files:
 
213
  usable_width = page_width - 72
214
  avg_line_chars = total_chars / total_lines if total_lines > 0 else 50
215
  ideal_lines_per_col = 20
216
+ suggested_columns = max(2, min(4, int(total_lines / ideal_lines_per_col) + 1))
217
  num_columns = num_columns if num_columns != 0 else suggested_columns
218
  col_width = usable_width / num_columns
219
  min_font_size = 6
 
225
  if avg_line_chars > col_width / adjusted_font_size * 10:
226
  adjusted_font_size = int(col_width / (avg_line_chars / 10))
227
  adjusted_font_size = max(min_font_size, adjusted_font_size)
228
+
229
+ # Adjust font size to fit one page based on longest line
230
+ if longest_line_words > 17:
231
+ font_scale = 17 / longest_line_words # Scale down from reference (17 words)
232
+ adjusted_font_size = max(min_font_size, int(adjusted_font_size * font_scale))
233
+
234
  item_style = ParagraphStyle(
235
  'ItemStyle', parent=styles['Normal'], fontName="DejaVuSans",
236
  fontSize=adjusted_font_size, leading=adjusted_font_size * 1.15, spaceAfter=1,
 
238
  )
239
  numbered_bold_style = ParagraphStyle(
240
  'NumberedBoldStyle', parent=styles['Normal'], fontName="NotoEmoji-Bold",
241
+ fontSize=adjusted_font_size, leading=adjusted_font_size * 1.15, spaceAfter=1,
 
242
  linkUnderline=True
243
  )
244
  section_style = ParagraphStyle(
 
323
  return None
324
 
325
  # PDF creation and linking functions
326
+ WORDS_12 = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve"]
327
+ WORDS_24 = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
328
+ "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty", "twenty one", "twenty two", "twenty three", "twenty four"]
329
 
330
  def create_crossfile_pdfs(source_pdf="TestSource.pdf", target_pdf="TestTarget.pdf"):
331
  """Create two PDFs with cross-file linking."""
 
333
  buffer = io.BytesIO()
334
  c = canvas.Canvas(buffer)
335
  c.setFont("Helvetica", 12)
336
+ for i, word in enumerate(WORDS_12, 1):
337
  y = 800 - (i * 20)
338
  c.drawString(50, y, f"{i}. {word}")
339
  c.showPage()
 
414
  c.drawString(50, 800, "Table of Contents")
415
  c.setFont("Helvetica", 12)
416
  toc_y_positions = []
417
+ for i, word in enumerate(WORDS_12, 1):
418
  y = 760 - (i * 20)
419
  c.drawString(50, y, f"{word}")
420
  toc_y_positions.append(y)
 
423
  # Page 2: Numbered list 1-20
424
  c.setFont("Helvetica", 12)
425
  list_y_positions = []
426
+ for i, word in enumerate(WORDS_24, 1):
427
  y = 800 - (i * 20)
428
  c.drawString(50, y, f"{i}. {word}")
429
  list_y_positions.append(y)
 
446
  toc_page = writer.pages[0]
447
  list_page = writer.pages[1]
448
  writer.add_outline_item("Table of Contents", 0, fit=Fit(fit_type="/Fit"))
449
+ for i, word in enumerate(WORDS_12, 1):
450
  y = list_y_positions[i-1]
451
  writer.add_outline_item(word, 1, fit=Fit(fit_type="/XYZ", fit_args=[50, y, 0]))
452
 
453
  # Add TOC links from page 1 to page 2
454
+ for i, word in enumerate(WORDS_12):
455
  toc_y = toc_y_positions[i]
456
  list_y = list_y_positions[i]
457
  link = Link(
 
472
  md_options = [os.path.splitext(os.path.basename(f))[0] for f in md_files]
473
 
474
  with st.sidebar:
475
+ st.markdown("### πŸ“„ PDF Options")
476
  if md_options:
477
  selected_md = st.selectbox("Select Markdown File", options=md_options, index=0)
478
  with open(f"{selected_md}.md", "r", encoding="utf-8") as f:
 
481
  st.warning("No markdown file found. Please add one to your folder.")
482
  selected_md = None
483
  st.session_state.markdown_content = ""
484
+
485
  available_font_files = {os.path.splitext(os.path.basename(f))[0]: f for f in glob.glob("*.ttf")}
486
+ selected_font_name = st.selectbox(
487
+ "Select Emoji Font",
488
+ options=list(available_font_files.keys()),
489
+ index=list(available_font_files.keys()).index("NotoEmoji-Bold") if "NotoEmoji-Bold" in available_font_files else 0
490
+ )
491
  base_font_size = st.slider("Font Size (points)", min_value=6, max_value=16, value=8, step=1)
 
 
 
 
 
 
 
492
 
493
+ add_space_before_numbered = st.checkbox("Add Space Ahead of Numbered Lines", value=False)
494
+ headings_to_fonts = st.checkbox(
495
+ "Headings to Fonts",
496
+ value=False,
497
+ help="Convert Markdown headings (# Heading) to styled fonts"
498
+ )
499
+ auto_columns = st.checkbox("AutoColumns", value=True)
500
 
501
+ # Calculate document stats
502
+ longest_line_words = 0
503
+ total_lines = 0
504
+ adjusted_font_size_display = base_font_size
505
+ if 'markdown_content' in st.session_state:
506
  current_markdown = st.session_state.markdown_content
507
  lines = current_markdown.strip().split('\n')
508
+ total_lines = len([line for line in lines if line.strip()])
509
  for line in lines:
510
  if line.strip():
511
  word_count = len(line.split())
512
  longest_line_words = max(longest_line_words, word_count)
513
+ if auto_columns:
514
+ if longest_line_words > 38:
515
+ recommended_columns = 2
516
+ elif longest_line_words < 18 and total_lines < 20:
517
+ recommended_columns = 4
518
+ else:
519
+ recommended_columns = 3
520
  else:
521
+ recommended_columns = 3
522
+ # Adjust font size for one-page fit
523
+ if longest_line_words > 17:
524
+ font_scale = 17 / longest_line_words
525
+ adjusted_font_size_display = max(6, int(base_font_size * font_scale))
526
+ st.markdown("**Document Stats**")
527
+ st.write(f"- Longest Line: {longest_line_words} words")
528
+ st.write(f"- Total Lines: {total_lines}")
529
+ st.write(f"- Recommended Columns: {recommended_columns}")
530
+ st.write(f"- Adjusted Font Size: {adjusted_font_size_display} points")
531
 
532
+ column_options = [2, 3, 4]
533
+ num_columns = st.selectbox(
534
+ "Number of Columns",
535
+ options=column_options,
536
+ index=column_options.index(recommended_columns)
537
+ )
538
  st.info("Font size and columns adjust to fit one page.")
539
 
540
+ st.markdown("### ✍️ Edit Markdown")
541
+ edited_markdown = st.text_area(
542
+ "Input Markdown",
543
+ value=st.session_state.markdown_content,
544
+ height=200,
545
+ key=f"markdown_{selected_md}_{selected_font_name}_{num_columns}"
546
+ )
547
 
548
+ st.markdown("### πŸ’Ύ Actions")
549
  col1, col2 = st.columns(2)
550
  with col1:
551
+ if st.button("πŸ”„ Update PDF"):
552
  st.session_state.markdown_content = edited_markdown
553
  if selected_md:
554
  with open(f"{selected_md}.md", "w", encoding="utf-8") as f:
 
566
 
567
  prefix = get_timestamp_prefix()
568
  st.download_button(
569
+ label="πŸ’Ύ Save Markdown",
570
  data=st.session_state.markdown_content,
571
  file_name=f"{prefix} {selected_md}.md" if selected_md else f"{prefix} default.md",
572
  mime="text/markdown"
573
  )
574
+
575
+ st.markdown("### πŸ”Š Text-to-Speech")
576
  VOICES = ["en-US-AriaNeural", "en-US-JennyNeural", "en-GB-SoniaNeural", "en-US-GuyNeural", "en-US-AnaNeural"]
577
  selected_voice = st.selectbox("Select Voice for TTS", options=VOICES, index=0)
578
  if st.button("Generate Audio"):
 
583
  with open(audio_file, "rb") as f:
584
  audio_bytes = f.read()
585
  st.download_button(
586
+ label="πŸ’Ύ Save Audio",
587
  data=audio_bytes,
588
  file_name=audio_filename,
589
  mime="audio/mpeg"
 
625
  pdf_bytes = create_pdf(
626
  st.session_state.markdown_content,
627
  base_font_size,
 
 
 
628
  num_columns,
629
  add_space_before_numbered,
630
  headings_to_fonts,
631
+ doc_title=selected_md if selected_md else "Untitled",
632
+ longest_line_words=longest_line_words,
633
+ total_lines=total_lines
634
  )
635
 
636
  with st.container():
637
+ st.markdown("### πŸ“Š PDF Preview")
638
  pdf_images = pdf_to_image(pdf_bytes)
639
  if pdf_images:
640
  for img in pdf_images:
 
644
 
645
  with st.sidebar:
646
  st.download_button(
647
+ label="πŸ’Ύ Save PDF",
648
  data=pdf_bytes,
649
  file_name=f"{prefix} {selected_md}.pdf" if selected_md else f"{prefix} output.pdf",
650
  mime="application/pdf"