You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2026/09/13 13:16:53 UTC

(juneau) 15/29: TODO-406: Load Excel/PDF export libs from IRS-matching cdnjs tags so the ribbon buttons work.

This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch juneau-release-manager
in repository https://gitbox.apache.org/repos/asf/juneau.git

commit 5a78225f4975e4406f45a5c2e1e9cf208164f97e
Author: James Bognar <ja...@apache.org>
AuthorDate: Fri Aug 21 08:01:15 2026 -0400

    TODO-406: Load Excel/PDF export libs from IRS-matching cdnjs tags so the ribbon buttons work.
    
    JSZip 3.10.1 and pdfMake 0.2.7 (plus vfs_fonts) must precede buttons.html5.min.js so DataTables Buttons feature-detects the globals and juneau-ribbon lights the optional Excel/PDF icons.
---
 src/main/resources/templates/base.ftlh             | 13 +++++++--
 .../apache/juneau/releng/rest/ReleaseRestTest.java | 32 ++++++++++++++++++++++
 2 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/src/main/resources/templates/base.ftlh b/src/main/resources/templates/base.ftlh
index d29e6eea18..5f0d9b2c60 100644
--- a/src/main/resources/templates/base.ftlh
+++ b/src/main/resources/templates/base.ftlh
@@ -42,9 +42,10 @@
     <link rel="icon" type="image/svg+xml" href="/img/oakleaf.svg">
     <#if activeTab?? && (activeTab == 'releases' || activeTab == 'admin')>
     <link rel="stylesheet" href="/datatables/dataTables.dataTables.min.css">
-    <#-- DataTables Buttons extension (copy/csv export) — caller-provided per ASF category-A discipline; CDN
-         coordinates per the toolkit design §6.11. Only the copy/csv cluster needs this; excel/pdf (JSZip/pdfmake)
-         stay unloaded and are feature-detected off by juneau-ribbon.js. -->
+    <#-- DataTables Buttons extension (copy/csv/excel/pdf export) — caller-provided per ASF category-A discipline;
+         CDN coordinates per the toolkit design §6.11. The excel/pdf cluster additionally needs JSZip + pdfMake,
+         loaded from cdnjs in the script block below (before buttons.html5.min.js) so juneau-ribbon.js
+         feature-detects window.JSZip / window.pdfMake and lights the Excel/PDF icon buttons. -->
     <link rel="stylesheet" href="https://cdn.datatables.net/buttons/3.2.0/css/buttons.dataTables.min.css">
     <#-- First-party toolkit base .tag chip stylesheet (neutral); the app's console-ui palette themes the same
          .tag.<domain>.<value> classes. This same stylesheet also carries the TODO-399 Phase C .jc-tab/.jc-panel
@@ -97,6 +98,12 @@
     <script src="/datatables/jquery.min.js"></script>
     <script src="/datatables/dataTables.min.js"></script>
     <script src="https://cdn.datatables.net/buttons/3.2.0/js/dataTables.buttons.min.js"></script>
+    <#-- JSZip (Excel export) + pdfMake (PDF export) — caller-provided category-A libs (MIT), pinned to cdnjs
+         coordinates; MUST load before buttons.html5.min.js so DataTables Buttons feature-detects window.JSZip /
+         window.pdfMake and juneau-ribbon.js lights the excel/pdf icon buttons declared .optional("excel","pdf"). -->
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.min.js"></script>
     <script src="https://cdn.datatables.net/buttons/3.2.0/js/buttons.html5.min.js"></script>
     <script src="${rendersJsUrl!'/rest/releases/juneau-renders.js'}"></script>
     <script src="${iconsJsUrl!'/rest/releases/juneau-icons.js'}"></script>
diff --git a/src/test/java/org/apache/juneau/releng/rest/ReleaseRestTest.java b/src/test/java/org/apache/juneau/releng/rest/ReleaseRestTest.java
index 7a815551b4..810adec2b2 100644
--- a/src/test/java/org/apache/juneau/releng/rest/ReleaseRestTest.java
+++ b/src/test/java/org/apache/juneau/releng/rest/ReleaseRestTest.java
@@ -127,6 +127,38 @@ class ReleaseRestTest {
 		}
 	}
 
+	/**
+	 * The Excel/PDF export buttons are declared {@code .optional("excel","pdf")} on {@link ReleaseRest} and are
+	 * feature-detected off {@code window.JSZip} / {@code window.pdfMake} by {@code juneau-ribbon.js}, so they only
+	 * render when JSZip + pdfMake are on the page. DataTables Buttons' HTML5 export reads those globals as
+	 * {@code buttons.html5.min.js} initializes, so all three export-dependency scripts must be included and ordered
+	 * before it. Asserts the served page carries the JSZip, pdfMake, and pdfMake {@code vfs_fonts} includes, each
+	 * ahead of {@code buttons.html5.min.js}.
+	 */
+	@Test
+	void pageIncludesExportDependencyScriptsBeforeButtonsHtml5() throws Exception {
+		try (var client = client(rest(List.of(release("9.2.1", "RELEASED"))))) {
+			try (var resp = client.request("GET", "/").run()) {
+				assertEquals(200, resp.getStatusCode());
+				var body = resp.getBodyAsString();
+				var jszipIdx = body.indexOf("jszip.min.js");
+				var pdfmakeIdx = body.indexOf("pdfmake.min.js");
+				var vfsIdx = body.indexOf("vfs_fonts.min.js");
+				var buttonsHtml5Idx = body.indexOf("buttons.html5.min.js");
+				assertTrue(jszipIdx >= 0, "Missing jszip.min.js script include: " + body);
+				assertTrue(pdfmakeIdx >= 0, "Missing pdfmake.min.js script include: " + body);
+				assertTrue(vfsIdx >= 0, "Missing vfs_fonts.min.js script include: " + body);
+				assertTrue(buttonsHtml5Idx >= 0, "Missing buttons.html5.min.js script include: " + body);
+				assertTrue(jszipIdx < buttonsHtml5Idx,
+					"jszip.min.js must be included before buttons.html5.min.js: " + body);
+				assertTrue(pdfmakeIdx < buttonsHtml5Idx,
+					"pdfmake.min.js must be included before buttons.html5.min.js: " + body);
+				assertTrue(vfsIdx < buttonsHtml5Idx,
+					"vfs_fonts.min.js must be included before buttons.html5.min.js: " + body);
+			}
+		}
+	}
+
 	/**
 	 * The {@code /data} endpoint speaks the DataTables server-side-processing contract: given a request carrying
 	 * DataTables params it returns a {@code DataTablesResults} envelope ({@code {draw, recordsTotal, recordsFiltered,