Support non-Markdown files in public share and add raw download endpoint
This commit is contained in:
parent
7c4f2964eb
commit
ff06d89eda
@ -2836,7 +2836,11 @@ async def public_share_pdf_download(token: str):
|
|||||||
record_access(token)
|
record_access(token)
|
||||||
raw = redact_file_content(raw, str(file_path))
|
raw = redact_file_content(raw, str(file_path))
|
||||||
post = parse_markdown_file(raw)
|
post = parse_markdown_file(raw)
|
||||||
html = _render_markdown(post.content, share["vault"], file_path)
|
ext = file_path.suffix.lower()
|
||||||
|
if ext == ".md":
|
||||||
|
html = _render_markdown(post.content, share["vault"], file_path)
|
||||||
|
else:
|
||||||
|
html = f'<pre style="font-family:monospace;font-size:12px;line-height:1.6;white-space:pre-wrap">{html_mod.escape(raw)}</pre>'
|
||||||
title = post.metadata.get("title", file_path.stem)
|
title = post.metadata.get("title", file_path.stem)
|
||||||
pdf_html = build_pdf_html(html, str(title))
|
pdf_html = build_pdf_html(html, str(title))
|
||||||
pdf_bytes = generate_pdf(pdf_html, str(title))
|
pdf_bytes = generate_pdf(pdf_html, str(title))
|
||||||
@ -2844,6 +2848,23 @@ async def public_share_pdf_download(token: str):
|
|||||||
return Response(content=pdf_bytes, media_type="application/pdf", headers={"Content-Disposition": f'attachment; filename="{safe_name}.pdf"'})
|
return Response(content=pdf_bytes, media_type="application/pdf", headers={"Content-Disposition": f'attachment; filename="{safe_name}.pdf"'})
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/s/{token}/raw")
|
||||||
|
async def public_share_raw(token: str):
|
||||||
|
"""Download the raw (original) shared document."""
|
||||||
|
share = get_share_by_token(token)
|
||||||
|
if not share:
|
||||||
|
raise HTTPException(404, "Share not found or expired")
|
||||||
|
vault_data = get_vault_data(share["vault"])
|
||||||
|
if not vault_data:
|
||||||
|
raise HTTPException(404, "Vault not found")
|
||||||
|
vault_root = Path(vault_data["path"])
|
||||||
|
file_path = _resolve_safe_path(vault_root, share["path"])
|
||||||
|
if not file_path.exists():
|
||||||
|
raise HTTPException(404, "File not found")
|
||||||
|
record_access(token)
|
||||||
|
return FileResponse(path=str(file_path), filename=file_path.name, media_type="application/octet-stream")
|
||||||
|
|
||||||
|
|
||||||
@app.get("/s/{token}")
|
@app.get("/s/{token}")
|
||||||
async def public_share_view(token: str):
|
async def public_share_view(token: str):
|
||||||
"""Public share view — no authentication required."""
|
"""Public share view — no authentication required."""
|
||||||
@ -2864,10 +2885,19 @@ async def public_share_view(token: str):
|
|||||||
record_access(token)
|
record_access(token)
|
||||||
raw = redact_file_content(raw, str(file_path))
|
raw = redact_file_content(raw, str(file_path))
|
||||||
post = parse_markdown_file(raw)
|
post = parse_markdown_file(raw)
|
||||||
html = _render_markdown(post.content, share["vault"], file_path)
|
ext = file_path.suffix.lower()
|
||||||
|
|
||||||
|
if ext == ".md":
|
||||||
|
html = _render_markdown(post.content, share["vault"], file_path)
|
||||||
|
else:
|
||||||
|
escaped = html_mod.escape(raw)
|
||||||
|
html = f'<pre style="background:var(--bg-card);border:1px solid var(--border);border-radius:8px;padding:16px;overflow-x:auto;font-size:0.85rem;line-height:1.6"><code>{escaped}</code></pre>'
|
||||||
|
|
||||||
title = post.metadata.get("title", file_path.stem)
|
title = post.metadata.get("title", file_path.stem)
|
||||||
|
|
||||||
# Build frontmatter section HTML
|
# JSON-escape raw content for embedding in HTML
|
||||||
|
import json as _json
|
||||||
|
raw_json = _json.dumps(raw)
|
||||||
fm_html = ""
|
fm_html = ""
|
||||||
if post.metadata:
|
if post.metadata:
|
||||||
fm_items = []
|
fm_items = []
|
||||||
@ -2943,10 +2973,11 @@ body{{font-family:system-ui,-apple-system,sans-serif;background:var(--bg);color:
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="content" id="content">{fm_html}{html}</div>
|
<div class="content" id="content">{fm_html}{html}</div>
|
||||||
|
<script id="raw-content" type="text/plain" style="display:none">{raw_json}</script>
|
||||||
<script>
|
<script>
|
||||||
function toggleTheme(){{var t=document.documentElement;var isDark=t.dataset.theme==="dark";t.dataset.theme=isDark?"light":"dark";document.getElementById("theme-icon-dark").style.display=isDark?"none":"";document.getElementById("theme-icon-light").style.display=isDark?"":"none";localStorage.setItem("obsigate-share-theme",t.dataset.theme)}}
|
function toggleTheme(){{var t=document.documentElement;var isDark=t.dataset.theme==="dark";t.dataset.theme=isDark?"light":"dark";document.getElementById("theme-icon-dark").style.display=isDark?"none":"";document.getElementById("theme-icon-light").style.display=isDark?"":"none";localStorage.setItem("obsigate-share-theme",t.dataset.theme)}}
|
||||||
(function(){{var s=localStorage.getItem("obsigate-share-theme");if(!s)s="dark";document.documentElement.dataset.theme=s;var isDark=s==="dark";document.getElementById("theme-icon-dark").style.display=isDark?"":"none";document.getElementById("theme-icon-light").style.display=isDark?"none":""}})();
|
(function(){{var s=localStorage.getItem("obsigate-share-theme");if(!s)s="dark";document.documentElement.dataset.theme=s;var isDark=s==="dark";document.getElementById("theme-icon-dark").style.display=isDark?"":"none";document.getElementById("theme-icon-light").style.display=isDark?"none":""}})();
|
||||||
function exportMD(){{var t=document.getElementById("content").innerText;var b=new Blob([t],{{type:"text/markdown"}});var a=document.createElement("a");a.href=URL.createObjectURL(b);a.download="{title}.md";a.click()}}
|
function exportMD(){{var raw=JSON.parse(document.getElementById("raw-content").textContent);var b=new Blob([raw],{{type:"text/markdown"}});var a=document.createElement("a");a.href=URL.createObjectURL(b);a.download="{title}.md";a.click()}}
|
||||||
</script></body></html>""")
|
</script></body></html>""")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user