(container, filePath, caption)
| 636 | } |
| 637 | |
| 638 | function appendFileCard(container, filePath, caption) { |
| 639 | const fileName = basename(filePath); |
| 640 | const title = caption || fileName; |
| 641 | const card = document.createElement("a"); |
| 642 | card.className = "file-card"; |
| 643 | card.href = buildFileDownloadUrl(filePath); |
| 644 | card.title = filePath; |
| 645 | card.setAttribute("download", fileName); |
| 646 | card.setAttribute("target", "_blank"); |
| 647 | card.setAttribute("rel", "noopener noreferrer"); |
| 648 | card.innerHTML = ` |
| 649 | <div class="file-card-icon">FILE</div> |
| 650 | <div class="file-card-copy"> |
| 651 | <div class="file-card-title">${escapeHtml(title)}</div> |
| 652 | <div class="file-card-meta">${escapeHtml(fileName)}</div> |
| 653 | </div> |
| 654 | <div class="file-card-action">Download</div> |
| 655 | `; |
| 656 | |
| 657 | const indicator = container.querySelector(".loading-indicator"); |
| 658 | if (indicator) { |
| 659 | container.insertBefore(card, indicator); |
| 660 | } else { |
| 661 | container.appendChild(card); |
| 662 | } |
| 663 | } |
| 664 | |
| 665 | function basename(filePath) { |
| 666 | const normalized = String(filePath).replace(/\\/g, "/"); |
no test coverage detected