Prak2005 commited on
Commit
1c475e2
Β·
verified Β·
1 Parent(s): b2bc1b8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +385 -96
app.py CHANGED
@@ -839,7 +839,8 @@ class MarkdownToPDFAgent:
839
 
840
  return output_files
841
 
842
- # Gradio Interface for Hugging Face
 
843
  def load_sample():
844
  """Load a sample markdown document."""
845
  return """# Sample Markdown Document
@@ -870,7 +871,7 @@ def hello_world():
870
  """
871
 
872
  def process_markdown(markdown_text, page_size, font_size, font_name,
873
- margin_size, include_toc, use_ai, api_key, enhancement_instructions):
874
  """
875
  Process markdown text and generate a PDF.
876
 
@@ -895,12 +896,14 @@ def process_markdown(markdown_text, page_size, font_size, font_name,
895
  include_toc=include_toc
896
  )
897
 
 
 
 
898
  # Setup AI enhancement if requested
899
  enhance = False
900
  if use_ai and api_key:
901
- if api_key:
902
- success = agent.setup_from_gemini(api_key)
903
- enhance = success
904
 
905
  try:
906
  # Create a temporary file for the markdown content
@@ -921,106 +924,393 @@ def process_markdown(markdown_text, page_size, font_size, font_name,
921
  os.unlink(temp_md_path)
922
 
923
  if output_file:
924
- return output_file
925
  else:
926
- return None
927
  except Exception as e:
928
  logger.error(f"Error processing markdown: {e}")
929
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
930
 
931
  # Define the Gradio interface
932
- with gr.Blocks(title="MarkdownMuse", theme=gr.themes.Soft()) as app:
933
- gr.Markdown(
934
- """
935
- # πŸ“ MarkdownMuse
936
-
937
- Transform your Markdown files into beautifully formatted PDFs with ease.
938
- """
939
- )
 
940
 
941
  with gr.Row():
 
942
  with gr.Column(scale=1):
943
- gr.Markdown("### πŸ“ Input")
944
 
945
  markdown_input = gr.TextArea(
946
  placeholder="Enter your markdown content here...",
947
  label="Markdown Content",
948
- lines=15
 
949
  )
950
 
951
- sample_btn = gr.Button("πŸ“‹ Load Sample")
 
 
952
 
953
- with gr.Accordion("βš™οΈ PDF Settings", open=False):
954
- page_size = gr.Radio(
955
- ["A4", "Letter"],
956
- label="Page Size",
957
- value="A4"
958
- )
959
-
960
- font_size = gr.Slider(
961
- minimum=8,
962
- maximum=14,
963
- value=10,
964
- step=1,
965
- label="Base Font Size (pt)"
966
- )
967
-
968
- font_name = gr.Dropdown(
969
- ["Helvetica", "Times-Roman", "Courier"],
970
- label="Font Family",
971
- value="Helvetica"
972
- )
973
-
974
- margin_size = gr.Slider(
975
- minimum=0.5,
976
- maximum=2.0,
977
- value=0.75,
978
- step=0.25,
979
- label="Margins (inches)"
980
- )
981
-
982
- include_toc = gr.Checkbox(
983
- value=True,
984
- label="Include Table of Contents"
985
- )
986
-
987
- with gr.Accordion("🧠 AI Enhancement", open=False):
988
- use_ai = gr.Checkbox(
989
- value=False,
990
- label="Enable AI Enhancement"
991
- )
992
-
993
- api_key = gr.Textbox(
994
- placeholder="Enter your Google Gemini API key...",
995
- label="Google Gemini API Key",
996
- type="password",
997
- visible=True
998
- )
999
-
1000
- enhancement_instructions = gr.TextArea(
1001
- placeholder="Optional: Provide specific instructions for how the AI should enhance your markdown...",
1002
- label="Enhancement Instructions",
1003
- lines=3,
1004
- visible=True
1005
- )
1006
-
1007
- convert_btn = gr.Button("πŸ”„ Convert to PDF", variant="primary")
 
 
 
 
 
 
 
 
 
1008
 
 
 
 
1009
  with gr.Column(scale=1):
1010
- gr.Markdown("### πŸ“‹ Output")
1011
 
1012
- output_pdf = gr.File(label="Generated PDF")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1013
 
1014
  # Set up event handlers
1015
  sample_btn.click(load_sample, outputs=markdown_input)
 
1016
 
1017
- # Add visibility toggle for API key based on checkbox
1018
- use_ai.change(
1019
- lambda x: [gr.update(visible=x), gr.update(visible=x)],
1020
- inputs=[use_ai],
1021
- outputs=[api_key, enhancement_instructions]
1022
- )
1023
-
1024
  convert_btn.click(
1025
  process_markdown,
1026
  inputs=[
@@ -1031,22 +1321,21 @@ with gr.Blocks(title="MarkdownMuse", theme=gr.themes.Soft()) as app:
1031
  margin_size,
1032
  include_toc,
1033
  use_ai,
1034
- api_key,
1035
  enhancement_instructions
1036
  ],
1037
- outputs=output_pdf
1038
- )
1039
-
1040
- gr.Markdown(
1041
- """
1042
- ### πŸ“š About MarkdownMuse
1043
-
1044
- This tool allows you to convert Markdown documents to beautifully formatted PDFs. Use the options to customize your output.
1045
-
1046
- Made with ❀️ using Gradio and ReportLab | © 2024
1047
- """
1048
  )
1049
 
1050
  # Launch the app
1051
  if __name__ == "__main__":
1052
- app.launch()
 
 
 
 
 
 
 
 
839
 
840
  return output_files
841
 
842
+
843
+ # Helper functions for the Gradio interface
844
  def load_sample():
845
  """Load a sample markdown document."""
846
  return """# Sample Markdown Document
 
871
  """
872
 
873
  def process_markdown(markdown_text, page_size, font_size, font_name,
874
+ margin_size, include_toc, use_ai, enhancement_instructions):
875
  """
876
  Process markdown text and generate a PDF.
877
 
 
896
  include_toc=include_toc
897
  )
898
 
899
+ # Get Gemini API key from environment
900
+ api_key = os.environ.get('GOOGLE_API_KEY')
901
+
902
  # Setup AI enhancement if requested
903
  enhance = False
904
  if use_ai and api_key:
905
+ success = agent.setup_from_gemini(api_key)
906
+ enhance = success
 
907
 
908
  try:
909
  # Create a temporary file for the markdown content
 
924
  os.unlink(temp_md_path)
925
 
926
  if output_file:
927
+ return output_file, "βœ… PDF generated successfully!"
928
  else:
929
+ return None, "❌ Error generating PDF. Please check your markdown syntax."
930
  except Exception as e:
931
  logger.error(f"Error processing markdown: {e}")
932
+ return None, f"❌ Error: {str(e)}"
933
+
934
+
935
+ # Check if the API key is available in the environment
936
+ has_api_key = bool(os.environ.get('GOOGLE_API_KEY'))
937
+
938
+ # Custom CSS for styling
939
+ custom_css = """
940
+ <style>
941
+ :root {
942
+ --primary-color: #6366F1;
943
+ --secondary-color: #8B5CF6;
944
+ --accent-color: #4f46e5;
945
+ --text-color: #1F2937;
946
+ --light-text: #F9FAFB;
947
+ --border-color: #E5E7EB;
948
+ --background-color: #F3F4F6;
949
+ --card-background: #FFFFFF;
950
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
951
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
952
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
953
+ --rounded-sm: 0.375rem;
954
+ --rounded-md: 0.5rem;
955
+ --rounded-lg: 0.75rem;
956
+ }
957
+
958
+ .header {
959
+ background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
960
+ color: var(--light-text);
961
+ padding: 2rem;
962
+ border-radius: var(--rounded-lg);
963
+ margin-bottom: 1.5rem;
964
+ box-shadow: var(--shadow-lg);
965
+ text-align: center;
966
+ position: relative;
967
+ overflow: hidden;
968
+ }
969
+
970
+ .header::before {
971
+ content: "";
972
+ position: absolute;
973
+ top: 0;
974
+ left: 0;
975
+ right: 0;
976
+ bottom: 0;
977
+ background: repeating-linear-gradient(
978
+ 45deg,
979
+ rgba(255, 255, 255, 0.05),
980
+ rgba(255, 255, 255, 0.05) 10px,
981
+ rgba(255, 255, 255, 0) 10px,
982
+ rgba(255, 255, 255, 0) 20px
983
+ );
984
+ }
985
+
986
+ .header h1 {
987
+ font-size: 2.5rem;
988
+ margin-bottom: 0.5rem;
989
+ font-weight: 700;
990
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
991
+ }
992
+
993
+ .header p {
994
+ font-size: 1.25rem;
995
+ opacity: 0.9;
996
+ max-width: 700px;
997
+ margin: 0 auto;
998
+ }
999
+
1000
+ .container {
1001
+ max-width: 1200px;
1002
+ margin: 0 auto;
1003
+ padding: 0 1rem;
1004
+ }
1005
+
1006
+ .card {
1007
+ background: var(--card-background);
1008
+ border-radius: var(--rounded-lg);
1009
+ padding: 1.5rem;
1010
+ box-shadow: var(--shadow-md);
1011
+ margin-bottom: 1.5rem;
1012
+ border: 1px solid var(--border-color);
1013
+ transition: transform 0.2s, box-shadow 0.2s;
1014
+ }
1015
+
1016
+ .card:hover {
1017
+ transform: translateY(-2px);
1018
+ box-shadow: var(--shadow-lg);
1019
+ }
1020
+
1021
+ .section-title {
1022
+ color: var(--primary-color);
1023
+ font-size: 1.5rem;
1024
+ font-weight: 600;
1025
+ margin-bottom: 1rem;
1026
+ padding-bottom: 0.75rem;
1027
+ border-bottom: 2px solid var(--border-color);
1028
+ }
1029
+
1030
+ .footer {
1031
+ text-align: center;
1032
+ margin-top: 2rem;
1033
+ padding: 1.5rem;
1034
+ background: var(--background-color);
1035
+ border-radius: var(--rounded-lg);
1036
+ font-size: 0.9rem;
1037
+ color: var(--text-color);
1038
+ box-shadow: var(--shadow-sm);
1039
+ }
1040
+
1041
+ .feature-icon {
1042
+ display: inline-block;
1043
+ background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
1044
+ color: white;
1045
+ width: 2.5rem;
1046
+ height: 2.5rem;
1047
+ line-height: 2.5rem;
1048
+ text-align: center;
1049
+ border-radius: 50%;
1050
+ margin-right: 0.75rem;
1051
+ font-size: 1.25rem;
1052
+ box-shadow: var(--shadow-sm);
1053
+ }
1054
+
1055
+ .button-row {
1056
+ display: flex;
1057
+ gap: 0.75rem;
1058
+ margin: 1rem 0;
1059
+ }
1060
+
1061
+ .primary-btn {
1062
+ background: linear-gradient(to right, var(--primary-color), var(--secondary-color)) !important;
1063
+ transition: all 0.3s ease !important;
1064
+ transform: translateY(0);
1065
+ box-shadow: var(--shadow-md) !important;
1066
+ font-weight: 600 !important;
1067
+ }
1068
+
1069
+ .primary-btn:hover {
1070
+ transform: translateY(-2px);
1071
+ box-shadow: var(--shadow-lg) !important;
1072
+ }
1073
+
1074
+ .secondary-btn {
1075
+ background: var(--background-color) !important;
1076
+ color: var(--text-color) !important;
1077
+ border: 1px solid var(--border-color) !important;
1078
+ font-weight: 500 !important;
1079
+ }
1080
+
1081
+ .tip-box {
1082
+ background: rgba(99, 102, 241, 0.1);
1083
+ border-left: 4px solid var(--primary-color);
1084
+ padding: 1rem;
1085
+ margin: 1rem 0;
1086
+ border-radius: var(--rounded-sm);
1087
+ }
1088
+
1089
+ .tip-title {
1090
+ color: var(--primary-color);
1091
+ font-weight: 600;
1092
+ margin-bottom: 0.5rem;
1093
+ }
1094
+
1095
+ /* Tab styling */
1096
+ .tab-active {
1097
+ border-bottom: 3px solid var(--primary-color);
1098
+ color: var(--primary-color);
1099
+ font-weight: 600;
1100
+ }
1101
+
1102
+ /* Customize Gradio components */
1103
+ .gr-box {
1104
+ border-radius: var(--rounded-md) !important;
1105
+ border: 1px solid var(--border-color) !important;
1106
+ }
1107
+
1108
+ .gr-button {
1109
+ border-radius: var(--rounded-md) !important;
1110
+ }
1111
+
1112
+ .gr-form {
1113
+ border-radius: var(--rounded-md) !important;
1114
+ border: 1px solid var(--border-color) !important;
1115
+ box-shadow: var(--shadow-sm) !important;
1116
+ }
1117
+
1118
+ .gr-input {
1119
+ border-radius: var(--rounded-md) !important;
1120
+ }
1121
+
1122
+ .gr-checkbox {
1123
+ border-radius: var(--rounded-sm) !important;
1124
+ }
1125
+
1126
+ .gr-panel {
1127
+ border-radius: var(--rounded-md) !important;
1128
+ }
1129
+
1130
+ .gr-accordion {
1131
+ border-radius: var(--rounded-md) !important;
1132
+ }
1133
+ </style>
1134
+ """
1135
 
1136
  # Define the Gradio interface
1137
+ with gr.Blocks(title="MarkdownMuse", theme=gr.themes.Soft()) as demo:
1138
+ # Header with custom styling
1139
+ gr.HTML(custom_css + """
1140
+ <div class="header">
1141
+ <h1>πŸ“ MarkdownMuse</h1>
1142
+ <p>Transform your Markdown files into beautifully formatted PDFs with a single click.
1143
+ Professional-looking documents made simple.</p>
1144
+ </div>
1145
+ """)
1146
 
1147
  with gr.Row():
1148
+ # Input Section
1149
  with gr.Column(scale=1):
1150
+ gr.Markdown("## πŸ“„ Input", elem_id="section-title")
1151
 
1152
  markdown_input = gr.TextArea(
1153
  placeholder="Enter your markdown content here...",
1154
  label="Markdown Content",
1155
+ lines=15,
1156
+ elem_id="markdown-input"
1157
  )
1158
 
1159
+ with gr.Row(elem_id="button-row"):
1160
+ sample_btn = gr.Button("πŸ“‹ Load Sample", size="sm", elem_classes="secondary-btn")
1161
+ clear_btn = gr.Button("πŸ—‘οΈ Clear", size="sm", elem_classes="secondary-btn")
1162
 
1163
+ with gr.Tabs():
1164
+ with gr.TabItem("πŸ“ PDF Settings", elem_classes="tab-item"):
1165
+ with gr.Row():
1166
+ with gr.Column(scale=1):
1167
+ page_size = gr.Radio(
1168
+ ["A4", "Letter"],
1169
+ label="Page Size",
1170
+ value="A4",
1171
+ elem_id="page-size"
1172
+ )
1173
+ include_toc = gr.Checkbox(
1174
+ value=True,
1175
+ label="Include Table of Contents",
1176
+ elem_id="include-toc"
1177
+ )
1178
+
1179
+ with gr.Column(scale=1):
1180
+ font_name = gr.Dropdown(
1181
+ ["Helvetica", "Times-Roman", "Courier"],
1182
+ label="Font Family",
1183
+ value="Helvetica",
1184
+ elem_id="font-name"
1185
+ )
1186
+ font_size = gr.Slider(
1187
+ minimum=8,
1188
+ maximum=14,
1189
+ value=10,
1190
+ step=1,
1191
+ label="Base Font Size (pt)",
1192
+ elem_id="font-size"
1193
+ )
1194
+
1195
+ margin_size = gr.Slider(
1196
+ minimum=0.5,
1197
+ maximum=2.0,
1198
+ value=0.75,
1199
+ step=0.25,
1200
+ label="Margins (inches)",
1201
+ elem_id="margin-size"
1202
+ )
1203
+
1204
+ with gr.TabItem("🧠 AI Enhancement", elem_classes="tab-item"):
1205
+ use_ai = gr.Checkbox(
1206
+ value=has_api_key,
1207
+ label="Enable AI Enhancement",
1208
+ elem_id="use-ai"
1209
+ )
1210
+
1211
+ # Only show API key message if no key is in environment
1212
+ if not has_api_key:
1213
+ gr.Markdown("""
1214
+ > **Note:** To use AI enhancement, add your Google Gemini API key to the Hugging Face Space secrets as `GOOGLE_API_KEY`.
1215
+ """, elem_id="api-key-note")
1216
+ else:
1217
+ gr.Markdown("""
1218
+ > **API Key Detected!** AI enhancement is available.
1219
+ """, elem_id="api-key-success")
1220
+
1221
+ enhancement_instructions = gr.TextArea(
1222
+ placeholder="Provide specific instructions for how the AI should enhance your markdown... (Optional)",
1223
+ label="Enhancement Instructions",
1224
+ lines=3,
1225
+ elem_id="enhancement-instructions"
1226
+ )
1227
 
1228
+ convert_btn = gr.Button("πŸ”„ Convert to PDF", variant="primary", elem_classes="primary-btn")
1229
+
1230
+ # Output Section
1231
  with gr.Column(scale=1):
1232
+ gr.Markdown("## πŸ“‘ Output", elem_id="section-title")
1233
 
1234
+ status = gr.Markdown("✨ Ready to convert your markdown to PDF.", elem_id="status")
1235
+ output_pdf = gr.File(label="Generated PDF", elem_id="output-pdf")
1236
+
1237
+ with gr.Accordion("πŸ’‘ Markdown Tips", open=False, elem_id="markdown-tips"):
1238
+ gr.HTML("""
1239
+ <div class="tip-box">
1240
+ <div class="tip-title">✨ Basic Syntax</div>
1241
+ <ul>
1242
+ <li><strong>Headings</strong>: Use <code>#</code> for h1, <code>##</code> for h2, etc.</li>
1243
+ <li><strong>Bold</strong>: Surround text with <code>**double asterisks**</code></li>
1244
+ <li><strong>Italic</strong>: Surround text with <code>*single asterisks*</code></li>
1245
+ <li><strong>Lists</strong>: Start lines with <code>-</code> or <code>*</code> for bullets, <code>1.</code> for numbered</li>
1246
+ <li><strong>Links</strong>: <code>[link text](http://example.com)</code></li>
1247
+ <li><strong>Images</strong>: <code>![alt text](image.jpg)</code></li>
1248
+ </ul>
1249
+ </div>
1250
+
1251
+ <div class="tip-box">
1252
+ <div class="tip-title">πŸ” Advanced Features</div>
1253
+ <ul>
1254
+ <li><strong>Tables</strong>: Use <code>|</code> to separate columns and <code>-</code> for header rows</li>
1255
+ <li><strong>Code Blocks</strong>: Wrap with triple backticks (<code>```</code> code <code>```</code>)</li>
1256
+ <li><strong>Blockquotes</strong>: Start lines with <code>></code></li>
1257
+ <li><strong>Horizontal Rule</strong>: Three dashes <code>---</code></li>
1258
+ </ul>
1259
+ </div>
1260
+
1261
+ <p><a href="https://www.markdownguide.org/basic-syntax/" target="_blank">Learn more about Markdown syntax β†’</a></p>
1262
+ """)
1263
+
1264
+ with gr.Accordion("πŸš€ Features", open=False, elem_id="features"):
1265
+ gr.HTML("""
1266
+ <div style="display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 0.5rem;">
1267
+ <div style="flex: 1; min-width: 200px;">
1268
+ <div style="display: flex; align-items: center; margin-bottom: 0.5rem;">
1269
+ <span class="feature-icon">πŸ“„</span>
1270
+ <strong>PDF Conversion</strong>
1271
+ </div>
1272
+ <p>Transform any markdown document into a professionally formatted PDF with proper styling.</p>
1273
+ </div>
1274
+
1275
+ <div style="flex: 1; min-width: 200px;">
1276
+ <div style="display: flex; align-items: center; margin-bottom: 0.5rem;">
1277
+ <span class="feature-icon">🧠</span>
1278
+ <strong>AI Enhancement</strong>
1279
+ </div>
1280
+ <p>Use AI to improve content formatting, fix grammar, and enhance readability.</p>
1281
+ </div>
1282
+
1283
+ <div style="flex: 1; min-width: 200px;">
1284
+ <div style="display: flex; align-items: center; margin-bottom: 0.5rem;">
1285
+ <span class="feature-icon">🎨</span>
1286
+ <strong>Custom Styling</strong>
1287
+ </div>
1288
+ <p>Control fonts, sizes, margins, and other style elements to match your needs.</p>
1289
+ </div>
1290
+
1291
+ <div style="flex: 1; min-width: 200px;">
1292
+ <div style="display: flex; align-items: center; margin-bottom: 0.5rem;">
1293
+ <span class="feature-icon">πŸ“‘</span>
1294
+ <strong>Table of Contents</strong>
1295
+ </div>
1296
+ <p>Automatically generate a structured table of contents from document headings.</p>
1297
+ </div>
1298
+ </div>
1299
+ """)
1300
+
1301
+ # Footer
1302
+ gr.HTML("""
1303
+ <div class="footer">
1304
+ <p><strong>MarkdownMuse</strong> | A powerful Markdown to PDF converter with AI enhancement capabilities</p>
1305
+ <p>Made with ❀️ using Python, ReportLab, and Gradio | <a href="https://github.com/your-username/markdownmuse" target="_blank">GitHub</a></p>
1306
+ </div>
1307
+ """)
1308
 
1309
  # Set up event handlers
1310
  sample_btn.click(load_sample, outputs=markdown_input)
1311
+ clear_btn.click(lambda: "", outputs=markdown_input)
1312
 
1313
+ # Process markdown and generate PDF
 
 
 
 
 
 
1314
  convert_btn.click(
1315
  process_markdown,
1316
  inputs=[
 
1321
  margin_size,
1322
  include_toc,
1323
  use_ai,
 
1324
  enhancement_instructions
1325
  ],
1326
+ outputs=[
1327
+ output_pdf,
1328
+ status
1329
+ ]
 
 
 
 
 
 
 
1330
  )
1331
 
1332
  # Launch the app
1333
  if __name__ == "__main__":
1334
+ try:
1335
+ print("Starting MarkdownMuse application...")
1336
+ demo.launch(server_name="0.0.0.0", server_port=7860)
1337
+ print("MarkdownMuse application launched successfully!")
1338
+ except Exception as e:
1339
+ print(f"ERROR LAUNCHING APP: {str(e)}")
1340
+ import traceback
1341
+ traceback.print_exc()