app/components/shell-footer.tsx
139 lines and 7 functions in DrDustinEdwards/dustinedwards-info, at commit 1590ba4 on 2026-10-24. This file on GitHub.
Functions
| Function | Lines | Complexity | Covered | CRAP | Mutation |
|---|---|---|---|---|---|
| XMark | 26 to 35 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| FooterAnchor | 38 to 46 | 4 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| ShellFooter | 53 to 145 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:65> | 65 to 80 | 2 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:83> | 83 to 87 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:98> | 98 to 120 | 2 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:128> | 128 to 132 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
Imports
It imports app/components/germomics-mark.tsx, app/components/private-tool-icons.tsx, app/components/site-logo.tsx, app/lib/footer.ts, app/lib/seo.ts. Imported by app/components/error-page.tsx, app/components/page-shell.tsx, app/components/taxonomy-listing.tsx, app/routes/blog.$slug.tsx, app/routes/blog._index.tsx, app/routes/home.tsx, app/routes/publications.$slug.tsx, app/routes/publications.tsx, app/routes/search.tsx.
Source
import { Link } from "react-router";
import { GermomicsMark } from "~/components/germomics-mark";
import { CapsidIcon, FlaskIcon, GearIcon, LampIcon, LockIcon } from "~/components/private-tool-icons";
import { SiteLogoHeader } from "~/components/site-logo";
import {
BRAND_PROFILES,
type FooterLink,
PRIVATE_TOOLS,
type PrivateTool,
SITE_HEADING,
SITE_LINKS,
SOCIAL_LINKS,
TOOLS_HEADING,
} from "~/lib/footer";
import { SITE } from "~/lib/seo";
const PRIVATE_ICONS: Record<PrivateTool["icon"], typeof LampIcon> = {
lamp: LampIcon,
gear: GearIcon,
capsid: CapsidIcon,
flask: FlaskIcon,
};
/** X's own logo path, unaltered, in the footer's ink. */
function XMark() {
return (
<svg className="footer-social-mark" viewBox="0 0 1200 1227" width="27" height="28" aria-hidden="true" focusable="false">
<path
fill="currentColor"
d="M714.163 519.284L1160.89 0H1055.03L667.137 450.887L357.328 0H0L468.492 681.821L0 1226.37H105.866L515.491 750.218L842.672 1226.37H1200L714.137 519.284H714.163ZM569.165 687.828L521.697 619.934L144.011 79.6944H306.615L611.412 515.685L658.88 583.579L1055.08 1150.3H892.476L569.165 687.854V687.828Z"
/>
</svg>
);
}
/** A route through Link; a file, feed or other site as a plain anchor, which Link would try to route. */
function FooterAnchor({ link }: { link: FooterLink }) {
const routed = !link.external && !/\.[a-z]+$/.test(link.to);
if (routed) return <Link to={link.to}>{link.label}</Link>;
return (
<a href={link.to} rel={link.me ? "me" : undefined}>
{link.label}
</a>
);
}
/**
* The links live in app/lib/footer.ts, where test/footer.test.mjs checks each one. The profile links carry
* rel="me", and `check:machine-readable` asserts that set equals `OWNER_PROFILES`. The bottom line is the
* copyright and nothing else (Dustin, 2026-10-11).
*/
export function ShellFooter() {
return (
<footer className="site-shell-footer">
<div className="tracks">
<div className="footer-grid">
{/* The brand block: logo, name, social marks, then the profile links and the feed. No title line: the hero carries it. */}
<div className="footer-identity">
<Link to="/" className="footer-home">
<SiteLogoHeader className="footer-logo" />
<span className="footer-name">{SITE.name}</span>
</Link>
<ul className="footer-social" aria-label="Social media">
{SOCIAL_LINKS.map((link) => (
<li key={link.to}>
<a href={link.to} className="footer-social-link">
{link.mark === "germomics" ? (
<span className="footer-social-glyph">
<GermomicsMark className="footer-social-mark" />
</span>
) : (
<span className="footer-social-glyph">
<XMark />
</span>
)}
<span className="footer-social-label">{link.label}</span>
</a>
</li>
))}
</ul>
<ul className="footer-links footer-profiles">
{BRAND_PROFILES.map((link) => (
<li key={link.to}>
<FooterAnchor link={link} />
</li>
))}
</ul>
</div>
{/* Beside the brand block: Workspace, then Site (Dustin, 2026-10-11). */}
<div className="footer-columns">
<nav className="footer-col" aria-labelledby="footer-workspace">
<h2 className="footer-heading" id="footer-workspace">
{TOOLS_HEADING}
</h2>
<ul className="footer-links">
{PRIVATE_TOOLS.map((tool) => {
const Icon = PRIVATE_ICONS[tool.icon];
const content = (
<>
<Icon className="footer-private-icon" />
{tool.label}
<LockIcon className="footer-private-lock" strokeWidth={2} />
</>
);
return (
<li key={tool.to}>
{tool.external ? (
<a href={tool.to} className="footer-private-link" aria-label={tool.name} title={tool.hover}>
{content}
</a>
) : (
<Link to={tool.to} className="footer-private-link" aria-label={tool.name} title={tool.hover}>
{content}
</Link>
)}
</li>
);
})}
</ul>
</nav>
<nav className="footer-col" aria-labelledby="footer-site">
<h2 className="footer-heading" id="footer-site">
{SITE_HEADING}
</h2>
<ul className="footer-links">
{SITE_LINKS.map((item) => (
<li key={item.to}>
<FooterAnchor link={item} />
</li>
))}
</ul>
</nav>
</div>
</div>
{/* The end year is computed at render: an edge-cached page can show last year's for a few days after
January 1, which Dustin accepted (2026-09-27) over a year that is edited by hand. */}
<p className="site-shell-footer-note">
© 2006–{new Date().getFullYear()} {SITE.name}
</p>
</div>
</footer>
);
}