Skip to content

Merge from alshedivat/al-folio#1

Open
dgnad wants to merge 135 commits into
dgnad:mainfrom
alshedivat:main
Open

Merge from alshedivat/al-folio#1
dgnad wants to merge 135 commits into
dgnad:mainfrom
alshedivat:main

Conversation

@dgnad
Copy link
Copy Markdown
Owner

@dgnad dgnad commented Apr 7, 2026

No description provided.

gdalle and others added 30 commits July 16, 2025 12:24
Signed-off-by: George Araújo <george.gcac@gmail.com>
This PR adds a few stylistic improvements to the distill-style blog
posts:

- Update distill blog post example to showcase sidenotes as an
alternative to styles in PR #3077
- Showcase equations in sidenotes (closes #1242)
- Add `overrides.js` to match footnotes and citation styles with global
theme styling
- Add "related posts" sections if enabled to distill style posts
- Add "giscus" section if enabled to distill style posts



https://github.com/user-attachments/assets/b19a9cd9-779d-4d89-a4fb-eb14fb384480
Adding a new personal website
Hi,
I noticed some weird behavior when I turned dark mode off (some of the
text seemed to disappear, it became white :) )

I traced it to: {% if site.enable_darkmode %} in head.liquid
where some darkmode features are place before the if statement.

When putting it inside the if statement then the weird behavior was
solved; see the pull request here :)

Cheers,
Jan
## Description

This pull request adds support for Academia.edu profiles to the al-folio
social media integrations. Academia.edu is widely used by academics to
share and discover research,.

The changes are minimal and well-contained:
1. Added configuration options in socials.yml for Academia.edu with
organization and username fields
2. Updated social.liquid to handle the new social integration using the
Academicons font which already includes support for Academia.edu

## Changes

The implementation uses Academicons, which already includes the
Academia.edu icon (`ai-academia`), making this addition a natural fit
for the theme.

Unlike some other social media links that only require a single ID or
URL, Academia.edu profiles include both an organization (subdomain) and
a username in the format:
`https://[organization].academia.edu/[username]`. The implemented
solution supports this pattern by adding two parameters in the
socials.yml file.

## Why this is important

Academia.edu is a popular platform used by millions of researchers
worldwide to share their work. Adding support for it in the al-folio
theme aligns with the theme's academic focus and enhances its utility
for scholarly users. Many academics maintain both personal websites and
Academia.edu profiles, and being able to link between them provides
better visibility for their research.

The Academicons font already includes support for Academia.edu, so
adding this feature is a natural extension that makes use of existing
resources in the theme.

## Testing

The changes have been tested locally with a sample Academia.edu profile,
and the icon displays correctly alongside other social media icons. The
changes are minimal and don't affect any existing functionality.

## Screenshot

<img width="991" alt="image"
src="https://github.com/user-attachments/assets/15468b67-3002-44ce-aa25-22bc10766664"
/>
my academic homepage, in case you'd like to link it :)
Co-authored-by: George <31376482+george-gca@users.noreply.github.com>
Currently, the `site.giscus.theme` option is ignored because
`giscus.liquid` always computes the theme as light/dark based on the
current site theme. This PR allows users to configure separate light and
dark giscus themes in `_config.yml`, which will support dynamic updates
when switching between light, dark, or system themes.

Fixes #3269
This reverts PR #2962. The inline script here is exactly the same as the
`/assets/js/google-analytics-setup.js` sourced on the following line, so
Google Analytics is being triggered twice.

It seems that #2962 originally added this because liquid templating of
the setup script didn't work (#3095). However, this was then properly
fixed in #3117.
Partially addresses issue #3280.

Currently, the RSS feed icon in the socials section will show whenever
`rss_icon` in `data/_socials.yml` has a value --- **even if that value
is `false`**.

Unlike the other social settings, which are empty by default, for
`rss_icon` the default setting is `true`.

So it makes sense that a user might expect `rss_icon: false` to disable
said icon.

This PR just adds a check if the value is `false` and hides the icon if
so.
Bumps [rexml](https://github.com/ruby/rexml) from 3.4.1 to 3.4.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ruby/rexml/releases">rexml's
releases</a>.</em></p>
<blockquote>
<h2>REXML 3.4.2 - 2025-08-26</h2>
<h3>Improvement</h3>
<ul>
<li>
<p>Improved performance.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/244">GH-244</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/245">GH-245</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/246">GH-246</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/249">GH-249</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/256">GH-256</a></li>
<li>Patch by NAITOH Jun</li>
</ul>
</li>
<li>
<p>Raise appropriate exception when failing to match start tag in
DOCTYPE</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/247">GH-247</a></li>
<li>Patch by NAITOH Jun</li>
</ul>
</li>
<li>
<p>Deprecate accepting array as an element in XPath.match, first and
each</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/252">GH-252</a></li>
<li>Patch by tomoya ishida</li>
</ul>
</li>
<li>
<p>Don't call needless encoding_updated</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/259">GH-259</a></li>
<li>Patch by Sutou Kouhei</li>
</ul>
</li>
<li>
<p>Reuse XPath::match</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/263">GH-263</a></li>
<li>Patch by pboling</li>
</ul>
</li>
<li>
<p>Cache redundant calls for doctype</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/264">GH-264</a></li>
<li>Patch by pboling</li>
</ul>
</li>
<li>
<p>Use Safe Navigation (&amp;.) from Ruby 2.3</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/265">GH-265</a></li>
<li>Patch by pboling</li>
</ul>
</li>
<li>
<p>Remove redundant return statements</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/266">GH-266</a></li>
<li>Patch by pboling</li>
</ul>
</li>
<li>
<p>Added XML declaration check &amp; Source#skip_spaces method</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/282">GH-282</a></li>
<li>Patch by NAITOH Jun</li>
<li>Reported by Sofi Aberegg</li>
</ul>
</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Fix docs typo
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/248">GH-248</a></li>
<li>Patch by James Coleman</li>
</ul>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ruby/rexml/blob/master/NEWS.md">rexml's
changelog</a>.</em></p>
<blockquote>
<h2>3.4.2 - 2025-08-26 {#version-3-4-2}</h2>
<h3>Improvement</h3>
<ul>
<li>
<p>Improved performance.</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/244">GH-244</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/245">GH-245</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/246">GH-246</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/249">GH-249</a></li>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/256">GH-256</a></li>
<li>Patch by NAITOH Jun</li>
</ul>
</li>
<li>
<p>Raise appropriate exception when failing to match start tag in
DOCTYPE</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/247">GH-247</a></li>
<li>Patch by NAITOH Jun</li>
</ul>
</li>
<li>
<p>Deprecate accepting array as an element in XPath.match, first and
each</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/252">GH-252</a></li>
<li>Patch by tomoya ishida</li>
</ul>
</li>
<li>
<p>Don't call needless encoding_updated</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/259">GH-259</a></li>
<li>Patch by Sutou Kouhei</li>
</ul>
</li>
<li>
<p>Reuse XPath::match</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/263">GH-263</a></li>
<li>Patch by pboling</li>
</ul>
</li>
<li>
<p>Cache redundant calls for doctype</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/264">GH-264</a></li>
<li>Patch by pboling</li>
</ul>
</li>
<li>
<p>Use Safe Navigation (&amp;.) from Ruby 2.3</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/265">GH-265</a></li>
<li>Patch by pboling</li>
</ul>
</li>
<li>
<p>Remove redundant return statements</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/266">GH-266</a></li>
<li>Patch by pboling</li>
</ul>
</li>
<li>
<p>Added XML declaration check &amp; Source#skip_spaces method</p>
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/282">GH-282</a></li>
<li>Patch by NAITOH Jun</li>
<li>Reported by Sofi Aberegg</li>
</ul>
</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Fix docs typo
<ul>
<li><a
href="https://redirect.github.com/ruby/rexml/issues/248">GH-248</a></li>
<li>Patch by James Coleman</li>
</ul>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/ruby/rexml/commit/f36916fe1c66b8cdc1fe482263115625e084d8fe"><code>f36916f</code></a>
Add 3.4.2 entry (<a
href="https://redirect.github.com/ruby/rexml/issues/284">#284</a>)</li>
<li><a
href="https://github.com/ruby/rexml/commit/5859bdeac792687eaf93d8e8f0b7e3c1e2ed5c23"><code>5859bde</code></a>
Added XML declaration check &amp; <code>Source#skip_spaces</code> method
(<a
href="https://redirect.github.com/ruby/rexml/issues/282">#282</a>)</li>
<li><a
href="https://github.com/ruby/rexml/commit/1d876e3bf658b7b4ec7c3372867521695e8eb023"><code>1d876e3</code></a>
Bump actions/checkout from 4 to 5 (<a
href="https://redirect.github.com/ruby/rexml/issues/283">#283</a>)</li>
<li><a
href="https://github.com/ruby/rexml/commit/c87bda8bb8773da7e5a0faf9f16ff165eb052a35"><code>c87bda8</code></a>
Remove ostruct from dev deps (<a
href="https://redirect.github.com/ruby/rexml/issues/281">#281</a>)</li>
<li><a
href="https://github.com/ruby/rexml/commit/c60ae027a3c20f359fdf76fa41ae64d22313f482"><code>c60ae02</code></a>
Remove bundler from dev deps (<a
href="https://redirect.github.com/ruby/rexml/issues/277">#277</a>)</li>
<li><a
href="https://github.com/ruby/rexml/commit/9b084d78708638cedff54743edc0907c4bd6574a"><code>9b084d7</code></a>
Fix &amp; Deprecate REXML::Text#text_indent (<a
href="https://redirect.github.com/ruby/rexml/issues/275">#275</a>)</li>
<li><a
href="https://github.com/ruby/rexml/commit/04a589a61bf4e366abee8764ee74b03f4aecc4aa"><code>04a589a</code></a>
Fix a bug that XPath can't be used for no document element (<a
href="https://redirect.github.com/ruby/rexml/issues/268">#268</a>)</li>
<li><a
href="https://github.com/ruby/rexml/commit/66232eaf680d0937ae59bea285cdb8e4d3d88a93"><code>66232ea</code></a>
Remove redundant return statements (<a
href="https://redirect.github.com/ruby/rexml/issues/266">#266</a>)</li>
<li><a
href="https://github.com/ruby/rexml/commit/63f3e9772595a64b036953f0ab026d2ea5560a3b"><code>63f3e97</code></a>
Use Safe Navigation (&amp;.) from Ruby 2.3 (<a
href="https://redirect.github.com/ruby/rexml/issues/265">#265</a>)</li>
<li><a
href="https://github.com/ruby/rexml/commit/d427fc5914fcc17d7247c5ff9099ee38639d6702"><code>d427fc5</code></a>
Avoid redundant calls for doctype (<a
href="https://redirect.github.com/ruby/rexml/issues/264">#264</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/ruby/rexml/compare/v3.4.1...v3.4.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rexml&package-manager=bundler&previous-version=3.4.1&new-version=3.4.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/alshedivat/al-folio/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ows (#3285)

Bumps
[lycheeverse/lychee-action](https://github.com/lycheeverse/lychee-action)
from 1.9.0 to 2.0.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/lycheeverse/lychee-action/releases">lycheeverse/lychee-action's
releases</a>.</em></p>
<blockquote>
<h2>Version 2.0.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix a typos by <a
href="https://github.com/szepeviktor"><code>@​szepeviktor</code></a> in
<a
href="https://redirect.github.com/lycheeverse/lychee-action/pull/257">lycheeverse/lychee-action#257</a></li>
<li>Document and use correct permissions in the GitHub workflows by <a
href="https://github.com/dscho"><code>@​dscho</code></a> in <a
href="https://redirect.github.com/lycheeverse/lychee-action/pull/258">lycheeverse/lychee-action#258</a></li>
<li>Add security policy by <a
href="https://github.com/mondeja"><code>@​mondeja</code></a> in <a
href="https://redirect.github.com/lycheeverse/lychee-action/pull/259">lycheeverse/lychee-action#259</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/szepeviktor"><code>@​szepeviktor</code></a>
made their first contribution in <a
href="https://redirect.github.com/lycheeverse/lychee-action/pull/257">lycheeverse/lychee-action#257</a></li>
<li><a href="https://github.com/mondeja"><code>@​mondeja</code></a> made
their first contribution in <a
href="https://redirect.github.com/lycheeverse/lychee-action/pull/259">lycheeverse/lychee-action#259</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/lycheeverse/lychee-action/compare/v2...v2.0.2">https://github.com/lycheeverse/lychee-action/compare/v2...v2.0.2</a></p>
<h2>Version 2.0.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Don't remove the lychee config file by <a
href="https://github.com/dmathieu"><code>@​dmathieu</code></a> in <a
href="https://redirect.github.com/lycheeverse/lychee-action/pull/255">lycheeverse/lychee-action#255</a></li>
<li>Bump lycheeverse/lychee-action from 1 to 2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/lycheeverse/lychee-action/pull/252">lycheeverse/lychee-action#252</a></li>
<li>Fix variable name in docs by <a
href="https://github.com/kdeldycke"><code>@​kdeldycke</code></a> in <a
href="https://redirect.github.com/lycheeverse/lychee-action/pull/253">lycheeverse/lychee-action#253</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/dmathieu"><code>@​dmathieu</code></a>
made their first contribution in <a
href="https://redirect.github.com/lycheeverse/lychee-action/pull/255">lycheeverse/lychee-action#255</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/lycheeverse/lychee-action/compare/v2...v2.0.1">https://github.com/lycheeverse/lychee-action/compare/v2...v2.0.1</a></p>
<h2>Version 2.0.0</h2>
<h2>Breaking Changes</h2>
<p><strong>Note:</strong> This release improves the action's robustness
by changing default behaviors. Changes are only required if you want to
opt out of the new failure conditions. Most users won't need to modify
their existing configurations.</p>
<h3>Fail pipeline on error by default</h3>
<p>We've changed the default behavior: pipelines will now fail on broken
links automatically. This addresses user feedback that not failing on
broken links was unexpected (see [issue <a
href="https://redirect.github.com/lycheeverse/lychee-action/issues/71">#71</a>](<a
href="https://redirect.github.com/lycheeverse/lychee-action/issues/71">lycheeverse/lychee-action#71</a>)).</p>
<p><strong>What you need to do:</strong></p>
<ul>
<li>Update to version 2 of this action to apply this change.</li>
<li>Users of the <code>lychee-action@master</code> branch don't need to
make any changes, as <code>fail: true</code> has been the default there
for a while.</li>
<li>If you prefer the old behavior, explicitly set <code>fail</code> to
<code>false</code> when updating:</li>
</ul>
<pre lang="yaml"><code>- name: Link Checker
  id: lychee
  uses: lycheeverse/lychee-action@v2
  with:
    fail: false  # Don't fail action on broken links
</code></pre>
<h3>Fail pipeline if no links were found</h3>
<p>Similar to the above change, we now fail the pipeline if no links are
found during a run. This helps warn users about potential configuration
issues.</p>
<p><strong>What you need to do:</strong></p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/lycheeverse/lychee-action/commit/7cd0af4c74a61395d455af97419279d86aafaede"><code>7cd0af4</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/lycheeverse/lychee-action/commit/8ad54d3568ac3176a9fb57a0233cf04410b55cde"><code>8ad54d3</code></a>
fix link</li>
<li><a
href="https://github.com/lycheeverse/lychee-action/commit/762333c18963fc10db515e32000e2e4dbcb11f5f"><code>762333c</code></a>
Create SECURITY.md (<a
href="https://redirect.github.com/lycheeverse/lychee-action/issues/259">#259</a>)</li>
<li><a
href="https://github.com/lycheeverse/lychee-action/commit/71a38a3bd757f6306a6c14206219391d4e5807ed"><code>71a38a3</code></a>
Document and use correct permissions in the GitHub workflows (<a
href="https://redirect.github.com/lycheeverse/lychee-action/issues/258">#258</a>)</li>
<li><a
href="https://github.com/lycheeverse/lychee-action/commit/f141760066406690a7f54a23762e3d146ea0d721"><code>f141760</code></a>
Fix a typos (<a
href="https://redirect.github.com/lycheeverse/lychee-action/issues/257">#257</a>)</li>
<li><a
href="https://github.com/lycheeverse/lychee-action/commit/2bb232618be239862e31382c5c0eaeba12e5e966"><code>2bb2326</code></a>
don't remove the lychee config file (<a
href="https://redirect.github.com/lycheeverse/lychee-action/issues/255">#255</a>)</li>
<li><a
href="https://github.com/lycheeverse/lychee-action/commit/731bf1a2affebd80fab6515ba61d2648a76929a4"><code>731bf1a</code></a>
Fix variable name (<a
href="https://redirect.github.com/lycheeverse/lychee-action/issues/253">#253</a>)</li>
<li><a
href="https://github.com/lycheeverse/lychee-action/commit/e360f3c89142a5391e094404ea45e5494f1317dd"><code>e360f3c</code></a>
Bump lycheeverse/lychee-action from 1 to 2 (<a
href="https://redirect.github.com/lycheeverse/lychee-action/issues/252">#252</a>)</li>
<li><a
href="https://github.com/lycheeverse/lychee-action/commit/f87f0a62993c2647717456af92593666acb3a500"><code>f87f0a6</code></a>
Update version to <code>lycheeverse/lychee-action@v2</code> in docs</li>
<li><a
href="https://github.com/lycheeverse/lychee-action/commit/7da8ec1fc4e01b5a12062ac6c589c10a4ce70d67"><code>7da8ec1</code></a>
Test latest lychee version tag (<a
href="https://redirect.github.com/lycheeverse/lychee-action/issues/236">#236</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/lycheeverse/lychee-action/compare/v1.9.0...v2.0.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=lycheeverse/lychee-action&package-manager=github_actions&previous-version=1.9.0&new-version=2.0.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/alshedivat/al-folio/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Hi! Thank you for this amazing template; I used it to make my portfolio.
I have added my website's star to the list of academics, hope that's
cool 😄
Bumps [nokogiri](https://github.com/sparklemotion/nokogiri) from 1.18.8
to 1.18.9.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/sparklemotion/nokogiri/releases">nokogiri's
releases</a>.</em></p>
<blockquote>
<h2>v1.18.9 / 2025-07-20</h2>
<h3>Security</h3>
<ul>
<li>[CRuby] Applied upstream libxml2 patches to address CVE-2025-6021,
CVE-2025-6170, CVE-2025-49794, CVE-2025-49795, and CVE-2025-49796. See
<a
href="https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-353f-x4gh-cqq8">GHSA-353f-x4gh-cqq8</a>
for more information.</li>
</ul>
<!-- raw HTML omitted -->

<pre><code>5bcfdf7aa8d1056a7ad5e52e1adffc64ef53d12d0724fbc6f458a3af1a4b9e32
nokogiri-1.18.9-aarch64-linux-gnu.gem
55e9e6ca46c4ad1715e313f407d8481d15be1e3b65d9f8e52ba1c124d01676a7
nokogiri-1.18.9-aarch64-linux-musl.gem
eea3f1f06463ff6309d3ff5b88033c4948d0da1ab3cc0a3a24f63c4d4a763979
nokogiri-1.18.9-arm64-darwin.gem
fe611ae65880e445a9c0f650d52327db239f3488626df4173c05beafd161d46e
nokogiri-1.18.9-arm-linux-gnu.gem
935605e14c0ba17da18d203922440bf6c0676c602659278d855d4622d756a324
nokogiri-1.18.9-arm-linux-musl.gem
ac5a7d93fd0e3cef388800b037407890882413feccca79eb0272a2715a82fa33
nokogiri-1.18.9.gem
1fe5b7aa4a054eda689a969bb4e03999960a6ea806582d327207d687168bceb5
nokogiri-1.18.9-java.gem
6b4fc1523aa0370c78653e38c94cb50e7f3ab786425de66ba7ad24222c1164a3
nokogiri-1.18.9-x64-mingw-ucrt.gem
e0d2deb03d3d7af8016e8c9df5ff4a7d692159cefb135cbb6a4109f265652348
nokogiri-1.18.9-x86_64-darwin.gem
b52f5defedc53d14f71eeaaf990da66b077e1918a2e13088b6a96d0230f44360
nokogiri-1.18.9-x86_64-linux-gnu.gem
e69359d6240c17e64cc9f43970d54f13bfc7b8cc516b819228f687e953425e69
nokogiri-1.18.9-x86_64-linux-musl.gem
</code></pre>
<!-- raw HTML omitted -->
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/sparklemotion/nokogiri/blob/main/CHANGELOG.md">nokogiri's
changelog</a>.</em></p>
<blockquote>
<h2>v1.18.9 / 2025-07-20</h2>
<h3>Security</h3>
<ul>
<li>[CRuby] Applied upstream libxml2 patches to address CVE-2025-6021,
CVE-2025-6170, CVE-2025-49794, CVE-2025-49795, and CVE-2025-49796. See
<a
href="https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-353f-x4gh-cqq8">GHSA-353f-x4gh-cqq8</a>
for more information.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/sparklemotion/nokogiri/commit/1dcd8ce30365ebd4620a3b823bf806b127eeefc3"><code>1dcd8ce</code></a>
version bump to v1.18.9</li>
<li><a
href="https://github.com/sparklemotion/nokogiri/commit/a05d2b44b930072af70dad12bddbac67f36c6f90"><code>a05d2b4</code></a>
Apply upstream patches to address multiple vulnerabilities (<a
href="https://redirect.github.com/sparklemotion/nokogiri/issues/3526">#3526</a>)</li>
<li><a
href="https://github.com/sparklemotion/nokogiri/commit/947a55e87edff3c6d76ffd81f07da728e67c9b82"><code>947a55e</code></a>
Apply upstream patches to address multiple vulnerabilities</li>
<li>See full diff in <a
href="https://github.com/sparklemotion/nokogiri/compare/v1.18.8...v1.18.9">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=nokogiri&package-manager=bundler&previous-version=1.18.8&new-version=1.18.9)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/alshedivat/al-folio/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
## Fix ToC Scroll-Spy Highlighting Issue

### Problem
When clicking on a ToC link in the sidebar, the page scrolls to the
correct section, but the ToC highlights the *previous* section instead
of the current one. The correct section only gets highlighted after
scrolling down a few pixels.

### Root Cause
The `scrollspy` in `assets/js/common.js` was initialized without an
offset parameter, so it didn't account for the fixed navigation header
height (~56px).

### Solution
Added `offset: 100` parameter to the scrollspy initialization to
properly detect when a section becomes visible, accounting for the
header and some buffer space.

### Changes
- Modified `assets/js/common.js`: Added offset parameter to scrollspy
configuration

### Testing
- [x] ToC correctly highlights the current section immediately after
clicking
- [x] Headings remain visible (not hidden under header)
- [x] Smooth scrolling works as expected

---------

Co-authored-by: Maruan <alshedivat@users.noreply.github.com>
Hello, the repository owner.

al-folio has been extremely amazing and very easy to set up—sincere
thanks to you and the contributors.

I've found one way that works on my end, where I can retain those very
useful page files, while I currently do not have enough content to fill
them in.

I might be wrong, but my site has been updating correctly. 

I hope that I could be able to contribute to this customization guide
and provide a solution for those users who want to continuously use this
to display their content as they gain more professional experiences
later.

Thank you.
As reported in Issue #3249, This pull request fixes a issue that makes
the active navbar dropdown menu item unable to follow the global
background color settings.

It achieves this by merging the definition of `.navbar .dropdown-menu`
and `.btn-group.dropdown .dropdown-menu` in the `_base.scss`. This
should not affect the looking of the dropdown menu in a button.

**Before:**
<img width="274" height="194" alt="before"
src="https://github.com/user-attachments/assets/4fa59325-8dc9-4156-a8f6-293ce467d00d"
/>

**After:**
<img width="274" height="194" alt="after"
src="https://github.com/user-attachments/assets/5bcf16bc-0b3e-4b27-b5f2-95ae50f3e40f"
/>

**Button dropdown menu:**
<img width="316" height="241" alt="button"
src="https://github.com/user-attachments/assets/5609e568-1635-491d-8451-354e48eed9c5"
/>
## Summary

This PR introduces an automated mechanism to update the citation count
for authors' publications.

- Inspired by @BernardoCama’s suggestion in #3150.
- Resolves #3150.

## Key Changes

- Adds an action to update publication citation counts.
    - Note: This action creates a commit on the main branch.
- To trigger further GitHub Actions workflows from this commit, a
Personal Access Token (PAT) must be used (the default GitHub Actions
token cannot trigger subsequent workflows).
- Adds and manages citation data in `_data/citations.yml`.
- Adds and adapts `bin/update_scholar_citations.py` to handle citation
updates.

## Usage Examples
### Timeout
<img width="758" height="415" alt="image"
src="https://github.com/user-attachments/assets/0a330d35-b386-4670-8668-62701f2dc68b"
/>

### Success

<img width="1684" height="857" alt="image"
src="https://github.com/user-attachments/assets/44aa0558-e02a-4f00-b8cb-9e0ce16dd53c"
/>
Add some clarification on how to enable mermaid.

---------

Signed-off-by: George Araújo <george.gcac@gmail.com>
Co-authored-by: George Araújo <george.gcac@gmail.com>
addresses the question #3176 and issue #3190

---------

Co-authored-by: George <31376482+george-gca@users.noreply.github.com>
## Description
Fixes code block overflow issues by adding proper CSS overflow handling
and responsive design: Code blocks overflow and don't scale properly
#3228

## Changes Made to _base.scss
- Added `overflow-x`: auto to enable horizontal scrolling for long code
lines
- Added `white-space: pre` to preserve code formatting while allowing
horizontal scrolling
- Added `word-wrap: normal` to prevent wrapping of long lines
- Added `-webkit-overflow-scrolling: touch` for smooth iOS scrolling
- Added responsive font sizes for different breakpoints (576px, 400px,
and 768px)
- Applied fixes to `pre`, `code`, and `figure.highlight` elements

## Related Issue
Closes  #3228

---------

Signed-off-by: George Araújo <george.gcac@gmail.com>
Co-authored-by: George Araújo <george.gcac@gmail.com>
george-gca and others added 30 commits January 31, 2026 19:56
Added CLAUDE.md file for AI assistant integration and updated Copilot agents description.
Implements cookie consent using vanilla-cookieconsent v3 to comply with
GDPR requirements. Analytics scripts are blocked until user consent is
obtained.

## Changes

**Library Integration**
- Added `vanilla-cookieconsent@3.1.0` to `_config.yml` third-party
libraries with SRI hashes
- Created `_scripts/cookie-consent-setup.js` with consent modal and
settings configuration
- Added CSS/JS includes in `_includes/head.liquid` and
`_includes/scripts.liquid`

**Analytics Blocking**
- Modified analytics scripts in `scripts.liquid` and
`distill_scripts.liquid` to use conditional `type="text/plain"
data-category="analytics"` when consent is disabled
- Blocks Google Analytics, Cronitor, Pirsch, and OpenPanel until consent
granted
- Library automatically converts blocked scripts to executable on user
acceptance

**Configuration**
- Added `enable_cookie_consent` flag (default: `false`)
- Cookie categories: `necessary` (always on), `analytics` (optional)
- 182-day cookie expiration, auto-clear on rejection

## Implementation

```liquid
{% if site.enable_cookie_consent %}
  <script type="text/plain" data-category="analytics" async src="...gtag.js"></script>
{% else %}
  <script async src="...gtag.js"></script>
{% endif %}
```

Enable in `_config.yml`:
```yaml
enable_cookie_consent: true
```

## Screenshots

**Consent Modal**

![Cookie consent
modal](https://github.com/user-attachments/assets/9edcddad-6a54-49ca-a164-083157d98370)

**Settings Modal**

![Cookie
preferences](https://github.com/user-attachments/assets/cf2a58ea-68c0-4699-b401-38377b98b718)

> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `cdn.jsdelivr.net`
>   - Triggering command: `/usr/bin/curl curl -s REDACTED` (dns block)
> - `cookieconsent.orestbida.com`
> - Triggering command:
`/home/REDACTED/work/_temp/ghcca-node/node/bin/node
/home/REDACTED/work/_temp/ghcca-node/node/bin/node --enable-source-maps
/home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js`
(dns block)
> - `medium.com`
> - Triggering command: `/usr/local/bin/ruby ruby
/usr/local/bundle/bin/bundle exec jekyll serve --watch --port=8080
--host=0.0.0.0 --livereload --verbose --trace --force_polling s
6_64-linux /etc/locale.gen by/backward -binutils_2.44-3grep .deb eb
/systemd-sysctl` (dns block)
> - `publish.twitter.com`
> - Triggering command: `/usr/local/bin/ruby ruby
/usr/local/bundle/bin/bundle exec jekyll serve --watch --port=8080
--host=0.0.0.0 --livereload --verbose --trace --force_polling lude��
lude/ruby-4.0.0//run/containerd/io.containerd.runtime.v2.task/moby/a4760212ce4eda97e32b6dfa4d3ea/usr/sbin/iptables
r/runc-log.json f8_range lude r-strong E r/wc7in709a54d7hshow` (dns
block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/alshedivat/al-folio/settings/copilot/coding_agent)
(admins only)
>
> </details>

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>GDPR compliant cookie consent dialog</issue_title>
> <issue_description>Hi,
> 
> since I am from Europe and want my site to be accessed by EU citizens
I need to ask users if they are ok with the use of cookies. Adding a
dialogue by default that that asks the user before any cookies /
localStorage are used would be nice.
> 
> I have integrated the dialog from
[https://www.cookieconsent.com/](https://www.cookieconsent.com/) on [my
website](http://hschwane.github.io) and am happy to file a PR if you are
interested. However It is not shown directly at the top, but below the
menu bar for some reason. Not sure how to fix that.
> </issue_description>
> 
> <agent_instructions>Implement this using cookie consent dialog from
https://github.com/orestbida/cookieconsent. The documentation is
available at
https://cookieconsent.orestbida.com/essential/getting-started.html.</agent_instructions>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> <comment_new><author>@alshedivat</author><body>
> @hschwane, thanks for pointing this out. It's would be great if you
could send a PR.
> 
> To answer your question about positioning, the menu bar has the
absolute position at the top of the page and keeps moving with
scrolling. You can change that behavior in `_config.yml` by setting
`navbar_fixed: false` (see [line
27](https://github.com/alshedivat/al-folio/blob/master/_config.yml#L27)).
If you send a PR with basic functionality, I can help with adjusting the
styles a bit. Thanks!</body></comment_new>
> <comment_new><author>@alshedivat</author><body>
> Just catching up on this discussion.
> 
> @hschwane, thanks for providing an implementation based on
`ihavecookies`! I looked through #223. It seems like
to be able to correctly (un)block different types of cookies (all of
which are third-party cookies) requires adding quite a bit of extra
JavaScript (including adding it directly to posts or pages in some
cases, e.g., when posts embed youtube videos or other external content).
This approach will put some extra burden on contributors and maintainers
of al-folio down the line.
> 
> By the way, the dialog from https://www.cookieconsent.com/ is similar
in that sense as it requires to manually add ALL scripts that use
cookies. So, if someone contributes a new feature to al-folio that uses
cookies, the contributor would have to go and update the cookie consent
dialog as well (or edit quite a bit of JS if `ihavecookies` is used).
> 
> Thinking about this more, I currently see only three options:
> 1. If we want to have cookie consent as a core part of al-folio (which
can be easily enabled or disabled), it needs to be a service that
automatically identifies and blocks cookies, without putting an extra
burden on the contributors or maintainers. The hosted version of [Cookie
Consent by Osano](https://www.osano.com/features/consent-management) is
an example.
> 2. Another option is to provide a very minimalistic cookie consent
dialog which simply says that the website uses cookies, without an
option to opt-in or opt-out (e.g., see the open-source edition of
[Osano](https://www.osano.com/cookieconsent/download/)).
> 3. Finally, not have cookie consent as part of al-folio, and make the
user responsible for figuring out whether they need a consent dialog and
which service to use.
> 
> Let me know what you think.</body></comment_new>
> <comment_new><author>@alshedivat</author><body>
> the best way to add GDPR compliant cookie consent is using
https://github.com/orestbida/cookieconsent</body></comment_new>
> </comments>
> 


</details>


> **Custom agent used: customization_agent**
> Expert customization assistant for the al-folio Jekyll academic
website template



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes #199

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for
you](https://github.com/alshedivat/al-folio/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Signed-off-by: George Araújo <george.gcac@gmail.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: george-gca <31376482+george-gca@users.noreply.github.com>
Co-authored-by: George Araújo <george.gcac@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This pull request improves the documentation to clarify the recommended
way to create a new site using the al-folio template, emphasizing the
use of the "Use this template" button instead of forking. It explains
the differences between the two approaches, highlights common pitfalls
with forking, and provides guidance for users who have already forked
the repository.

Documentation improvements regarding repository creation:

* Added a prominent section in `README.md` explaining why "Use this
template" is preferred over forking, including step-by-step instructions
and advice for users who have already forked.
* Updated `QUICKSTART.md` to strongly recommend using the "Use this
template" button, clarified the steps for creating a new repository, and
included tips for users who have already forked by mistake.
* Added a new section in `INSTALL.md` detailing the differences between
using the template and forking, common pitfalls, and best practices for
contributing.

Signed-off-by: George Araújo <george.gcac@gmail.com>
Adding my personal academic website to the academics list
This PR adds Fukushima Lab to the **User community** section in
`README.md` under **Labs**. Thank you for maintaining such a great and
inspiring website template.

Added link:
- https://kenji-fukushima-lab.github.io/

Co-authored-by: Kenji Fukushima <kf@MacBookPro.elecom>
Add vud.org to community list.
Hello, please add my academic website to the community page. Thank you
for maintaining this project.
Add new workshop to README.md
Please let my website be on the growing list! I'm Deden Habibi Ali
Alfathimy, a researcher in outer space politics, with personal website
https://deden.id using al-folio.
## Overview

This PR delivers the `v1.0` architecture and runtime upgrade for
`al-folio`.

`al-folio` moves from a monolithic theme repo to a **thin starter +
plugin ecosystem** model, while preserving visual identity and core
behavior.

## What this PR changes

### 1) Starter becomes orchestration-only

`al-folio` is now responsible for:

- starter wiring (`Gemfile`, `_config.yml`)
- sample/demo content
- user-facing docs
- visual regression and cross-plugin integration tests

Component/runtime ownership is moved to dedicated gems.

### 2) Runtime and feature ownership split into plugins

`al_folio_core` now provides shared runtime/layout primitives and
contracts, and delegates feature modules to owning gems.

Key plugin ownership in v1:

- `al_folio_core`: core theme runtime/contracts
- `al_folio_distill`: Distill layouts/runtime
- `al_folio_cv`: CV rendering
- `al_search`: search runtime and modal behavior
- `al_icons`: icon runtime (Font Awesome, Academicons, Scholar Icons)
- `al_cookie`: cookie-consent runtime
- `al_img_tools`: image/gallery/lightbox tooling
- `al_math`: math/TikZ runtime integration
- additional `al-*` plugins for
analytics/charts/citations/comments/newsletter/external posts/upgrade
tooling

### 3) Styling/runtime modernization

- Tailwind-first v1 runtime is established.
- Legacy Bootstrap behavior is isolated behind optional
`al_folio_bootstrap_compat` for migration windows.
- jQuery-dependent runtime paths are removed/replaced in plugin-owned
implementations.

### 4) Test ownership policy is enforced

- `al-folio` keeps only starter-level integration and visual integrity
checks.
- Component correctness tests are owned by the corresponding plugin
repos.

This mirrors runtime ownership and reduces duplication/drift.

### 5) Upgrade and migration workflow

`al_folio_upgrade` is integrated for audit/apply/report migration flows,
including:

- config contract checks
- ownership drift detection
- local override drift audit/diff/acknowledgement workflow
- legacy marker detection
- plugin wiring validation

### 6) Documentation and contributor model for v1

Docs are updated to reflect modular v1 behavior and contribution
routing.

New governance additions include:

- plugin ownership/boundary guidance (`docs/BOUNDARIES.md`)
- plugin naming convention (theme-coupled vs reusable plugin tracks)
- featured-vs-bundled plugin distinction
- plugin catalog source + page (`_data/featured_plugins.yml`,
`_pages/plugins.md`)
- plugin feature proposal issue template
- PR template updates for ownership routing
- agent-facing setup and migration skills

## Compatibility and migration notes

- Plugin integration in starter is via `Gemfile` + `_config.yml`.
- `al-folio` starter intentionally does not use a gemspec in v1.
- Transitional Bootstrap compatibility remains available via
`al_folio_bootstrap_compat`.
- Existing front-matter contracts are preserved where possible; runtime
implementations are now plugin-owned.
- Customized sites can track local override drift with `bundle exec
al-folio upgrade overrides audit` and `.al-folio-overrides.yml`.

## Validation strategy in this PR

- visual parity checks against the v0.16.3 baseline
- starter integration suites (comments, plugin toggles, distill, compat,
upgrade CLI)
- style contract checks and repository linting

## Scope intent

This is the foundational v1 architecture PR.

Post-merge feature work should generally target owning plugin repos
first, with `al-folio` limited to starter wiring, docs, examples, and
integration/visual validation.

_Written by Codex on behalf of @alshedivat._
…3634)

## Summary

Fixes the broken navigation bar on the live demo
(https://alshedivat.github.io/al-folio/) introduced by the v1.0 upgrade
(#2968), plus two related production/deploy-only issues found while
auditing for the same class of bug.

## Root cause of the navbar break

The v1.0 upgrade made the site **Tailwind-first**. The deploy builds
with `JEKYLL_ENV=production`, which activates **jekyll-minifier**. Its
CSS compressor (`cssminify2`) mangles Tailwind v4 spacing tokens
**inside `calc()`**:

```
calc(var(--spacing)*0)   ->   calc(var( -  - spacing)*0)   // invalid
```

`cssminify2` treats the `--` inside `calc(var(--…))` as minus operators
and inserts spaces, producing an invalid custom-property name. This
silently breaks **every** spacing/positioning utility — most visibly
`.fixed-top`, so the fixed navbar is no longer pinned (`top/left/right`
drop out) and renders incorrectly. On the live site this affects 33
`var(--spacing)` references in `tailwind.css`.

It only manifests in **production**: a local `bundle exec jekyll serve`
is development mode (minifier off), and the `visual-regression` workflow
also serves in dev mode — so neither caught it.

### Why this fix

`tailwind.css` is already minified by al_folio_core's Tailwind build,
and `main.css` is compiled by Sass with `style: compressed`.
Re-minifying them with `cssminify2` adds nothing (it actually makes
`tailwind.css` ~315 bytes **larger**) and only introduces this
corruption. So we disable redundant CSS minification, mirroring the
existing `compress_javascript: false` (terser handles JS).

Verified end-to-end:
- The gem source `tailwind.css` has 82 intact `var(--spacing)`;
`cssminify2` corrupts all 82.
- jekyll-minifier (`lib/jekyll-minifier.rb:1061`): `return
output_file(path, content) unless config.compress_css?` — with
`compress_css: false`, `.css` files are written verbatim.
- A real `JEKYLL_ENV=production` build now emits `tailwind.css` with 82
intact `var(--spacing)`, 0 corrupted, and
`.fixed-top{...;position:fixed}` intact.
- PurgeCSS (the next deploy stage) preserves `calc(var(--spacing)*0)`
unchanged.

## Changes

1. **`_config.yml` — `jekyll-minifier.compress_css: false`** (the navbar
fix).
2. **`test/integration_css_minify.sh` + `unit-tests.yml`** — a
regression test that builds in **production mode** (the mode that
exposes this bug class) and asserts no `var( - - )` corruption, intact
`var(--spacing)`, a valid `.fixed-top`, and a non-empty `main.css`.
Passes with the fix; fails without it (83 corruptions). Closes the CI
blind spot that let this ship.
3. **`_config.yml` — drop dead `jekyll-minifier` exclude**
`assets/js/search/*.js`. That is a v0 path; in v1 the search runtime
ships under `assets/al_search/js/...`, so the glob matched nothing.
4. **`purgecss.config.js` — safelist `medium-zoom-overlay` /
`medium-zoom-image--opened`.** These classes are injected at runtime, so
they never appear in the static HTML PurgeCSS scans; their `z-index:999`
overlay rule was being purged on the deployed site, letting the
scroll-progress bar / ToC bleed through a zoomed image. Verified: the
rule survives purge with the safelist and is dropped without it.

## Broader audit — plugin fixes (released + pinned here)

I audited for the same bug class (regressions invisible to dev-mode
builds / leftovers from the v1 jQuery removal). The confirmed
plugin-owned issues were each fixed in their own repo, merged after
green CI, released to RubyGems, and pinned in this PR's `Gemfile`:

- **al_folio_core 1.0.10**
([#18](al-org-dev/al-folio-core#18)) —
`main.css` cache-bust was permanently the empty-string MD5
(`bust_css_cache` globbed a non-existent `assets/_sass`) → stale CSS
after deploys; `bib.liquid` "N more authors" used `$(this)` → threw and
never expanded; `figure.liquid` `onerror` used `$()` → dead broken-image
fallback.
- **al_charts 1.0.1**
([#7](al-org-dev/al-charts#7)) —
`chartjs-setup.js` was jQuery → `chartjs` charts threw `$ is not
defined` and never rendered.
- **al_folio_distill 1.0.2**
([#2](al-org-dev/al-folio-distill#2)) —
`overrides.js` top-level `$(window).on("load")` → distill
footnote/citation theming never applied + console error.

Verified end-to-end with a production build after the pin bumps:
`main.css` now cache-busts to a real hash (`9278fad1…`, not
`d41d8cd9…`), zero jQuery `$(` in the built HTML, and the Tailwind
spacing utilities / `.fixed-top` navbar are intact.

Also noted (not fixed here): the `visual-regression` workflow only
renders in dev mode, so it can't catch production-only CSS regressions —
`test/integration_css_minify.sh` is the immediate guard; a production
screenshot leg would be a fuller backstop.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary

Expands `CLAUDE.md` from a bare `@AGENTS.md` import into a useful entry
point for coding agents, while **keeping** that import so `AGENTS.md`'s
ownership boundaries, validated command set, and PR-routing rules still
flow in (and stay the short, ecosystem-neutral shared file).

The added content is the cross-repo "big picture" that no single file in
this repo currently documents — gathered by reading the starter
internals plus all 16 `al-*` / `al_folio_*` plugin gems:

- **al_folio_core hub + delegation map** — a `wrapper → tag → gem` table
for every bundled plugin, so a runtime change can be routed to the
owning repo in one lookup.
- **Sibling-repos-on-disk** layout and how to point the `Gemfile` at a
local gem checkout (`path:`) to test a gem fix against the site.
- **Cross-repo invariants** — two-layer feature gating (config flag
*and* front matter), `AssetsGenerator` build-time asset injection, the
`Gemfile` ↔ `_config.yml` plugin-list sync, the v1 config contract
(enforced by core's `:after_init` and `al-folio upgrade audit`),
`.al-folio-overrides.yml` drift tracking, and the time-boxed
bootstrap-compat path.
- **Daily dev loop** that `AGENTS.md` omits (`jekyll serve`, single
integration test, snapshot refresh, upgrade subcommands).
- The v1 Docker `/tmp/_site` rationale and the `style_contract.js`
boundary that fails CI if runtime/build files leak into the starter.

Every specific claim (gem versions, tag names, config keys) is grounded
in the actual repos. Prettier-clean.

> Split out from the navbar-fix PR (#3634) per request; this PR is
docs-only and independent.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## Summary

In the "User community" README section several links didn't work
anymore. I updated them where I was able to find a new link from the
same person, and removed the ones where I didn't find a new link.

## Ownership Routing

- [x] I confirmed this PR targets the correct repo based on
`docs/BOUNDARIES.md`.
- [x] This PR only changes starter-owned scope (`al-folio`) **or** I am
porting a routed change and linked the owning repo issue/PR.

## Plugin Ecosystem (if applicable)

- [x] Not applicable
- [ ] This PR proposes a plugin for **featured-only** listing.
- [ ] This PR proposes a plugin for **bundled** starter inclusion.

## Starter Wiring Changes

- [x] Not applicable
- [ ] Updated `Gemfile` dependency wiring.
- [ ] Updated `_config.yml` plugin activation/config.
- [ ] Updated `_data/featured_plugins.yml` metadata.

## Validation

- [x] `npm ci`
- [ ] `bundle exec jekyll build`
- [x] `npm run lint:prettier`
- [x] `npm run lint:style-contract`
- [ ] Integration tests (`test/integration_*.sh`) as needed
- [ ] Visual tests (`npm run test:visual`) as needed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.