awacke1 commited on
Commit
502e545
·
verified ·
1 Parent(s): 41bb485

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +20 -27
app.py CHANGED
@@ -17,10 +17,9 @@ st.set_page_config(layout="wide", initial_sidebar_state="collapsed")
17
  def create_pdf_tab(default_markdown):
18
  # Dynamically load all .ttf fonts from the current directory
19
  # Fonts are sourced from: https://fonts.google.com/download/next-steps
20
- # We use glob to find all .ttf files, making the font list dynamic instead of hardcoded.
21
  font_files = glob.glob("*.ttf")
22
  if not font_files:
23
- st.error("No .ttf font files found in the current directory. Please add some, e.g., NotoColorEmoji-Regular.ttf.")
24
  return
25
  available_fonts = {os.path.splitext(os.path.basename(f))[0]: f for f in font_files}
26
 
@@ -28,12 +27,11 @@ def create_pdf_tab(default_markdown):
28
  with st.sidebar:
29
  selected_font_name = st.selectbox("Select Font", options=list(available_fonts.keys()), index=0 if "NotoColorEmoji-Regular" in available_fonts else 0)
30
  selected_font_path = available_fonts[selected_font_name]
31
- base_font_size = st.slider("Font Size (points)", min_value=6, max_value=16, value=9, step=1) # Default to 9
32
  plain_text_mode = st.checkbox("Render as Plain Text (Preserve Bold Only)", value=False)
33
  auto_bold_numbers = st.checkbox("Auto-Bold Numbered Lines", value=False)
34
- num_columns = st.selectbox("Number of Columns", options=[1, 2, 3, 4, 5, 6], index=3) # Default to 4
35
 
36
- # Markdown editor and buttons
37
  if 'markdown_content' not in st.session_state:
38
  st.session_state.markdown_content = default_markdown
39
 
@@ -44,16 +42,18 @@ def create_pdf_tab(default_markdown):
44
 
45
  st.download_button(label="Save Markdown", data=st.session_state.markdown_content, file_name="deities_guide.md", mime="text/markdown")
46
 
47
- # Register the selected font with ReportLab
48
- # Note: Fonts must be TrueType (.ttf) for ReportLab compatibility.
49
- pdfmetrics.registerFont(TTFont(selected_font_name, selected_font_path))
 
 
 
 
 
50
 
51
- # Emoji font application function
52
- # This function handles Unicode emojis in the text, applying the selected font to them.
53
- # We use a regex to match emoji ranges (Unicode blocks like Miscellaneous Symbols, Emoticons, etc.).
54
- # To avoid multi-character emoji issues (e.g., base char + variation selector U+FE0F), we limit to the first character.
55
- # Noto Color Emoji (NotoColorEmoji-Regular.ttf) is recommended as it supports a full range of modern emojis,
56
- # including color rendering, though ReportLab renders in black-and-white by default.
57
  def apply_emoji_font(text, emoji_font):
58
  emoji_pattern = re.compile(
59
  r"([\U0001F300-\U0001F5FF" # Miscellaneous Symbols and Pictographs
@@ -71,16 +71,13 @@ def create_pdf_tab(default_markdown):
71
  )
72
  def replace_emoji(match):
73
  emoji = match.group(1)
74
- # Limit to first character to avoid rendering issues with multi-codepoint emojis
75
- # Example: ✝️ (U+271D U+FE0F) becomes just ✝ (U+271D), dropping the variation selector
76
- if len(emoji) > 1:
77
  emoji = emoji[0]
 
78
  return f'<font face="{emoji_font}">{emoji}</font>'
79
  return emoji_pattern.sub(replace_emoji, text)
80
 
81
- # Convert markdown to PDF content
82
- # This function processes markdown lines, filtering out headers and applying bolding rules.
83
- # If auto_bold_numbers is True, lines starting with "number. " (e.g., "1. ") are bolded.
84
  def markdown_to_pdf_content(markdown_text, plain_text_mode, auto_bold_numbers):
85
  lines = markdown_text.strip().split('\n')
86
  pdf_content = []
@@ -111,10 +108,6 @@ def create_pdf_tab(default_markdown):
111
  return pdf_content, total_lines
112
 
113
  # Create PDF
114
- # This function builds a PDF using ReportLab, arranging content in columns.
115
- # We use a double A4 landscape layout (A4 width * 2) for wide content.
116
- # Spacers are added before numbered sections for visual separation.
117
- # Paragraph styles define font sizes and bolding, with emojis rendered via the selected font.
118
  def create_pdf(markdown_text, base_font_size, plain_text_mode, num_columns, auto_bold_numbers):
119
  buffer = io.BytesIO()
120
  page_width = A4[0] * 2
@@ -129,6 +122,7 @@ def create_pdf_tab(default_markdown):
129
  item_font_size = base_font_size
130
  section_font_size = base_font_size * 1.1
131
 
 
132
  section_style = ParagraphStyle(
133
  'SectionStyle', parent=styles['Heading2'], fontName="Helvetica-Bold",
134
  textColor=colors.darkblue, fontSize=section_font_size, leading=section_font_size * 1.2, spaceAfter=2
@@ -186,8 +180,7 @@ def create_pdf_tab(default_markdown):
186
  buffer.seek(0)
187
  return buffer.getvalue()
188
 
189
- # Convert PDF to image for preview
190
- # Uses PyMuPDF (fitz) to render PDF pages as images for Streamlit display.
191
  def pdf_to_image(pdf_bytes):
192
  try:
193
  doc = fitz.open(stream=pdf_bytes, filetype="pdf")
@@ -245,7 +238,7 @@ default_markdown = """# Deities Guide: Mythology and Moral Lessons 🌟
245
 
246
  5. 🌠 Ascension and Signs
247
  - Paths: Birth, deeds, revelation, as with Jesus and Arjuna.
248
- - Signs: Miracles and prophecies, like those in the Quran and Gita Kobe.
249
  - Morals: Obedience and devotion shape destiny.
250
 
251
  6. 🎲 Storytelling and Games
 
17
  def create_pdf_tab(default_markdown):
18
  # Dynamically load all .ttf fonts from the current directory
19
  # Fonts are sourced from: https://fonts.google.com/download/next-steps
 
20
  font_files = glob.glob("*.ttf")
21
  if not font_files:
22
+ st.error("No .ttf font files found in the current directory. Please add some, e.g., NotoColorEmoji-Regular.ttf or NotoEmoji-Regular.ttf.")
23
  return
24
  available_fonts = {os.path.splitext(os.path.basename(f))[0]: f for f in font_files}
25
 
 
27
  with st.sidebar:
28
  selected_font_name = st.selectbox("Select Font", options=list(available_fonts.keys()), index=0 if "NotoColorEmoji-Regular" in available_fonts else 0)
29
  selected_font_path = available_fonts[selected_font_name]
30
+ base_font_size = st.slider("Font Size (points)", min_value=6, max_value=16, value=9, step=1)
31
  plain_text_mode = st.checkbox("Render as Plain Text (Preserve Bold Only)", value=False)
32
  auto_bold_numbers = st.checkbox("Auto-Bold Numbered Lines", value=False)
33
+ num_columns = st.selectbox("Number of Columns", options=[1, 2, 3, 4, 5, 6], index=3)
34
 
 
35
  if 'markdown_content' not in st.session_state:
36
  st.session_state.markdown_content = default_markdown
37
 
 
42
 
43
  st.download_button(label="Save Markdown", data=st.session_state.markdown_content, file_name="deities_guide.md", mime="text/markdown")
44
 
45
+ # Register the selected font
46
+ # Noto Color Emoji is a color font, which ReportLab may not render correctly (monochrome only).
47
+ # If emojis don’t show, try a monochrome font like NotoEmoji-Regular.ttf as a fallback.
48
+ try:
49
+ pdfmetrics.registerFont(TTFont(selected_font_name, selected_font_path))
50
+ except Exception as e:
51
+ st.error(f"Failed to register font {selected_font_name}: {e}")
52
+ return
53
 
54
+ # Emoji font application
55
+ # We apply the selected font to emojis, falling back to plain text if the font doesn’t support them.
56
+ # ReportLab needs explicit font tagging for emojis; Noto Color Emoji may need special handling.
 
 
 
57
  def apply_emoji_font(text, emoji_font):
58
  emoji_pattern = re.compile(
59
  r"([\U0001F300-\U0001F5FF" # Miscellaneous Symbols and Pictographs
 
71
  )
72
  def replace_emoji(match):
73
  emoji = match.group(1)
74
+ if len(emoji) > 1: # Limit to first character to avoid multi-codepoint issues
 
 
75
  emoji = emoji[0]
76
+ # Wrap emoji in font tag; if it doesn’t render, it’ll show as text
77
  return f'<font face="{emoji_font}">{emoji}</font>'
78
  return emoji_pattern.sub(replace_emoji, text)
79
 
80
+ # Markdown to PDF content
 
 
81
  def markdown_to_pdf_content(markdown_text, plain_text_mode, auto_bold_numbers):
82
  lines = markdown_text.strip().split('\n')
83
  pdf_content = []
 
108
  return pdf_content, total_lines
109
 
110
  # Create PDF
 
 
 
 
111
  def create_pdf(markdown_text, base_font_size, plain_text_mode, num_columns, auto_bold_numbers):
112
  buffer = io.BytesIO()
113
  page_width = A4[0] * 2
 
122
  item_font_size = base_font_size
123
  section_font_size = base_font_size * 1.1
124
 
125
+ # Use Helvetica as a fallback for text, emoji font for emojis
126
  section_style = ParagraphStyle(
127
  'SectionStyle', parent=styles['Heading2'], fontName="Helvetica-Bold",
128
  textColor=colors.darkblue, fontSize=section_font_size, leading=section_font_size * 1.2, spaceAfter=2
 
180
  buffer.seek(0)
181
  return buffer.getvalue()
182
 
183
+ # PDF to image
 
184
  def pdf_to_image(pdf_bytes):
185
  try:
186
  doc = fitz.open(stream=pdf_bytes, filetype="pdf")
 
238
 
239
  5. 🌠 Ascension and Signs
240
  - Paths: Birth, deeds, revelation, as with Jesus and Arjuna.
241
+ - Signs: Miracles and prophecies, like those in the Quran and Gita.
242
  - Morals: Obedience and devotion shape destiny.
243
 
244
  6. 🎲 Storytelling and Games