burtenshaw commited on
Commit
a947fe6
·
1 Parent(s): 76563a1

switch to bs pdf command not decktape

Browse files
Files changed (1) hide show
  1. app/app.py +34 -86
app/app.py CHANGED
@@ -136,115 +136,63 @@ def reconstruct_presentation_markdown(slides_data):
136
 
137
 
138
  def generate_pdf_from_markdown(markdown_file_path, output_pdf_path):
139
- """Generates a PDF from a Markdown file using bs export + decktape."""
140
- logger.info(f"Attempting PDF gen: {markdown_file_path} -> {output_pdf_path}")
 
 
141
  working_dir = os.path.dirname(markdown_file_path)
142
  markdown_filename = os.path.basename(markdown_file_path)
143
- html_output_dir_name = "bs_html_output"
144
- html_output_dir_abs = os.path.join(working_dir, html_output_dir_name)
145
- expected_html_filename = os.path.splitext(markdown_filename)[0] + ".html"
146
- generated_html_path_abs = os.path.join(html_output_dir_abs, expected_html_filename)
147
- pdf_gen_success = False # Flag to track success
148
-
149
- # ---- Step 1: Generate HTML using bs export ----
150
- try:
151
- Path(html_output_dir_abs).mkdir(parents=True, exist_ok=True)
152
- export_command = ["bs", "export", markdown_filename, "-o", html_output_dir_name]
153
- logger.info(f"Running: {' '.join(export_command)} in CWD: {working_dir}")
154
- export_result = subprocess.run(
155
- export_command,
156
- cwd=working_dir,
157
- capture_output=True,
158
- text=True,
159
- check=True,
160
- timeout=60,
161
- )
162
- logger.info("Backslide (bs export) OK.")
163
- logger.debug(f"bs export stdout:\n{export_result.stdout}")
164
- logger.debug(f"bs export stderr:\n{export_result.stderr}")
165
 
166
- if not os.path.exists(generated_html_path_abs):
167
- logger.error(f"Expected HTML not found: {generated_html_path_abs}")
168
- try:
169
- files_in_dir = os.listdir(html_output_dir_abs)
170
- logger.error(f"Files in {html_output_dir_abs}: {files_in_dir}")
171
- except FileNotFoundError:
172
- logger.error(
173
- f"HTML output directory {html_output_dir_abs} not found after bs run."
174
- )
175
- raise FileNotFoundError(
176
- f"Generated HTML not found: {generated_html_path_abs}"
177
- )
178
 
179
- except FileNotFoundError:
180
- logger.error(
181
- "`bs` command not found. Install backslide (`npm install -g backslide`)."
182
- )
183
- raise gr.Error("HTML generation tool (backslide/bs) not found.")
184
- except subprocess.CalledProcessError as e:
185
- logger.error(f"Backslide (bs export) failed (code {e.returncode}).")
186
- logger.error(f"bs stderr:\n{e.stderr}")
187
- raise gr.Error(f"Backslide HTML failed: {e.stderr[:500]}...")
188
- except subprocess.TimeoutExpired:
189
- logger.error("Backslide (bs export) timed out.")
190
- raise gr.Error("HTML generation timed out (backslide).")
191
- except Exception as e:
192
- logger.error(f"Unexpected error during bs export: {e}", exc_info=True)
193
- raise gr.Error(f"Unexpected error during HTML generation: {e}")
194
-
195
- # ---- Step 2: Generate PDF from HTML using decktape ----
196
  try:
197
- Path(output_pdf_path).parent.mkdir(parents=True, exist_ok=True)
198
- html_file_url = Path(generated_html_path_abs).as_uri()
199
- decktape_command = ["decktape", html_file_url, str(output_pdf_path)]
200
- logger.info(f"Running PDF conversion: {' '.join(decktape_command)}")
201
- decktape_result = subprocess.run(
202
- decktape_command,
203
  capture_output=True,
204
  text=True,
205
  check=True,
206
- timeout=120,
207
  )
208
- logger.info("Decktape command executed successfully.")
209
- logger.debug(f"decktape stdout:\n{decktape_result.stdout}")
210
- logger.debug(f"decktape stderr:\n{decktape_result.stderr}")
211
 
212
  if os.path.exists(output_pdf_path):
213
  logger.info(f"PDF generated successfully: {output_pdf_path}")
214
- pdf_gen_success = True # Mark as success
215
  return output_pdf_path
216
  else:
217
- logger.error("Decktape command finished but output PDF not found.")
218
- return None
219
 
220
  except FileNotFoundError:
221
  logger.error(
222
- "`decktape` command not found. Install decktape (`npm install -g decktape`)."
 
 
 
 
223
  )
224
- raise gr.Error("PDF generation tool (decktape) not found.")
225
  except subprocess.CalledProcessError as e:
226
- logger.error(f"Decktape command failed (code {e.returncode}).")
227
- logger.error(f"decktape stderr:\n{e.stderr}")
228
- raise gr.Error(f"Decktape PDF failed: {e.stderr[:500]}...")
 
229
  except subprocess.TimeoutExpired:
230
- logger.error("Decktape command timed out.")
231
- raise gr.Error("PDF generation timed out (decktape).")
232
  except Exception as e:
233
- logger.error(
234
- f"Unexpected error during decktape PDF generation: {e}", exc_info=True
235
- )
236
  raise gr.Error(f"Unexpected error during PDF generation: {e}")
237
  finally:
238
- # --- Cleanup HTML output directory ---
239
- if os.path.exists(html_output_dir_abs):
240
- try:
241
- shutil.rmtree(html_output_dir_abs)
242
- logger.info(f"Cleaned up HTML temp dir: {html_output_dir_abs}")
243
- except Exception as cleanup_e:
244
- logger.warning(
245
- f"Could not cleanup HTML dir {html_output_dir_abs}: {cleanup_e}"
246
- )
247
- # Log final status
248
  if pdf_gen_success:
249
  logger.info(f"PDF generation process completed for {output_pdf_path}.")
250
  else:
 
136
 
137
 
138
  def generate_pdf_from_markdown(markdown_file_path, output_pdf_path):
139
+ """Generates a PDF from a Markdown file using bs pdf."""
140
+ logger.info(
141
+ f"Attempting PDF gen using bs pdf: {markdown_file_path} -> {output_pdf_path}"
142
+ )
143
  working_dir = os.path.dirname(markdown_file_path)
144
  markdown_filename = os.path.basename(markdown_file_path)
145
+ # Ensure output directory exists (bs pdf might not create it)
146
+ Path(output_pdf_path).parent.mkdir(parents=True, exist_ok=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
+ pdf_gen_success = False
 
 
 
 
 
 
 
 
 
 
 
149
 
150
+ # ---- Run bs pdf ----
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  try:
152
+ # Use the absolute path for the output file
153
+ pdf_command = ["bs", "pdf", markdown_filename, "-o", str(output_pdf_path)]
154
+ logger.info(f"Running: {' '.join(pdf_command)} in CWD: {working_dir}")
155
+ pdf_result = subprocess.run(
156
+ pdf_command,
157
+ cwd=working_dir,
158
  capture_output=True,
159
  text=True,
160
  check=True,
161
+ timeout=180, # Combined timeout (adjust as needed)
162
  )
163
+ logger.info("bs pdf command executed successfully.")
164
+ logger.debug(f"bs pdf stdout:\n{pdf_result.stdout}")
165
+ logger.debug(f"bs pdf stderr:\n{pdf_result.stderr}")
166
 
167
  if os.path.exists(output_pdf_path):
168
  logger.info(f"PDF generated successfully: {output_pdf_path}")
169
+ pdf_gen_success = True
170
  return output_pdf_path
171
  else:
172
+ logger.error("bs pdf command finished but output PDF not found.")
173
+ raise gr.Error("bs pdf finished but failed to create the PDF file.")
174
 
175
  except FileNotFoundError:
176
  logger.error(
177
+ "`bs` command not found. Install backslide (`npm install -g backslide`) "
178
+ "and ensure its dependencies (like decktape) are met."
179
+ )
180
+ raise gr.Error(
181
+ "PDF generation tool (backslide/bs) not found or not configured correctly."
182
  )
 
183
  except subprocess.CalledProcessError as e:
184
+ logger.error(f"Backslide (bs pdf) failed (code {e.returncode}).")
185
+ # stderr from bs pdf might include decktape errors if it failed
186
+ logger.error(f"bs pdf stderr:\n{e.stderr}")
187
+ raise gr.Error(f"Backslide PDF generation failed: {e.stderr[:500]}...")
188
  except subprocess.TimeoutExpired:
189
+ logger.error("Backslide (bs pdf) timed out.")
190
+ raise gr.Error("PDF generation timed out (backslide/bs pdf).")
191
  except Exception as e:
192
+ logger.error(f"Unexpected error during bs pdf: {e}", exc_info=True)
 
 
193
  raise gr.Error(f"Unexpected error during PDF generation: {e}")
194
  finally:
195
+ # No intermediate HTML cleanup needed anymore
 
 
 
 
 
 
 
 
 
196
  if pdf_gen_success:
197
  logger.info(f"PDF generation process completed for {output_pdf_path}.")
198
  else: