import asyncio
import markdown
from pyppeteer import launch
async def markdown_to_image(markdown_text: str, output_path: str, browser=None):
"""将 Markdown 转换为 HTML 并使用 Puppeteer 截图。"""
try:
# 将 Markdown 转换为 HTML
html = markdown.markdown(markdown_text)
# 使用传入的浏览器实例或创建新的
should_close_browser = False
if browser is None:
browser = await launch(headless=True, args=['--no-sandbox', '--disable-setuid-sandbox'])
should_close_browser = True
page = await browser.newPage()
# 设置页面样式,使内容更美观
await page.setContent(f"""
{html}
""")
# 等待内容渲染完成
await asyncio.sleep(0.5)
# 获取内容尺寸并设置视口
dimensions = await page.evaluate('''() => {
const container = document.querySelector('.container');
return {
width: container.offsetWidth + 60, // 加上 body 的 padding
height: container.offsetHeight + 60
}
}''')
# 设置视口大小
await page.setViewport({
'width': dimensions['width'],
'height': dimensions['height'],
'deviceScaleFactor': 2 # 提高图片清晰度
})
# 截图,使用透明背景
await page.screenshot({
'path': output_path,
'omitBackground': True, # 透明背景
'clip': {
'x': 0,
'y': 0,
'width': dimensions['width'],
'height': dimensions['height']
}
})
# 关闭页面
await page.close()
# 如果是我们创建的浏览器实例,则关闭它
if should_close_browser:
await browser.close()
except Exception as e:
# 确保资源被释放
if 'page' in locals() and page is not None:
await page.close()
if should_close_browser and 'browser' in locals() and browser is not None:
await browser.close()
raise # 重新抛出异常以便上层处理