From 8eef35fec8bbc157242df6f1b07e709394aa2e2b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Sep 2025 01:10:42 +0000 Subject: [PATCH 1/3] Initial plan From 69b72c263ab3e143d26c77ed1ed8cf64a4743400 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Sep 2025 01:16:29 +0000 Subject: [PATCH 2/3] Add GitHub repo and homepage links to project cards - Modified showRepo() function to include dedicated GitHub and homepage links - Added CSS styling for .repo__link, .repo__link--github, and .repo__link--homepage - Updated click handler to prevent navigation when clicking on link buttons - Projects with homepages show both GitHub and Homepage buttons - Projects without homepages show only GitHub button - Preserves existing card click behavior as fallback Co-authored-by: roblarsen <361421+roblarsen@users.noreply.github.com> --- assets/app.babel.js | 14 ++++- assets/app.js | 126 +++++++++++++++++++------------------------- assets/style.css | 36 +++++++++++++ 3 files changed, 104 insertions(+), 72 deletions(-) diff --git a/assets/app.babel.js b/assets/app.babel.js index 31a9e04..75098a9 100644 --- a/assets/app.babel.js +++ b/assets/app.babel.js @@ -28,6 +28,12 @@ function showRepo(repo) { const url = getRepoUrl(repo); const language = repo.language !== null ? `·${repo.language}` : ''; + + // Create links for GitHub repo and homepage + const githubLink = `GitHub`; + const homepageLink = repo.homepage ? + `Homepage` : ''; + const linksHtml = ``; const $item = $( `
@@ -35,10 +41,16 @@

${repo.name}

${repo.watchers} stargazers ${language}

${getRepoDesc(repo)}

+ ${linksHtml}
` ); - $item.on("click",()=> window.location = url) + $item.on("click", (e) => { + // Don't navigate if clicking on a link + if (!$(e.target).hasClass('repo__link')) { + window.location = url; + } + }); $item.appendTo('#repos'); } diff --git a/assets/app.js b/assets/app.js index 5f6633b..f7b7bd9 100644 --- a/assets/app.js +++ b/assets/app.js @@ -1,44 +1,53 @@ "use strict"; +function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; } +function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } +function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } (function ($, undefined) { var orgName = 'h5bp'; - var stars = 0; // Return the repo url + var stars = 0; + // Return the repo url function getRepoUrl(repo) { return repo.homepage || repo.html_url; - } // Return the repo description - + } + // Return the repo description function getRepoDesc(repo) { return repo.description; - } // Display a repo's overview (for recent updates section) - + } + // Display a repo's overview (for recent updates section) function showRepoOverview(repo) { var item = "\n
  • \n ").concat(repo.name, "\n ·\n ").concat(html5prettyDate(repo.pushed_at), "\n
  • "); $(item).appendTo("#updated-repos"); - } // Create an entry for the repo in the grid of org repos - + } + // Create an entry for the repo in the grid of org repos function showRepo(repo) { var url = getRepoUrl(repo); var language = repo.language !== null ? "·".concat(repo.language) : ''; - var $item = $("
    \n
    \n

    ".concat(repo.name, "

    \n

    ").concat(repo.watchers, " stargazers ").concat(language, "

    \n

    ").concat(getRepoDesc(repo), "

    \n
    \n
    ")); - $item.on("click", function () { - return window.location = url; + + // Create links for GitHub repo and homepage + var githubLink = "GitHub"); + var homepageLink = repo.homepage ? "Homepage") : ''; + var linksHtml = "
    ".concat(githubLink).concat(homepageLink, "
    "); + var $item = $("
    \n
    \n

    ".concat(repo.name, "

    \n

    ").concat(repo.watchers, " stargazers ").concat(language, "

    \n

    ").concat(getRepoDesc(repo), "

    \n ").concat(linksHtml, "\n
    \n
    ")); + $item.on("click", function (e) { + // Don't navigate if clicking on a link + if (!$(e.target).hasClass('repo__link')) { + window.location = url; + } }); $item.appendTo('#repos'); } - $.getJSON("https://api.github.com/orgs/".concat(orgName, "/repos?callback=?"), function (result) { var repos = result.data; $('#num-repos').text(repos.length); - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - + var _iterator = _createForOfIteratorHelper(repos), + _step; try { - for (var _iterator = repos[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + for (_iterator.s(); !(_step = _iterator.n()).done;) { var repo = _step.value; repo.pushed_at = new Date(repo.pushed_at); var weekHalfLife = 1.146 * Math.pow(10, -9); @@ -50,55 +59,32 @@ repo.hotness += weightForWatchers * repo.watchers / createdDelta; } } catch (err) { - _didIteratorError = true; - _iteratorError = err; + _iterator.e(err); } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } + _iterator.f(); } - repos.sort(function (a, b) { if (a.hotness < b.hotness) return 1; if (b.hotness < a.hotness) return -1; return 0; }); - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - + var _iterator2 = _createForOfIteratorHelper(repos), + _step2; try { - for (var _iterator2 = repos[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var _repo = _step2.value; stars += _repo.stargazers_count; - if (_repo.archived === false) { showRepo(_repo); } } } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; + _iterator2.e(err); } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return != null) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } + _iterator2.f(); } - - $("#num-stargazers").text(stars.toLocaleString()); // Sort by most-recently pushed to. - + $("#num-stargazers").text(stars.toLocaleString()); + // Sort by most-recently pushed to. repos.sort(function (a, b) { if (a.pushed_at < b.pushed_at) { return 1; @@ -117,48 +103,46 @@ $(function () { $('#num-members').text(members.length); }); - }); // Relative times + }); + // Relative times function prettyDate(rawdate) { var date, - seconds, - formats, - i = 0, - f; + seconds, + formats, + i = 0, + f; date = new Date(rawdate); seconds = (new Date() - date) / 1000; formats = [[60, 'seconds', 1], [120, '1 minute ago'], [3600, 'minutes', 60], [7200, '1 hour ago'], [86400, 'hours', 3600], [172800, 'Yesterday'], [604800, 'days', 86400], [1209600, '1 week ago'], [2678400, 'weeks', 604800]]; - while (f = formats[i++]) { if (seconds < f[0]) { return f[2] ? Math.floor(seconds / f[2]) + ' ' + f[1] + ' ago' : f[1]; } } - return 'A while ago'; - } // Wraps prettyDate in an HTML5