Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -13,10 +13,10 @@ from pygments.styles import get_all_styles
|
|
| 13 |
|
| 14 |
app = Flask(__name__)
|
| 15 |
|
| 16 |
-
|
|
|
|
| 17 |
os.makedirs(TEMP_DIR, exist_ok=True)
|
| 18 |
|
| 19 |
-
# --- FORMAT PARSING AND DETECTION (Unchanged) ---
|
| 20 |
def parse_repo2markdown(text):
|
| 21 |
components = []
|
| 22 |
pattern = re.compile(r'### File: (.*?)\n([\s\S]*?)(?=\n### File:|\Z)', re.MULTILINE)
|
|
@@ -55,7 +55,6 @@ def parse_changelog(text):
|
|
| 55 |
components.append({'type': 'version', 'filename': parts[i].replace('##', '').strip(), 'content': parts[i+1].strip()})
|
| 56 |
return components
|
| 57 |
|
| 58 |
-
|
| 59 |
@app.route('/parse', methods=['POST'])
|
| 60 |
def parse_endpoint():
|
| 61 |
text = request.form.get('markdown_text', '')
|
|
@@ -76,7 +75,6 @@ def parse_endpoint():
|
|
| 76 |
except Exception as e:
|
| 77 |
return jsonify({'error': f'Failed to parse: {e}'}), 500
|
| 78 |
|
| 79 |
-
# --- HTML & PNG BUILDER (Unchanged but correct logic) ---
|
| 80 |
def build_full_html(markdown_text, styles, include_fontawesome):
|
| 81 |
wrapper_id = "#output-wrapper"
|
| 82 |
font_family = styles.get('font_family', "'Arial', sans-serif")
|
|
@@ -96,8 +94,6 @@ def build_full_html(markdown_text, styles, include_fontawesome):
|
|
| 96 |
font-family: {font_family}; font-size: {styles.get('font_size', '16')}px;
|
| 97 |
color: {styles.get('text_color', '#333')}; background-color: {styles.get('background_color', '#fff')};
|
| 98 |
}}
|
| 99 |
-
/* ... other scoped styles ... */
|
| 100 |
-
|
| 101 |
{wrapper_id} table {{ border-collapse: collapse; width: 100%; }}
|
| 102 |
{wrapper_id} th, {wrapper_id} td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
|
| 103 |
{wrapper_id} th {{ background-color: #f2f2f2; }}
|
|
@@ -122,7 +118,6 @@ def build_full_html(markdown_text, styles, include_fontawesome):
|
|
| 122 |
|
| 123 |
return full_html
|
| 124 |
|
| 125 |
-
# --- API ENDPOINT for Conversion (CHANGED) ---
|
| 126 |
@app.route('/convert', methods=['POST'])
|
| 127 |
def convert_endpoint():
|
| 128 |
data = request.json
|
|
@@ -132,7 +127,6 @@ def convert_endpoint():
|
|
| 132 |
styles=data.get('styles', {}),
|
| 133 |
include_fontawesome=data.get('include_fontawesome', False)
|
| 134 |
)
|
| 135 |
-
# Define options here to avoid repetition and add the required fix
|
| 136 |
options = {"quiet": "", 'encoding': "UTF-8", "--no-cache": ""}
|
| 137 |
|
| 138 |
if data.get('download', False):
|
|
@@ -150,7 +144,6 @@ def convert_endpoint():
|
|
| 150 |
traceback.print_exc()
|
| 151 |
return jsonify({'error': f'Failed to convert content: {str(e)}'}), 500
|
| 152 |
|
| 153 |
-
# --- MAIN PAGE RENDERER (with corrected CSS) ---
|
| 154 |
@app.route('/')
|
| 155 |
def index():
|
| 156 |
highlight_styles = sorted(list(get_all_styles()))
|
|
@@ -182,22 +175,19 @@ def index():
|
|
| 182 |
.component-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px; }
|
| 183 |
.component-container { border: 1px solid #e0e0e0; border-radius: 5px; background: #fafafa; }
|
| 184 |
.component-header { background: #f1f1f1; padding: 8px 12px; border-bottom: 1px solid #e0e0e0; display: flex; align-items: center; gap: 10px; }
|
| 185 |
-
.component-content textarea { height: 150px; }
|
| 186 |
.selection-controls { margin: 15px 0; display: flex; gap: 10px; }
|
| 187 |
</style>
|
| 188 |
</head>
|
| 189 |
<body>
|
| 190 |
<h1>Intelligent Markdown Converter</h1>
|
| 191 |
<form id="main-form" onsubmit="return false;">
|
| 192 |
-
<!-- Input and Styling sections -->
|
| 193 |
<fieldset><legend>1. Load Content</legend><div id="info-box" class="info"></div><textarea id="markdown-text-input" name="markdown_text" rows="8"></textarea><div style="margin-top: 10px; display: flex; align-items: center; gap: 10px;"><label for="markdown-file-input">Or upload a file:</label><input type="file" id="markdown-file-input" name="markdown_file" accept=".md,.txt,text/markdown"></div><div style="margin-top: 15px;"><button type="button" id="load-btn" class="action-btn">Load & Analyze</button></div></fieldset>
|
| 194 |
<fieldset id="components-fieldset" style="display:none;"><legend>2. Select Components</legend><div class="selection-controls"><button type="button" onclick="toggleAllComponents(true)">Select All</button><button type="button" onclick="toggleAllComponents(false)">Deselect All</button></div><div id="components-container" class="component-grid"></div></fieldset>
|
| 195 |
<fieldset><legend>3. Configure Styles</legend><div class="style-grid"><div><label>Font Family:</label><select id="font_family"><optgroup label="Sans-Serif"><option value="'Arial', sans-serif">Arial</option><option value="'Roboto', sans-serif">Roboto</option></optgroup><optgroup label="Serif"><option value="'Times New Roman', serif">Times New Roman</option><option value="'Georgia', serif">Georgia</option></optgroup></select></div><div><label>Font Size (px):</label><input type="number" id="font_size" value="16"></div><div><label>Highlight Theme:</label><select id="highlight_theme"><option value="none">None</option>{% for style in highlight_styles %}<option value="{{ style }}" {% if style == 'default' %}selected{% endif %}>{{ style }}</option>{% endfor %}</select></div><div><label>Text Color:</label><input type="color" id="text_color" value="#333333"></div><div><label>Background Color:</label><input type="color" id="background_color" value="#ffffff"></div><div><label>Code Padding (px):</label><input type="number" id="code_padding" value="15"></div></div><div><input type="checkbox" id="include_fontawesome"><label for="include_fontawesome">Include Font Awesome</label></div><div><label for="custom_css">Custom CSS:</label><textarea id="custom_css" rows="3"></textarea></div></fieldset>
|
| 196 |
<div class="main-actions"><button type="button" id="generate-btn" class="generate-btn">Generate Preview</button></div>
|
| 197 |
</form>
|
| 198 |
-
|
| 199 |
<div id="error-box" class="error"></div>
|
| 200 |
-
|
| 201 |
<div id="preview-section" style="display:none;">
|
| 202 |
<h2>Preview</h2>
|
| 203 |
<div class="preview-header">
|
|
@@ -212,8 +202,6 @@ def index():
|
|
| 212 |
<div id="png-preview-container" class="preview-container"></div>
|
| 213 |
</div>
|
| 214 |
<script>
|
| 215 |
-
// --- All JavaScript is unchanged from the previous correct version ---
|
| 216 |
-
// It correctly gathers style info without modifying the parent page.
|
| 217 |
const loadBtn = document.getElementById('load-btn'), generateBtn = document.getElementById('generate-btn'),
|
| 218 |
downloadHtmlBtn = document.getElementById('download-html-btn'), downloadPngBtn = document.getElementById('download-png-btn'),
|
| 219 |
markdownTextInput = document.getElementById('markdown-text-input'), markdownFileInput = document.getElementById('markdown-file-input'),
|
|
@@ -243,7 +231,6 @@ def index():
|
|
| 243 |
include_fontawesome: document.getElementById('include_fontawesome').checked,
|
| 244 |
};
|
| 245 |
}
|
| 246 |
-
loadBtn.addEventListener('click', async () => { /* Logic unchanged */ });
|
| 247 |
generateBtn.addEventListener('click', async () => {
|
| 248 |
generateBtn.textContent = 'Generating...'; generateBtn.disabled = true; errorBox.style.display = 'none';
|
| 249 |
const payload = buildPayload();
|
|
@@ -303,6 +290,4 @@ def index():
|
|
| 303 |
""", highlight_styles=highlight_styles)
|
| 304 |
|
| 305 |
if __name__ == "__main__":
|
| 306 |
-
# Ensure you have installed the required libraries:
|
| 307 |
-
# pip install Flask markdown imgkit pygments
|
| 308 |
app.run(host="0.0.0.0", port=7860)
|
|
|
|
| 13 |
|
| 14 |
app = Flask(__name__)
|
| 15 |
|
| 16 |
+
# Corrected line to use the universally writable /tmp directory
|
| 17 |
+
TEMP_DIR = "/tmp/markdown_temp"
|
| 18 |
os.makedirs(TEMP_DIR, exist_ok=True)
|
| 19 |
|
|
|
|
| 20 |
def parse_repo2markdown(text):
|
| 21 |
components = []
|
| 22 |
pattern = re.compile(r'### File: (.*?)\n([\s\S]*?)(?=\n### File:|\Z)', re.MULTILINE)
|
|
|
|
| 55 |
components.append({'type': 'version', 'filename': parts[i].replace('##', '').strip(), 'content': parts[i+1].strip()})
|
| 56 |
return components
|
| 57 |
|
|
|
|
| 58 |
@app.route('/parse', methods=['POST'])
|
| 59 |
def parse_endpoint():
|
| 60 |
text = request.form.get('markdown_text', '')
|
|
|
|
| 75 |
except Exception as e:
|
| 76 |
return jsonify({'error': f'Failed to parse: {e}'}), 500
|
| 77 |
|
|
|
|
| 78 |
def build_full_html(markdown_text, styles, include_fontawesome):
|
| 79 |
wrapper_id = "#output-wrapper"
|
| 80 |
font_family = styles.get('font_family', "'Arial', sans-serif")
|
|
|
|
| 94 |
font-family: {font_family}; font-size: {styles.get('font_size', '16')}px;
|
| 95 |
color: {styles.get('text_color', '#333')}; background-color: {styles.get('background_color', '#fff')};
|
| 96 |
}}
|
|
|
|
|
|
|
| 97 |
{wrapper_id} table {{ border-collapse: collapse; width: 100%; }}
|
| 98 |
{wrapper_id} th, {wrapper_id} td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
|
| 99 |
{wrapper_id} th {{ background-color: #f2f2f2; }}
|
|
|
|
| 118 |
|
| 119 |
return full_html
|
| 120 |
|
|
|
|
| 121 |
@app.route('/convert', methods=['POST'])
|
| 122 |
def convert_endpoint():
|
| 123 |
data = request.json
|
|
|
|
| 127 |
styles=data.get('styles', {}),
|
| 128 |
include_fontawesome=data.get('include_fontawesome', False)
|
| 129 |
)
|
|
|
|
| 130 |
options = {"quiet": "", 'encoding': "UTF-8", "--no-cache": ""}
|
| 131 |
|
| 132 |
if data.get('download', False):
|
|
|
|
| 144 |
traceback.print_exc()
|
| 145 |
return jsonify({'error': f'Failed to convert content: {str(e)}'}), 500
|
| 146 |
|
|
|
|
| 147 |
@app.route('/')
|
| 148 |
def index():
|
| 149 |
highlight_styles = sorted(list(get_all_styles()))
|
|
|
|
| 175 |
.component-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px; }
|
| 176 |
.component-container { border: 1px solid #e0e0e0; border-radius: 5px; background: #fafafa; }
|
| 177 |
.component-header { background: #f1f1f1; padding: 8px 12px; border-bottom: 1px solid #e0e0e0; display: flex; align-items: center; gap: 10px; }
|
| 178 |
+
.component-content textarea { height: 150px; }
|
| 179 |
.selection-controls { margin: 15px 0; display: flex; gap: 10px; }
|
| 180 |
</style>
|
| 181 |
</head>
|
| 182 |
<body>
|
| 183 |
<h1>Intelligent Markdown Converter</h1>
|
| 184 |
<form id="main-form" onsubmit="return false;">
|
|
|
|
| 185 |
<fieldset><legend>1. Load Content</legend><div id="info-box" class="info"></div><textarea id="markdown-text-input" name="markdown_text" rows="8"></textarea><div style="margin-top: 10px; display: flex; align-items: center; gap: 10px;"><label for="markdown-file-input">Or upload a file:</label><input type="file" id="markdown-file-input" name="markdown_file" accept=".md,.txt,text/markdown"></div><div style="margin-top: 15px;"><button type="button" id="load-btn" class="action-btn">Load & Analyze</button></div></fieldset>
|
| 186 |
<fieldset id="components-fieldset" style="display:none;"><legend>2. Select Components</legend><div class="selection-controls"><button type="button" onclick="toggleAllComponents(true)">Select All</button><button type="button" onclick="toggleAllComponents(false)">Deselect All</button></div><div id="components-container" class="component-grid"></div></fieldset>
|
| 187 |
<fieldset><legend>3. Configure Styles</legend><div class="style-grid"><div><label>Font Family:</label><select id="font_family"><optgroup label="Sans-Serif"><option value="'Arial', sans-serif">Arial</option><option value="'Roboto', sans-serif">Roboto</option></optgroup><optgroup label="Serif"><option value="'Times New Roman', serif">Times New Roman</option><option value="'Georgia', serif">Georgia</option></optgroup></select></div><div><label>Font Size (px):</label><input type="number" id="font_size" value="16"></div><div><label>Highlight Theme:</label><select id="highlight_theme"><option value="none">None</option>{% for style in highlight_styles %}<option value="{{ style }}" {% if style == 'default' %}selected{% endif %}>{{ style }}</option>{% endfor %}</select></div><div><label>Text Color:</label><input type="color" id="text_color" value="#333333"></div><div><label>Background Color:</label><input type="color" id="background_color" value="#ffffff"></div><div><label>Code Padding (px):</label><input type="number" id="code_padding" value="15"></div></div><div><input type="checkbox" id="include_fontawesome"><label for="include_fontawesome">Include Font Awesome</label></div><div><label for="custom_css">Custom CSS:</label><textarea id="custom_css" rows="3"></textarea></div></fieldset>
|
| 188 |
<div class="main-actions"><button type="button" id="generate-btn" class="generate-btn">Generate Preview</button></div>
|
| 189 |
</form>
|
|
|
|
| 190 |
<div id="error-box" class="error"></div>
|
|
|
|
| 191 |
<div id="preview-section" style="display:none;">
|
| 192 |
<h2>Preview</h2>
|
| 193 |
<div class="preview-header">
|
|
|
|
| 202 |
<div id="png-preview-container" class="preview-container"></div>
|
| 203 |
</div>
|
| 204 |
<script>
|
|
|
|
|
|
|
| 205 |
const loadBtn = document.getElementById('load-btn'), generateBtn = document.getElementById('generate-btn'),
|
| 206 |
downloadHtmlBtn = document.getElementById('download-html-btn'), downloadPngBtn = document.getElementById('download-png-btn'),
|
| 207 |
markdownTextInput = document.getElementById('markdown-text-input'), markdownFileInput = document.getElementById('markdown-file-input'),
|
|
|
|
| 231 |
include_fontawesome: document.getElementById('include_fontawesome').checked,
|
| 232 |
};
|
| 233 |
}
|
|
|
|
| 234 |
generateBtn.addEventListener('click', async () => {
|
| 235 |
generateBtn.textContent = 'Generating...'; generateBtn.disabled = true; errorBox.style.display = 'none';
|
| 236 |
const payload = buildPayload();
|
|
|
|
| 290 |
""", highlight_styles=highlight_styles)
|
| 291 |
|
| 292 |
if __name__ == "__main__":
|
|
|
|
|
|
|
| 293 |
app.run(host="0.0.0.0", port=7860)
|