From 898b01b3a9e3ee47b9b223471f5e9744b67c64ab Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 May 2026 18:12:56 +0000 Subject: [PATCH 1/7] Add citation copy buttons, DOI badge, and seminal articles section Agent-Logs-Url: https://github.com/Bioconductor/bioconductor.org/sessions/1c891688-7cff-4ad6-9e72-04bb485a5953 Co-authored-by: LiNk-NY <4392950+LiNk-NY@users.noreply.github.com> --- assets/js/bioconductor.js | 55 +++++++++++++++++++++++++ assets/style/pages/packages.css | 37 +++++++++++++++++ content/about/index.md | 26 ++++++++++++ layouts/_bioc_views_package_detail.html | 3 +- layouts/components/packages/badges.html | 1 + 5 files changed, 121 insertions(+), 1 deletion(-) diff --git a/assets/js/bioconductor.js b/assets/js/bioconductor.js index 6c86338b3..53f6d60d1 100644 --- a/assets/js/bioconductor.js +++ b/assets/js/bioconductor.js @@ -331,6 +331,8 @@ var handleCitations = function () { segs.push(pkg); segs.push("citation.html"); url = segs.join("/"); + var bibUrl = url.replace("citation.html", "citation.bib"); + var pkgName = jQuery("#bioc-citation-outer").data("package") || pkg; jQuery.ajax({ url: url, dataType: "html", @@ -342,6 +344,59 @@ var handleCitations = function () { data = data.replace(" (????)", ""); jQuery("#bioc-citation").html(data); + + // Extract preferred DOI from citation text + var citationText = jQuery("#bioc-citation").text(); + var doiMatch = citationText.match(/\bdoi:?(10\.\d{4,}\/\S+)/i) || + citationText.match(/https?:\/\/doi\.org\/(10\.\d{4,}\/\S+)/i); + var preferredDoi = doiMatch ? doiMatch[1] : "10.18129/B9.bioc." + pkgName; + // Strip trailing punctuation from DOI + preferredDoi = preferredDoi.replace(/[.,;)>]+$/, ""); + + // Update DOI badge with preferred citation DOI + var encodedDoi = preferredDoi.replace(/-/g, "--").replace(/_/g, "__").replace(/\//g, "%2F"); + var badgeHtml = '' + + ''; + jQuery("#citation-doi-badge").html(badgeHtml); + + // Add copy/download action buttons + var actionsHtml = + '' + + ''; + jQuery("#bioc-citation-actions").html(actionsHtml); + + jQuery("#bioc-copy-text-btn").on("click", function () { + var btn = jQuery(this); + var text = jQuery("#bioc-citation").text().trim(); + navigator.clipboard.writeText(text).then(function () { + var orig = btn.text(); + btn.text("Copied!").addClass("copied"); + setTimeout(function () { btn.text(orig).removeClass("copied"); }, 2000); + }); + }); + + jQuery("#bioc-copy-bibtex-btn").on("click", function () { + var btn = jQuery(this); + btn.prop("disabled", true); + jQuery.ajax({ + url: bibUrl, + dataType: "text", + success: function (bibData) { + navigator.clipboard.writeText(bibData).then(function () { + var orig = "\uD83D\uDCCB Copy BibTeX"; + btn.text("Copied!").addClass("copied"); + setTimeout(function () { btn.text(orig).removeClass("copied").prop("disabled", false); }, 2000); + }); + }, + error: function () { + btn.text("BibTeX unavailable").prop("disabled", false); + setTimeout(function () { btn.text("\uD83D\uDCCB Copy BibTeX"); }, 3000); + }, + }); + }); + jQuery("#bioc-citation-outer").show(); }, error: function (data, textStatus, jqXHR) { diff --git a/assets/style/pages/packages.css b/assets/style/pages/packages.css index 850a6315a..8c2e1159c 100644 --- a/assets/style/pages/packages.css +++ b/assets/style/pages/packages.css @@ -128,6 +128,43 @@ ul.ui-autocomplete li::marker { margin: 0.5rem 0 1rem; } +.citation-actions { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin: 0.75rem 0 0.25rem; +} + +.citation-btn { + background: var(--neutral-n50); + color: var(--primary-p400); + border: 1px solid var(--neutral-n75); + border-radius: 8rem; + cursor: pointer; + font-size: 0.85rem; + padding: 0.2rem 0.75rem; + transition: background 0.2s; +} + +.citation-btn:hover { + background: var(--primary-p50); +} + +.citation-btn:active { + background: var(--primary-p200); +} + +.citation-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.citation-btn.copied { + background: #d4edda; + color: #155724; + border-color: #c3e6cb; +} + @media (max-device-width: 1450px), (max-width: 1450px) { .biocViewsTreeContainer { display: flex; diff --git a/content/about/index.md b/content/about/index.md index 7dbbdcd41..06da2549f 100644 --- a/content/about/index.md +++ b/content/about/index.md @@ -43,6 +43,32 @@ Methods 12:115-121][1] and Gentleman et al., 2004 [Genome Biology [1]: http://www.nature.com/nmeth/journal/v12/n2/abs/nmeth.3252.html [2]: https://genomebiology.biomedcentral.com/track/pdf/10.1186/gb-2004-5-10-r80.pdf +
+ +

Huber W, Carey VJ, Gentleman R, Anders S, Carlson M, Carvalho BS, +Bravo HC, Davis S, Gatto L, Girke T, Gottardo R, Hahne F, Hansen KD, Irizarry RA, +Lawrence M, Love MI, MacDonald J, Obenchain V, OleΕ› AK, PagΓ¨s H, Reyes A, Shannon P, +Smyth GK, Tenenbaum D, Waldron L, Morgan M (2015). "Orchestrating high-throughput +genomic analysis with Bioconductor." Nature Methods, 12(2), +115–121. doi:10.1038/nmeth.3252.

+
+ + +
+ +

Gentleman RC, Carey VJ, Bates DM, Bolstad B, Dettling M, Dudoit S, +Ellis B, Gautier L, Ge Y, Gentry J, Hornik K, Hothorn T, Huber W, Iacus S, Irizarry R, +Leisch F, Li C, Maechler M, Rossini AJ, Sawitzki G, Smith C, Smyth G, Tierney L, Yang JYH, +Zhang J (2004). "Bioconductor: open software development for computational biology and +bioinformatics." Genome Biology, 5(10), R80. +doi:10.1186/gb-2004-5-10-r80.

+
+ + +
+ +
+
<%= render('/components/homepage/join/') %>
diff --git a/layouts/_bioc_views_package_detail.html b/layouts/_bioc_views_package_detail.html index 4575078e6..f37158998 100644 --- a/layouts/_bioc_views_package_detail.html +++ b/layouts/_bioc_views_package_detail.html @@ -34,9 +34,10 @@

<%= @package[:Title]%>

Maintainer: <%= filter_emails(@package[:Maintainer])%>

-
+
Citation (from within R, enter citation("<%=@package[:Package]%>")):
+
diff --git a/layouts/components/packages/badges.html b/layouts/components/packages/badges.html index 9a8490d0b..dfd203ece 100644 --- a/layouts/components/packages/badges.html +++ b/layouts/components/packages/badges.html @@ -161,4 +161,5 @@ 10.18129/B9.bioc.<%=@item[:Package]%>

+
From de14f6fbc8fd3fda649593a0c17ea0eeb40a3b89 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 May 2026 18:17:30 +0000 Subject: [PATCH 2/7] Fix XSS via DOI sanitization, add ARIA live region for clipboard feedback Agent-Logs-Url: https://github.com/Bioconductor/bioconductor.org/sessions/1c891688-7cff-4ad6-9e72-04bb485a5953 Co-authored-by: LiNk-NY <4392950+LiNk-NY@users.noreply.github.com> --- assets/js/bioconductor.js | 90 ++++++++++++++++++------- content/about/index.md | 8 +-- layouts/_bioc_views_package_detail.html | 1 + 3 files changed, 71 insertions(+), 28 deletions(-) diff --git a/assets/js/bioconductor.js b/assets/js/bioconductor.js index 53f6d60d1..2fdb199b4 100644 --- a/assets/js/bioconductor.js +++ b/assets/js/bioconductor.js @@ -320,6 +320,37 @@ var getHrefForSymlinks = function (href) { } }; +// Copy text to clipboard and show brief feedback on the button +var copyToClipboardWithFeedback = function (btn, text, label, statusEl) { + navigator.clipboard.writeText(text).then(function () { + btn.text("Copied!").addClass("copied"); + if (statusEl) { statusEl.text("Copied to clipboard."); } + setTimeout(function () { + btn.text(label).removeClass("copied"); + if (statusEl) { statusEl.text(""); } + }, 2000); + }).catch(function () { + btn.text("Copy failed").prop("disabled", false); + if (statusEl) { statusEl.text("Copy failed. Please copy the text manually."); } + setTimeout(function () { + btn.text(label); + if (statusEl) { statusEl.text(""); } + }, 3000); + }); +}; + +// Copy a static citation text to clipboard; used for hardcoded project citations. +// Called from inline onclick handlers in content pages. +var copyStaticCitationText = function (btn, text) { + copyToClipboardWithFeedback(jQuery(btn), text, btn.textContent, null); +}; + +// Copy a static BibTeX string to clipboard; used for hardcoded project citations. +// Called from inline onclick handlers in content pages. +var copyStaticBibtex = function (btn, bibtex) { + copyToClipboardWithFeedback(jQuery(btn), bibtex, btn.textContent, null); +}; + var handleCitations = function () { if (jQuery("#bioc-citation").length) { jQuery("#bioc-citation-outer").hide(); @@ -345,23 +376,34 @@ var handleCitations = function () { data = data.replace(" (????)", ""); jQuery("#bioc-citation").html(data); - // Extract preferred DOI from citation text + // Extract preferred DOI from citation text. + // Use a precise pattern that avoids capturing trailing punctuation. var citationText = jQuery("#bioc-citation").text(); - var doiMatch = citationText.match(/\bdoi:?(10\.\d{4,}\/\S+)/i) || - citationText.match(/https?:\/\/doi\.org\/(10\.\d{4,}\/\S+)/i); + var doiPattern = /\bdoi:?(10\.\d{4,}\/[^\s.,;)>]+)/i; + var urlPattern = /https?:\/\/doi\.org\/(10\.\d{4,}\/[^\s.,;)>]+)/i; + var doiMatch = citationText.match(doiPattern) || citationText.match(urlPattern); var preferredDoi = doiMatch ? doiMatch[1] : "10.18129/B9.bioc." + pkgName; - // Strip trailing punctuation from DOI - preferredDoi = preferredDoi.replace(/[.,;)>]+$/, ""); - // Update DOI badge with preferred citation DOI + // Sanitize DOI: only allow characters valid in a DOI (alphanumeric, + // and the punctuation permitted by the DOI specification). + if (!/^10\.\d{4,}\/[\w./:;()\[\]<>-]+$/.test(preferredDoi)) { + preferredDoi = "10.18129/B9.bioc." + pkgName; + } + + // Build shields.io badge URL. Shields.io requires hyphens doubled, + // underscores doubled, and slashes percent-encoded in badge label text. var encodedDoi = preferredDoi.replace(/-/g, "--").replace(/_/g, "__").replace(/\//g, "%2F"); - var badgeHtml = '' + - ''; - jQuery("#citation-doi-badge").html(badgeHtml); - // Add copy/download action buttons + // Build badge using DOM construction to avoid XSS via preferredDoi + var $badgeLink = jQuery("") + .attr("href", "https://doi.org/" + preferredDoi) + .attr("title", "Preferred citation DOI"); + var $badgeImg = jQuery("") + .attr("src", "https://img.shields.io/badge/DOI-" + encodedDoi + "-blue") + .attr("alt", "DOI badge"); + jQuery("#citation-doi-badge").empty().append($badgeLink.append($badgeImg)); + + // Add copy action buttons var actionsHtml = '' + ''; @@ -369,30 +411,30 @@ var handleCitations = function () { jQuery("#bioc-copy-text-btn").on("click", function () { var btn = jQuery(this); + var statusEl = jQuery("#bioc-citation-status"); var text = jQuery("#bioc-citation").text().trim(); - navigator.clipboard.writeText(text).then(function () { - var orig = btn.text(); - btn.text("Copied!").addClass("copied"); - setTimeout(function () { btn.text(orig).removeClass("copied"); }, 2000); - }); + copyToClipboardWithFeedback(btn, text, "\uD83D\uDCCB Copy Text", statusEl); }); jQuery("#bioc-copy-bibtex-btn").on("click", function () { var btn = jQuery(this); + var statusEl = jQuery("#bioc-citation-status"); + var origLabel = "\uD83D\uDCCB Copy BibTeX"; btn.prop("disabled", true); jQuery.ajax({ url: bibUrl, dataType: "text", success: function (bibData) { - navigator.clipboard.writeText(bibData).then(function () { - var orig = "\uD83D\uDCCB Copy BibTeX"; - btn.text("Copied!").addClass("copied"); - setTimeout(function () { btn.text(orig).removeClass("copied").prop("disabled", false); }, 2000); - }); + copyToClipboardWithFeedback(btn, bibData, origLabel, statusEl); + btn.prop("disabled", false); }, error: function () { - btn.text("BibTeX unavailable").prop("disabled", false); - setTimeout(function () { btn.text("\uD83D\uDCCB Copy BibTeX"); }, 3000); + btn.text("BibTeX unavailable"); + if (statusEl) { statusEl.text("BibTeX format is not available for this package."); } + setTimeout(function () { + btn.text(origLabel).prop("disabled", false); + if (statusEl) { statusEl.text(""); } + }, 3000); }, }); }); diff --git a/content/about/index.md b/content/about/index.md index 06da2549f..6828227f7 100644 --- a/content/about/index.md +++ b/content/about/index.md @@ -52,8 +52,8 @@ Smyth GK, Tenenbaum D, Waldron L, Morgan M (2015). "Orchestrating high-throughpu genomic analysis with Bioconductor." Nature Methods, 12(2), 115–121. doi:10.1038/nmeth.3252.

- - + +

Gentleman RC, Carey VJ, Bates DM, Bolstad B, Dettling M, Dudoit S, @@ -63,8 +63,8 @@ Zhang J (2004). "Bioconductor: open software development for computational biolo bioinformatics." Genome Biology, 5(10), R80. doi:10.1186/gb-2004-5-10-r80.

- - + +
diff --git a/layouts/_bioc_views_package_detail.html b/layouts/_bioc_views_package_detail.html index f37158998..508ffd3e7 100644 --- a/layouts/_bioc_views_package_detail.html +++ b/layouts/_bioc_views_package_detail.html @@ -38,6 +38,7 @@

<%= @package[:Title]%>

Citation (from within R, enter citation("<%=@package[:Package]%>")):
+
From 3cea8ce2c6d7cc5a34bcd2071e42df59ae743fdc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 May 2026 18:20:40 +0000 Subject: [PATCH 3/7] Use data attributes for static citation buttons, improve DOI encoding and sanitization Agent-Logs-Url: https://github.com/Bioconductor/bioconductor.org/sessions/1c891688-7cff-4ad6-9e72-04bb485a5953 Co-authored-by: LiNk-NY <4392950+LiNk-NY@users.noreply.github.com> --- assets/js/bioconductor.js | 57 +++++++++++++++++++++++---------------- content/about/index.md | 8 +++--- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/assets/js/bioconductor.js b/assets/js/bioconductor.js index 2fdb199b4..16c5e68b2 100644 --- a/assets/js/bioconductor.js +++ b/assets/js/bioconductor.js @@ -330,7 +330,7 @@ var copyToClipboardWithFeedback = function (btn, text, label, statusEl) { if (statusEl) { statusEl.text(""); } }, 2000); }).catch(function () { - btn.text("Copy failed").prop("disabled", false); + btn.text("Copy failed"); if (statusEl) { statusEl.text("Copy failed. Please copy the text manually."); } setTimeout(function () { btn.text(label); @@ -339,16 +339,18 @@ var copyToClipboardWithFeedback = function (btn, text, label, statusEl) { }); }; -// Copy a static citation text to clipboard; used for hardcoded project citations. -// Called from inline onclick handlers in content pages. -var copyStaticCitationText = function (btn, text) { - copyToClipboardWithFeedback(jQuery(btn), text, btn.textContent, null); -}; - -// Copy a static BibTeX string to clipboard; used for hardcoded project citations. -// Called from inline onclick handlers in content pages. -var copyStaticBibtex = function (btn, bibtex) { - copyToClipboardWithFeedback(jQuery(btn), bibtex, btn.textContent, null); +// Attach event listeners to static citation copy buttons that use data attributes. +// Handles .citation-btn elements with data-citation-text or data-bibtex attributes, +// replacing the need for inline onclick handlers in content pages. +var handleStaticCitationButtons = function () { + jQuery(document).on("click", ".citation-btn[data-citation-text]", function () { + var btn = jQuery(this); + copyToClipboardWithFeedback(btn, btn.data("citation-text"), btn.text(), null); + }); + jQuery(document).on("click", ".citation-btn[data-bibtex]", function () { + var btn = jQuery(this); + copyToClipboardWithFeedback(btn, btn.data("bibtex"), btn.text(), null); + }); }; var handleCitations = function () { @@ -377,29 +379,37 @@ var handleCitations = function () { jQuery("#bioc-citation").html(data); // Extract preferred DOI from citation text. - // Use a precise pattern that avoids capturing trailing punctuation. + // Use a permissive pattern (same character set as the sanitization step below). var citationText = jQuery("#bioc-citation").text(); - var doiPattern = /\bdoi:?(10\.\d{4,}\/[^\s.,;)>]+)/i; - var urlPattern = /https?:\/\/doi\.org\/(10\.\d{4,}\/[^\s.,;)>]+)/i; + var doiChars = "[\\w./:;()\\[\\]<>-]+"; + var doiPattern = new RegExp("\\bdoi:?(10\\.\\d{4,}\\/" + doiChars + ")", "i"); + var urlPattern = new RegExp("https?:\\/\\/doi\\.org\\/(10\\.\\d{4,}\\/" + doiChars + ")", "i"); var doiMatch = citationText.match(doiPattern) || citationText.match(urlPattern); var preferredDoi = doiMatch ? doiMatch[1] : "10.18129/B9.bioc." + pkgName; - // Sanitize DOI: only allow characters valid in a DOI (alphanumeric, - // and the punctuation permitted by the DOI specification). - if (!/^10\.\d{4,}\/[\w./:;()\[\]<>-]+$/.test(preferredDoi)) { + // Sanitize DOI: only allow characters valid in a DOI (alphanumeric and + // DOI-permitted punctuation). Falls back to the package landing page DOI. + if (!/^10\.\d{4,}\/[\w./:;()[\]<>-]+$/.test(preferredDoi)) { preferredDoi = "10.18129/B9.bioc." + pkgName; } // Build shields.io badge URL. Shields.io requires hyphens doubled, - // underscores doubled, and slashes percent-encoded in badge label text. - var encodedDoi = preferredDoi.replace(/-/g, "--").replace(/_/g, "__").replace(/\//g, "%2F"); - - // Build badge using DOM construction to avoid XSS via preferredDoi + // underscores doubled, slashes and other special chars percent-encoded + // in the badge label text. + var encodedDoi = preferredDoi + .replace(/-/g, "--") + .replace(/_/g, "__") + .replace(/[^A-Za-z0-9.-]/g, function (c) { return encodeURIComponent(c); }); + + // Build badge using DOM construction. encodeURI ensures the URL is valid + // and safe even before the DOI sanitization step above. + var doiHref = encodeURI("https://doi.org/" + preferredDoi); + var badgeSrc = encodeURI("https://img.shields.io/badge/DOI-" + encodedDoi + "-blue"); var $badgeLink = jQuery("") - .attr("href", "https://doi.org/" + preferredDoi) + .attr("href", doiHref) .attr("title", "Preferred citation DOI"); var $badgeImg = jQuery("") - .attr("src", "https://img.shields.io/badge/DOI-" + encodedDoi + "-blue") + .attr("src", badgeSrc) .attr("alt", "DOI badge"); jQuery("#citation-doi-badge").empty().append($badgeLink.append($badgeImg)); @@ -458,6 +468,7 @@ jQuery(function () { }); jQuery(".rpack").tooltip({ tip: "#tooltip" }); //{ effect: 'slide'}); handleCitations(); + handleStaticCitationButtons(); }); var submit_tryitnow = function () { diff --git a/content/about/index.md b/content/about/index.md index 6828227f7..b88ecd421 100644 --- a/content/about/index.md +++ b/content/about/index.md @@ -52,8 +52,8 @@ Smyth GK, Tenenbaum D, Waldron L, Morgan M (2015). "Orchestrating high-throughpu genomic analysis with Bioconductor." Nature Methods, 12(2), 115–121. doi:10.1038/nmeth.3252.

- - + +

Gentleman RC, Carey VJ, Bates DM, Bolstad B, Dettling M, Dudoit S, @@ -63,8 +63,8 @@ Zhang J (2004). "Bioconductor: open software development for computational biolo bioinformatics." Genome Biology, 5(10), R80. doi:10.1186/gb-2004-5-10-r80.

- - + +
From 75e43885d753e60cf207696141e6f0ed54adba1d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 May 2026 18:22:04 +0000 Subject: [PATCH 4/7] Fix DOI character class to exclude angle brackets, fix shields.io underscore encoding Agent-Logs-Url: https://github.com/Bioconductor/bioconductor.org/sessions/1c891688-7cff-4ad6-9e72-04bb485a5953 Co-authored-by: LiNk-NY <4392950+LiNk-NY@users.noreply.github.com> --- assets/js/bioconductor.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/assets/js/bioconductor.js b/assets/js/bioconductor.js index 16c5e68b2..c5b867289 100644 --- a/assets/js/bioconductor.js +++ b/assets/js/bioconductor.js @@ -379,9 +379,9 @@ var handleCitations = function () { jQuery("#bioc-citation").html(data); // Extract preferred DOI from citation text. - // Use a permissive pattern (same character set as the sanitization step below). + // Use a pattern matching only valid DOI characters per the DOI specification. var citationText = jQuery("#bioc-citation").text(); - var doiChars = "[\\w./:;()\\[\\]<>-]+"; + var doiChars = "[\\w./:;()\\[\\]_-]+"; var doiPattern = new RegExp("\\bdoi:?(10\\.\\d{4,}\\/" + doiChars + ")", "i"); var urlPattern = new RegExp("https?:\\/\\/doi\\.org\\/(10\\.\\d{4,}\\/" + doiChars + ")", "i"); var doiMatch = citationText.match(doiPattern) || citationText.match(urlPattern); @@ -389,17 +389,18 @@ var handleCitations = function () { // Sanitize DOI: only allow characters valid in a DOI (alphanumeric and // DOI-permitted punctuation). Falls back to the package landing page DOI. - if (!/^10\.\d{4,}\/[\w./:;()[\]<>-]+$/.test(preferredDoi)) { + if (!/^10\.\d{4,}\/[\w./:;()[\]_-]+$/.test(preferredDoi)) { preferredDoi = "10.18129/B9.bioc." + pkgName; } - // Build shields.io badge URL. Shields.io requires hyphens doubled, - // underscores doubled, slashes and other special chars percent-encoded - // in the badge label text. + // Build shields.io badge URL. Shields.io requires hyphens doubled and + // underscores doubled in the badge label. Slashes and other special chars + // must be percent-encoded. The underscore is excluded from percent-encoding + // because it is doubled in the preceding step. var encodedDoi = preferredDoi .replace(/-/g, "--") .replace(/_/g, "__") - .replace(/[^A-Za-z0-9.-]/g, function (c) { return encodeURIComponent(c); }); + .replace(/[^A-Za-z0-9._-]/g, function (c) { return encodeURIComponent(c); }); // Build badge using DOM construction. encodeURI ensures the URL is valid // and safe even before the DOI sanitization step above. From 3835f9a3d85d4ac175ac3e1f54c113eb9d94ef4b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 May 2026 20:35:59 +0000 Subject: [PATCH 5/7] Move seminal citations to package pages and add clipboard fallback Agent-Logs-Url: https://github.com/Bioconductor/bioconductor.org/sessions/f87f98f7-0089-445e-a2e7-eb77b4e8f968 Co-authored-by: LiNk-NY <4392950+LiNk-NY@users.noreply.github.com> --- assets/js/bioconductor.js | 35 ++++++++++++++++++++++++- content/about/index.md | 26 ------------------ layouts/_bioc_views_package_detail.html | 24 ++++++++++++++++- 3 files changed, 57 insertions(+), 28 deletions(-) diff --git a/assets/js/bioconductor.js b/assets/js/bioconductor.js index c5b867289..67145cdb3 100644 --- a/assets/js/bioconductor.js +++ b/assets/js/bioconductor.js @@ -320,9 +320,42 @@ var getHrefForSymlinks = function (href) { } }; +var fallbackCopyText = function (text) { + return new Promise(function (resolve, reject) { + var textarea = document.createElement("textarea"); + textarea.value = text; + textarea.setAttribute("readonly", ""); + textarea.style.position = "absolute"; + textarea.style.left = "-9999px"; + document.body.appendChild(textarea); + textarea.select(); + textarea.setSelectionRange(0, textarea.value.length); + try { + if (document.execCommand("copy")) { + resolve(); + } else { + reject(new Error("Copy command failed")); + } + } catch (e) { + reject(e); + } finally { + document.body.removeChild(textarea); + } + }); +}; + +var writeTextToClipboard = function (text) { + if (navigator.clipboard && window.isSecureContext) { + return navigator.clipboard.writeText(text).catch(function () { + return fallbackCopyText(text); + }); + } + return fallbackCopyText(text); +}; + // Copy text to clipboard and show brief feedback on the button var copyToClipboardWithFeedback = function (btn, text, label, statusEl) { - navigator.clipboard.writeText(text).then(function () { + writeTextToClipboard(text).then(function () { btn.text("Copied!").addClass("copied"); if (statusEl) { statusEl.text("Copied to clipboard."); } setTimeout(function () { diff --git a/content/about/index.md b/content/about/index.md index b88ecd421..7dbbdcd41 100644 --- a/content/about/index.md +++ b/content/about/index.md @@ -43,32 +43,6 @@ Methods 12:115-121][1] and Gentleman et al., 2004 [Genome Biology [1]: http://www.nature.com/nmeth/journal/v12/n2/abs/nmeth.3252.html [2]: https://genomebiology.biomedcentral.com/track/pdf/10.1186/gb-2004-5-10-r80.pdf -
- -

Huber W, Carey VJ, Gentleman R, Anders S, Carlson M, Carvalho BS, -Bravo HC, Davis S, Gatto L, Girke T, Gottardo R, Hahne F, Hansen KD, Irizarry RA, -Lawrence M, Love MI, MacDonald J, Obenchain V, OleΕ› AK, PagΓ¨s H, Reyes A, Shannon P, -Smyth GK, Tenenbaum D, Waldron L, Morgan M (2015). "Orchestrating high-throughput -genomic analysis with Bioconductor." Nature Methods, 12(2), -115–121. doi:10.1038/nmeth.3252.

-
- - -
- -

Gentleman RC, Carey VJ, Bates DM, Bolstad B, Dettling M, Dudoit S, -Ellis B, Gautier L, Ge Y, Gentry J, Hornik K, Hothorn T, Huber W, Iacus S, Irizarry R, -Leisch F, Li C, Maechler M, Rossini AJ, Sawitzki G, Smith C, Smyth G, Tierney L, Yang JYH, -Zhang J (2004). "Bioconductor: open software development for computational biology and -bioinformatics." Genome Biology, 5(10), R80. -doi:10.1186/gb-2004-5-10-r80.

-
- - -
- -
-
<%= render('/components/homepage/join/') %>
diff --git a/layouts/_bioc_views_package_detail.html b/layouts/_bioc_views_package_detail.html index 508ffd3e7..35452e7b7 100644 --- a/layouts/_bioc_views_package_detail.html +++ b/layouts/_bioc_views_package_detail.html @@ -40,6 +40,29 @@

<%= @package[:Title]%>

+
+ Seminal Bioconductor project articles: +

Huber W, Carey VJ, Gentleman R, Anders S, Carlson M, Carvalho BS, + Bravo HC, Davis S, Gatto L, Girke T, Gottardo R, Hahne F, Hansen KD, Irizarry RA, + Lawrence M, Love MI, MacDonald J, Obenchain V, OleΕ› AK, PagΓ¨s H, Reyes A, Shannon P, + Smyth GK, Tenenbaum D, Waldron L, Morgan M (2015). "Orchestrating high-throughput + genomic analysis with Bioconductor." Nature Methods, 12(2), + 115–121. doi:10.1038/nmeth.3252.

+
+ + +
+

Gentleman RC, Carey VJ, Bates DM, Bolstad B, Dettling M, Dudoit S, + Ellis B, Gautier L, Ge Y, Gentry J, Hornik K, Hothorn T, Huber W, Iacus S, Irizarry R, + Leisch F, Li C, Maechler M, Rossini AJ, Sawitzki G, Smith C, Smyth G, Tierney L, Yang JYH, + Zhang J (2004). "Bioconductor: open software development for computational biology and + bioinformatics." Genome Biology, 5(10), R80. + doi:10.1186/gb-2004-5-10-r80.

+
+ + +
+
@@ -49,4 +72,3 @@

<%= @package[:Title]%>

<%= render("/components/packages/details/", :package => @package) %> <%= render("/components/packages/archives/", :package => @package) %> - From 84ac32a855b81d33deb86aed821e54f6f7fde024 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 May 2026 20:38:12 +0000 Subject: [PATCH 6/7] Harden DOI parsing/encoding and add accessibility labels for citation buttons Agent-Logs-Url: https://github.com/Bioconductor/bioconductor.org/sessions/f87f98f7-0089-445e-a2e7-eb77b4e8f968 Co-authored-by: LiNk-NY <4392950+LiNk-NY@users.noreply.github.com> --- assets/js/bioconductor.js | 32 ++++++++++++------------- layouts/_bioc_views_package_detail.html | 8 +++---- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/assets/js/bioconductor.js b/assets/js/bioconductor.js index 67145cdb3..49e1a38cc 100644 --- a/assets/js/bioconductor.js +++ b/assets/js/bioconductor.js @@ -353,6 +353,13 @@ var writeTextToClipboard = function (text) { return fallbackCopyText(text); }; +var encodeForShieldsIO = function (text) { + return text + .replace(/-/g, "--") + .replace(/_/g, "__") + .replace(/[^A-Za-z0-9._-]/g, function (c) { return encodeURIComponent(c); }); +}; + // Copy text to clipboard and show brief feedback on the button var copyToClipboardWithFeedback = function (btn, text, label, statusEl) { writeTextToClipboard(text).then(function () { @@ -414,7 +421,7 @@ var handleCitations = function () { // Extract preferred DOI from citation text. // Use a pattern matching only valid DOI characters per the DOI specification. var citationText = jQuery("#bioc-citation").text(); - var doiChars = "[\\w./:;()\\[\\]_-]+"; + var doiChars = "[\\w.()/_-]+"; var doiPattern = new RegExp("\\bdoi:?(10\\.\\d{4,}\\/" + doiChars + ")", "i"); var urlPattern = new RegExp("https?:\\/\\/doi\\.org\\/(10\\.\\d{4,}\\/" + doiChars + ")", "i"); var doiMatch = citationText.match(doiPattern) || citationText.match(urlPattern); @@ -422,23 +429,14 @@ var handleCitations = function () { // Sanitize DOI: only allow characters valid in a DOI (alphanumeric and // DOI-permitted punctuation). Falls back to the package landing page DOI. - if (!/^10\.\d{4,}\/[\w./:;()[\]_-]+$/.test(preferredDoi)) { + if (!/^10\.\d{4,}\/[\w.()/_-]+$/.test(preferredDoi)) { preferredDoi = "10.18129/B9.bioc." + pkgName; } - // Build shields.io badge URL. Shields.io requires hyphens doubled and - // underscores doubled in the badge label. Slashes and other special chars - // must be percent-encoded. The underscore is excluded from percent-encoding - // because it is doubled in the preceding step. - var encodedDoi = preferredDoi - .replace(/-/g, "--") - .replace(/_/g, "__") - .replace(/[^A-Za-z0-9._-]/g, function (c) { return encodeURIComponent(c); }); - - // Build badge using DOM construction. encodeURI ensures the URL is valid - // and safe even before the DOI sanitization step above. - var doiHref = encodeURI("https://doi.org/" + preferredDoi); - var badgeSrc = encodeURI("https://img.shields.io/badge/DOI-" + encodedDoi + "-blue"); + var encodedDoi = encodeForShieldsIO(preferredDoi); + + var doiHref = "https://doi.org/" + encodeURIComponent(preferredDoi); + var badgeSrc = "https://img.shields.io/badge/DOI-" + encodedDoi + "-blue"; var $badgeLink = jQuery("") .attr("href", doiHref) .attr("title", "Preferred citation DOI"); @@ -449,8 +447,8 @@ var handleCitations = function () { // Add copy action buttons var actionsHtml = - '' + - ''; + '' + + ''; jQuery("#bioc-citation-actions").html(actionsHtml); jQuery("#bioc-copy-text-btn").on("click", function () { diff --git a/layouts/_bioc_views_package_detail.html b/layouts/_bioc_views_package_detail.html index 35452e7b7..d2c409950 100644 --- a/layouts/_bioc_views_package_detail.html +++ b/layouts/_bioc_views_package_detail.html @@ -49,8 +49,8 @@

<%= @package[:Title]%>

genomic analysis with Bioconductor." Nature Methods, 12(2), 115–121. doi:
10.1038/nmeth.3252.

- - + +

Gentleman RC, Carey VJ, Bates DM, Bolstad B, Dettling M, Dudoit S, Ellis B, Gautier L, Ge Y, Gentry J, Hornik K, Hothorn T, Huber W, Iacus S, Irizarry R, @@ -59,8 +59,8 @@

<%= @package[:Title]%>

bioinformatics." Genome Biology, 5(10), R80. doi:10.1186/gb-2004-5-10-r80.

- - + +
From 1614b0f75b7e5febe08d76443666e3cd6a9986fb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 May 2026 20:39:27 +0000 Subject: [PATCH 7/7] Refactor DOI and clipboard constants for maintainability Agent-Logs-Url: https://github.com/Bioconductor/bioconductor.org/sessions/f87f98f7-0089-445e-a2e7-eb77b4e8f968 Co-authored-by: LiNk-NY <4392950+LiNk-NY@users.noreply.github.com> --- assets/js/bioconductor.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/assets/js/bioconductor.js b/assets/js/bioconductor.js index 49e1a38cc..fdbe64279 100644 --- a/assets/js/bioconductor.js +++ b/assets/js/bioconductor.js @@ -353,10 +353,15 @@ var writeTextToClipboard = function (text) { return fallbackCopyText(text); }; +var CLIPBOARD_EMOJI = "\uD83D\uDCCB"; +var DOI_BODY_PATTERN = "[\\w.()/_-]+"; +var DOI_PATTERN = "10\\.\\d{4,}\\/" + DOI_BODY_PATTERN; + var encodeForShieldsIO = function (text) { return text .replace(/-/g, "--") .replace(/_/g, "__") + .replace(/ /g, "_") .replace(/[^A-Za-z0-9._-]/g, function (c) { return encodeURIComponent(c); }); }; @@ -421,15 +426,14 @@ var handleCitations = function () { // Extract preferred DOI from citation text. // Use a pattern matching only valid DOI characters per the DOI specification. var citationText = jQuery("#bioc-citation").text(); - var doiChars = "[\\w.()/_-]+"; - var doiPattern = new RegExp("\\bdoi:?(10\\.\\d{4,}\\/" + doiChars + ")", "i"); - var urlPattern = new RegExp("https?:\\/\\/doi\\.org\\/(10\\.\\d{4,}\\/" + doiChars + ")", "i"); + var doiPattern = new RegExp("\\bdoi:?(" + DOI_PATTERN + ")", "i"); + var urlPattern = new RegExp("https?:\\/\\/doi\\.org\\/(" + DOI_PATTERN + ")", "i"); var doiMatch = citationText.match(doiPattern) || citationText.match(urlPattern); var preferredDoi = doiMatch ? doiMatch[1] : "10.18129/B9.bioc." + pkgName; // Sanitize DOI: only allow characters valid in a DOI (alphanumeric and // DOI-permitted punctuation). Falls back to the package landing page DOI. - if (!/^10\.\d{4,}\/[\w.()/_-]+$/.test(preferredDoi)) { + if (!(new RegExp("^" + DOI_PATTERN + "$")).test(preferredDoi)) { preferredDoi = "10.18129/B9.bioc." + pkgName; } @@ -447,21 +451,21 @@ var handleCitations = function () { // Add copy action buttons var actionsHtml = - '' + - ''; + '' + + ''; jQuery("#bioc-citation-actions").html(actionsHtml); jQuery("#bioc-copy-text-btn").on("click", function () { var btn = jQuery(this); var statusEl = jQuery("#bioc-citation-status"); var text = jQuery("#bioc-citation").text().trim(); - copyToClipboardWithFeedback(btn, text, "\uD83D\uDCCB Copy Text", statusEl); + copyToClipboardWithFeedback(btn, text, CLIPBOARD_EMOJI + " Copy Text", statusEl); }); jQuery("#bioc-copy-bibtex-btn").on("click", function () { var btn = jQuery(this); var statusEl = jQuery("#bioc-citation-status"); - var origLabel = "\uD83D\uDCCB Copy BibTeX"; + var origLabel = CLIPBOARD_EMOJI + " Copy BibTeX"; btn.prop("disabled", true); jQuery.ajax({ url: bibUrl,