Skip to content

Commit f1d0b8c

Browse files
committed
add citation
1 parent a14d77e commit f1d0b8c

6 files changed

Lines changed: 145 additions & 1 deletion

File tree

src/features/project-page/ProjectPage.astro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import AbstractSection from "./components/AbstractSection.astro";
88
import DemosSection from "./components/DemosSection.astro";
99
import MethodSection from "./components/MethodSection.astro";
1010
import ExperimentsSection from "./components/ExperimentsSection.astro";
11+
import CitationSection from "./components/CitationSection.astro";
1112
---
1213
<Base title="Ψ₀: An Open Foundation Model Towards Universal Humanoid Loco-Manipulation">
1314
<main class="page">
@@ -36,6 +37,7 @@ import ExperimentsSection from "./components/ExperimentsSection.astro";
3637
<ExperimentsSection
3738
experiments={projectPageContent.experiments}
3839
/>
40+
<CitationSection citation={projectPageContent.citation} />
3941
<footer class="site-footer">
4042
<p>{footerConfig.copyright}</p>
4143
<a href={projectPageContent.footer.sourceCodeHref}>{projectPageContent.footer.sourceCodeLabel}</a>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
const { citation } = Astro.props;
3+
---
4+
<section id="citation" class="section citation-section">
5+
<header class="section-head citation-section-head">
6+
<h2>{citation.sectionTitle}</h2>
7+
<button
8+
class="citation-copy-button"
9+
type="button"
10+
data-copy-citation
11+
data-copied-label={citation.copiedLabel}
12+
>
13+
<span data-copy-label>{citation.copyLabel}</span>
14+
</button>
15+
</header>
16+
<article class="citation-panel">
17+
<div class="citation-bibtex-wrap">
18+
<pre class="citation-bibtex"><code data-citation-bibtex>{citation.bibtex}</code></pre>
19+
</div>
20+
</article>
21+
</section>
22+
23+
<script is:inline>
24+
const bindCitationCopy = () => {
25+
const button = document.querySelector("[data-copy-citation]");
26+
const code = document.querySelector("[data-citation-bibtex]");
27+
const label = button?.querySelector("[data-copy-label]");
28+
if (!button || !code || !label) return;
29+
30+
const defaultLabel = label.textContent;
31+
const copiedLabel = button.dataset.copiedLabel || "Copied";
32+
33+
button.addEventListener("click", async () => {
34+
const text = code.textContent.trim();
35+
36+
try {
37+
await navigator.clipboard.writeText(text);
38+
label.textContent = copiedLabel;
39+
} catch {
40+
const selection = window.getSelection();
41+
const range = document.createRange();
42+
range.selectNodeContents(code);
43+
selection?.removeAllRanges();
44+
selection?.addRange(range);
45+
label.textContent = "Selected";
46+
}
47+
48+
window.setTimeout(() => {
49+
label.textContent = defaultLabel;
50+
}, 1600);
51+
});
52+
};
53+
54+
if (document.readyState === "loading") {
55+
document.addEventListener("DOMContentLoaded", bindCitationCopy, { once: true });
56+
} else {
57+
bindCitationCopy();
58+
}
59+
</script>

src/features/project-page/content/projectContent.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ const withBase = (path) => {
136136
* rows: Record<string, string>[];
137137
* };
138138
* };
139+
* citation: {
140+
* sectionTitle: string;
141+
* copyLabel: string;
142+
* copiedLabel: string;
143+
* bibtex: string;
144+
* };
139145
* footer: {
140146
* sourceCodeLabel: string;
141147
* };
@@ -186,6 +192,7 @@ export const projectPageContent = {
186192
href: "https://arxiv.org/abs/2603.12263",
187193
external: true,
188194
},
195+
{ label: "Cite", href: "#citation" },
189196
{
190197
label: "Model",
191198
href: "https://huggingface.co/usc-psi-lab/psi-model",
@@ -695,6 +702,17 @@ export const projectPageContent = {
695702
],
696703
},
697704
},
705+
citation: {
706+
sectionTitle: "Cite",
707+
copyLabel: "Copy",
708+
copiedLabel: "Copied",
709+
bibtex: `@article{wei2026psi0,
710+
title={{$\\Psi_0$}: An Open Foundation Model Towards Universal Humanoid Loco-Manipulation},
711+
author={Wei, Songlin and Jing, Hongyi and Li, Boqian and Zhao, Zhenyu and Mao, Jiageng and Ni, Zhenhao and He, Sicheng and Liu, Jie and Liu, Xiawei and Kang, Kaidi and others},
712+
journal={arXiv preprint arXiv:2603.12263},
713+
year={2026}
714+
}`,
715+
},
698716
footer: {
699717
sourceCodeLabel: "Website Source Code",
700718
sourceCodeHref: "https://github.com/physical-superintelligence-lab/Psi0",

src/features/project-page/content/siteConfig.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ export const tableOfContents = [
2626
{ id: "demos", label: "Demos" },
2727
{ id: "method", label: "Method" },
2828
{ id: "experiments", label: "Experiments" },
29+
{ id: "citation", label: "Cite" },
2930
];

src/features/project-page/project-page.css

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,58 @@
11811181
text-align: left;
11821182
}
11831183

1184+
.citation-section-head {
1185+
flex-direction: row;
1186+
align-items: center;
1187+
justify-content: space-between;
1188+
gap: 12px;
1189+
}
1190+
1191+
.citation-panel {
1192+
border-radius: 18px;
1193+
border: 1px solid rgba(76, 79, 105, 0.08);
1194+
background: rgba(252, 249, 245, 0.72);
1195+
padding: 12px;
1196+
}
1197+
1198+
.citation-bibtex-wrap {
1199+
overflow: hidden;
1200+
border-radius: 14px;
1201+
border: 1px solid rgba(76, 79, 105, 0.1);
1202+
background: rgba(255, 252, 247, 0.82);
1203+
}
1204+
1205+
.citation-copy-button {
1206+
min-height: 30px;
1207+
padding: 0 12px;
1208+
border: 1px solid rgba(76, 79, 105, 0.12);
1209+
border-radius: 999px;
1210+
background: rgba(255, 252, 247, 0.72);
1211+
color: var(--subtext0);
1212+
font-family: "IBM Plex Mono", "Space Mono", "Courier New", monospace;
1213+
font-size: 11px;
1214+
line-height: 1;
1215+
letter-spacing: 0.08em;
1216+
text-transform: uppercase;
1217+
cursor: pointer;
1218+
}
1219+
1220+
.citation-copy-button:focus-visible {
1221+
outline: 2px solid rgba(76, 79, 105, 0.24);
1222+
outline-offset: 3px;
1223+
}
1224+
1225+
.citation-bibtex {
1226+
margin: 0;
1227+
padding: 16px;
1228+
overflow-x: auto;
1229+
color: var(--text);
1230+
font-family: "IBM Plex Mono", "Space Mono", "Courier New", monospace;
1231+
font-size: 12.5px;
1232+
line-height: 1.55;
1233+
white-space: pre;
1234+
}
1235+
11841236
@media (min-width: 1400px) {
11851237
.page {
11861238
max-width: 1220px;

tests/project-page/content.test.mjs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import fs from "node:fs";
44
import path from "node:path";
55

66
import { projectPageContent } from "../../src/features/project-page/content/projectContent.js";
7-
import { demoLayout, footerConfig } from "../../src/features/project-page/content/siteConfig.js";
7+
import { demoLayout, footerConfig, tableOfContents } from "../../src/features/project-page/content/siteConfig.js";
88

99
const repoRoot = process.cwd();
1010

@@ -17,6 +17,7 @@ test("project page content exposes the expected top-level sections", () => {
1717
"demos",
1818
"method",
1919
"experiments",
20+
"citation",
2021
"footer",
2122
]);
2223
});
@@ -28,6 +29,7 @@ test("hero content is populated and action links are present", () => {
2829
assert.ok(hero.affiliations.length >= 1);
2930
assert.ok(hero.actions.length >= 2);
3031
assert.equal(hero.actions.some((action) => action.label === "SIMPLE"), true);
32+
assert.equal(hero.actions.some((action) => action.label === "Cite" && action.href === "#citation"), true);
3133
assert.equal(hero.repoStats.length, 2);
3234
for (const action of hero.actions) {
3335
assert.ok(action.label.length > 0);
@@ -93,6 +95,15 @@ test("experiment tables match their declared columns", () => {
9395
}
9496
});
9597

98+
test("citation content exposes BibTeX for the paper", () => {
99+
const { citation } = projectPageContent;
100+
assert.equal(citation.sectionTitle, "Cite");
101+
assert.deepEqual(Object.keys(citation), ["sectionTitle", "copyLabel", "copiedLabel", "bibtex"]);
102+
assert.match(citation.bibtex, /^@article\{wei2026psi0,/);
103+
assert.match(citation.bibtex, /arXiv preprint arXiv:2603\.12263/);
104+
assert.match(citation.bibtex, /year=\{2026\}/);
105+
});
106+
96107
test("referenced public assets exist", () => {
97108
const assetPaths = new Set([
98109
projectPageContent.hero.teaserVideoSrc,
@@ -124,4 +135,5 @@ test("shared carousel layout remains centralized in siteConfig", () => {
124135
assert.ok(value.length > 0);
125136
}
126137
assert.match(footerConfig.copyright, /^Copyright/);
138+
assert.equal(tableOfContents.some((item) => item.id === "citation" && item.label === "Cite"), true);
127139
});

0 commit comments

Comments
 (0)