Prak2005 commited on
Commit
f25c75d
Β·
verified Β·
1 Parent(s): ba0b6c8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +382 -176
app.py CHANGED
@@ -838,7 +838,9 @@ class MarkdownToPDFAgent:
838
  output_files.append(processed_file)
839
 
840
  return output_files
841
- # Helper functions for the Gradio interface
 
 
842
  def load_sample():
843
  """Load a sample markdown document."""
844
  return """# Sample Markdown Document
@@ -869,7 +871,7 @@ def hello_world():
869
  """
870
 
871
  def process_markdown(markdown_text, page_size, font_size, font_name,
872
- margin_size, include_toc, use_ai, api_key, enhancement_instructions):
873
  """
874
  Process markdown text and generate a PDF.
875
 
@@ -894,12 +896,14 @@ def process_markdown(markdown_text, page_size, font_size, font_name,
894
  include_toc=include_toc
895
  )
896
 
 
 
 
897
  # Setup AI enhancement if requested
898
  enhance = False
899
  if use_ai and api_key:
900
- if api_key:
901
- success = agent.setup_from_gemini(api_key)
902
- enhance = success
903
 
904
  try:
905
  # Create a temporary file for the markdown content
@@ -927,189 +931,385 @@ def process_markdown(markdown_text, page_size, font_size, font_name,
927
  logger.error(f"Error processing markdown: {e}")
928
  return None, f"❌ Error: {str(e)}"
929
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
930
  # Define the Gradio interface
931
- with gr.Blocks(title="MarkdownMuse") as demo:
932
- # Custom CSS for enhanced UI
933
- demo.load(css="""
934
- .header {
935
- background: linear-gradient(90deg, #6366F1 0%, #8B5CF6 100%);
936
- color: white;
937
- padding: 20px;
938
- border-radius: 10px;
939
- margin-bottom: 20px;
940
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
941
- text-align: center;
942
- }
943
-
944
- .container {
945
- max-width: 1200px;
946
- margin: 0 auto;
947
- padding: 0 15px;
948
- }
949
-
950
- .card {
951
- background: white;
952
- border-radius: 10px;
953
- padding: 20px;
954
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
955
- margin-bottom: 20px;
956
- }
957
-
958
- .footer {
959
- text-align: center;
960
- margin-top: 30px;
961
- padding: 15px;
962
- background: #f5f5f5;
963
- border-radius: 10px;
964
- font-size: 14px;
965
- }
966
-
967
- .primary-btn {
968
- background: linear-gradient(90deg, #6366F1 0%, #8B5CF6 100%);
969
- }
970
-
971
- .icon {
972
- vertical-align: middle;
973
- margin-right: 5px;
974
- }
975
-
976
- .section-title {
977
- border-bottom: 2px solid #f0f0f0;
978
- padding-bottom: 10px;
979
- margin-bottom: 15px;
980
- color: #4B5563;
981
- }
982
-
983
- .tab-active {
984
- border-bottom: 3px solid #6366F1;
985
- }
986
  """)
987
 
988
- with gr.Column():
989
- # Header
990
- gr.HTML("""
991
- <div class="header">
992
- <h1>πŸ“ MarkdownMuse</h1>
993
- <p>Transform your Markdown files into beautifully formatted PDFs with ease</p>
994
- </div>
995
- """)
996
-
997
- with gr.Row(equal_height=True):
998
- # Input Section
999
- with gr.Column(scale=1, elem_classes="card"):
1000
- gr.Markdown("## πŸ“„ Input", elem_classes="section-title")
1001
-
1002
- markdown_input = gr.TextArea(
1003
- placeholder="Enter your markdown content here...",
1004
- label="Markdown Content",
1005
- lines=15,
1006
- max_lines=30
1007
- )
1008
-
1009
- with gr.Row():
1010
- sample_btn = gr.Button("πŸ“‹ Load Sample", size="sm")
1011
- clear_btn = gr.Button("πŸ—‘οΈ Clear", size="sm")
1012
-
1013
- with gr.Tabs():
1014
- with gr.TabItem("πŸ“ PDF Settings"):
1015
- with gr.Row():
1016
- with gr.Column(scale=1):
1017
- page_size = gr.Radio(
1018
- ["A4", "Letter"],
1019
- label="Page Size",
1020
- value="A4"
1021
- )
1022
- include_toc = gr.Checkbox(
1023
- value=True,
1024
- label="Include Table of Contents"
1025
- )
1026
-
1027
- with gr.Column(scale=1):
1028
- font_name = gr.Dropdown(
1029
- ["Helvetica", "Times-Roman", "Courier"],
1030
- label="Font Family",
1031
- value="Helvetica"
1032
- )
1033
- font_size = gr.Slider(
1034
- minimum=8,
1035
- maximum=14,
1036
- value=10,
1037
- step=1,
1038
- label="Base Font Size (pt)"
1039
- )
1040
-
1041
- margin_size = gr.Slider(
1042
- minimum=0.5,
1043
- maximum=2.0,
1044
- value=0.75,
1045
- step=0.25,
1046
- label="Margins (inches)"
1047
- )
1048
-
1049
- with gr.TabItem("🧠 AI Enhancement"):
1050
- use_ai = gr.Checkbox(
1051
- value=False,
1052
- label="Enable AI Enhancement"
1053
- )
1054
-
1055
- api_key = gr.Textbox(
1056
- placeholder="Enter your Google Gemini API key...",
1057
- label="Google Gemini API Key",
1058
- type="password"
1059
- )
1060
 
1061
- enhancement_instructions = gr.TextArea(
1062
- placeholder="Optional: Provide specific instructions for how the AI should enhance your markdown...",
1063
- label="Enhancement Instructions",
1064
- lines=3
1065
- )
1066
-
1067
- convert_btn = gr.Button("πŸ”„ Convert to PDF", variant="primary", elem_classes="primary-btn")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1068
 
1069
- # Output Section
1070
- with gr.Column(scale=1, elem_classes="card"):
1071
- gr.Markdown("## πŸ“‘ Output", elem_classes="section-title")
 
 
 
 
 
 
 
 
 
 
1072
 
1073
- status = gr.Markdown("Ready to convert your markdown to PDF.")
1074
- output_pdf = gr.File(label="Generated PDF")
 
 
 
 
 
 
 
1075
 
1076
- with gr.Accordion("πŸ’‘ Markdown Tips", open=False):
1077
- gr.Markdown("""
1078
- ### Basic Syntax
1079
- - **Headings**: Use `#` for h1, `##` for h2, etc.
1080
- - **Bold**: Surround text with `**double asterisks**`
1081
- - **Italic**: Surround text with `*single asterisks*`
1082
- - **Lists**: Start lines with `-` or `*` for bullets, `1.` for numbered
1083
- - **Links**: `[link text](http://example.com)`
1084
- - **Images**: `![alt text](image.jpg)`
 
 
 
 
1085
 
1086
- ### Advanced Features
1087
- - **Tables**: Use `|` to separate columns and `-` for header rows
1088
- - **Code Blocks**: Wrap with triple backticks (``` code ```)
1089
- - **Blockquotes**: Start lines with `>`
 
 
 
1090
 
1091
- [Learn more about Markdown syntax](https://www.markdownguide.org/basic-syntax/)
1092
- """)
1093
-
1094
- # Footer
1095
- gr.HTML("""
1096
- <div class="footer">
1097
- <p>MarkdownMuse | A powerful Markdown to PDF converter with AI enhancement capabilities</p>
1098
- <p>Made with ❀️ using Python, ReportLab, and Gradio | © 2024</p>
1099
- </div>
1100
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1101
 
1102
  # Set up event handlers
1103
  sample_btn.click(load_sample, outputs=markdown_input)
1104
  clear_btn.click(lambda: "", outputs=markdown_input)
1105
 
1106
- # Update visibility of AI options based on checkbox
1107
- use_ai.change(
1108
- lambda x: [gr.update(visible=x), gr.update(visible=x)],
1109
- inputs=[use_ai],
1110
- outputs=[api_key, enhancement_instructions]
1111
- )
1112
-
1113
  # Process markdown and generate PDF
1114
  convert_btn.click(
1115
  process_markdown,
@@ -1121,7 +1321,6 @@ with gr.Blocks(title="MarkdownMuse") as demo:
1121
  margin_size,
1122
  include_toc,
1123
  use_ai,
1124
- api_key,
1125
  enhancement_instructions
1126
  ],
1127
  outputs=[
@@ -1132,4 +1331,11 @@ with gr.Blocks(title="MarkdownMuse") as demo:
1132
 
1133
  # Launch the app
1134
  if __name__ == "__main__":
1135
- app.launch()
 
 
 
 
 
 
 
 
838
  output_files.append(processed_file)
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
 
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,
 
1321
  margin_size,
1322
  include_toc,
1323
  use_ai,
 
1324
  enhancement_instructions
1325
  ],
1326
  outputs=[
 
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()