awacke1 commited on
Commit
91db81f
·
verified ·
1 Parent(s): d2cd664

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -33
app.py CHANGED
@@ -1,18 +1,40 @@
 
 
 
 
 
1
  import streamlit as st
2
- import base64
 
 
3
  from reportlab.lib.pagesizes import A4
4
  from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
5
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
6
  from reportlab.lib import colors
7
- import io
8
- import re
9
- import fitz # PyMuPDF
10
- from PIL import Image
11
 
12
- # Set page config for wide layout and collapsed sidebar
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  st.set_page_config(layout="wide", initial_sidebar_state="collapsed")
14
 
15
- # Initial markdown content
16
  default_markdown = """# Cutting-Edge ML Outline
17
 
18
  ## Core ML Techniques
@@ -80,7 +102,7 @@ default_markdown = """# Cutting-Edge ML Outline
80
  - Documentation synthesis
81
  """
82
 
83
- # Process multilevel markdown for PDF output
84
  def markdown_to_pdf_content(markdown_text):
85
  lines = markdown_text.strip().split('\n')
86
  pdf_content = []
@@ -94,13 +116,13 @@ def markdown_to_pdf_content(markdown_text):
94
  continue
95
 
96
  if line.startswith('# '):
 
97
  pass
98
  elif line.startswith('## '):
99
  if current_item and sub_items:
100
  pdf_content.append([current_item, sub_items])
101
  sub_items = []
102
  current_item = None
103
-
104
  section = line.replace('## ', '').strip()
105
  pdf_content.append(f"<b>{section}</b>")
106
  in_list_item = False
@@ -108,7 +130,6 @@ def markdown_to_pdf_content(markdown_text):
108
  if current_item and sub_items:
109
  pdf_content.append([current_item, sub_items])
110
  sub_items = []
111
-
112
  current_item = line.strip()
113
  in_list_item = True
114
  elif line.startswith('- ') and in_list_item:
@@ -126,7 +147,7 @@ def markdown_to_pdf_content(markdown_text):
126
 
127
  return left_column, right_column
128
 
129
- # Main PDF creation with parameterized text sizes
130
  def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
131
  buffer = io.BytesIO()
132
  doc = SimpleDocTemplate(
@@ -141,10 +162,7 @@ def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
141
  styles = getSampleStyleSheet()
142
  story = []
143
 
144
- page_height = A4[0] - 72
145
- title_height = 20
146
  spacer_height = 10
147
-
148
  left_column, right_column = markdown_to_pdf_content(markdown_text)
149
 
150
  total_items = 0
@@ -156,24 +174,28 @@ def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
156
  else:
157
  total_items += 1
158
 
159
- # 🔧 Adjust this multiplier to control autosizing sensitivity
160
  if auto_size:
161
  base_font_size = max(6, min(12, 200 / total_items))
162
 
163
- # 🔧 Font size parameters - tweak these ratios as needed
164
  item_font_size = base_font_size
165
  subitem_font_size = base_font_size * 0.9
166
  section_font_size = base_font_size * 1.2
167
  title_font_size = min(16, base_font_size * 1.5)
168
 
169
- title_style = styles['Heading1']
170
- title_style.textColor = colors.darkblue
171
- title_style.alignment = 1
172
- title_style.fontSize = title_font_size
 
 
 
 
 
173
 
174
  section_style = ParagraphStyle(
175
  'SectionStyle',
176
  parent=styles['Heading2'],
 
177
  textColor=colors.darkblue,
178
  fontSize=section_font_size,
179
  leading=section_font_size * 1.2,
@@ -183,15 +205,16 @@ def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
183
  item_style = ParagraphStyle(
184
  'ItemStyle',
185
  parent=styles['Normal'],
 
186
  fontSize=item_font_size,
187
  leading=item_font_size * 1.2,
188
- fontName='Helvetica-Bold',
189
  spaceAfter=1
190
  )
191
 
192
  subitem_style = ParagraphStyle(
193
  'SubItemStyle',
194
  parent=styles['Normal'],
 
195
  fontSize=subitem_font_size,
196
  leading=subitem_font_size * 1.2,
197
  leftIndent=10,
@@ -252,12 +275,12 @@ def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
252
  buffer.seek(0)
253
  return buffer.getvalue()
254
 
255
- # Function to convert PDF bytes to image using fitz
256
  def pdf_to_image(pdf_bytes):
257
  try:
258
  doc = fitz.open(stream=pdf_bytes, filetype="pdf")
259
  page = doc[0]
260
- pix = page.get_pixmap(matrix=fitz.Matrix(2.0, 2.0)) # 2x zoom
261
  img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
262
  doc.close()
263
  return img
@@ -265,7 +288,7 @@ def pdf_to_image(pdf_bytes):
265
  st.error(f"Failed to render PDF preview: {e}")
266
  return None
267
 
268
- # Sidebar for settings (collapsed by default)
269
  with st.sidebar:
270
  auto_size = st.checkbox("Auto-size text", value=True)
271
  if not auto_size:
@@ -274,15 +297,15 @@ with st.sidebar:
274
  base_font_size = 10
275
  st.info("Font size will auto-adjust between 6-12 points based on content length.")
276
 
277
- # Use session state to persist markdown content
278
  if 'markdown_content' not in st.session_state:
279
  st.session_state.markdown_content = default_markdown
280
 
281
- # Generate PDF
282
  with st.spinner("Generating PDF..."):
283
  pdf_bytes = create_main_pdf(st.session_state.markdown_content, base_font_size, auto_size)
284
 
285
- # Display PDF preview in a full-width container
286
  with st.container():
287
  pdf_image = pdf_to_image(pdf_bytes)
288
  if pdf_image:
@@ -290,7 +313,7 @@ with st.container():
290
  else:
291
  st.info("Download the PDF to view it locally.")
292
 
293
- # Download button
294
  st.download_button(
295
  label="Download PDF",
296
  data=pdf_bytes,
@@ -298,22 +321,22 @@ st.download_button(
298
  mime="application/pdf"
299
  )
300
 
301
- # Markdown editor
302
  edited_markdown = st.text_area(
303
  "Modify the markdown content below:",
304
  value=st.session_state.markdown_content,
305
  height=300
306
  )
307
 
308
- # Update markdown and regenerate PDF on change
309
  if st.button("Update PDF"):
310
  st.session_state.markdown_content = edited_markdown
311
- st.rerun()
312
 
313
- # Save markdown option
314
  st.download_button(
315
  label="Save Markdown",
316
  data=st.session_state.markdown_content,
317
  file_name="ml_outline.md",
318
  mime="text/markdown"
319
- )
 
1
+ import os
2
+ import urllib.request
3
+ import io
4
+ import re
5
+
6
  import streamlit as st
7
+ from PIL import Image
8
+ import fitz # PyMuPDF
9
+
10
  from reportlab.lib.pagesizes import A4
11
  from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
12
  from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
13
  from reportlab.lib import colors
14
+ from reportlab.pdfbase import pdfmetrics
15
+ from reportlab.pdfbase.ttfonts import TTFont
16
+
17
+ # --- Step 1: Auto-download and register the emoji-supporting font ---
18
 
19
+ # URL for the Noto Emoji TTF file
20
+ font_url = "https://github.com/googlefonts/noto-emoji/raw/main/fonts/NotoEmoji-Regular.ttf"
21
+ font_path = "NotoEmoji-Regular.ttf"
22
+
23
+ if not os.path.exists(font_path):
24
+ st.info("Downloading Noto Emoji font...")
25
+ try:
26
+ urllib.request.urlretrieve(font_url, font_path)
27
+ st.success("Noto Emoji font downloaded.")
28
+ except Exception as e:
29
+ st.error(f"Failed to download font: {e}")
30
+
31
+ # Register the downloaded font with ReportLab under the name "NotoEmoji"
32
+ pdfmetrics.registerFont(TTFont('NotoEmoji', font_path))
33
+
34
+ # --- Streamlit App Setup ---
35
  st.set_page_config(layout="wide", initial_sidebar_state="collapsed")
36
 
37
+ # Default markdown content with emojis
38
  default_markdown = """# Cutting-Edge ML Outline
39
 
40
  ## Core ML Techniques
 
102
  - Documentation synthesis
103
  """
104
 
105
+ # --- Markdown to PDF content processing ---
106
  def markdown_to_pdf_content(markdown_text):
107
  lines = markdown_text.strip().split('\n')
108
  pdf_content = []
 
116
  continue
117
 
118
  if line.startswith('# '):
119
+ # Skip main title if desired
120
  pass
121
  elif line.startswith('## '):
122
  if current_item and sub_items:
123
  pdf_content.append([current_item, sub_items])
124
  sub_items = []
125
  current_item = None
 
126
  section = line.replace('## ', '').strip()
127
  pdf_content.append(f"<b>{section}</b>")
128
  in_list_item = False
 
130
  if current_item and sub_items:
131
  pdf_content.append([current_item, sub_items])
132
  sub_items = []
 
133
  current_item = line.strip()
134
  in_list_item = True
135
  elif line.startswith('- ') and in_list_item:
 
147
 
148
  return left_column, right_column
149
 
150
+ # --- Main PDF Creation ---
151
  def create_main_pdf(markdown_text, base_font_size=10, auto_size=False):
152
  buffer = io.BytesIO()
153
  doc = SimpleDocTemplate(
 
162
  styles = getSampleStyleSheet()
163
  story = []
164
 
 
 
165
  spacer_height = 10
 
166
  left_column, right_column = markdown_to_pdf_content(markdown_text)
167
 
168
  total_items = 0
 
174
  else:
175
  total_items += 1
176
 
 
177
  if auto_size:
178
  base_font_size = max(6, min(12, 200 / total_items))
179
 
 
180
  item_font_size = base_font_size
181
  subitem_font_size = base_font_size * 0.9
182
  section_font_size = base_font_size * 1.2
183
  title_font_size = min(16, base_font_size * 1.5)
184
 
185
+ # Define styles using the emoji-supporting font "NotoEmoji"
186
+ title_style = ParagraphStyle(
187
+ 'Heading1',
188
+ parent=styles['Heading1'],
189
+ fontName='NotoEmoji',
190
+ textColor=colors.darkblue,
191
+ alignment=1,
192
+ fontSize=title_font_size
193
+ )
194
 
195
  section_style = ParagraphStyle(
196
  'SectionStyle',
197
  parent=styles['Heading2'],
198
+ fontName='NotoEmoji',
199
  textColor=colors.darkblue,
200
  fontSize=section_font_size,
201
  leading=section_font_size * 1.2,
 
205
  item_style = ParagraphStyle(
206
  'ItemStyle',
207
  parent=styles['Normal'],
208
+ fontName='NotoEmoji',
209
  fontSize=item_font_size,
210
  leading=item_font_size * 1.2,
 
211
  spaceAfter=1
212
  )
213
 
214
  subitem_style = ParagraphStyle(
215
  'SubItemStyle',
216
  parent=styles['Normal'],
217
+ fontName='NotoEmoji',
218
  fontSize=subitem_font_size,
219
  leading=subitem_font_size * 1.2,
220
  leftIndent=10,
 
275
  buffer.seek(0)
276
  return buffer.getvalue()
277
 
278
+ # --- Function to Convert PDF Bytes to Image (for Preview) ---
279
  def pdf_to_image(pdf_bytes):
280
  try:
281
  doc = fitz.open(stream=pdf_bytes, filetype="pdf")
282
  page = doc[0]
283
+ pix = page.get_pixmap(matrix=fitz.Matrix(2.0, 2.0)) # 2x zoom for clarity
284
  img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
285
  doc.close()
286
  return img
 
288
  st.error(f"Failed to render PDF preview: {e}")
289
  return None
290
 
291
+ # --- Sidebar UI for Settings ---
292
  with st.sidebar:
293
  auto_size = st.checkbox("Auto-size text", value=True)
294
  if not auto_size:
 
297
  base_font_size = 10
298
  st.info("Font size will auto-adjust between 6-12 points based on content length.")
299
 
300
+ # --- Persist Markdown Content in Session State ---
301
  if 'markdown_content' not in st.session_state:
302
  st.session_state.markdown_content = default_markdown
303
 
304
+ # --- Generate PDF ---
305
  with st.spinner("Generating PDF..."):
306
  pdf_bytes = create_main_pdf(st.session_state.markdown_content, base_font_size, auto_size)
307
 
308
+ # --- Display PDF Preview in UI ---
309
  with st.container():
310
  pdf_image = pdf_to_image(pdf_bytes)
311
  if pdf_image:
 
313
  else:
314
  st.info("Download the PDF to view it locally.")
315
 
316
+ # --- PDF Download Button ---
317
  st.download_button(
318
  label="Download PDF",
319
  data=pdf_bytes,
 
321
  mime="application/pdf"
322
  )
323
 
324
+ # --- Markdown Editor ---
325
  edited_markdown = st.text_area(
326
  "Modify the markdown content below:",
327
  value=st.session_state.markdown_content,
328
  height=300
329
  )
330
 
331
+ # --- Update PDF on Button Click ---
332
  if st.button("Update PDF"):
333
  st.session_state.markdown_content = edited_markdown
334
+ st.experimental_rerun()
335
 
336
+ # --- Markdown Download Button ---
337
  st.download_button(
338
  label="Save Markdown",
339
  data=st.session_state.markdown_content,
340
  file_name="ml_outline.md",
341
  mime="text/markdown"
342
+ )