discovery-media-player 0.1.49 → 0.1.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -2
- package/server/browser.generated.js +1 -1
- package/server/handler.js +71 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "discovery-media-player",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.51",
|
|
4
4
|
"description": "Self-hosted document viewer: per-recipient tracked links, reading analytics, live presentation. The core knows nothing about the application hosting it — everything it borrows arrives through an injected context.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pdf-viewer",
|
|
@@ -61,7 +61,8 @@
|
|
|
61
61
|
"lint": "eslint bin context server src build",
|
|
62
62
|
"lint:fix": "eslint bin context server src build --fix",
|
|
63
63
|
"typecheck": "tsc --noEmit",
|
|
64
|
-
"prepublishOnly": "npm run build && npm test"
|
|
64
|
+
"prepublishOnly": "npm run build && npm test",
|
|
65
|
+
"test:e2e": "vitest run --config vitest.e2e.config.mjs"
|
|
65
66
|
},
|
|
66
67
|
"engines": {
|
|
67
68
|
"node": ">=22"
|
|
@@ -71,6 +72,7 @@
|
|
|
71
72
|
"esbuild": "^0.28.2",
|
|
72
73
|
"eslint": "^10.8.1",
|
|
73
74
|
"jsdom": "^30.0.1",
|
|
75
|
+
"playwright-core": "^1.62.1",
|
|
74
76
|
"typescript": "^5.5.4",
|
|
75
77
|
"typescript-eslint": "^8.46.4",
|
|
76
78
|
"vitest": "^4.1.10"
|
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
// Injecté par api/doc.js dans un <script nonce=…> de la visionneuse. Le code navigateur du
|
|
5
5
|
// player vit en modules TypeScript testés sous player/src/ — c'est ici qu'il atterrit.
|
|
6
6
|
"use strict";
|
|
7
|
-
module.exports = { PLAYER_BROWSER_JS: "\"use strict\";var Player=(()=>{var C=Object.defineProperty,Ue=Object.defineProperties,De=Object.getOwnPropertyDescriptor,We=Object.getOwnPropertyDescriptors,Ve=Object.getOwnPropertyNames,ye=Object.getOwnPropertySymbols;var Me=Object.prototype.hasOwnProperty,Fe=Object.prototype.propertyIsEnumerable;var ve=(e,n,t)=>n in e?C(e,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[n]=t,B=(e,n)=>{for(var t in n||(n={}))Me.call(n,t)&&ve(e,t,n[t]);if(ye)for(var t of ye(n))Fe.call(n,t)&&ve(e,t,n[t]);return e},xe=(e,n)=>Ue(e,We(n));var v=(e,n)=>{for(var t in n)C(e,t,{get:n[t],enumerable:!0})},ze=(e,n,t,r)=>{if(n&&typeof n==\"object\"||typeof n==\"function\")for(let o of Ve(n))!Me.call(e,o)&&o!==t&&C(e,o,{get:()=>n[o],enumerable:!(r=De(n,o))||r.enumerable});return e};var je=e=>ze(C({},\"__esModule\",{value:!0}),e);var zn={};v(zn,{bridge:()=>L,cadence:()=>N,chat:()=>H,live:()=>$,presentation:()=>U,presentationState:()=>W,tracking:()=>O,viewer:()=>D});var L={};v(L,{onHostMessage:()=>en,onPlayerMessage:()=>Je,parseHostMessage:()=>Te,parsePlayerMessage:()=>we,sendToHost:()=>qe,sendToPlayer:()=>Qe,toWire:()=>Y});var K=\"3dd-doc-\",Ge=/^[A-Za-z0-9_-]{1,64}$/,Be=[\"close\",\"share\",\"embed-ready\",\"present-left\",\"present-denied\"],Ke=[\"embed-denied\"],Ye=[\"present-invite\",\"present-handover\",\"present-switch\"],Ze=[\"handover-done\"];function Y(e){let n={type:K+e.type};return\"slug\"in e&&e.slug&&(n.slug=e.slug),\"reason\"in e&&e.reason&&(n.reason=String(e.reason).slice(0,40)),n}function _e(e,n,t){if(!e||typeof e!=\"object\")return null;let r=e.type;if(typeof r!=\"string\"||!r.startsWith(K))return null;let o=r.slice(K.length);if(n.includes(o))return{type:o};if(Ke.includes(o)){let a=e.reason;return{type:o,reason:/^[a-z-]{1,40}$/.test(String(a||\"\"))?String(a):\"unknown\"}}if(!t.includes(o))return null;let i=e.slug;return typeof i!=\"string\"||!Ge.test(i)?null:{type:o,slug:i}}function we(e){return _e(e,Be,Ye)}function Te(e){return _e(e,Ze,[])}function qe(e,n){try{let t=n||(typeof window!=\"undefined\"?window.parent:null);t&&t.postMessage(Y(e),\"*\")}catch(t){}}function Qe(e,n){var t;try{(t=e==null?void 0:e.contentWindow)==null||t.postMessage(Y(n),\"*\")}catch(r){}}function Xe(e,n){var r;if(!e)return!0;let t=(r=e.contentWindow)!=null?r:e;return n===t}function Je(e,n,t){let r=n||(typeof window!=\"undefined\"?window:null);if(!r)return()=>{};let o=i=>{if(!Xe(t,i.source))return;let a=we(i.data);a&&e(a)};return r.addEventListener(\"message\",o),()=>r.removeEventListener(\"message\",o)}function en(e,n){var i;let t=n||(typeof window!=\"undefined\"?window:null);if(!t)return()=>{};let r=(i=t.parent)!=null?i:null,o=a=>{if(!r||r===t||a.source!==r)return;let l=Te(a.data);l&&e(l)};return t.addEventListener(\"message\",o),()=>t.removeEventListener(\"message\",o)}var O={};v(O,{createTracker:()=>ln});var N={};v(N,{PRESENTER_ACTIONS_PER_HOUR:()=>X,PRESENT_CACHE_MS:()=>rn,PRESENT_QUOTA_MARGIN:()=>Ae,PRESENT_QUOTA_PER_HOUR:()=>on,PRESENT_READS_PER_HOUR:()=>Re,PRESENT_READ_BURST:()=>Ie,PRESENT_READ_COALESCE_MS:()=>Pe,PRESENT_RESYNC_MS:()=>Se,PRESENT_SIGNAL_BUDGET_PER_HOUR:()=>tn,PRESENT_WRITE_TIMEOUT_MS:()=>J,READERS_PER_EGRESS:()=>q,RESYNC_READS_PER_HOUR:()=>ke,SESSION_IDLE_MS:()=>Q,SESSION_INTERVAL_MS:()=>Z,SESSION_QUOTA_PER_HOUR:()=>nn,SESSION_WRITES_PER_HOUR:()=>Ee});var Z=12e3,Ee=Math.ceil(300),q=25,nn=Ee*q,Q=18e4,Se=25e3,ke=Math.ceil(36e5/Se),X=720,Re=ke+X,tn=X,Ie=20,J=1e4,Pe=400,rn=Pe,Ae=4,on=(Re+Ie)*q*Ae;var sn=[\"mousemove\",\"mousedown\",\"keydown\",\"wheel\",\"touchstart\",\"pointerdown\"];function an(){let e=typeof globalThis!=\"undefined\"?globalThis.crypto:void 0;if(e&&typeof e.randomUUID==\"function\")return e.randomUUID().replace(/-/g,\"\");if(e&&typeof e.getRandomValues==\"function\"){let n=e.getRandomValues(new Uint8Array(16));return Array.from(n,t=>t.toString(16).padStart(2,\"0\")).join(\"\")}return Math.random().toString(36).slice(2)+Date.now().toString(36)}function un(e,n){return t=>{try{let r=JSON.stringify(t),o=n.navigator;o&&typeof o.sendBeacon==\"function\"?o.sendBeacon(e,new Blob([r],{type:\"application/json\"})):n.fetch(e,{method:\"POST\",headers:{\"Content-Type\":\"application/json\"},body:r,keepalive:!0})}catch(r){}}}function ln(e={}){var ge,be;let n=e.win||(typeof window!=\"undefined\"?window:null),t=e.doc||n&&n.document,r=e.now||(()=>Date.now()),o=e.endpoint||\"/api/doc\",i=(ge=e.idleMs)!=null?ge:Q,a=(be=e.sessionEveryMs)!=null?be:12e3,l=e.slug||\"\",d=e.internal||null,m=e.sessionId||an(),p=e.send||un(o,n),c={},u=0,g=0,f=0,M=0,y=null,E=r(),S=!1,V=!1,P=[],He=()=>!!l||!!d,ce=s=>{if(He())try{p(s)}catch(b){}},F=()=>!!t&&t.visibilityState===\"visible\"&&!S,de=s=>{let b=r()-s,_=Math.max(0,E-s)+i;return Math.max(0,Math.min(b,_))},z=()=>{y!=null&&u>0&&(c[u]=(c[u]||0)+de(y)/1e3),y=F()?r():null},pe=()=>{z(),y=null},j=()=>{y==null&&F()&&(y=r())},G=()=>{let s=0;for(let b in c)s+=c[b];return y!=null&&(s+=de(y)/1e3),Math.round(s)},fe=()=>{let s={};for(let b in c)s[b]=Math.round(c[b]);return s},k=()=>{E=r(),S&&(S=!1,j())},me=(s,b)=>{d||ce({slug:l,event:s,page:b||g,maxPage:f,seconds:G(),sessionId:m})},A=()=>{z();let s={event:\"session\",sessionId:m,numPages:M,maxPage:f,totalSeconds:G(),pagesTime:fe()};d?(s.internal=!0,s.docId=d.docId,s.email=d.email,s.name=d.name,d.it&&(s.it=d.it)):s.slug=l,ce(s)},R=(s,b,_,he)=>{!s||typeof s.addEventListener!=\"function\"||(s.addEventListener(b,_,he),P.push(()=>{s.removeEventListener(b,_,he)}))};return{sessionId:m,totalSeconds:G,maxPage:()=>f,pageTimes:fe,start(){if(V)return;V=!0,me(\"open\",1),u=1,E=r(),y=F()?r():null,R(t,\"visibilitychange\",()=>{t.visibilityState===\"hidden\"?(pe(),A()):(k(),j())}),R(n,\"focus\",()=>{k(),j()});for(let _ of sn)R(n,_,k,{passive:!0});R(e.scrollElement,\"scroll\",k,{passive:!0}),R(n,\"beforeunload\",A);let s=n.setInterval(()=>{!S&&r()-E>i&&(S=!0,pe())},5e3),b=n.setInterval(A,a);P.push(()=>{n.clearInterval(s),n.clearInterval(b)})},setPage(s){!s||s===g||(E=r(),z(),u=s,g=s,s>f&&(f=s,me(\"page\",s)))},setPageCount(s){M=s||0},noteActivity:k,flush:A,stop(){for(;P.length;){let s=P.pop();try{s==null||s()}catch(b){}}V=!1}}}var $={};v($,{STORAGE_KEYS:()=>x,attendeeKey:()=>fn,authorToken:()=>mn,avatarHtml:()=>ee,canModerate:()=>oe,createBudget:()=>Mn,createFileEcritures:()=>xn,createScheduler:()=>yn,escapeHtml:()=>h,fetchBorne:()=>vn,flattenPresence:()=>cn,formatMessageBody:()=>ne,initials:()=>Ce,isMentioned:()=>gn,isMine:()=>w,presenceId:()=>_n,reactorId:()=>re,shouldNotify:()=>bn,unreadLabel:()=>hn});var x={attendeeKey:\"3dd-present-attkey\",authorToken:\"3dd-present-authtoken\",chatMuted:\"3dd-present-mute\",presenceId:\"3dd-present-uid\"};function h(e){return String(e==null?\"\":e).replace(/&/g,\"&\").replace(/</g,\"<\").replace(/>/g,\">\").replace(/\"/g,\""\")}function Ce(e){let n=(e||\"?\").trim().split(/\\s+/);return(((n[0]||\"\")[0]||\"?\")+((n[1]||\"\")[0]||\"\")).toUpperCase()}function ee(e,n){return e?`<img src=\"${h(e)}\" alt=\"\">`:h(Ce(n))}function ne(e){let n=h(e);return n=n.replace(/(https?:\\/\\/[^\\s<]+)/g,t=>`<a href=\"${t}\" target=_blank rel=noreferrer class=cm-link>${t}</a>`),n=n.replace(/(^|\\s)@([\\p{L}0-9_'.-]+)/gu,(t,r,o)=>`${r}<span class=cm-mention>@${o}</span>`),n}function cn(e){let n={},t=[];for(let r in e||{})for(let o of(e||{})[r]||[]){let i=String(o.uid||o.email||o.name||\"\").toLowerCase()||`_${r}_${t.length}`;n[i]?o.role===\"presenter\"&&(n[i]=o):(n[i]=o,t.push(i))}return t.map(r=>n[r])}function dn(e,n){try{return e?e.getItem(n):null}catch(t){return null}}function pn(e,n,t){try{e==null||e.setItem(n,t)}catch(r){}}function fn(e,n=\"anon\",t=te){try{if(!e)return`anon-${n}`;let r=e.getItem(x.attendeeKey);if(r)return r;let o=`anon-${t()}`;return e.setItem(x.attendeeKey,o),o}catch(r){return`anon-${n}`}}function te(){let e=typeof globalThis!=\"undefined\"?globalThis.crypto:void 0;if(e&&typeof e.randomUUID==\"function\")return e.randomUUID().replace(/-/g,\"\");if(e&&typeof e.getRandomValues==\"function\"){let n=e.getRandomValues(new Uint8Array(24));return Array.from(n,t=>t.toString(16).padStart(2,\"0\")).join(\"\")}try{console.warn(\"[player] crypto indisponible : jeton d'auteur affaibli\")}catch(n){}return Math.random().toString(36).slice(2)+Math.random().toString(36).slice(2)}function mn(e,n=te){let t=dn(e,x.authorToken);if(t)return t;let r=n();return pn(e,x.authorToken,r),r}function re(e){return String(e&&(e.email||e.name)||\"\").toLowerCase()}function w(e,n){return!e||!n?!1:e.author_email&&n.email?e.author_email===n.email:!e.author_email&&!n.email?e.author_name===n.name:!1}function oe(e){return!!(e&&e.role===\"presenter\")}function gn(e,n){if(!n||!n.name)return!1;let t=(n.name.split(/\\s+/)[0]||\"\").toLowerCase();return t?String(e&&e.body||\"\").toLowerCase().includes(`@${t}`)&&!w(e,n):!1}function bn(e){let{msg:n,me:t,historyLoaded:r,chatHidden:o}=e;return!r||!n||n.deleted||w(n,t)?!1:o}function hn(e){return!e||e<=0?\"\":e>9?\"9+\":String(e)}function yn(e,n={}){var g;let t=(g=n.minMs)!=null?g:300,r=n.now||(()=>Date.now()),o=n.setTimer||((f,M)=>setTimeout(f,M)),i=n.clearTimer||(f=>clearTimeout(f)),a=!1,l=!1,d=-1/0,m=null,p=!1;function c(){if(p||a){l=!0;return}let f=t-(r()-d);if(f>0){u(f);return}a=!0,l=!1,d=r();let M=!1;e(()=>{M||(M=!0,a=!1,l&&!p&&c())})}function u(f){p||m!==null||(m=o(()=>{m=null,c()},Math.max(0,f)))}return{signaler(){p||c()},maintenant(){p||(d=-1/0,c())},arreter(){p=!0,m!==null&&(i(m),m=null)}}}function vn(e,n,t=J,r={}){let o=r.fetch||(typeof fetch==\"function\"?fetch:void 0);if(!o)return Promise.reject(new Error(\"fetch indisponible\"));let i=r.setTimer||((u,g)=>setTimeout(u,g)),a=r.clearTimer||(u=>clearTimeout(u)),l=null;try{l=new AbortController}catch(u){}let d=l?xe(B({},n||{}),{signal:l.signal}):B({},n||{}),m=null,p=new Promise((u,g)=>{m=i(()=>{try{l==null||l.abort()}catch(f){}g(new Error(\"delai\"))},t)}),c=()=>{try{a(m)}catch(u){}};return Promise.race([o(e,d),p]).then(u=>(c(),u),u=>{throw c(),u})}function Mn(e){let n=e.now||(()=>Date.now()),t=Math.max(1,e.rafale),r=t,o=n();return{prendre(){let i=n();return r=Math.min(t,r+(i-o)*e.parHeure/36e5),o=i,r<1?!1:(r-=1,!0)},restants:()=>r}}function xn(e={}){var m;let n=(m=e.minMs)!=null?m:0,t=e.now||(()=>Date.now()),r=e.setTimer||((p,c)=>setTimeout(p,c)),o=new Map,i=!1,a=-1/0,l=!1;function d(){if(i||o.size===0)return;let p=n-(t()-a);if(p>0){if(l)return;l=!0,r(()=>{l=!1,d()},p);return}let c=o.keys().next().value,u=o.get(c);o.delete(c),i=!0,a=t(),Promise.resolve().then(u.tache).then(g=>u.regler(g),()=>u.regler(null)).then(()=>{i=!1,d()})}return{poser(p,c){return new Promise(u=>{let g=o.get(p);o.set(p,{tache:c,regler:f=>{g&&g.regler(f),u(f)}}),d()})},enAttente:()=>o.size}}function _n(e,n=te){try{if(e){let t=e.getItem(x.presenceId);if(t)return t;let r=`p-${n()}`;return e.setItem(x.presenceId,r),r}}catch(t){}return`p-${n()}`}var H={};v(H,{messageClassName:()=>Tn,renderActions:()=>Oe,renderAttachment:()=>Ne,renderMessage:()=>wn,renderReactions:()=>Le});function Le(e,n){let t=e&&e.reactions||{},r=re(n),o=\"\";for(let i in t){let a=t[i]||[];if(!a.length)continue;let l=a.indexOf(r)>=0;o+=`<button class=\"re-chip${l?\" on\":\"\"}\" data-e=\"${h(i)}\">${h(i)} ${a.length}</button>`}return o}function Ne(e){if(!e||!e.url)return\"\";let n=h(e.url);if(e.kind===\"image\")return`<a class=cm-att href=\"${n}\" target=_blank rel=noreferrer><img src=\"${n}\" alt=\"\" loading=lazy></a>`;let t=h(e.name||\"Document.pdf\");return`<a class=cm-att-pdf href=\"${n}\" target=_blank rel=noreferrer data-pdf=\"${n}\"><span class=cm-att-ph></span><span class=cm-pdflabel>${t}</span></a>`}function Oe(e,n){let t=w(e,n.me),r=`<button class=cm-react title=\"R\\xE9agir\">${n.reactIcon||\"\"}</button><button class=cm-reply title=\"R\\xE9pondre\">\\u21A9</button>`;return t&&(r+='<button class=cm-edit title=\"Modifier\">\\u270E</button>'),(t||oe(n.me))&&(r+='<button class=cm-del-btn title=\"Supprimer\">\\u{1F5D1}</button>'),r}function wn(e,n){if(e.deleted)return'<span class=a></span><span class=b><div class=\"txt cm-del\">Message supprim\\xE9</div></span>';let t=e.reply_to?`<div class=cm-q><b>${h(e.reply_name||\"\")}</b> ${h(e.reply_text||\"\")}</div>`:\"\",r=e.edited?\" <span class=cm-ed>(modifi\\xE9)</span>\":\"\",o=e.body?`<div class=txt>${ne(e.body)}${r}</div>`:\"\",i=e.is_presenter?\" <span class=tag>pr\\xE9sentateur</span>\":\"\";return`<span class=a>${ee(e.author_avatar,e.author_name)}</span><span class=b><div class=who><b>${h(e.author_name||\"Invit\\xE9\")}</b>${i}</div>`+t+o+Ne(e.attachment)+`<div class=cm-re>${Le(e,n.me)}</div></span><span class=cm-act>${Oe(e,n)}</span>`}function Tn(e,n,t){return\"cm\"+(w(e,n)?\" me\":\"\")+(e.deleted?\" isdel\":\"\")+(t?\" mentioned\":\"\")}var U={};v(U,{DEFAULT_CENTER:()=>ae,DEFAULT_ZOOM:()=>ue,MAP_TYPES:()=>I,cycleMapType:()=>En,initialMapContent:()=>kn,mapTypeLabel:()=>Sn,sanitizeContent:()=>le});var I=[\"roadmap\",\"satellite\",\"hybrid\"],ae=[46.6,2.5],ue=6;function T(e){let n=Number(e);return Number.isFinite(n)?n:null}function ie(e){if(!Array.isArray(e))return null;let n=T(e[0]),t=T(e[1]);return n!=null&&t!=null?[n,t]:null}var se=(e,n,t)=>Math.max(n,Math.min(t,e));function le(e){if(!e||typeof e!=\"object\")return null;let n=e;if(n.kind===\"pdf\"||n.kind==null)return null;if(n.kind===\"streetview\"){let t=ie(n.position);if(!t)return null;let r=n.pov&&typeof n.pov==\"object\"?n.pov:null,o=r?{heading:T(r.heading)||0,pitch:se(T(r.pitch)||0,-90,90)}:{heading:0,pitch:0};return{kind:\"streetview\",position:t,pov:o,zoom:se(T(n.zoom)||1,0,5)}}return n.kind!==\"map\"?null:{kind:\"map\",center:ie(n.center)||[...ae],zoom:se(Math.trunc(T(n.zoom)||ue),1,21),marker:ie(n.marker),mapType:I.includes(n.mapType)?n.mapType:null,label:String(n.label||\"\").slice(0,160)||null}}function En(e){let n=I.indexOf(e);return I[(n+1)%I.length]}function Sn(e){return e===\"roadmap\"?\"\\u{1F6F0} Satellite\":e===\"satellite\"?\"\\u{1F5FA} Hybride\":\"\\u{1F5FA} Plan\"}function kn(){return{kind:\"map\",center:[...ae],zoom:ue,marker:null,mapType:null,label:null}}var D={};v(D,{CURRENT_PAGE_MARGIN:()=>Ln,DEFAULT_ASPECT:()=>Pn,MAX_ZOOM:()=>In,MIN_PAGE_WIDTH:()=>An,MIN_ZOOM:()=>Rn,PRERENDER_MARGIN:()=>Cn,arrowState:()=>$n,averageColor:()=>Dn,clampPage:()=>$e,clampZoom:()=>Nn,fitWidth:()=>Un,isImageDocument:()=>Wn,progressPercent:()=>On});var Rn=.5,In=3,Pn=1.35,An=280,Cn=\"500px 0px\",Ln=\"-48% 0px -48% 0px\";function Nn(e){let n=Math.round((Number(e)||0)*10)/10;return Math.max(.5,Math.min(3,n))}function $e(e,n){return Math.max(1,Math.min(n||1,Number(e)||1))}function On(e,n){return n?Math.round($e(e,n)/n*100):0}function $n(e,n){return{prevDisabled:e<=1,nextDisabled:!!n&&e>=n}}var Hn=28;function Un(e){var a;let n=(a=e.zoom)!=null?a:1,t=Math.max(280,e.containerWidth||900)*n;if(!e.onePage)return t;let r=e.aspect||1.35,i=((e.containerHeight||600)-Hn-(e.overlap||0)-(e.reserve||0))/r;return i>120?Math.min(t,i):t}function Dn(e){let n=e.length/4;if(!n)return\"rgb(0,0,0)\";let t=0,r=0,o=0;for(let i=0;i<e.length;i+=4)t+=e[i],r+=e[i+1],o+=e[i+2];return`rgb(${Math.round(t/n)},${Math.round(r/n)},${Math.round(o/n)})`}function Wn(e,n){return/[.](png|jpe?g|webp|gif|avif)($|[?])/i.test(String(e||n||\"\"))}var W={};v(W,{presentationTransition:()=>Vn,switchDocUrl:()=>Fn});function Vn(e,n={}){if(!e)return[{kind:\"nothing\"}];if(e.active===!1)return[{kind:\"ended\"}];let t=le(e.content);if(t)return[{kind:\"show-map\",content:t}];let r=[{kind:\"leave-map\"}];return e.file_url&&e.file_url!==n.docUrl?(r.push({kind:\"switch-doc\",url:e.file_url,name:e.file_name||void 0,title:e.doc_title||void 0,updatedAt:e.updated_at||void 0}),r):(e.current_page&&r.push({kind:\"show-page\",page:e.current_page}),r)}function Fn(e,n){let t=encodeURIComponent(n||String(Date.now()));return`${e}${e.includes(\"?\")?\"&\":\"?\"}v=${t}`}return je(zn);})();", SOURCE_HASH: "0308434f00e5e31f" };
|
|
7
|
+
module.exports = { PLAYER_BROWSER_JS: "\"use strict\";var Player=(()=>{var C=Object.defineProperty,He=Object.defineProperties,De=Object.getOwnPropertyDescriptor,We=Object.getOwnPropertyDescriptors,Ve=Object.getOwnPropertyNames,he=Object.getOwnPropertySymbols;var Me=Object.prototype.hasOwnProperty,Be=Object.prototype.propertyIsEnumerable;var ve=(e,n,t)=>n in e?C(e,n,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[n]=t,G=(e,n)=>{for(var t in n||(n={}))Me.call(n,t)&&ve(e,t,n[t]);if(he)for(var t of he(n))Be.call(n,t)&&ve(e,t,n[t]);return e},we=(e,n)=>He(e,We(n));var v=(e,n)=>{for(var t in n)C(e,t,{get:n[t],enumerable:!0})},ze=(e,n,t,r)=>{if(n&&typeof n==\"object\"||typeof n==\"function\")for(let o of Ve(n))!Me.call(e,o)&&o!==t&&C(e,o,{get:()=>n[o],enumerable:!(r=De(n,o))||r.enumerable});return e};var Fe=e=>ze(C({},\"__esModule\",{value:!0}),e);var jn={};v(jn,{bridge:()=>L,cadence:()=>N,chat:()=>$,live:()=>U,presentation:()=>H,presentationState:()=>W,tracking:()=>O,viewer:()=>D});var L={};v(L,{onHostMessage:()=>en,onPlayerMessage:()=>Je,parseHostMessage:()=>Te,parsePlayerMessage:()=>_e,sendToHost:()=>qe,sendToPlayer:()=>Qe,toWire:()=>Y});var K=\"3dd-doc-\",je=/^[A-Za-z0-9_-]{1,64}$/,Ge=[\"close\",\"share\",\"embed-ready\",\"present-left\",\"present-denied\"],Ke=[\"embed-denied\"],Ye=[\"present-invite\",\"present-handover\",\"present-switch\"],Ze=[\"handover-done\"];function Y(e){let n={type:K+e.type};return\"slug\"in e&&e.slug&&(n.slug=e.slug),\"reason\"in e&&e.reason&&(n.reason=String(e.reason).slice(0,40)),n}function xe(e,n,t){if(!e||typeof e!=\"object\")return null;let r=e.type;if(typeof r!=\"string\"||!r.startsWith(K))return null;let o=r.slice(K.length);if(n.includes(o))return{type:o};if(Ke.includes(o)){let a=e.reason;return{type:o,reason:/^[a-z-]{1,40}$/.test(String(a||\"\"))?String(a):\"unknown\"}}if(!t.includes(o))return null;let s=e.slug;return typeof s!=\"string\"||!je.test(s)?null:{type:o,slug:s}}function _e(e){return xe(e,Ge,Ye)}function Te(e){return xe(e,Ze,[])}function qe(e,n){try{let t=n||(typeof window!=\"undefined\"?window.parent:null);t&&t.postMessage(Y(e),\"*\")}catch(t){}}function Qe(e,n){var t;try{(t=e==null?void 0:e.contentWindow)==null||t.postMessage(Y(n),\"*\")}catch(r){}}function Xe(e,n){var r;if(!e)return!0;let t=(r=e.contentWindow)!=null?r:e;return n===t}function Je(e,n,t){let r=n||(typeof window!=\"undefined\"?window:null);if(!r)return()=>{};let o=s=>{if(!Xe(t,s.source))return;let a=_e(s.data);a&&e(a)};return r.addEventListener(\"message\",o),()=>r.removeEventListener(\"message\",o)}function en(e,n){var s;let t=n||(typeof window!=\"undefined\"?window:null);if(!t)return()=>{};let r=(s=t.parent)!=null?s:null,o=a=>{if(!r||r===t||a.source!==r)return;let l=Te(a.data);l&&e(l)};return t.addEventListener(\"message\",o),()=>t.removeEventListener(\"message\",o)}var O={};v(O,{createTracker:()=>un});var N={};v(N,{PRESENTER_ACTIONS_PER_HOUR:()=>X,PRESENT_CACHE_MS:()=>rn,PRESENT_QUOTA_MARGIN:()=>Ae,PRESENT_QUOTA_PER_HOUR:()=>on,PRESENT_READS_PER_HOUR:()=>Re,PRESENT_READ_BURST:()=>Pe,PRESENT_READ_COALESCE_MS:()=>Ie,PRESENT_RESYNC_MS:()=>Se,PRESENT_SIGNAL_BUDGET_PER_HOUR:()=>tn,PRESENT_WRITE_TIMEOUT_MS:()=>J,READERS_PER_EGRESS:()=>q,RESYNC_READS_PER_HOUR:()=>ke,SESSION_IDLE_MS:()=>Q,SESSION_INTERVAL_MS:()=>Z,SESSION_QUOTA_PER_HOUR:()=>nn,SESSION_WRITES_PER_HOUR:()=>Ee});var Z=12e3,Ee=Math.ceil(300),q=25,nn=Ee*q,Q=18e4,Se=25e3,ke=Math.ceil(36e5/Se),X=720,Re=ke+X,tn=X,Pe=20,J=1e4,Ie=400,rn=Ie,Ae=4,on=(Re+Pe)*q*Ae;var sn=[\"mousemove\",\"mousedown\",\"keydown\",\"wheel\",\"touchstart\",\"pointerdown\"];function an(){let e=typeof globalThis!=\"undefined\"?globalThis.crypto:void 0;if(e&&typeof e.randomUUID==\"function\")return e.randomUUID().replace(/-/g,\"\");if(e&&typeof e.getRandomValues==\"function\"){let n=e.getRandomValues(new Uint8Array(16));return Array.from(n,t=>t.toString(16).padStart(2,\"0\")).join(\"\")}return Math.random().toString(36).slice(2)+Date.now().toString(36)}function ln(e,n){return t=>{try{let r=JSON.stringify(t),o=n.navigator;o&&typeof o.sendBeacon==\"function\"?o.sendBeacon(e,new Blob([r],{type:\"application/json\"})):n.fetch(e,{method:\"POST\",headers:{\"Content-Type\":\"application/json\"},body:r,keepalive:!0})}catch(r){}}}function un(e={}){var ge,be;let n=e.win||(typeof window!=\"undefined\"?window:null),t=e.doc||n&&n.document,r=e.now||(()=>Date.now()),o=e.endpoint||\"/api/doc\",s=(ge=e.idleMs)!=null?ge:Q,a=(be=e.sessionEveryMs)!=null?be:12e3,l=e.slug||\"\",d=e.internal||null,m=e.sessionId||an(),p=e.send||ln(o,n),c={},u=0,g=0,f=0,M=0,h=null,E=r(),S=!1,V=!1,I=[],$e=()=>!!l||!!d,ce=i=>{if($e())try{p(i)}catch(b){}},B=()=>!!t&&t.visibilityState===\"visible\"&&!S,de=i=>{let b=r()-i,x=Math.max(0,E-i)+s;return Math.max(0,Math.min(b,x))},z=()=>{h!=null&&u>0&&(c[u]=(c[u]||0)+de(h)/1e3),h=B()?r():null},pe=()=>{z(),h=null},F=()=>{h==null&&B()&&(h=r())},j=()=>{let i=0;for(let b in c)i+=c[b];return h!=null&&(i+=de(h)/1e3),Math.round(i)},fe=()=>{let i={};for(let b in c)i[b]=Math.round(c[b]);return i},k=()=>{E=r(),S&&(S=!1,F())},me=(i,b)=>{d||ce({slug:l,event:i,page:b||g,maxPage:f,seconds:j(),sessionId:m})},A=()=>{z();let i={event:\"session\",sessionId:m,numPages:M,maxPage:f,totalSeconds:j(),pagesTime:fe()};d?(i.internal=!0,i.docId=d.docId,i.email=d.email,i.name=d.name,d.it&&(i.it=d.it)):i.slug=l,ce(i)},R=(i,b,x,ye)=>{!i||typeof i.addEventListener!=\"function\"||(i.addEventListener(b,x,ye),I.push(()=>{i.removeEventListener(b,x,ye)}))};return{sessionId:m,totalSeconds:j,maxPage:()=>f,pageTimes:fe,start(){if(V)return;V=!0,me(\"open\",1),u=1,E=r(),h=B()?r():null,R(t,\"visibilitychange\",()=>{t.visibilityState===\"hidden\"?(pe(),A()):(k(),F())}),R(n,\"focus\",()=>{k(),F()});for(let x of sn)R(n,x,k,{passive:!0});R(e.scrollElement,\"scroll\",k,{passive:!0}),R(n,\"beforeunload\",A);let i=n.setInterval(()=>{!S&&r()-E>s&&(S=!0,pe())},5e3),b=n.setInterval(A,a);I.push(()=>{n.clearInterval(i),n.clearInterval(b)})},setPage(i){!i||i===g||(E=r(),z(),u=i,g=i,i>f&&(f=i,me(\"page\",i)))},setPageCount(i){M=i||0},noteActivity:k,flush:A,stop(){for(;I.length;){let i=I.pop();try{i==null||i()}catch(b){}}V=!1}}}var U={};v(U,{STORAGE_KEYS:()=>w,attendeeKey:()=>fn,authorToken:()=>mn,avatarHtml:()=>ee,canModerate:()=>oe,createBudget:()=>Mn,createFileEcritures:()=>wn,createScheduler:()=>hn,escapeHtml:()=>y,fetchBorne:()=>vn,flattenPresence:()=>cn,formatMessageBody:()=>ne,initials:()=>Ce,isMentioned:()=>gn,isMine:()=>_,presenceId:()=>xn,reactorId:()=>re,shouldNotify:()=>bn,unreadLabel:()=>yn});var w={attendeeKey:\"3dd-present-attkey\",authorToken:\"3dd-present-authtoken\",chatMuted:\"3dd-present-mute\",presenceId:\"3dd-present-uid\"};function y(e){return String(e==null?\"\":e).replace(/&/g,\"&\").replace(/</g,\"<\").replace(/>/g,\">\").replace(/\"/g,\""\")}function Ce(e){let n=(e||\"?\").trim().split(/\\s+/);return(((n[0]||\"\")[0]||\"?\")+((n[1]||\"\")[0]||\"\")).toUpperCase()}function ee(e,n){return e?`<img src=\"${y(e)}\" alt=\"\">`:y(Ce(n))}function ne(e){let n=y(e);return n=n.replace(/(https?:\\/\\/[^\\s<]+)/g,t=>`<a href=\"${t}\" target=_blank rel=noreferrer class=cm-link>${t}</a>`),n=n.replace(/(^|\\s)@([\\p{L}0-9_'.-]+)/gu,(t,r,o)=>`${r}<span class=cm-mention>@${o}</span>`),n}function cn(e){let n=new Map;for(let t in e||{})for(let r of(e||{})[t]||[]){let o=String(r.uid||r.email||r.name||\"\").toLowerCase()||`_${t}_${n.size}`;(!n.get(o)||r.role===\"presenter\")&&n.set(o,r)}return[...n.values()]}function dn(e,n){try{return e?e.getItem(n):null}catch(t){return null}}function pn(e,n,t){try{e==null||e.setItem(n,t)}catch(r){}}function fn(e,n=\"anon\",t=te){try{if(!e)return`anon-${n}`;let r=e.getItem(w.attendeeKey);if(r)return r;let o=`anon-${t()}`;return e.setItem(w.attendeeKey,o),o}catch(r){return`anon-${n}`}}function te(){let e=typeof globalThis!=\"undefined\"?globalThis.crypto:void 0;if(e&&typeof e.randomUUID==\"function\")return e.randomUUID().replace(/-/g,\"\");if(e&&typeof e.getRandomValues==\"function\"){let n=e.getRandomValues(new Uint8Array(24));return Array.from(n,t=>t.toString(16).padStart(2,\"0\")).join(\"\")}try{console.warn(\"[player] crypto indisponible : jeton d'auteur affaibli\")}catch(n){}return Math.random().toString(36).slice(2)+Math.random().toString(36).slice(2)}function mn(e,n=te){let t=dn(e,w.authorToken);if(t)return t;let r=n();return pn(e,w.authorToken,r),r}function re(e){return String(e&&(e.email||e.name)||\"\").toLowerCase()}function _(e,n){return!e||!n?!1:e.author_email&&n.email?e.author_email===n.email:!e.author_email&&!n.email?e.author_name===n.name:!1}function oe(e){return!!(e&&e.role===\"presenter\")}function gn(e,n){if(!n||!n.name)return!1;let t=(n.name.split(/\\s+/)[0]||\"\").toLowerCase();return t?String(e&&e.body||\"\").toLowerCase().includes(`@${t}`)&&!_(e,n):!1}function bn(e){let{msg:n,me:t,historyLoaded:r,chatHidden:o}=e;return!r||!n||n.deleted||_(n,t)?!1:o}function yn(e){return!e||e<=0?\"\":e>9?\"9+\":String(e)}function hn(e,n={}){var g;let t=(g=n.minMs)!=null?g:300,r=n.now||(()=>Date.now()),o=n.setTimer||((f,M)=>setTimeout(f,M)),s=n.clearTimer||(f=>clearTimeout(f)),a=!1,l=!1,d=-1/0,m=null,p=!1;function c(){if(p||a){l=!0;return}let f=t-(r()-d);if(f>0){u(f);return}a=!0,l=!1,d=r();let M=!1;e(()=>{M||(M=!0,a=!1,l&&!p&&c())})}function u(f){p||m!==null||(m=o(()=>{m=null,c()},Math.max(0,f)))}return{signaler(){p||c()},maintenant(){p||(d=-1/0,c())},arreter(){p=!0,m!==null&&(s(m),m=null)}}}function vn(e,n,t=J,r={}){let o=r.fetch||(typeof fetch==\"function\"?fetch:void 0);if(!o)return Promise.reject(new Error(\"fetch indisponible\"));let s=r.setTimer||((u,g)=>setTimeout(u,g)),a=r.clearTimer||(u=>clearTimeout(u)),l=null;try{l=new AbortController}catch(u){}let d=l?we(G({},n||{}),{signal:l.signal}):G({},n||{}),m=null,p=new Promise((u,g)=>{m=s(()=>{try{l==null||l.abort()}catch(f){}g(new Error(\"delai\"))},t)}),c=()=>{try{a(m)}catch(u){}};return Promise.race([o(e,d),p]).then(u=>(c(),u),u=>{throw c(),u})}function Mn(e){let n=e.now||(()=>Date.now()),t=Math.max(1,e.rafale),r=t,o=n();return{prendre(){let s=n();return r=Math.min(t,r+(s-o)*e.parHeure/36e5),o=s,r<1?!1:(r-=1,!0)},restants:()=>r}}function wn(e={}){var m;let n=(m=e.minMs)!=null?m:0,t=e.now||(()=>Date.now()),r=e.setTimer||((p,c)=>setTimeout(p,c)),o=new Map,s=!1,a=-1/0,l=!1;function d(){if(s||o.size===0)return;let p=n-(t()-a);if(p>0){if(l)return;l=!0,r(()=>{l=!1,d()},p);return}let c=o.keys().next().value,u=o.get(c);o.delete(c),s=!0,a=t(),Promise.resolve().then(u.tache).then(g=>u.regler(g),()=>u.regler(null)).then(()=>{s=!1,d()})}return{poser(p,c){return new Promise(u=>{let g=o.get(p);o.set(p,{tache:c,regler:f=>{g&&g.regler(f),u(f)}}),d()})},enAttente:()=>o.size}}function xn(e,n=te){try{if(e){let t=e.getItem(w.presenceId);if(t)return t;let r=`p-${n()}`;return e.setItem(w.presenceId,r),r}}catch(t){}return`p-${n()}`}var $={};v($,{messageClassName:()=>Tn,renderActions:()=>Oe,renderAttachment:()=>Ne,renderMessage:()=>_n,renderReactions:()=>Le});function Le(e,n){let t=e&&e.reactions||{},r=re(n),o=\"\";for(let s in t){let a=t[s]||[];if(!a.length)continue;let l=a.indexOf(r)>=0;o+=`<button class=\"re-chip${l?\" on\":\"\"}\" data-e=\"${y(s)}\">${y(s)} ${a.length}</button>`}return o}function Ne(e){if(!e||!e.url)return\"\";let n=y(e.url);if(e.kind===\"image\")return`<a class=cm-att href=\"${n}\" target=_blank rel=noreferrer><img src=\"${n}\" alt=\"\" loading=lazy></a>`;let t=y(e.name||\"Document.pdf\");return`<a class=cm-att-pdf href=\"${n}\" target=_blank rel=noreferrer data-pdf=\"${n}\"><span class=cm-att-ph></span><span class=cm-pdflabel>${t}</span></a>`}function Oe(e,n){let t=_(e,n.me),r=`<button class=cm-react title=\"R\\xE9agir\">${n.reactIcon||\"\"}</button><button class=cm-reply title=\"R\\xE9pondre\">\\u21A9</button>`;return t&&(r+='<button class=cm-edit title=\"Modifier\">\\u270E</button>'),(t||oe(n.me))&&(r+='<button class=cm-del-btn title=\"Supprimer\">\\u{1F5D1}</button>'),r}function _n(e,n){if(e.deleted)return'<span class=a></span><span class=b><div class=\"txt cm-del\">Message supprim\\xE9</div></span>';let t=e.reply_to?`<div class=cm-q><b>${y(e.reply_name||\"\")}</b> ${y(e.reply_text||\"\")}</div>`:\"\",r=e.edited?\" <span class=cm-ed>(modifi\\xE9)</span>\":\"\",o=e.body?`<div class=txt>${ne(e.body)}${r}</div>`:\"\",s=e.is_presenter?\" <span class=tag>pr\\xE9sentateur</span>\":\"\";return`<span class=a>${ee(e.author_avatar,e.author_name)}</span><span class=b><div class=who><b>${y(e.author_name||\"Invit\\xE9\")}</b>${s}</div>`+t+o+Ne(e.attachment)+`<div class=cm-re>${Le(e,n.me)}</div></span><span class=cm-act>${Oe(e,n)}</span>`}function Tn(e,n,t){return\"cm\"+(_(e,n)?\" me\":\"\")+(e.deleted?\" isdel\":\"\")+(t?\" mentioned\":\"\")}var H={};v(H,{DEFAULT_CENTER:()=>ae,DEFAULT_ZOOM:()=>le,MAP_TYPES:()=>P,cycleMapType:()=>En,initialMapContent:()=>kn,mapTypeLabel:()=>Sn,sanitizeContent:()=>ue});var P=[\"roadmap\",\"satellite\",\"hybrid\"],ae=[46.6,2.5],le=6;function T(e){let n=Number(e);return Number.isFinite(n)?n:null}function ie(e){if(!Array.isArray(e))return null;let n=T(e[0]),t=T(e[1]);return n!=null&&t!=null?[n,t]:null}var se=(e,n,t)=>Math.max(n,Math.min(t,e));function ue(e){if(!e||typeof e!=\"object\")return null;let n=e;if(n.kind===\"pdf\"||n.kind==null)return null;if(n.kind===\"streetview\"){let t=ie(n.position);if(!t)return null;let r=n.pov&&typeof n.pov==\"object\"?n.pov:null,o=r?{heading:T(r.heading)||0,pitch:se(T(r.pitch)||0,-90,90)}:{heading:0,pitch:0};return{kind:\"streetview\",position:t,pov:o,zoom:se(T(n.zoom)||1,0,5)}}return n.kind!==\"map\"?null:{kind:\"map\",center:ie(n.center)||[...ae],zoom:se(Math.trunc(T(n.zoom)||le),1,21),marker:ie(n.marker),mapType:P.includes(n.mapType)?n.mapType:null,label:String(n.label||\"\").slice(0,160)||null}}function En(e){let n=P.indexOf(e);return P[(n+1)%P.length]}function Sn(e){return e===\"roadmap\"?\"\\u{1F6F0} Satellite\":e===\"satellite\"?\"\\u{1F5FA} Hybride\":\"\\u{1F5FA} Plan\"}function kn(){return{kind:\"map\",center:[...ae],zoom:le,marker:null,mapType:null,label:null}}var D={};v(D,{CURRENT_PAGE_MARGIN:()=>Ln,DEFAULT_ASPECT:()=>In,MAX_ZOOM:()=>Pn,MIN_PAGE_WIDTH:()=>An,MIN_ZOOM:()=>Rn,PRERENDER_MARGIN:()=>Cn,arrowState:()=>Un,averageColor:()=>Dn,clampPage:()=>Ue,clampZoom:()=>Nn,fitWidth:()=>Hn,isImageDocument:()=>Wn,progressPercent:()=>On,workerBlobUrl:()=>Vn});var Rn=.5,Pn=3,In=1.35,An=280,Cn=\"500px 0px\",Ln=\"-48% 0px -48% 0px\";function Nn(e){let n=Math.round((Number(e)||0)*10)/10;return Math.max(.5,Math.min(3,n))}function Ue(e,n){return Math.max(1,Math.min(n||1,Number(e)||1))}function On(e,n){return n?Math.round(Ue(e,n)/n*100):0}function Un(e,n){return{prevDisabled:e<=1,nextDisabled:!!n&&e>=n}}var $n=28;function Hn(e){var a;let n=(a=e.zoom)!=null?a:1,t=Math.max(280,e.containerWidth||900)*n;if(!e.onePage)return t;let r=e.aspect||1.35,s=((e.containerHeight||600)-$n-(e.overlap||0)-(e.reserve||0))/r;return s>120?Math.min(t,s):t}function Dn(e){let n=e.length/4;if(!n)return\"rgb(0,0,0)\";let t=0,r=0,o=0;for(let s=0;s<e.length;s+=4)t+=e[s],r+=e[s+1],o+=e[s+2];return`rgb(${Math.round(t/n)},${Math.round(r/n)},${Math.round(o/n)})`}function Wn(e,n){return/[.](png|jpe?g|webp|gif|avif)($|[?])/i.test(String(e||n||\"\"))}async function Vn(e,n,t={}){let r=t.fetch||(typeof fetch==\"function\"?(a=>fetch(a)):null),o=t.subtle!==void 0?t.subtle:typeof globalThis!=\"undefined\"&&globalThis.crypto?globalThis.crypto.subtle:null,s=t.creerUrl||(a=>URL.createObjectURL(a));if(!r||!o||!n)return null;try{let a=await r(e);if(!a.ok)return null;let l=await a.arrayBuffer(),d=await o.digest(\"SHA-384\",l);return`sha384-${Bn(new Uint8Array(d))}`!==n?null:s(new Blob([l],{type:\"application/javascript\"}))}catch(a){return null}}function Bn(e){let n=\"\";for(let t of e)n+=String.fromCharCode(t);return btoa(n)}var W={};v(W,{presentationTransition:()=>zn,switchDocUrl:()=>Fn});function zn(e,n={}){if(!e)return[{kind:\"nothing\"}];if(e.active===!1)return[{kind:\"ended\"}];let t=ue(e.content);if(t)return[{kind:\"show-map\",content:t}];let r=[{kind:\"leave-map\"}];return e.file_url&&e.file_url!==n.docUrl?(r.push({kind:\"switch-doc\",url:e.file_url,name:e.file_name||void 0,title:e.doc_title||void 0,updatedAt:e.updated_at||void 0}),r):(e.current_page&&r.push({kind:\"show-page\",page:e.current_page}),r)}function Fn(e,n){let t=encodeURIComponent(n||String(Date.now()));return`${e}${e.includes(\"?\")?\"&\":\"?\"}v=${t}`}return Fe(jn);})();", SOURCE_HASH: "e2da117ea7402386" };
|
package/server/handler.js
CHANGED
|
@@ -77,7 +77,55 @@ const originOf = (u) => { try { return new URL(u).origin; } catch { return ""; }
|
|
|
77
77
|
//
|
|
78
78
|
// Signalé par un audit externe. Fermer le chemin d'abord, migrer ensuite — dans cet ordre.
|
|
79
79
|
const PDFJS = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174";
|
|
80
|
-
|
|
80
|
+
// ⚠️ VERSION EXACTE, PAS `@2` (constat P2-4). L'étiquette `@2` de jsdelivr suit la dernière 2.x :
|
|
81
|
+
// la page servait donc, aux visiteurs, le code que Supabase avait publié le matin même — sans que
|
|
82
|
+
// personne n'ait rien déployé, ni relu, ni pu revenir en arrière. Le jour où elle résolvait vers
|
|
83
|
+
// 2.112.3, un correctif de la veille aurait changé ce qui tourne dans le navigateur d'un client
|
|
84
|
+
// pendant une présentation en cours. Une dépendance mouvante n'est pas une dépendance, c'est un
|
|
85
|
+
// abonnement à ce que décide un tiers.
|
|
86
|
+
const SUPAJS = "https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2.112.3/dist/umd/supabase.js";
|
|
87
|
+
const LEAFLET = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js";
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Empreintes des dépendances tierces (constat P2-4).
|
|
91
|
+
*
|
|
92
|
+
* ⚠️ CE QUI EST EN JEU : un script tiers entre dans la page avec EXACTEMENT les droits de notre
|
|
93
|
+
* code — même origine, même session, même accès au document affiché. Une version épinglée dit
|
|
94
|
+
* seulement quel fichier on demande ; elle ne dit rien de ce qu'on reçoit. L'empreinte, elle, fait
|
|
95
|
+
* refuser le navigateur si un octet a changé, quelle que soit la raison : CDN compromis, compte de
|
|
96
|
+
* publication détourné, ou intermédiaire.
|
|
97
|
+
*
|
|
98
|
+
* ⚠️ ET ELLE OBLIGE À ÉPINGLER. `integrity` sur une URL mouvante casserait la page à la première
|
|
99
|
+
* publication du tiers : les deux vont ensemble, l'un n'a pas de sens sans l'autre.
|
|
100
|
+
*
|
|
101
|
+
* Relevées sur les octets réellement servis, pas recopiées d'une documentation. Pour les vérifier
|
|
102
|
+
* ou les mettre à jour après une montée de version :
|
|
103
|
+
*
|
|
104
|
+
* curl -sL <url> | openssl dgst -sha384 -binary | openssl base64 -A
|
|
105
|
+
*
|
|
106
|
+
* Le banc navigateur les reconfronte à ce que les CDN servent — deux exemplaires d'un même fait
|
|
107
|
+
* doivent être comparés par quelqu'un au moins une fois.
|
|
108
|
+
*/
|
|
109
|
+
const TIERS = {
|
|
110
|
+
pdf: { url: PDFJS + "/pdf.min.js", sri: "sha384-/1qUCSGwTur9vjf/z9lmu/eCUYbpOTgSjmpbMQZ1/CtX2v/WcAIKqRv+U1DUCG6e" },
|
|
111
|
+
// ⚠️ Le worker N'A PAS DE BALISE, donc pas d'attribut `integrity` : il est chargé par pdf.js,
|
|
112
|
+
// pas par le document. Mais ses octets passent déjà par notre code (ils sont récupérés en texte
|
|
113
|
+
// puis transformés en blob de même origine, sans quoi le navigateur refuserait un worker
|
|
114
|
+
// distant) — on les vérifie donc à la main, là où ils passent. Sans ça, l'empreinte de
|
|
115
|
+
// `pdf.min.js` protégerait la petite moitié et laisserait la grande (1 Mo contre 300 ko) entrer
|
|
116
|
+
// sans contrôle, alors même qu'elle voit tout le contenu du document.
|
|
117
|
+
pdfWorker: { url: PDFJS + "/pdf.worker.min.js", sri: "sha384-SnzOobpRMLXZ52iJvZm/C0fYw0OQemTXzTjIsdsfMcrCtCEe9qgzxTd3RSklO5x2" },
|
|
118
|
+
supa: { url: SUPAJS, sri: "sha384-qafw21c/iciq0VXsi9FzkfoQv5I/V0iqE4lSNcKXPnW9/UTJLnv5CcN4FHxVLnKg" },
|
|
119
|
+
leaflet: { url: LEAFLET, sri: "sha384-cxOPjt7s7Iz04uaHJceBmS+qpjv2JkIHNVcuOrM+YHwZOmJGBXI00mdUXEq65HTH" },
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// ⚠️ `crossorigin` EST OBLIGATOIRE avec `integrity` sur une ressource d'une autre origine : sans
|
|
123
|
+
// lui, la réponse est opaque, le navigateur ne peut pas la lire pour la hacher, et il refuse le
|
|
124
|
+
// script — silencieusement du point de vue de la page. L'oublier ne dégrade pas la protection,
|
|
125
|
+
// ça casse la page. Les deux ne se séparent jamais : d'où cette fonction, plutôt que trois
|
|
126
|
+
// balises écrites à la main dont l'une finirait par en perdre un.
|
|
127
|
+
const balise = (nonce, tiers) =>
|
|
128
|
+
`<script nonce="${nonce}" src="${tiers.url}" integrity="${tiers.sri}" crossorigin="anonymous"></script>`;
|
|
81
129
|
|
|
82
130
|
// ————— Couche LIVE partagée (présence + chat historisé) — présentateur ET audience —————
|
|
83
131
|
// CSS injecté dans les deux vues.
|
|
@@ -625,7 +673,7 @@ var Map3DD=(function(){
|
|
|
625
673
|
function loadLeaflet(cb){ if(window.L){cb();return;} var iv=setInterval(function(){if(window.L){clearInterval(iv);cb();}},80);
|
|
626
674
|
if(leafletLoading)return; leafletLoading=true;
|
|
627
675
|
var css=document.createElement('link');css.rel='stylesheet';css.href='https://unpkg.com/leaflet@1.9.4/dist/leaflet.css';document.head.appendChild(css);
|
|
628
|
-
var s=document.createElement('script');s.src='
|
|
676
|
+
var s=document.createElement('script');s.src='${TIERS.leaflet.url}';s.integrity='${TIERS.leaflet.sri}';s.crossOrigin='anonymous';document.body.appendChild(s); }
|
|
629
677
|
// Google Maps JS chargé à la demande, seulement si une clé est fournie (GMAPS_KEY).
|
|
630
678
|
function loadGoogle(cb){ if(window.google&&window.google.maps){cb();return;} if(!GMAPS_KEY)return; var iv=setInterval(function(){if(window.google&&window.google.maps){clearInterval(iv);cb();}},120);
|
|
631
679
|
if(gLoading)return; gLoading=true;
|
|
@@ -1547,7 +1595,15 @@ function sendHtml(res, status, html, scriptSrc, imgExtra, frameAncestors) {
|
|
|
1547
1595
|
// personne n'a franchie serait un mauvais échange. `'self'` ferme l'exfiltration, qui est le
|
|
1548
1596
|
// risque réel.
|
|
1549
1597
|
"form-action 'self'",
|
|
1550
|
-
//
|
|
1598
|
+
// ⚠️ CE COMMENTAIRE ANNONÇAIT `'none'` POUR LA PAGE PUBLIQUE, ET C'ÉTAIT FAUX. Un lien tracé
|
|
1599
|
+
// sans `embed` est servi en `frame-ancestors 'self'` (cf. la route `doc`) : encadrement de
|
|
1600
|
+
// MÊME ORIGINE uniquement, ce qui reste sain — un détournement de clic suppose une page
|
|
1601
|
+
// étrangère, et une page hostile sur notre propre origine serait déjà une compromission bien
|
|
1602
|
+
// pire. Mais la phrase, elle, faisait croire à un refus total.
|
|
1603
|
+
//
|
|
1604
|
+
// Trouvé en écrivant l'essai de bout en bout : l'assertion recopiait ce commentaire, et c'est
|
|
1605
|
+
// elle qui est tombée. Le comportement est désormais VÉRIFIÉ par ce banc, donc ce que vous
|
|
1606
|
+
// lisez ici ne peut plus dériver seul.
|
|
1551
1607
|
`frame-ancestors ${frameAncestors || "'none'"}`,
|
|
1552
1608
|
].join("; "));
|
|
1553
1609
|
res.end(html);
|
|
@@ -1997,8 +2053,8 @@ ${LEGAL_CSS}
|
|
|
1997
2053
|
${legalFooter({ tracked: !preview && !!share.slug, sansExpediteur: !share.recipient_email && !share.created_by })}
|
|
1998
2054
|
${brandLogo || !brandIntroRuntime ? "" : `<script nonce="${nonce}">(${brandIntroRuntime.toString()})();</script>`}
|
|
1999
2055
|
<script nonce="${nonce}">${PLAYER_BROWSER_JS}</script>
|
|
2000
|
-
|
|
2001
|
-
${preview ?
|
|
2056
|
+
${balise(nonce, TIERS.pdf)}
|
|
2057
|
+
${preview ? `${balise(nonce, TIERS.supa)}
|
|
2002
2058
|
<script nonce="${nonce}">var LIVECFG={supaUrl:${JSON.stringify(share.supa_url || "")},supaKey:${JSON.stringify(share.supa_key || "")},hostAuthKey:${JSON.stringify(cleSessionHote())},liveAuthKey:${JSON.stringify(CLE_SESSION_PLAYER)},guestKey:${JSON.stringify(CLE_INVITE)}};var GMAPS_KEY=${JSON.stringify((PLAYER.config && PLAYER.config.mapsKey) || "" || "")};${LIVE_JS}
|
|
2003
2059
|
${MAP_JS}</script>` : ""}
|
|
2004
2060
|
<script nonce="${nonce}">
|
|
@@ -2290,8 +2346,8 @@ ${LEGAL_CSS}
|
|
|
2290
2346
|
// Vrai worker SAME-ORIGIN via blob (un Worker cross-origin est bloqué par le navigateur → "fake worker").
|
|
2291
2347
|
var wsrc=CFG.pdfjs+'/pdf.worker.min.js';
|
|
2292
2348
|
try{
|
|
2293
|
-
|
|
2294
|
-
try{ pdfjsLib.GlobalWorkerOptions.workerSrc =
|
|
2349
|
+
Player.viewer.workerBlobUrl(wsrc,'${TIERS.pdfWorker.sri}').then(function(u){
|
|
2350
|
+
try{ pdfjsLib.GlobalWorkerOptions.workerSrc = u || wsrc; }catch(e){ pdfjsLib.GlobalWorkerOptions.workerSrc=wsrc; }
|
|
2295
2351
|
start();
|
|
2296
2352
|
}).catch(function(){ pdfjsLib.GlobalWorkerOptions.workerSrc=wsrc; start(); });
|
|
2297
2353
|
}catch(e){ pdfjsLib.GlobalWorkerOptions.workerSrc=wsrc; start(); }
|
|
@@ -2577,8 +2633,8 @@ function presentHtml(pres, nonce, logoUrl, supaUrl, supaKey) {
|
|
|
2577
2633
|
${PLAYER.branding.poweredBy ? `<div class=brand>Propulsé par ${esc(PLAYER.branding.poweredBy)}</div>` : ""}
|
|
2578
2634
|
${legalFooter({ tracked: true })}
|
|
2579
2635
|
<script nonce="${nonce}">${PLAYER_BROWSER_JS}</script>
|
|
2580
|
-
|
|
2581
|
-
|
|
2636
|
+
${balise(nonce, TIERS.pdf)}
|
|
2637
|
+
${balise(nonce, TIERS.supa)}
|
|
2582
2638
|
<script nonce="${nonce}">
|
|
2583
2639
|
(function(){
|
|
2584
2640
|
var CFG=${cfg.replace(/</g, "\\u003c")};
|
|
@@ -2603,8 +2659,8 @@ function presentHtml(pres, nonce, logoUrl, supaUrl, supaKey) {
|
|
|
2603
2659
|
}
|
|
2604
2660
|
var wsrc=CFG.pdfjs+'/pdf.worker.min.js';
|
|
2605
2661
|
function boot(){
|
|
2606
|
-
|
|
2607
|
-
try{ pdfjsLib.GlobalWorkerOptions.workerSrc=
|
|
2662
|
+
Player.viewer.workerBlobUrl(wsrc,'${TIERS.pdfWorker.sri}').then(function(u){
|
|
2663
|
+
try{ pdfjsLib.GlobalWorkerOptions.workerSrc = u || wsrc; }catch(e){ pdfjsLib.GlobalWorkerOptions.workerSrc=wsrc; }
|
|
2608
2664
|
load();
|
|
2609
2665
|
}).catch(function(){ pdfjsLib.GlobalWorkerOptions.workerSrc=wsrc; load(); });
|
|
2610
2666
|
}
|
|
@@ -3847,6 +3903,9 @@ async function handler(req, res) {
|
|
|
3847
3903
|
}
|
|
3848
3904
|
}
|
|
3849
3905
|
|
|
3850
|
-
|
|
3906
|
+
// ⚠️ `TIERS` est exporté pour être CONFRONTÉ, pas pour être utilisé. Le banc navigateur et la
|
|
3907
|
+
// forge doivent pouvoir demander « quelles dépendances tierces, à quelles empreintes » sans en
|
|
3908
|
+
// tenir une seconde liste — c'est la seule façon qu'une empreinte périmée finisse par se voir.
|
|
3909
|
+
module.exports = { handler, init, TIERS };
|
|
3851
3910
|
|
|
3852
3911
|
// redeploy: forcer le build production (Vercel a sauté la prod du merge #463 — wording re-partage).
|