broadfield-dev commited on
Commit
48891a9
·
verified ·
1 Parent(s): 80a56ff

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -13
app.py CHANGED
@@ -77,14 +77,14 @@ def parse_endpoint():
77
  except Exception as e:
78
  return jsonify({'error': f'Failed to parse: {e}'}), 500
79
 
80
- # --- HTML & PNG BUILDER (CHANGED) ---
81
  def build_full_html(markdown_text, styles, include_fontawesome):
82
  wrapper_id = "#output-wrapper"
83
  font_family = styles.get('font_family', "'Arial', sans-serif")
84
-
85
- # *** THIS IS THE FIX: Forcefully disable ALL external network calls ***
86
  google_font_link = ""
87
- fontawesome_link = ""
 
88
 
89
  highlight_theme = styles.get('highlight_theme', 'default')
90
  pygments_css = ""
@@ -111,6 +111,8 @@ def build_full_html(markdown_text, styles, include_fontawesome):
111
  html_content = markdown.markdown(markdown_text, extensions=md_extensions, extension_configs={'codehilite': {'css_class': 'codehilite'}})
112
  final_html_body = f'<div id="output-wrapper">{html_content}</div>'
113
 
 
 
114
  full_html = f"""<!DOCTYPE html>
115
  <html><head><meta charset="UTF-8">{google_font_link}{fontawesome_link}<style>
116
  #ouput-wrapper {{ background-color: {styles.get('background_color', '#fff')}; padding: 25px; display: inline-block;}}
@@ -131,7 +133,7 @@ def convert_endpoint():
131
  include_fontawesome=data.get('include_fontawesome', False)
132
  )
133
 
134
- # We need xvfb because wkhtmltoimage is a headless browser
135
  options = {
136
  "quiet": "",
137
  'encoding': "UTF-8",
@@ -161,7 +163,7 @@ def convert_endpoint():
161
  if temp_html_path and os.path.exists(temp_html_path):
162
  os.remove(temp_html_path)
163
 
164
- # --- MAIN PAGE RENDERER (Unchanged) ---
165
  @app.route('/')
166
  def index():
167
  highlight_styles = sorted(list(get_all_styles()))
@@ -236,7 +238,7 @@ def index():
236
  if (componentsFieldset.style.display === 'block') {
237
  const parts = [];
238
  componentsContainer.querySelectorAll('.component-container').forEach(div => {
239
- if (div.querySelector('.component-checkbox').checked) { parts.push(div.dataset.reconstructed || div.dataset.content); }
240
  });
241
  finalMarkdown = parts.join('\\n\\n---\\n\\n');
242
  } else { finalMarkdown = markdownTextInput.value; }
@@ -293,11 +295,33 @@ def index():
293
  if (result.format !== 'Unknown') {
294
  componentsFieldset.style.display = 'block';
295
  result.components.forEach((comp, index) => {
296
- const div = document.createElement('div'); div.className = 'component-container'; div.dataset.type = comp.type; div.dataset.filename = comp.filename; div.dataset.content = comp.content;
297
- let reconstructedContent = comp.content;
298
- if (comp.is_code_block) { div.dataset.isCodeBlock = 'true'; div.dataset.language = comp.language || ''; reconstructedContent = "```" + (comp.language || '') + "\\n" + comp.content + "\\n```"; }
299
- if (comp.type === 'section') div.dataset.reconstructed = `## ${comp.filename}\\n${comp.content}`; if (comp.type === 'version') div.dataset.reconstructed = `## ${comp.filename}\\n${comp.content}`;
300
- div.innerHTML = `<div class="component-header"><input type="checkbox" id="comp-check-${index}" class="component-checkbox" checked><label for="comp-check-${index}">${comp.filename}</label></div><div class="component-content"><textarea readonly>${comp.content}</textarea></div>`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  componentsContainer.appendChild(div);
302
  });
303
  }
@@ -310,4 +334,4 @@ def index():
310
  """, highlight_styles=highlight_styles)
311
 
312
  if __name__ == "__main__":
313
- app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)))
 
77
  except Exception as e:
78
  return jsonify({'error': f'Failed to parse: {e}'}), 500
79
 
80
+ # --- HTML & PNG BUILDER (Unchanged) ---
81
  def build_full_html(markdown_text, styles, include_fontawesome):
82
  wrapper_id = "#output-wrapper"
83
  font_family = styles.get('font_family', "'Arial', sans-serif")
84
+ google_font_name = font_family.split(',')[0].strip("'\"")
 
85
  google_font_link = ""
86
+ if " " in google_font_name and google_font_name not in ["Times New Roman", "Courier New"]:
87
+ google_font_link = f'<link href="https://fonts.googleapis.com/css2?family={google_font_name.replace(" ", "+")}:wght@400;700&display=swap" rel="stylesheet">'
88
 
89
  highlight_theme = styles.get('highlight_theme', 'default')
90
  pygments_css = ""
 
111
  html_content = markdown.markdown(markdown_text, extensions=md_extensions, extension_configs={'codehilite': {'css_class': 'codehilite'}})
112
  final_html_body = f'<div id="output-wrapper">{html_content}</div>'
113
 
114
+ fontawesome_link = '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">' if include_fontawesome else ""
115
+
116
  full_html = f"""<!DOCTYPE html>
117
  <html><head><meta charset="UTF-8">{google_font_link}{fontawesome_link}<style>
118
  #ouput-wrapper {{ background-color: {styles.get('background_color', '#fff')}; padding: 25px; display: inline-block;}}
 
133
  include_fontawesome=data.get('include_fontawesome', False)
134
  )
135
 
136
+ # Use xvfb, which is required for stable headless rendering.
137
  options = {
138
  "quiet": "",
139
  'encoding': "UTF-8",
 
163
  if temp_html_path and os.path.exists(temp_html_path):
164
  os.remove(temp_html_path)
165
 
166
+ # --- MAIN PAGE RENDERER (with corrected JavaScript) ---
167
  @app.route('/')
168
  def index():
169
  highlight_styles = sorted(list(get_all_styles()))
 
238
  if (componentsFieldset.style.display === 'block') {
239
  const parts = [];
240
  componentsContainer.querySelectorAll('.component-container').forEach(div => {
241
+ if (div.querySelector('.component-checkbox').checked) { parts.push(div.dataset.reconstructed); }
242
  });
243
  finalMarkdown = parts.join('\\n\\n---\\n\\n');
244
  } else { finalMarkdown = markdownTextInput.value; }
 
295
  if (result.format !== 'Unknown') {
296
  componentsFieldset.style.display = 'block';
297
  result.components.forEach((comp, index) => {
298
+ const div = document.createElement('div');
299
+ div.className = 'component-container';
300
+
301
+ // *** THIS IS THE FIX ***
302
+ // We create the full markdown for reconstruction here, ensuring headings are preserved.
303
+ let full_content_for_reconstruction;
304
+ let display_content = comp.content; // Content for the <textarea>
305
+
306
+ let content_with_fences = comp.content;
307
+ if (comp.is_code_block) {
308
+ content_with_fences = "```" + (comp.language || '') + "\\n" + comp.content + "\\n```";
309
+ }
310
+
311
+ if (comp.type === 'file') {
312
+ // For repo2md, format each file as a Level 3 heading with its content
313
+ full_content_for_reconstruction = `### File: ${comp.filename}\\n${content_with_fences}`;
314
+ } else if (comp.type === 'section' || comp.type === 'version') {
315
+ // For other formats, use a Level 2 heading
316
+ full_content_for_reconstruction = `## ${comp.filename}\\n${comp.content}`;
317
+ } else {
318
+ // For intro text, use the content as-is
319
+ full_content_for_reconstruction = comp.content;
320
+ }
321
+
322
+ div.dataset.reconstructed = full_content_for_reconstruction;
323
+
324
+ div.innerHTML = `<div class="component-header"><input type="checkbox" id="comp-check-${index}" class="component-checkbox" checked><label for="comp-check-${index}">${comp.filename}</label></div><div class="component-content"><textarea readonly>${display_content}</textarea></div>`;
325
  componentsContainer.appendChild(div);
326
  });
327
  }
 
334
  """, highlight_styles=highlight_styles)
335
 
336
  if __name__ == "__main__":
337
+ app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)))```