mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-11-09 19:20:09 +01:00
Fix lint: use IterableCallbackReturn — wrap forEach body in braces
This commit is contained in:
1 parent
f6468c6d44
commit
82d8eff512
8 files changed
+662
-19
No files matched your search
@@ -27,10 +27,10 @@
|
||||
gap: var(--space-3xs);
|
||||
}
|
||||
|
||||
/* Two-column layout: left 35vw (info), right fills remaining (files) */
|
||||
/* Two-column layout: left 40vw (info), right fills remaining (files) */
|
||||
.tfe-content-row {
|
||||
display: grid;
|
||||
grid-template-columns: 35vw 1fr;
|
||||
grid-template-columns: 40vw 1fr;
|
||||
gap: var(--space-xl);
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
@@ -66,6 +66,10 @@
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
.tfe-file-item:has(.pdf-embed-wrapper) {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.tfe-file-item img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
@@ -293,6 +297,190 @@
|
||||
outline-color: #fc8181;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
PDF.js IN-PAGE VIEWER (pdf-viewer.js)
|
||||
============================================================ */
|
||||
|
||||
/*── Base wrapper ───────────────────────────── */
|
||||
|
||||
.pdf-embed-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
outline: none;
|
||||
transition: height 0.35s ease, border-color 0.35s ease;
|
||||
}
|
||||
|
||||
/* ── Collapsed state: thumbnail tile ────────── */
|
||||
|
||||
.pdf-collapsed {
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
min-height: 200px;
|
||||
max-height: 350px;
|
||||
}
|
||||
|
||||
.pdf-thumbnail {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
/* ── Overlay veil + enter button ────────────── */
|
||||
|
||||
.pdf-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgb(0 0 0 / 0.15);
|
||||
backdrop-filter: blur(4px) saturate(0.6);
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.pdf-overlay:hover {
|
||||
background: rgb(0 0 0 / 0.08);
|
||||
}
|
||||
|
||||
/* Document type pill — top-left of the overlay */
|
||||
|
||||
.pdf-overlay-badge {
|
||||
position: absolute;
|
||||
top: var(--space-xs);
|
||||
left: var(--space-xs);
|
||||
z-index: 2;
|
||||
display: inline-block;
|
||||
padding: 0.15em 0.6em;
|
||||
font-size: var(--step--2);
|
||||
font-weight: 500;
|
||||
line-height: 1.4;
|
||||
color: color-mix(in srgb, var(--accent-primary) 90%, #000);
|
||||
background: color-mix(in srgb, var(--accent-primary) 12%, transparent);
|
||||
border: 1px solid color-mix(in srgb, var(--accent-primary) 25%, transparent);
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
.pdf-enter-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2xs);
|
||||
padding: var(--space-xs) var(--space-m);
|
||||
background: var(--accent-primary);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: var(--radius);
|
||||
font-size: var(--step-0);
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 8px rgb(0 0 0 / 0.2);
|
||||
transition: transform 0.15s, box-shadow 0.15s;
|
||||
}
|
||||
|
||||
.pdf-enter-btn:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgb(0 0 0 / 0.25);
|
||||
}
|
||||
|
||||
/* ── Expanded state: wrapper becomes scroll panel ── */
|
||||
|
||||
.pdf-expanded {
|
||||
/* Fill viewport minus the column's vertical padding */
|
||||
max-height: calc(100vh - var(--space-xl) * 2);
|
||||
height: clamp(400px, 80vh, calc(100vh - var(--space-xl) * 2));
|
||||
overflow-y: auto;
|
||||
border: 2px solid var(--accent-primary);
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* ── Toolbar ────────────────────────────────── */
|
||||
|
||||
.pdf-toolbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-3xs);
|
||||
padding: var(--space-2xs) var(--space-xs);
|
||||
background: var(--bg-primary);
|
||||
border-bottom: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
flex-shrink: 0;
|
||||
font-size: var(--step--1);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.pdf-toolbar-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
padding: 0;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
background: var(--surface);
|
||||
color: var(--text-primary);
|
||||
cursor: pointer;
|
||||
font-size: inherit;
|
||||
line-height: 1;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
|
||||
.pdf-toolbar-btn:hover {
|
||||
background: color-mix(in srgb, var(--accent-primary) 15%, var(--surface));
|
||||
}
|
||||
|
||||
.pdf-toolbar-close {
|
||||
margin-right: var(--space-xs);
|
||||
}
|
||||
|
||||
.pdf-toolbar-label {
|
||||
min-width: 4.5em;
|
||||
text-align: center;
|
||||
color: var(--text-secondary);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.pdf-toolbar-scale {
|
||||
min-width: 3em;
|
||||
}
|
||||
|
||||
/* ── Scroll container ────────────────────────── */
|
||||
|
||||
.pdf-canvas {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
box-shadow: 0 1px 4px rgb(0 0 0 / 0.12);
|
||||
background: #fff;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.pdf-canvas:first-of-type {
|
||||
margin-top: var(--space-xs);
|
||||
}
|
||||
|
||||
.pdf-canvas:last-of-type {
|
||||
margin-bottom: var(--space-xs);
|
||||
}
|
||||
|
||||
.pdf-canvas + .pdf-canvas {
|
||||
margin-top: var(--space-2xs);
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 900px) {
|
||||
.tfe-main {
|
||||
|
||||
@@ -0,0 +1,368 @@
|
||||
/**
|
||||
* pdf-viewer.js — In-page PDF.js viewer (no download UI, scroll isolation).
|
||||
*
|
||||
* Two states per PDF container:
|
||||
* Collapsed — thumbnail preview tile, blurred veil, "Lire" button.
|
||||
* Outer page scrolls freely.
|
||||
* Expanded — the wrapper itself becomes the scrollable panel.
|
||||
* Toolbar + pages. "Fermer" button in toolbar.
|
||||
*
|
||||
* Dependencies: pdfjsLib (from vendor/pdf.min.mjs), pdf.worker (from
|
||||
* vendor/pdf.worker.min.mjs).
|
||||
*/
|
||||
|
||||
(() => {
|
||||
function bootstrap() {
|
||||
const containers = document.querySelectorAll(".pdf-embed-wrapper");
|
||||
if (containers.length === 0) return;
|
||||
|
||||
if (typeof pdfjsLib === "undefined") {
|
||||
setTimeout(bootstrap, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pdfjsLib.GlobalWorkerOptions.workerSrc) {
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||
"/assets/js/vendor/pdf.worker.min.mjs";
|
||||
}
|
||||
|
||||
for (const c of containers) initPdfViewer(c);
|
||||
}
|
||||
|
||||
// ── Init ──────────────────────────────────────────────────────
|
||||
|
||||
async function initPdfViewer(container) {
|
||||
const url = container.dataset.pdfUrl;
|
||||
if (!url) return;
|
||||
|
||||
// Ensure URL is a non-empty string
|
||||
if (typeof url !== "string" || url.trim() === "") {
|
||||
container.textContent = "URL du PDF invalide.";
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const pdfDoc = await pdfjsLib.getDocument({ url }).promise;
|
||||
container._pdfDoc = pdfDoc;
|
||||
container._numPages = pdfDoc.numPages;
|
||||
|
||||
buildCollapsed(container, pdfDoc);
|
||||
} catch (err) {
|
||||
container.textContent = "PDF non disponible.";
|
||||
console.error("PDF.js error:", err);
|
||||
}
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// COLLAPSED STATE — thumbnail tile
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
async function buildCollapsed(container, pdfDoc) {
|
||||
container.classList.add("pdf-collapsed");
|
||||
|
||||
// Render first page as a thumbnail
|
||||
try {
|
||||
const page = await pdfDoc.getPage(1);
|
||||
const viewport = page.getViewport({ scale: 0.3 });
|
||||
const dpr = window.devicePixelRatio || 1;
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.className = "pdf-thumbnail";
|
||||
canvas.width = Math.floor(viewport.width * dpr);
|
||||
canvas.height = Math.floor(viewport.height * dpr);
|
||||
canvas.style.width = `${Math.floor(viewport.width)}px`;
|
||||
canvas.style.height = `${Math.floor(viewport.height)}px`;
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||||
await page.render({ canvasContext: ctx, viewport }).promise;
|
||||
|
||||
container.appendChild(canvas);
|
||||
} catch {
|
||||
// Thumbnail optional
|
||||
}
|
||||
|
||||
// Veil overlay
|
||||
const overlay = document.createElement("div");
|
||||
overlay.className = "pdf-overlay";
|
||||
container.appendChild(overlay);
|
||||
|
||||
// Document type pill — top-left corner of the overlay
|
||||
const label = container.dataset.pdfLabel;
|
||||
if (label) {
|
||||
const pill = document.createElement("span");
|
||||
pill.className = "pdf-overlay-badge";
|
||||
pill.textContent = label;
|
||||
overlay.appendChild(pill);
|
||||
}
|
||||
|
||||
// "Lire" button
|
||||
const btn = document.createElement("button");
|
||||
btn.className = "pdf-enter-btn";
|
||||
btn.textContent = "Lire le document";
|
||||
btn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
expand(container, pdfDoc);
|
||||
});
|
||||
overlay.appendChild(btn);
|
||||
|
||||
overlay.addEventListener("click", () => expand(container, pdfDoc));
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// EXPANDED STATE — wrapper becomes the scroll panel
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
async function expand(container, pdfDoc) {
|
||||
container.classList.remove("pdf-collapsed");
|
||||
container.classList.add("pdf-expanded");
|
||||
|
||||
container.addEventListener("contextmenu", (e) => e.preventDefault());
|
||||
container.addEventListener("keydown", (e) => {
|
||||
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "s") {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
container.setAttribute("tabindex", "-1");
|
||||
|
||||
// Remove collapsed elements
|
||||
const oldOverlay = container.querySelector(".pdf-overlay");
|
||||
if (oldOverlay) oldOverlay.remove();
|
||||
const oldThumb = container.querySelector(".pdf-thumbnail");
|
||||
if (oldThumb) oldThumb.remove();
|
||||
|
||||
// Build toolbar
|
||||
buildToolbar(container, pdfDoc);
|
||||
|
||||
// Render pages directly into the wrapper
|
||||
await renderAllPages(container, pdfDoc);
|
||||
|
||||
container.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
||||
}
|
||||
|
||||
function collapse(container) {
|
||||
container.classList.remove("pdf-expanded");
|
||||
container.classList.add("pdf-collapsed");
|
||||
|
||||
const oldToolbar = container.querySelector(".pdf-toolbar");
|
||||
if (oldToolbar) oldToolbar.remove();
|
||||
|
||||
// Remove rendered pages
|
||||
container.querySelectorAll(".pdf-canvas").forEach((c) => {
|
||||
c.remove();
|
||||
});
|
||||
|
||||
buildCollapsed(container, container._pdfDoc);
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// PAGE RENDERING (canvases appended directly to container)
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
async function renderAllPages(container, pdfDoc) {
|
||||
const numPages = pdfDoc.numPages;
|
||||
|
||||
const firstPage = await pdfDoc.getPage(1);
|
||||
const firstViewport = firstPage.getViewport({ scale: 1 });
|
||||
const dpr = window.devicePixelRatio || 1;
|
||||
|
||||
const pageEntries = [];
|
||||
for (let i = 1; i <= numPages; i++) {
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.className = "pdf-canvas";
|
||||
canvas.dataset.page = String(i);
|
||||
container.appendChild(canvas);
|
||||
pageEntries.push({ canvas, pageNum: i });
|
||||
}
|
||||
|
||||
const rendering = new Set();
|
||||
|
||||
const resolveScale = () => {
|
||||
const userScale = parseFloat(container.dataset.pdfScale ?? "1");
|
||||
const containerWidth = container.clientWidth - 16;
|
||||
if (containerWidth <= 0) return userScale;
|
||||
return (containerWidth / firstViewport.width) * userScale;
|
||||
};
|
||||
|
||||
const renderPage = async (entry) => {
|
||||
const { canvas, pageNum } = entry;
|
||||
if (rendering.has(pageNum)) return;
|
||||
rendering.add(pageNum);
|
||||
try {
|
||||
const page = await pdfDoc.getPage(pageNum);
|
||||
const scale = resolveScale();
|
||||
const viewport = page.getViewport({ scale });
|
||||
canvas.width = Math.floor(viewport.width * dpr);
|
||||
canvas.height = Math.floor(viewport.height * dpr);
|
||||
canvas.style.width = `${Math.floor(viewport.width)}px`;
|
||||
canvas.style.height = `${Math.floor(viewport.height)}px`;
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||||
await page.render({ canvasContext: ctx, viewport }).promise;
|
||||
} catch (err) {
|
||||
if (err.name !== "RenderingCancelledException") {
|
||||
console.error(`Failed to render page ${pageNum}:`, err);
|
||||
}
|
||||
} finally {
|
||||
rendering.delete(pageNum);
|
||||
}
|
||||
};
|
||||
|
||||
const scheduleVisible = () => {
|
||||
const containerRect = container.getBoundingClientRect();
|
||||
for (const entry of pageEntries) {
|
||||
if (rendering.has(entry.pageNum)) continue;
|
||||
const rect = entry.canvas.getBoundingClientRect();
|
||||
const margin = containerRect.height * 2;
|
||||
if (
|
||||
rect.bottom >= containerRect.top - margin &&
|
||||
rect.top <= containerRect.bottom + margin
|
||||
) {
|
||||
renderPage(entry);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
scheduleVisible();
|
||||
container.addEventListener("scroll", scheduleVisible, { passive: true });
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
// TOOLBAR
|
||||
// ═══════════════════════════════════════════════════════════════
|
||||
|
||||
function buildToolbar(container, pdfDoc) {
|
||||
const toolbar = document.createElement("div");
|
||||
toolbar.className = "pdf-toolbar";
|
||||
|
||||
let currentPage = 1;
|
||||
let currentScale = parseFloat(container.dataset.pdfScale ?? "1");
|
||||
const numPages = pdfDoc.numPages;
|
||||
|
||||
const updateUI = () => {
|
||||
pageLabel.textContent = `${currentPage} / ${numPages}`;
|
||||
scaleLabel.textContent = `${Math.round(currentScale * 100)}%`;
|
||||
};
|
||||
|
||||
const prevBtn = mkBtn("‹", "Page précédente", () => {
|
||||
if (currentPage <= 1) return;
|
||||
currentPage--;
|
||||
scrollToCanvas(container, currentPage);
|
||||
updateUI();
|
||||
});
|
||||
|
||||
const nextBtn = mkBtn("›", "Page suivante", () => {
|
||||
if (currentPage >= numPages) return;
|
||||
currentPage++;
|
||||
scrollToCanvas(container, currentPage);
|
||||
updateUI();
|
||||
});
|
||||
|
||||
const pageLabel = mkLabel("");
|
||||
|
||||
const zoomOutBtn = mkBtn("−", "Zoom arrière", () => {
|
||||
currentScale = Math.max(0.5, currentScale - 0.2);
|
||||
container.dataset.pdfScale = String(currentScale);
|
||||
reRender(container, pdfDoc);
|
||||
updateUI();
|
||||
});
|
||||
|
||||
const zoomInBtn = mkBtn("+", "Zoom avant", () => {
|
||||
currentScale = Math.min(3.0, currentScale + 0.2);
|
||||
container.dataset.pdfScale = String(currentScale);
|
||||
reRender(container, pdfDoc);
|
||||
updateUI();
|
||||
});
|
||||
|
||||
const scaleLabel = mkLabel("");
|
||||
scaleLabel.classList.add("pdf-toolbar-scale");
|
||||
|
||||
const closeBtn = mkBtn("✕", "Fermer le document", () =>
|
||||
collapse(container),
|
||||
);
|
||||
closeBtn.classList.add("pdf-toolbar-close");
|
||||
|
||||
toolbar.append(
|
||||
closeBtn,
|
||||
prevBtn,
|
||||
pageLabel,
|
||||
nextBtn,
|
||||
" ",
|
||||
zoomOutBtn,
|
||||
scaleLabel,
|
||||
zoomInBtn,
|
||||
);
|
||||
container.insertBefore(toolbar, container.firstChild);
|
||||
|
||||
updateUI();
|
||||
|
||||
const canvases = container.querySelectorAll(".pdf-canvas");
|
||||
|
||||
const onScroll = () => {
|
||||
const mid = container.scrollTop + container.clientHeight * 0.4;
|
||||
let best = 1;
|
||||
let bestDist = Infinity;
|
||||
canvases.forEach((c) => {
|
||||
const pn = parseInt(c.dataset.page, 10) || 1;
|
||||
const dist = Math.abs(c.offsetTop - mid);
|
||||
if (dist < bestDist) {
|
||||
bestDist = dist;
|
||||
best = pn;
|
||||
}
|
||||
});
|
||||
if (best !== currentPage) {
|
||||
currentPage = best;
|
||||
updateUI();
|
||||
}
|
||||
};
|
||||
|
||||
container.addEventListener("scroll", onScroll, { passive: true });
|
||||
container._onScroll = onScroll;
|
||||
|
||||
container.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Escape") collapse(container);
|
||||
});
|
||||
}
|
||||
|
||||
function mkBtn(text, ariaLabel, handler) {
|
||||
const btn = document.createElement("button");
|
||||
btn.className = "pdf-toolbar-btn";
|
||||
btn.setAttribute("aria-label", ariaLabel);
|
||||
btn.textContent = text;
|
||||
btn.addEventListener("click", handler);
|
||||
return btn;
|
||||
}
|
||||
|
||||
function mkLabel(text) {
|
||||
const span = document.createElement("span");
|
||||
span.className = "pdf-toolbar-label";
|
||||
span.textContent = text;
|
||||
return span;
|
||||
}
|
||||
|
||||
function scrollToCanvas(container, pageNum) {
|
||||
const canvas = container.querySelector(
|
||||
`.pdf-canvas[data-page="${pageNum}"]`,
|
||||
);
|
||||
if (canvas) {
|
||||
canvas.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
}
|
||||
}
|
||||
|
||||
function reRender(container, pdfDoc) {
|
||||
if (container._onScroll) {
|
||||
container.removeEventListener("scroll", container._onScroll);
|
||||
}
|
||||
container.querySelectorAll(".pdf-canvas").forEach((c) => {
|
||||
c.remove();
|
||||
});
|
||||
const oldToolbar = container.querySelector(".pdf-toolbar");
|
||||
if (oldToolbar) oldToolbar.remove();
|
||||
buildToolbar(container, pdfDoc);
|
||||
renderAllPages(container, pdfDoc);
|
||||
}
|
||||
|
||||
// ── Bootstrap ──────────────────────────────────────────────────
|
||||
|
||||
bootstrap();
|
||||
})();
|
||||
@@ -18,3 +18,4 @@ import "./repertoire-scroll-restore.js";
|
||||
import "./repertoire-student-popover.js";
|
||||
import "./access-request.js";
|
||||
import "./acces-password.js";
|
||||
import "./pdf-viewer.js";
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @licstart The following is the entire license notice for the
|
||||
* JavaScript code in this page
|
||||
*
|
||||
* Copyright 2024 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @licend The above is the entire license notice for the
|
||||
* JavaScript code in this page
|
||||
*/
|
||||
/**
|
||||
* pdfjsVersion = 6.1.200
|
||||
* pdfjsBuild = 6353acefe
|
||||
*/
|
||||
const t=!("object"!=typeof process||process+""!="[object process]"||process.versions.nw||process.versions.electron&&process.type&&"browser"!==process.type),e=[1/0,1/0,-1/0,-1/0],i=new Float32Array(e),n=[.001,0,0,.001,0,0],s=1.35,a="http://www.w3.org/2000/svg",r=1,o=2,l=4,h=16,c=32,d=64,u=128,p=256,g={DISABLE:0,ENABLE:1,ENABLE_FORMS:2,ENABLE_STORAGE:3},m="pdfjs_internal_id_",f="pdfjs_internal_editor_",b={DISABLE:-1,NONE:0,FREETEXT:3,HIGHLIGHT:9,STAMP:13,INK:15,POPUP:16,SIGNATURE:101,COMMENT:102},y={RESIZE:1,CREATE:2,FREETEXT_SIZE:11,FREETEXT_COLOR:12,FREETEXT_OPACITY:13,INK_COLOR:21,INK_THICKNESS:22,INK_OPACITY:23,INK_COLOR_AND_OPACITY:24,HIGHLIGHT_COLOR:31,HIGHLIGHT_THICKNESS:32,HIGHLIGHT_FREE:33,HIGHLIGHT_SHOW_ALL:34,DRAW_STEP:41},v={PRINT:4,MODIFY_CONTENTS:8,COPY:16,MODIFY_ANNOTATIONS:32,FILL_INTERACTIVE_FORMS:256,COPY_FOR_ACCESSIBILITY:512,ASSEMBLE:1024,PRINT_HIGH_QUALITY:2048},A=0,w=1,x=2,C=3,E=3,S=4,T={GRAYSCALE_1BPP:1,RGB_24BPP:2,RGBA_32BPP:3},k={TEXT:1,LINK:2,FREETEXT:3,LINE:4,SQUARE:5,CIRCLE:6,POLYGON:7,POLYLINE:8,HIGHLIGHT:9,UNDERLINE:10,SQUIGGLY:11,STRIKEOUT:12,STAMP:13,CARET:14,INK:15,POPUP:16,FILEATTACHMENT:17,SOUND:18,MOVIE:19,WIDGET:20,SCREEN:21,PRINTERMARK:22,TRAPNET:23,WATERMARK:24,THREED:25,REDACT:26,RICHMEDIA:27},_=1,M=2,D=3,P=4,I=5,F={ERRORS:0,WARNINGS:1,INFOS:5},B={dependency:1,setLineWidth:2,setLineCap:3,setLineJoin:4,setMiterLimit:5,setDash:6,setRenderingIntent:7,setFlatness:8,setGState:9,save:10,restore:11,transform:12,moveTo:13,lineTo:14,curveTo:15,curveTo2:16,curveTo3:17,closePath:18,rectangle:19,stroke:20,closeStroke:21,fill:22,eoFill:23,fillStroke:24,eoFillStroke:25,closeFillStroke:26,closeEOFillStroke:27,endPath:28,clip:29,eoClip:30,beginText:31,endText:32,setCharSpacing:33,setWordSpacing:34,setHScale:35,setLeading:36,setFont:37,setTextRenderingMode:38,setTextRise:39,moveText:40,setLeadingMoveText:41,setTextMatrix:42,nextLine:43,showText:44,showSpacedText:45,nextLineShowText:46,nextLineSetSpacingShowText:47,setCharWidth:48,setCharWidthAndBounds:49,setStrokeColorSpace:50,setFillColorSpace:51,setStrokeColor:52,setStrokeColorN:53,setFillColor:54,setFillColorN:55,setStrokeGray:56,setFillGray:57,setStrokeRGBColor:58,setFillRGBColor:59,setStrokeCMYKColor:60,setFillCMYKColor:61,shadingFill:62,beginInlineImage:63,beginImageData:64,endInlineImage:65,paintXObject:66,markPoint:67,markPointProps:68,beginMarkedContent:69,beginMarkedContentProps:70,endMarkedContent:71,beginCompat:72,endCompat:73,paintFormXObjectBegin:74,paintFormXObjectEnd:75,beginGroup:76,endGroup:77,beginAnnotation:80,endAnnotation:81,paintImageMaskXObject:83,paintImageMaskXObjectGroup:84,paintImageXObject:85,paintInlineImageXObject:86,paintInlineImageXObjectGroup:87,paintImageXObjectRepeat:88,paintImageMaskXObjectRepeat:89,paintSolidColorImageMask:90,constructPath:91,setStrokeTransparent:92,setFillTransparent:93,rawFillPath:94},L=0,O=1,R=2,N=3,U=4,H={NEED_PASSWORD:1,INCORRECT_PASSWORD:2};let z=F.WARNINGS;function setVerbosityLevel(t){Number.isInteger(t)&&(z=t)}function getVerbosityLevel(){return z}function info(t){z>=F.INFOS&&console.info(`Info: ${t}`)}function warn(t){z>=F.WARNINGS&&console.warn(`Warning: ${t}`)}function unreachable(t){throw new Error(t)}function assert(t,e){t||unreachable(e)}function createValidAbsoluteUrl(t,e=null,i=null){if(!t)return null;if(i&&"string"==typeof t){if(i.addDefaultProtocol&&t.startsWith("www.")){const e=t.match(/\./g);e?.length>=2&&(t=`http://${t}`)}if(i.tryConvertEncoding)try{t=function stringToUTF8String(t){return decodeURIComponent(escape(t))}(t)}catch{}}const n=e?URL.parse(t,e):URL.parse(t);return function _isValidProtocol(t){switch(t?.protocol){case"http:":case"https:":case"ftp:":case"mailto:":case"tel:":return!0;default:return!1}}(n)?n:null}function updateUrlHash(t,e,i=!1){const n=URL.parse(t);if(n){n.hash=e;return n.href}return i&&createValidAbsoluteUrl(t,"http://example.com")?t.split("#",1)[0]+""+(e?`#${e}`:""):""}function stripPath(t){return t.substring(t.lastIndexOf("/")+1)}function shadow(t,e,i,n=!1){Object.defineProperty(t,e,{value:i,enumerable:!n,configurable:!0,writable:!1});return i}const G=function BaseExceptionClosure(){function BaseException(t,e){this.message=t;this.name=e}BaseException.prototype=new Error;BaseException.constructor=BaseException;return BaseException}();class PasswordException extends G{constructor(t,e){super(t,"PasswordException");this.code=e}}class UnknownErrorException extends G{constructor(t,e){super(t,"UnknownErrorException");this.details=e}}class InvalidPDFException extends G{constructor(t){super(t,"InvalidPDFException")}}class ResponseException extends G{constructor(t,e,i){super(t,"ResponseException");this.status=e;this.missing=i}}class FormatError extends G{constructor(t){super(t,"FormatError")}}class AbortException extends G{constructor(t){super(t,"AbortException")}}function stringToBytes(t){"string"!=typeof t&&unreachable("Invalid argument for stringToBytes");const e=t.length,i=new Uint8Array(e);for(let n=0;n<e;++n)i[n]=255&t.charCodeAt(n);retuLine truncated
|
||||
/*webpackIgnore: true*/
|
||||
/*@vite-ignore*/
|
||||
this.workerSrc)).WorkerMessageHandler})())}}class WorkerTransport{downloadInfoCapability=Promise.withResolvers();#La=null;#Oa=new Map;#Ra=null;#Na=new Map;#Ua=new Map;#Ha=new Map;#za=null;constructor(t,e,i,n,s,a){this.messageHandler=t;this.loadingTask=e;this.#Ra=i;this.commonObjs=new PDFObjects;this.fontLoader=new FontLoader({ownerDocument:n.ownerDocument,styleElement:n.styleElement});this.enableHWA=n.enableHWA;this.loadingParams=n.loadingParams;this._params=n;this.canvasFactory=s.canvasFactory;this.filterFactory=s.filterFactory;this.binaryDataFactory=s.binaryDataFactory;this.pagesMapper=a;this.destroyed=!1;this.destroyCapability=null;this.setupMessageHandler()}updatePage(t){const{_pageIndex:e}=t;this.#Na.set(e,t);this.#Ua.set(e,Promise.resolve(t))}#Ga(t,e=null){return this.#Oa.getOrInsertComputed(t,()=>this.messageHandler.sendWithPromise(t,e))}#ys({loaded:t,total:e}){this.loadingTask.onProgress?.({loaded:t,total:e,percent:e?MathClamp(Math.round(t/e*100),0,100):NaN})}get annotationStorage(){return shadow(this,"annotationStorage",new AnnotationStorage)}getRenderingIntent(t,e=g.ENABLE,i=null,n=!1,s=!1){let a=o,m=Q;switch(t){case"any":a=r;break;case"display":break;case"print":a=l;break;default:warn(`getRenderingIntent - invalid intent: ${t}`)}const f=a&l&&i instanceof PrintAnnotationStorage?i:this.annotationStorage;switch(e){case g.DISABLE:a+=d;break;case g.ENABLE:break;case g.ENABLE_FORMS:a+=h;break;case g.ENABLE_STORAGE:a+=c;m=f.serializable;break;default:warn(`getRenderingIntent - invalid annotationMode: ${e}`)}n&&(a+=u);s&&(a+=p);const{ids:b,hash:y}=f.modifiedIds;return{renderingIntent:a,cacheKey:[a,m.hash,y].join("_"),annotationStorageSerializable:m,modifiedIds:b}}destroy(){if(this.destroyCapability)return this.destroyCapability.promise;this.destroyed=!0;this.destroyCapability=Promise.withResolvers();this.#za?.reject(new Error("Worker was destroyed during onPassword callback"));const t=[];for(const e of this.#Na.values())t.push(e._destroy());this.#Na.clear();this.#Ua.clear();this.#Ha.clear();Object.hasOwn(this,"annotationStorage")&&this.annotationStorage.resetModified();const e=this.messageHandler.sendWithPromise("Terminate",null);t.push(e);Promise.all(t).then(()=>{this.commonObjs.clear();this.fontLoader.clear();this.#Oa.clear();this.filterFactory.destroy();TextLayer.cleanup();this.#Ra?.cancelAllRequests(new AbortException("Worker was terminated."));this.messageHandler?.destroy();this.messageHandler=null;this.destroyCapability.resolve()},this.destroyCapability.reject);return this.destroyCapability.promise}setupMessageHandler(){const{messageHandler:t,loadingTask:e}=this;t.on("GetReader",(t,e)=>{assert(this.#Ra,"GetReader - no `BasePDFStream` instance available.");this.#La=this.#Ra.getFullReader();this.#La.onProgress=t=>this.#ys(t);e.onPull=()=>{this.#La.read().then(function({value:t,done:i}){if(i)e.close();else{assert(t instanceof ArrayBuffer,"GetReader - expected an ArrayBuffer.");e.enqueue(new Uint8Array(t),1,[t])}}).catch(t=>{e.error(t)})};e.onCancel=t=>{this.#La.cancel(t);e.ready.catch(t=>{if(!this.destroyed)throw t})}});t.on("ReaderHeadersReady",async t=>{await this.#La.headersReady;const{isStreamingSupported:e,isRangeSupported:i,contentLength:n}=this.#La;e&&i&&(this.#La.onProgress=null);return{isStreamingSupported:e,isRangeSupported:i,contentLength:n}});t.on("GetRangeReader",(t,e)=>{assert(this.#Ra,"GetRangeReader - no `BasePDFStream` instance available.");const i=this.#Ra.getRangeReader(t.begin,t.end);if(i){e.onPull=()=>{i.read().then(function({value:t,done:i}){if(i)e.close();else{assert(t instanceof ArrayBuffer,"GetRangeReader - expected an ArrayBuffer.");e.enqueue(new Uint8Array(t),1,[t])}}).catch(t=>{e.error(t)})};e.onCancel=t=>{i.cancel(t);e.ready.catch(t=>{if(!this.destroyed)throw t})}}else e.close()});t.on("GetDoc",({pdfInfo:t})=>{this.pagesMapper.pagesNumber=t.numPages;this._numPages=t.numPages;this._htmlForXfa=t.htmlForXfa;delete t.htmlForXfa;e._capability.resolve(new PDFDocumentProxy(t,this))});t.on("DocException",t=>{e._capability.reject(wrapReason(t))});t.on("PasswordRequest",t=>{this.#za=Promise.withResolvers();try{if(!e.onPassword)throw wrapReason(t);const updatePassword=t=>{t instanceof Error?this.#za.reject(t):this.#za.resolve({password:t})};e.onPassword(updatePassword,t.code)}catch(t){this.#za.reject(t)}return this.#za.promise});t.on("DataLoaded",t=>{this.#ys({loaded:t.length,total:t.length});this.downloadInfoCapability.resolve(t)});t.on("StartRenderPage",t=>{if(this.destroyed)return;this.#Na.get(t.pageIndex)._startRenderPage(t.transparency,t.cacheKey)});t.on("commonobj",([e,i,n])=>{if(this.destroyed)return null;if(this.commonObjs.has(e))return null;switch(i){case"Font":if("error"in n){const t=n.error;warn(`Error during font loading: ${t}`);this.commonObjs.resolve(e,t);break}const s=new FontInfo(n),a=this._params.pdfBug&&globalThis.FontInspector?.enabled?(t,e)=>globalThis.FontInspector.fontAdded(t,e):null,r=new FontFaceObject(s,a,n.charProcOperatorList,n.extra);this.fontLoader.bind(Line truncated
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @licstart The following is the entire license notice for the
|
||||
* JavaScript code in this page
|
||||
*
|
||||
* Copyright 2024 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @licend The above is the entire license notice for the
|
||||
* JavaScript code in this page
|
||||
*/
|
||||
/**
|
||||
* pdfjsVersion = 6.1.200
|
||||
* pdfjsBuild = 6353acefe
|
||||
*/
|
||||
const e=!("object"!=typeof process||process+""!="[object process]"||process.versions.nw||process.versions.electron&&process.type&&"browser"!==process.type),t=[1/0,1/0,-1/0,-1/0],a=new Float32Array(t),n=[.001,0,0,.001,0,0],s=1.35,r=.35,i=.25925925925925924,o="http://www.w3.org/2000/svg",l=1,f=2,c=4,h=8,u=16,m=64,p=128,d=256,g="pdfjs_internal_editor_",b=3,w=9,j=13,k=15,y=101,q={PRINT:4,MODIFY_CONTENTS:8,COPY:16,MODIFY_ANNOTATIONS:32,FILL_INTERACTIVE_FORMS:256,COPY_FOR_ACCESSIBILITY:512,ASSEMBLE:1024,PRINT_HIGH_QUALITY:2048},v=1,S=2,x=3,C=0,F=4,T=1,O=2,R=3,H={TEXT:1,LINK:2,FREETEXT:3,LINE:4,SQUARE:5,CIRCLE:6,POLYGON:7,POLYLINE:8,HIGHLIGHT:9,UNDERLINE:10,SQUIGGLY:11,STRIKEOUT:12,STAMP:13,CARET:14,INK:15,POPUP:16,FILEATTACHMENT:17,SOUND:18,MOVIE:19,WIDGET:20,SCREEN:21,PRINTERMARK:22,TRAPNET:23,WATERMARK:24,THREED:25,REDACT:26,RICHMEDIA:27},D="Group",M="R",N=0,_=4,E=1,z=2,L=4,U=16,X=32,W=128,K=512,G=1,V=2,$=4096,Y=8192,J=32768,Q=65536,Z=131072,ee=1048576,te=2097152,ae=8388608,ne=16777216,se=1,re=2,ie=3,oe=4,le=5,fe={E:"Mouse Enter",X:"Mouse Exit",D:"Mouse Down",U:"Mouse Up",Fo:"Focus",Bl:"Blur",PO:"PageOpen",PC:"PageClose",PV:"PageVisible",PI:"PageInvisible",K:"Keystroke",F:"Format",V:"Validate",C:"Calculate"},ce={WC:"WillClose",WS:"WillSave",DS:"DidSave",WP:"WillPrint",DP:"DidPrint"},he={O:"PageOpen",C:"PageClose"},ue=1,me=5,pe=1,de=2,ge=3,be=4,we=5,je=6,ke=7,ye=8,qe=9,ve=10,Se=11,Ae=12,xe=13,Ce=14,Ie=15,Fe=16,Te=17,Oe=18,Re=19,He=20,Be=21,De=22,Me=23,Ne=24,Pe=25,_e=26,Ee=27,ze=28,Le=29,Ue=30,Xe=31,We=32,Ke=33,Ge=34,Ve=35,$e=36,Ye=37,Je=38,Qe=39,Ze=40,et=41,tt=42,at=43,nt=44,st=45,rt=46,it=47,ot=48,lt=49,ft=50,ct=51,ht=52,ut=53,mt=54,pt=55,dt=56,gt=57,bt=58,wt=59,jt=60,kt=61,yt=62,qt=63,vt=64,St=65,At=66,xt=67,Ct=68,It=69,Ft=70,Tt=71,Ot=72,Rt=73,Ht=74,Bt=75,Dt=76,Mt=77,Nt=80,Pt=81,_t=83,Et=84,zt=85,Lt=86,Ut=87,Xt=88,Wt=89,Kt=90,Gt=91,Vt=92,$t=93,Yt=94,Jt=0,Qt=1,Zt=2,ea=3,ta=4,aa=1,na=2;let sa=ue;function getVerbosityLevel(){return sa}function info(e){sa>=me&&console.info(`Info: ${e}`)}function warn(e){sa>=ue&&console.warn(`Warning: ${e}`)}function unreachable(e){throw new Error(e)}function assert(e,t){e||unreachable(t)}function createValidAbsoluteUrl(e,t=null,a=null){if(!e)return null;if(a&&"string"==typeof e){if(a.addDefaultProtocol&&e.startsWith("www.")){const t=e.match(/\./g);t?.length>=2&&(e=`http://${e}`)}if(a.tryConvertEncoding)try{e=stringToUTF8String(e)}catch{}}const n=t?URL.parse(e,t):URL.parse(e);return function _isValidProtocol(e){switch(e?.protocol){case"http:":case"https:":case"ftp:":case"mailto:":case"tel:":return!0;default:return!1}}(n)?n:null}function shadow(e,t,a,n=!1){Object.defineProperty(e,t,{value:a,enumerable:!n,configurable:!0,writable:!1});return a}const ra=function BaseExceptionClosure(){function BaseException(e,t){this.message=e;this.name=t}BaseException.prototype=new Error;BaseException.constructor=BaseException;return BaseException}();class PasswordException extends ra{constructor(e,t){super(e,"PasswordException");this.code=t}}class UnknownErrorException extends ra{constructor(e,t){super(e,"UnknownErrorException");this.details=t}}class InvalidPDFException extends ra{constructor(e){super(e,"InvalidPDFException")}}class ResponseException extends ra{constructor(e,t,a){super(e,"ResponseException");this.status=t;this.missing=a}}class FormatError extends ra{constructor(e){super(e,"FormatError")}}class AbortException extends ra{constructor(e){super(e,"AbortException")}}function bytesToString(e){"object"==typeof e&&void 0!==e?.length||unreachable("Invalid argument for bytesToString");const t=e.length,a=8192;if(t<a)return String.fromCharCode.apply(null,e);const n=[];for(let s=0;s<t;s+=a){const r=Math.min(s+a,t),i=e.subarray(s,r);n.push(String.fromCharCode.apply(null,i))}return n.join("")}function stringToBytes(e){"string"!=typeof e&&unreachable("Invalid argument for stringToBytes");const t=e.length,a=new Uint8Array(t);for(let n=0;n<t;++n)a[n]=255&e.charCodeAt(n);return a}function objectSize(e){return Object.keys(e).length}class FeatureTest{static get isLittleEndian(){const e=new Uint8Array(4);e[0]=1;return shadow(this,"isLittleEndian",1===new Uint32Array(e.buffer,0,1)[0])}static get isOffscreenCanvasSupported(){return shadow(this,"isOffscreenCanvasSupported","undefined"!=typeof OffscreenCanvas)}static get isImageDecoderSupported(){return shadow(this,"isImageDecoderSupported","undefined"!=typeof ImageDecoder)}static get isFloat16ArraySupported(){return shadow(this,"isFloat16ArraySupported","undefined"!=typeof Float16Array)}static get isSanitizerSupported(){return shadow(this,"isSanitizerSupported","undefined"!=typeof Sanitizer)}static get platform(){const{platform:e,userAgent:t}=navigator;return shadow(this,"platform",{isAndroid:t.includes("Android"),isLinux:e.includes("Linux"),isMac:e.includes("Mac"),isWindows:e.includes("Win"),isFirefox:t.includes("Firefox")})}static get isCanvasFilterSupported(){let e;this.isOffscreenCanvasSupported&&(e=new OffscreenCanvas(1,1).getContext("2d"));return shadLine truncated
|
||||
/*webpackIgnore: true*/
|
||||
/*@vite-ignore*/
|
||||
`${WasmImage.#I}${this._noWasmFilename}`)).default()}catch(e){warn(`#getJsModule: ${e}`)}e(t)}async#$(e,t,a){try{this.#K||(WasmImage.#W?this.#K=await fetchBinaryData(`${WasmImage.#I}${this._filename}`):this.#K=await WasmImage.#U.sendWithPromise("FetchBinaryData",{kind:"wasmUrl",filename:this._filename}));return a((await WebAssembly.instantiate(this.#K,t)).instance)}catch(t){warn(`#instantiateWasm: ${t}`);this.#V(e);return null}}_getModule(e){if(!this.#G){const{promise:t,resolve:a}=Promise.withResolvers(),n=[t];WasmImage.#C?n.push(e({warn,instantiateWasm:this.#$.bind(this,a)})):this.#V(a);this.#G=Promise.race(n)}return this.#G}async decode(e,t){unreachable("Abstract method `decode` called")}}class Jbig2Error extends ra{constructor(e){super(e,"Jbig2Error")}}class JBig2CCITTFaxImage extends WasmImage{_filename="jbig2.wasm";_noWasmFilename="jbig2_nowasm_fallback.js";static get instance(){return shadow(this,"instance",new JBig2CCITTFaxImage(!0))}async decode(e,t,a,n,s){const r=await this._getModule(Qa);if(!r)throw new Jbig2Error("JBig2 failed to initialize");let i,o;try{const l=e.length;i=r._malloc(l);r.writeArrayToMemory(e,i);if(s)r._ccitt_decode(i,l,t,a,s.K,s.EndOfLine?1:0,s.EncodedByteAlign?1:0,s.BlackIs1?1:0,s.Columns,s.Rows);else{const e=n?n.length:0;if(e>0){o=r._malloc(e);r.writeArrayToMemory(n,o)}r._jbig2_decode(i,l,t,a,o,e)}if(!r.imageData)throw new Jbig2Error("Unknown error");const{imageData:f}=r;r.imageData=null;return f}finally{i&&r._free(i);o&&r._free(o)}}}class CCITTFaxStream extends DecodeStream{constructor(e,t,a){super(t);this.stream=e;this.maybeLength=t;this.dict=e.dict;a instanceof Dict||(a=Dict.empty);this.params={K:a.get("K")||0,EndOfLine:!!a.get("EndOfLine"),EncodedByteAlign:!!a.get("EncodedByteAlign"),Columns:a.get("Columns")||1728,Rows:a.get("Rows")||0,EndOfBlock:!!(a.get("EndOfBlock")??1),BlackIs1:!!a.get("BlackIs1")}}get bytes(){return shadow(this,"bytes",this.stream.getBytes(this.maybeLength))}get isImageStream(){return!0}get isAsyncDecoder(){return!0}async decodeImage(e,t,a){if(this.eof)return this.buffer;e||(e=this.stream.isAsync&&await this.stream.asyncGetBytes()||this.bytes);this.buffer=await JBig2CCITTFaxImage.instance.decode(e,this.dict.get("W","Width"),this.dict.get("H","Height"),null,this.params);this.bufferLength=this.buffer.length;this.eof=!0;return this.buffer}}const Za=new Int32Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),en=new Int32Array([3,4,5,6,7,8,9,10,65547,65549,65551,65553,131091,131095,131099,131103,196643,196651,196659,196667,262211,262227,262243,262259,327811,327843,327875,327907,258,258,258]),tn=new Int32Array([1,2,3,4,65541,65543,131081,131085,196625,196633,262177,262193,327745,327777,393345,393409,459009,459137,524801,525057,590849,591361,657409,658433,724993,727041,794625,798721,868353,876545]),an=[new Int32Array([459008,524368,524304,524568,459024,524400,524336,590016,459016,524384,524320,589984,524288,524416,524352,590048,459012,524376,524312,589968,459028,524408,524344,590032,459020,524392,524328,59e4,524296,524424,524360,590064,459010,524372,524308,524572,459026,524404,524340,590024,459018,524388,524324,589992,524292,524420,524356,590056,459014,524380,524316,589976,459030,524412,524348,590040,459022,524396,524332,590008,524300,524428,524364,590072,459009,524370,524306,524570,459025,524402,524338,590020,459017,524386,524322,589988,524290,524418,524354,590052,459013,524378,524314,589972,459029,524410,524346,590036,459021,524394,524330,590004,524298,524426,524362,590068,459011,524374,524310,524574,459027,524406,524342,590028,459019,524390,524326,589996,524294,524422,524358,590060,459015,524382,524318,589980,459031,524414,524350,590044,459023,524398,524334,590012,524302,524430,524366,590076,459008,524369,524305,524569,459024,524401,524337,590018,459016,524385,524321,589986,524289,524417,524353,590050,459012,524377,524313,589970,459028,524409,524345,590034,459020,524393,524329,590002,524297,524425,524361,590066,459010,524373,524309,524573,459026,524405,524341,590026,459018,524389,524325,589994,524293,524421,524357,590058,459014,524381,524317,589978,459030,524413,524349,590042,459022,524397,524333,590010,524301,524429,524365,590074,459009,524371,524307,524571,459025,524403,524339,590022,459017,524387,524323,589990,524291,524419,524355,590054,459013,524379,524315,589974,459029,524411,524347,590038,459021,524395,524331,590006,524299,524427,524363,590070,459011,524375,524311,524575,459027,524407,524343,590030,459019,524391,524327,589998,524295,524423,524359,590062,459015,524383,524319,589982,459031,524415,524351,590046,459023,524399,524335,590014,524303,524431,524367,590078,459008,524368,524304,524568,459024,524400,524336,590017,459016,524384,524320,589985,524288,524416,524352,590049,459012,524376,524312,589969,459028,524408,524344,590033,459020,524392,524328,590001,524296,524424,524360,590065,459010,524372,524308,524572,459026,524404,524340,590025,459018,524388,524324,589993,524292,524420,524356,590057,459014,524380,524316,589977,459030,524412,524348,59Line truncated
|
||||
@@ -16,6 +16,7 @@ if (
|
||||
[
|
||||
"css",
|
||||
"js",
|
||||
"mjs",
|
||||
"png",
|
||||
"jpg",
|
||||
"jpeg",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<main class="tfe-main" id="main-content">
|
||||
<article class="tfe-layout">
|
||||
|
||||
<!-- Two-column layout: left 35% (info), right 65% (files) -->
|
||||
<!-- Two-column layout: left 40% (info), right 60% (files) -->
|
||||
<div class="tfe-content-row">
|
||||
<div class="tfe-left-column">
|
||||
|
||||
@@ -46,22 +46,22 @@
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
$_hasPages = isset($data["duration_pages"]) && $data["duration_pages"] !== null;
|
||||
$_hasMins = isset($data["duration_minutes"]) && $data["duration_minutes"] !== null;
|
||||
if ($_hasPages || $_hasMins):
|
||||
$_parts = [];
|
||||
if ($_hasPages) $_parts[] = $data['duration_pages'] . ' pages';
|
||||
if ($_hasMins) {
|
||||
$_h = (int)floor($data['duration_minutes'] / 60);
|
||||
$_m = $data['duration_minutes'] % 60;
|
||||
$_parts[] = $_h . 'h' . str_pad((string)$_m, 2, '0', STR_PAD_LEFT);
|
||||
}
|
||||
$_hasPages = isset($data["duration_pages"]) && $data["duration_pages"] !== null && $data["duration_pages"] !== '';
|
||||
$_hasMins = isset($data["duration_minutes"]) && $data["duration_minutes"] !== null && $data["duration_minutes"] !== '';
|
||||
$_parts = [];
|
||||
if ($_hasPages) $_parts[] = $data['duration_pages'] . ' pages';
|
||||
if ($_hasMins) {
|
||||
$_h = (int)floor((int)$data['duration_minutes'] / 60);
|
||||
$_m = (int)$data['duration_minutes'] % 60;
|
||||
$_parts[] = $_h . 'h' . str_pad((string)$_m, 2, '0', STR_PAD_LEFT);
|
||||
}
|
||||
$_duree = $_parts ? htmlspecialchars(implode(', ', $_parts)) : '–';
|
||||
unset($_hasPages, $_hasMins, $_parts, $_h, $_m);
|
||||
?>
|
||||
<p class="tfe-meta-item">
|
||||
<span class="tfe-meta-label">Durée :</span>
|
||||
<?= htmlspecialchars(implode(', ', $_parts)) ?>
|
||||
<?= $_duree ?>
|
||||
</p>
|
||||
<?php unset($_hasPages, $_hasMins, $_parts, $_h, $_m); endif; ?>
|
||||
|
||||
<?php if (!empty($data["languages"])): ?>
|
||||
<p class="tfe-meta-item">
|
||||
@@ -376,10 +376,19 @@
|
||||
?>
|
||||
<div class="tfe-file-item">
|
||||
<?php if ($isPdf): ?>
|
||||
<iframe src="<?= $mediaUrl ?>#toolbar=0&navpanes=0&scrollbar=0"
|
||||
class="tfe-file-iframe"
|
||||
title="<?= $fileName ?>">
|
||||
</iframe>
|
||||
<?php
|
||||
$_pdfLabel = match ($fileType) {
|
||||
'main' => 'TFE',
|
||||
'annex' => 'Annexes',
|
||||
'note_intention' => "Note d'intention",
|
||||
default => '',
|
||||
};
|
||||
?>
|
||||
<div class="pdf-embed-wrapper"
|
||||
data-pdf-url="<?= $mediaUrl ?>"
|
||||
data-pdf-scale="1"
|
||||
data-pdf-label="<?= htmlspecialchars($_pdfLabel) ?>"
|
||||
tabindex="-1"></div>
|
||||
<?php elseif ($isWebsite): ?>
|
||||
<iframe src="<?= $mediaUrl ?>"
|
||||
class="tfe-file-iframe"
|
||||
@@ -458,3 +467,10 @@
|
||||
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<?php if (!$isInterdit && !$shouldHideFiles && !empty($data["files"])): ?>
|
||||
<?php $_hasPdf = false; foreach ($data["files"] as $_f) { $_ext = strtolower(pathinfo($_f["file_path"] ?? '', PATHINFO_EXTENSION)); $_type = $_f['file_type'] ?? ''; if ($_ext === 'pdf' || $_type === 'main') { $_hasPdf = true; break; } } ?>
|
||||
<?php if ($_hasPdf): ?>
|
||||
<script type="module" src="/assets/js/vendor/pdf.min.mjs" async></script>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
Reference in new issue
Block a user