From 6ac4c0e3a07d6487f038998a6678b16c3eec9ad2 Mon Sep 17 00:00:00 2001 From: Gary Goh Date: Sat, 11 Jul 2026 18:14:11 +0800 Subject: [PATCH 1/8] Add Docker dev env, Ruby 4 compat, remove dead Travis CI - Dockerfile + docker-compose.yml: reproducible local build on pinned Ruby 3.2 (fixes host Ruby 4.0 dropping ostruct/bigdecimal/etc from default gems) - Gemfile: explicitly list ostruct/bigdecimal/csv/logger/faraday-retry for Ruby 4.x local builds (harmless on 3.2); add jekyll-jupyter-notebook - Remove obsolete .travis.yml and bin/cibuild, bin/deploy (deploy is via .github/workflows/deploy.yml) Co-Authored-By: Claude Opus 4.8 --- .dockerignore | 9 ++++ .travis.yml | 19 -------- Dockerfile | 21 +++++++++ Gemfile | 12 +++++ bin/cibuild | 1 - bin/deploy | 112 --------------------------------------------- docker-compose.yml | 15 ++++++ 7 files changed, 57 insertions(+), 132 deletions(-) create mode 100644 .dockerignore delete mode 100644 .travis.yml create mode 100644 Dockerfile delete mode 100755 bin/cibuild delete mode 100755 bin/deploy create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000..2e6eff12b14d7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +_site +.git +.jekyll-cache +.jekyll-metadata +.sass-cache +.bundle +vendor +Gemfile.lock +.DS_Store diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 328023abbe332..0000000000000 --- a/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: ruby -rvm: - - 2.4.1 - -# Assume bundler is being used, therefore -# the `install` step will run `bundle install` by default. -script: ./bin/cibuild - -env: - global: - - NOKOGIRI_USE_SYSTEM_LIBRARIES=true # speeds up installation of html-proofer - -sudo: false # route your build to the container-based infrastructure for a faster build - -cache: bundler # caching bundler gem packages will speed up build - -# Optional: disable email notifications about the outcome of your builds -notifications: - email: false diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000..8f878ae55206b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +# Development image for building the al-folio site on a pinned Ruby. +# +# Rationale: newer host Rubies (e.g. Ruby 4.0) dropped several libraries from +# the default gem set (ostruct, bigdecimal, ...), which breaks the legacy plugin +# chain. Pinning Ruby 3.2 here gives a reliable local build/serve regardless of +# the host toolchain. Deployment still happens via GitHub Actions. +FROM ruby:3.2 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /srv/jekyll + +COPY Gemfile ./ +RUN gem install bundler && bundle install + +EXPOSE 4000 35729 + +CMD ["bundle", "exec", "jekyll", "serve", \ + "--host", "0.0.0.0", "--livereload", "--force_polling", "--watch"] diff --git a/Gemfile b/Gemfile index e293de7cbc252..afb5609c3c9aa 100644 --- a/Gemfile +++ b/Gemfile @@ -1,9 +1,11 @@ source 'https://rubygems.org' + group :jekyll_plugins do gem 'jekyll' gem 'jekyll-email-protect' gem 'jekyll-feed' gem 'jekyll-github-metadata' + gem 'jekyll-jupyter-notebook' gem 'jekyll-paginate-v2' gem 'jekyll-scholar' gem 'jekyll-twitter-plugin' @@ -14,3 +16,13 @@ group :jekyll_plugins do gem 'unicode_utils' gem 'webrick' end + +# Ruby 4.0 removed these from the default gem set. Listing them explicitly keeps +# the build working on Ruby 4.x while remaining harmless on Ruby 3.2 (where they +# are still available as gems). The Docker image pins Ruby 3.2, so this is only +# load-bearing for local builds on a newer host Ruby. +gem 'ostruct' +gem 'bigdecimal' +gem 'csv' +gem 'logger' +gem 'faraday-retry' diff --git a/bin/cibuild b/bin/cibuild deleted file mode 100755 index d5c9e1956fe72..0000000000000 --- a/bin/cibuild +++ /dev/null @@ -1 +0,0 @@ -bundle exec jekyll build diff --git a/bin/deploy b/bin/deploy deleted file mode 100755 index 070e2f750e738..0000000000000 --- a/bin/deploy +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env bash - -# Run this script to deploy the app to Github Pages - -# Parse cmd arguments - -SRC_BRANCH="master" -DEPLOY_BRANCH="gh-pages" - -USAGE_MSG="usage: deploy [-h|--help] [-u|--user] [-s|--src SRC_BRANCH] [-d|--deploy DEPLOY_BRANCH] [--verbose] [--no-push]" - -while [[ $# > 0 ]]; do - key="$1" - - case $key in - -h|--help) - echo $USAGE_MSG - exit 0 - ;; - -u|--user) - SRC_BRANCH="source" - DEPLOY_BRANCH="master" - ;; - -s|--src) - SRC_BRANCH="$2" - shift - ;; - -d|--deploy) - DEPLOY_BRANCH="$2" - shift - ;; - --verbose) - set -x - ;; - --no-push) - NO_PUSH="--no-push" - ;; - *) - echo "Option $1 is unknown." >&2 - echo $USAGE_MSG >&2 - exit 1 - ;; - esac - shift -done - -# Exit if any subcommand fails -set -e - -echo "Deploying..." -echo "Source branch: $SRC_BRANCH" -echo "Deploy branch: $DEPLOY_BRANCH" - -read -r -p "Do you want to proceed? [y/N] " response -if [[ ! $response =~ ^([yY][eE][sS]|[yY])+$ ]] -then - echo "Aborting." - [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 -fi - -# Check if there are any uncommitted changes -if ! git diff-index --quiet HEAD --; then - echo "Changes to the following files are uncommitted:" - git diff-index --name-only HEAD -- - echo "Please commit the changes before proceeding." - echo "Aborting." - [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 -fi - -# Check if there are any untracked files -if ! test -z "$(git ls-files --exclude-standard --others)"; then - echo "There are untracked files:" - git ls-files --exclude-standard --others - echo "Please commit those files or stash them before proceeding." - echo "Aborting." - [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 -fi - -# Switch to source branch (creates it if necessary from the current branch) -if [ `git branch | grep $SRC_BRANCH | tr ' ' '\n' | tail -1` ] -then - git checkout $SRC_BRANCH -else - git checkout -b $SRC_BRANCH -fi - -# Checkout DEPLOY_BRANCH branch -if [ `git branch | grep $DEPLOY_BRANCH` ] -then - git branch -D $DEPLOY_BRANCH -fi -git checkout -b $DEPLOY_BRANCH - -# Build site -bundle exec jekyll build - -# Delete and move files -find . -maxdepth 1 ! -name '_site' ! -name '.git' ! -name 'CNAME' ! -name '.gitignore' -exec rm -rf {} \; -mv _site/* . -rm -R _site/ - -# Push to DEPLOY_BRANCH -git add -fA -git commit --allow-empty -m "$(git log -1 --pretty=%B) [ci skip]" -[[ ${NO_PUSH} ]] || git push -f -q origin $DEPLOY_BRANCH - -# Move back to SRC_BRANCH -git checkout $SRC_BRANCH - -echo "Deployed successfully!" - -exit 0 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000000..b2f43f5061b3c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +# Local development: `docker compose up` then open http://localhost:4000 +# Live-reload is served on port 35729. The repo is mounted so edits reload live; +# installed gems are cached in a named volume to avoid re-installing each run. +services: + jekyll: + build: . + ports: + - "4000:4000" + - "35729:35729" + volumes: + - .:/srv/jekyll + - bundle:/usr/local/bundle + +volumes: + bundle: From 4cbd9ff3dea85a0b69f1591d9640a85842cc395a Mon Sep 17 00:00:00 2001 From: Gary Goh Date: Sat, 11 Jul 2026 18:15:01 +0800 Subject: [PATCH 2/8] Add "system" option to theme toggle (light/dark/system) The navbar toggle now cycles light -> dark -> system. In "system" mode the palette follows the OS prefers-color-scheme and updates live when it changes. The active setting drives which icon is shown (sun/moon/adjust). Co-Authored-By: Claude Opus 4.8 --- _includes/header.html | 7 +- _sass/_themes.scss | 28 ++++---- assets/js/dark_mode.js | 14 ++-- assets/js/theme.js | 154 ++++++++++++++++++++++++----------------- 4 files changed, 114 insertions(+), 89 deletions(-) diff --git a/_includes/header.html b/_includes/header.html index faccf681fce21..bf99d3cfb36a0 100644 --- a/_includes/header.html +++ b/_includes/header.html @@ -78,9 +78,10 @@ {% endfor %} {% if site.enable_darkmode %} {% endif %} diff --git a/_sass/_themes.scss b/_sass/_themes.scss index 696ca6fb9452e..ec2a035b5559c 100644 --- a/_sass/_themes.scss +++ b/_sass/_themes.scss @@ -15,15 +15,6 @@ --global-footer-link-color: #{$white-color}; --global-distill-app-color: #{$grey-color}; --global-cv-bg-color: #{$white-color}; - - .fa-sun { - display : none; - } - .fa-moon { - padding-left: 10px; - padding-top: 12px; - display : block; - } } html[data-theme='dark'] { @@ -39,13 +30,22 @@ html[data-theme='dark'] { --global-footer-link-color: #{$black-color}; --global-distill-app-color: #{$grey-color-light}; --global-cv-bg-color: #{$code-bg-color-dark}; +} - .fa-sun { +// Navbar theme toggle: show the icon for the ACTIVE setting +// (light -> sun, dark -> moon, system -> adjust). One icon at a time. +#light-toggle { + .fa-sun, + .fa-moon, + .fa-adjust { + display: none; padding-left: 10px; padding-top: 12px; - display : block; - } - .fa-moon { - display : none; } } +html[data-theme-setting='light'] #light-toggle .fa-sun { display: block; } +html[data-theme-setting='dark'] #light-toggle .fa-moon { display: block; } +html[data-theme-setting='system'] #light-toggle .fa-adjust { display: block; } + +// Fallback before JS sets the attribute: show the system icon. +html:not([data-theme-setting]) #light-toggle .fa-adjust { display: block; } diff --git a/assets/js/dark_mode.js b/assets/js/dark_mode.js index c3abe36f83a0e..5ceee11120879 100644 --- a/assets/js/dark_mode.js +++ b/assets/js/dark_mode.js @@ -1,7 +1,7 @@ -$(document).ready(function() { - const mode_toggle = document.getElementById("light-toggle"); - - mode_toggle.addEventListener("click", function() { - toggleTheme(localStorage.getItem("theme")); - }); -}); +$(document).ready(function() { + const mode_toggle = document.getElementById("light-toggle"); + + mode_toggle.addEventListener("click", function() { + toggleTheme(); + }); +}); diff --git a/assets/js/theme.js b/assets/js/theme.js index 4d6aac6d0d3ad..6f4f52d5bc961 100644 --- a/assets/js/theme.js +++ b/assets/js/theme.js @@ -1,65 +1,89 @@ ---- -layout: none ---- - -// Has to be in the head tag, otherwise a flicker effect will occur. - -let toggleTheme = (theme) => { - if (theme == "dark") { - setTheme("light"); - } else { - setTheme("dark"); - } -} - - -let setTheme = (theme) => { - transTheme(); - if (theme) { - document.documentElement.setAttribute("data-theme", theme); - } - else { - document.documentElement.removeAttribute("data-theme"); - } - localStorage.setItem("theme", theme); - - - // Code Syntax Highlighting - if (theme == "dark") { - var syntax_link = '' - } else { - var syntax_link = '' - } - $('#syntax-theme').remove(); - $('head').append(syntax_link); - - // Updates the background of medium-zoom overlay. - if (typeof medium_zoom !== 'undefined') { - medium_zoom.update({ - background: getComputedStyle(document.documentElement) - .getPropertyValue('--global-bg-color') + 'ee', // + 'ee' for trasparency. - }) - } -}; - - -let transTheme = () => { - document.documentElement.classList.add("transition"); - window.setTimeout(() => { - document.documentElement.classList.remove("transition"); - }, 500) -} - - -let initTheme = (theme) => { - if (theme == null) { - const userPref = window.matchMedia; - if (userPref && userPref('(prefers-color-scheme: dark)').matches) { - theme = 'dark'; - } - } - setTheme(theme); -} - - -initTheme(localStorage.getItem("theme")); +--- +layout: none +--- + +// Has to be in the head tag, otherwise a flicker effect will occur. + +// Theme setting is one of: "light", "dark", "system". +// "system" follows the OS `prefers-color-scheme` and updates live. + +let systemPrefersDark = () => + window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; + +let getThemeSetting = () => { + const stored = localStorage.getItem("theme"); + if (stored === "light" || stored === "dark" || stored === "system") { + return stored; + } + return "system"; +}; + +// Cycle: light -> dark -> system -> light +let toggleTheme = () => { + const current = getThemeSetting(); + let next; + if (current === "light") { + next = "dark"; + } else if (current === "dark") { + next = "system"; + } else { + next = "light"; + } + localStorage.setItem("theme", next); + applyTheme(); +}; + +let applyTheme = () => { + transTheme(); + + const setting = getThemeSetting(); + const effective = setting === "system" ? (systemPrefersDark() ? "dark" : "light") : setting; + + // Drives the icon shown in the navbar toggle. + document.documentElement.setAttribute("data-theme-setting", setting); + + // Drives the actual colour palette (light == no attribute). + if (effective === "dark") { + document.documentElement.setAttribute("data-theme", "dark"); + } else { + document.documentElement.removeAttribute("data-theme"); + } + + // Code Syntax Highlighting + let syntax_link; + if (effective === "dark") { + syntax_link = ''; + } else { + syntax_link = ''; + } + if (window.jQuery) { + $("#syntax-theme").remove(); + $("head").append(syntax_link); + } + + // Updates the background of medium-zoom overlay. + if (typeof medium_zoom !== "undefined") { + medium_zoom.update({ + background: getComputedStyle(document.documentElement) + .getPropertyValue("--global-bg-color") + "ee", // + 'ee' for transparency. + }); + } +}; + +let transTheme = () => { + document.documentElement.classList.add("transition"); + window.setTimeout(() => { + document.documentElement.classList.remove("transition"); + }, 500); +}; + +// Re-apply when the OS theme changes while we're following the system. +if (window.matchMedia) { + window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => { + if (getThemeSetting() === "system") { + applyTheme(); + } + }); +} + +applyTheme(); From f2cfa6c3b83a51b8cdf323c962113251bbeecdf8 Mon Sep 17 00:00:00 2001 From: Gary Goh Date: Sat, 11 Jul 2026 18:16:05 +0800 Subject: [PATCH 3/8] Add publication venue badges + citation/attention badges - Colored venue badges driven by _data/venues.yml (color: per venue) - "Selected" star badge on selected publications - Client-side Altmetric donut + Dimensions citation-count badges, rendered only for entries with a DOI; toggled via enable_publication_badges in config Co-Authored-By: Claude Opus 4.8 --- _config.yml | 5 +++++ _data/venues.yml | 8 +++++++- _includes/scripts/misc.html | 8 ++++++++ _layouts/bib.html | 24 +++++++++++++++++++++--- _sass/_base.scss | 9 +++++++++ 5 files changed, 50 insertions(+), 4 deletions(-) diff --git a/_config.yml b/_config.yml index 2e2459e661f8b..4deacacb63f61 100644 --- a/_config.yml +++ b/_config.yml @@ -219,6 +219,11 @@ enable_navbar_social: # navbar on the about page enable_project_categories: true # enables categorization of projects into # multiple categories enable_medium_zoom: true # enables image zoom feature (as on medium.com) +enable_search: true # enables the ninja-keys command-palette site search +# Client-side citation / attention badges on publications (render only when a DOI is present) +enable_publication_badges: + altmetric: true + dimensions: true # ----------------------------------------------------------------------------- # Library versions diff --git a/_data/venues.yml b/_data/venues.yml index eb581d1ddfb94..bf880a0e3a110 100644 --- a/_data/venues.yml +++ b/_data/venues.yml @@ -1,17 +1,23 @@ arXiv: url: https://arxiv.org + color: "#b31b1b" AAAI: url: https://aaai.org/Conferences/AAAI/aaai.php + color: "#1a4b8c" ICPR: url: https://iapr.org/conferences/ + color: "#0076df" IEEE BigData: url: https://bigdata.ieee.org + color: "#00629b" ICDM: url: http://icdm.bigke.org + color: "#6a1b9a" SUTD: - url: https://www.sutd.edu.sg/ \ No newline at end of file + url: https://www.sutd.edu.sg/ + color: "#c8102e" diff --git a/_includes/scripts/misc.html b/_includes/scripts/misc.html index 4962f20d623b7..8932b48db851f 100644 --- a/_includes/scripts/misc.html +++ b/_includes/scripts/misc.html @@ -11,6 +11,14 @@ {% endif %} + +{% if site.enable_publication_badges.altmetric %} + +{% endif %} +{% if site.enable_publication_badges.dimensions %} + +{% endif %} + diff --git a/_layouts/bib.html b/_layouts/bib.html index c1a6f263a317c..e868b65bd370b 100644 --- a/_layouts/bib.html +++ b/_layouts/bib.html @@ -4,10 +4,16 @@
{% if entry.abbr %} - {% if site.data.venues[entry.abbr] %} - {{entry.abbr}} + {% assign venue = site.data.venues[entry.abbr] %} + {% if venue %} + + {% if venue.url %}{{ entry.abbr }}{% else %}{{ entry.abbr }}{% endif %} + {% else %} - {{entry.abbr}} + {{ entry.abbr }} + {% endif %} + {% if entry.selected %} + ★ {% endif %} {% endif %}
@@ -137,6 +143,18 @@ {% endif %}
+ + {% if entry.doi %} +
+ {% if site.enable_publication_badges.altmetric %} + + {% endif %} + {% if site.enable_publication_badges.dimensions %} + + {% endif %} +
+ {% endif %} + {% if entry.abstract %}