Release v0.51.278 — Release IT (stage-p3g — repair inline PDF preview #3652) (#3684)
Some checks failed
Release & Docker / release (push) Has been cancelled
Some checks failed
Release & Docker / release (push) Has been cancelled
* fix(ui): repair inline PDF preview (blob module loader + CSP worker-src) (#3652, #3649) Co-authored-by: sky <example@email.com> * docs(changelog): v0.51.278 — Release IT (stage-p3g, #3652 only); widen CSP test window --------- Co-authored-by: nesquena-hermes <[email protected]> Co-authored-by: sky <example@email.com>
This commit is contained in:
@@ -3,6 +3,11 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.51.278] — 2026-06-05 — Release IT (stage-p3g — repair inline PDF preview)
|
||||
|
||||
### Fixed
|
||||
- **Inline PDF preview in chat now renders again.** The PDF.js loader previously created a `<script>` with both `src` and `textContent` set (the latter is ignored when `src` is present), so PDF.js never initialized and the preview hung on the spinner before degrading to a download link. It now loads PDF.js via a blob module script that sets the worker source, passes `isEvalSupported:false` to harden the parser, and revokes the blob URL on load. CSP gains `blob:` in `script-src` and a scoped `worker-src blob: 'self' https://cdn.jsdelivr.net` to permit the worker. (#3652, @xx77yy; closes #3649)
|
||||
|
||||
## [v0.51.277] — 2026-06-05 — Release IS (stage-p3f — preserve context-window in usage indicator)
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -57,7 +57,8 @@ def _security_headers(handler):
|
||||
handler.send_header(
|
||||
'Content-Security-Policy',
|
||||
"default-src 'self' https://*.cloudflareaccess.com; "
|
||||
"script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://static.cloudflareinsights.com; "
|
||||
"script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://static.cloudflareinsights.com blob:; "
|
||||
"worker-src blob: 'self' https://cdn.jsdelivr.net; "
|
||||
"style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com; "
|
||||
"img-src 'self' data: https: blob:; font-src 'self' data: https://fonts.gstatic.com; connect-src 'self' https://cdn.jsdelivr.net; "
|
||||
"manifest-src 'self' https://*.cloudflareaccess.com; "
|
||||
|
||||
16
static/ui.js
16
static/ui.js
@@ -8515,7 +8515,7 @@ function loadPdfInline(container){
|
||||
el.outerHTML=`<div class="pdf-preview-fallback"><a class="msg-media-link" href="api/media?path=${encodeURIComponent(path)}&download=1" download="${esc(fname)}">📎 ${esc(fname)}</a><br><span style="color:var(--muted);font-size:12px">${t('pdf_too_large')}</span></div>`;
|
||||
return;
|
||||
}
|
||||
return pdfjsLib.getDocument({data:buf}).promise;
|
||||
return pdfjsLib.getDocument({data:buf, isEvalSupported:false}).promise;
|
||||
})
|
||||
.then(pdf=>{
|
||||
if(!pdf) return;
|
||||
@@ -8548,16 +8548,14 @@ function loadPdfInline(container){
|
||||
loadPdf(window._pdfjsLib);
|
||||
} else if(!_pdfjsLoading){
|
||||
_pdfjsLoading=true;
|
||||
const _pdfSrc='https://cdn.jsdelivr.net/npm/pdfjs-dist@4.9.155/build/pdf.min.mjs';
|
||||
const _pdfWorker='https://cdn.jsdelivr.net/npm/pdfjs-dist@4.9.155/build/pdf.worker.min.mjs';
|
||||
const _pdfBlob=new Blob([`import*as p from'${_pdfSrc}';p.GlobalWorkerOptions.workerSrc='${_pdfWorker}';window._pdfjsLib=p;window._pdfjsReady=true;window.dispatchEvent(new Event('pdfjs-ready'));`],{type:'application/javascript'});
|
||||
const s=document.createElement('script');
|
||||
s.src='https://cdn.jsdelivr.net/npm/pdfjs-dist@4.9.155/build/pdf.min.mjs';
|
||||
s.type='module';
|
||||
s.textContent=`
|
||||
import * as pdfjsLib from '${s.src}';
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc='https://cdn.jsdelivr.net/npm/pdfjs-dist@4.9.155/build/pdf.worker.min.mjs';
|
||||
window._pdfjsLib=pdfjsLib;
|
||||
window._pdfjsReady=true;
|
||||
window.dispatchEvent(new Event('pdfjs-ready'));
|
||||
`;
|
||||
const _pdfBlobUrl=URL.createObjectURL(_pdfBlob);
|
||||
s.src=_pdfBlobUrl;
|
||||
s.onload=()=>URL.revokeObjectURL(_pdfBlobUrl);
|
||||
document.head.appendChild(s);
|
||||
window.addEventListener('pdfjs-ready',()=>{ _pdfjsReady=true; loadPdf(window._pdfjsLib); },{once:true});
|
||||
setTimeout(()=>{
|
||||
|
||||
@@ -18,8 +18,11 @@ class TestManifestSrcCSP:
|
||||
text = (ROOT / "api" / "helpers.py").read_text(encoding="utf-8")
|
||||
start = text.find("Content-Security-Policy")
|
||||
assert start != -1, "Content-Security-Policy not found in helpers.py"
|
||||
# Grab the full CSP string (up to the closing paren of send_header)
|
||||
chunk = text[start:start + 600]
|
||||
# Grab the full CSP string (up to the closing paren of send_header).
|
||||
# Widened from 600 -> 1000 after the PDF-preview fix (#3652) added
|
||||
# `blob:` to script-src + a `worker-src` directive, pushing later
|
||||
# directives (form-action) past the old window.
|
||||
chunk = text[start:start + 1000]
|
||||
return chunk
|
||||
|
||||
def test_manifest_src_self_present(self):
|
||||
|
||||
Reference in New Issue
Block a user