Skip to content

Commit 73b5d75

Browse files
committed
feat(research): equal-contribution and PI superscript markers
Extends the conditional sup system in HeadingResearch beyond the existing `*` (corresponding) + numeric affiliation indices to cover the two other academic conventions that come up on multi-author papers: † Equal contribution — `equalContribution: true` ‡ Principal investigator — `principalInvestigator: true` Both new fields are optional booleans on the Author type. Existing entries are unaffected. Suppression rules (each marker only renders when it disambiguates): * shows when 2+ authors AND ≥1 corresponding † shows when 2+ authors AND ≥2 flagged equal-contribution (a single "equal" author is meaningless) ‡ shows when 2+ authors AND ≥1 PI ¹² shows when 2+ affiliations Marker order on each author follows academic typesetting convention: symbol markers (*†‡) first, then numeric affiliation indices. Each <sup> keeps its cursor-help + native title tooltip ("Corresponding author", "Equal contribution", "Principal investigator", or the resolved affiliation name). The previous standalone "*Corresponding author" caption is replaced by a single combined caption line that stacks all active markers separated by ` · ` — e.g. "*Corresponding author · †Equal contribution · ‡Principal investigator" — kept tight and rendered only when at least one symbol marker is showing. Documented the new flags + the combined caption behavior in CLAUDE.md and README.md (research-authoring section now has a flag/glyph/rule table). Frontmatter example shows the two new fields commented out so a fork sees them and can opt in. Verified locally: yarn type-check, yarn lint, yarn test (48/48), yarn build (50 routes) — all clean.
1 parent e51fe44 commit 73b5d75

4 files changed

Lines changed: 64 additions & 8 deletions

File tree

CLAUDE.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,13 @@ ISR endpoint at `GET /api/revalidate?secret=<SECRET>&slug=/blog/<slug>`. Secret
128128
- Frontmatter `published` for blog and research is `MM/DD/YYYY` (portfolio uses `date`). `featured: true` surfaces an entry on the home page. Optional `updated: "MM/DD/YYYY"` overrides `published` as the freshness signal — it flows into `dateModified` (BlogPosting / ScholarlyArticle JSON-LD), `<meta property="article:modified_time">`, and the sitemap `lastmod`. Set it whenever you make a substantive content edit; leave it off for typo fixes.
129129
- Authoring convention: open every blog post with a 60–120 word TL;DR paragraph immediately under the H1. LLM crawlers (ChatGPT, Perplexity, AI Overviews) draw ~44% of their citations from the first 30% of an article, so front-loading the answer compounds visibility.
130130
- **Research authoring**: use the YAML folded scalar (`abstract: >-`) — block scalar (`|`) preserves newlines and the abstract renders with broken lines. Authors use a structured array; `affiliations` indices are 1-based and reference the entry's `affiliations` array. `section` drives listing-page grouping (`top-tier` / `conferences` / `journals` / `workshops` / `others`). `new: true` renders a NEW badge inline with the title on the listing card. `comingSoon: true` swaps the listing thumbnail for the `ComingSoonImage` pastel placeholder (no thumbnail/teaser required). Authors matching `SITE_AUTHOR.name` are auto-bolded across `HeadingResearch` and `ResearchItem`.
131-
- **Author / affiliation superscripts** in `HeadingResearch` are conditional: `*` (corresponding author) only renders when there are 2+ authors AND at least one is `corresponding: true`; `¹ ² ³` (affiliation indices) only render when there are 2+ affiliations. The affiliation legend below the author line drops its leading `<sup>` under the same rule. Single-author / single-affiliation entries collapse to clean text — no orphan markers. When markers do render, each `<sup>` has `cursor-help` and a native `title` tooltip explaining what it means (resolves to the affiliation's full name for index sups, "Corresponding author" for the asterisk). A "\*Corresponding author" caption appears below the affiliation line when the asterisk is shown.
131+
- **Author / affiliation superscripts** in `HeadingResearch` are conditional. Each marker only renders when it actually disambiguates something:
132+
- `*` (corresponding author) — `corresponding: true` on the author. Shows when **2+ authors** AND at least one is corresponding.
133+
- `` (equal contribution) — `equalContribution: true` on the author. Shows when **2+ authors** AND at least 2 are flagged. Renders on every flagged author.
134+
- `` (principal investigator) — `principalInvestigator: true` on the author. Shows when **2+ authors** AND at least one is PI.
135+
- `¹ ² ³` (affiliation indices) — derived from `affiliations: [...]` on each author. Shows when **2+ affiliations** exist on the entry.
136+
137+
Marker order on each author follows academic convention: `*†‡` then numeric indices. The affiliation legend below the author line drops its leading `<sup>` under the same `showAffSup` rule. Single-author / single-affiliation entries collapse to clean text — no orphan markers. Each `<sup>` has `cursor-help` + a native `title` tooltip (affiliation index sups resolve to the full affiliation name; symbol sups resolve to their caption text). A combined caption line appears below the affiliation row when any symbol marker is shown — e.g. `*Corresponding author · †Equal contribution · ‡Principal investigator` — joined by ` · `.
132138

133139
## Indexing Helper
134140

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,8 @@ authors:
337337
email: 'aannafee@gmu.edu'
338338
affiliations: [1] # 1-based indices into the entry's affiliations array
339339
corresponding: true
340+
# equalContribution: true # OPTIONAL: → † on each flagged author + a "†Equal contribution" caption
341+
# principalInvestigator: true # OPTIONAL: → ‡ on PI + a "‡Principal investigator" caption
340342
affiliations:
341343
- name: 'George Mason University'
342344
location: 'Fairfax, Virginia, USA'
@@ -375,7 +377,16 @@ bibtex: |
375377

376378
The detail page renders the structured fields in the hero (status chip from `venue.status`, authors with affiliation superscripts, venue line, action-button row driven by `links` and `bibtex`). Authors matching `SITE_AUTHOR.name` are bolded. The `bibtex` field renders as a copy-to-clipboard code block anchored at `#bibtex`.
377379

378-
**Author / affiliation superscripts are conditional**: `*` (corresponding author) only renders when there are 2+ authors and at least one is `corresponding: true`; `¹ ² ³` (affiliation indices) only render when there are 2+ affiliations. Single-author / single-affiliation entries skip both — no orphan markers. When the markers do show, they carry hover tooltips (native `title` + `cursor-help`) that resolve to the actual affiliation names so the meaning is clear without scrolling.
380+
**Author / affiliation superscripts are conditional** — each marker only renders when it actually disambiguates something:
381+
382+
| Flag on `Author` | Glyph | Caption | Renders when |
383+
| ----------------------------- | ------- | ----------------------- | ------------------------------- |
384+
| `corresponding: true` | `*` | \*Corresponding author | 2+ authors AND ≥1 corresponding |
385+
| `equalContribution: true` | `` | †Equal contribution | 2+ authors AND ≥2 flagged equal |
386+
| `principalInvestigator: true` | `` | ‡Principal investigator | 2+ authors AND ≥1 PI |
387+
| `affiliations: [n]` | `¹ ² ³` | _(legend below)_ | 2+ affiliations on the entry |
388+
389+
Marker order on each author: `*†‡` then numeric affiliation indices (academic convention). Single-author / single-affiliation entries skip everything — no orphan markers. When markers do show, each `<sup>` carries a native `title` tooltip (affiliation index sups resolve to the full affiliation name; symbol sups resolve to their caption). A combined caption line — e.g. `*Corresponding author · †Equal contribution · ‡Principal investigator` — auto-renders below the affiliation row.
379390

380391
The research listing page (`/research`) renders an Overview paragraph, a date-column News timeline, and a colored chip row of Research Areas above the section-grouped listings. Section headings across the page (Overview / News / Research Areas / Top-Tier Venues / Conferences / Journals / Workshops / Others) share a single `<SectionHeading>` component (`text-lg md:text-xl`, `font-bold`, `text-black dark:text-white`, bordered bottom).
381392

src/components/content/research/HeadingResearch.tsx

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { SITE_AUTHOR } from '@/libs/constants/site'
44
import { twclsx } from '@/libs/twclsx'
55

66
import { Affiliation, Author, ResearchLinks, Venue } from 'me'
7+
import { Fragment } from 'react'
78
import {
89
HiGlobeAlt,
910
HiOutlineDatabase,
@@ -100,12 +101,23 @@ export const HeadingResearch: React.FunctionComponent<HeadingResearchProps> = (p
100101
</div>
101102
)}
102103

103-
{/* Suppress meaningless markers: only show affiliation superscripts when there are 2+ affiliations,
104-
and only show the corresponding-author asterisk when there are 2+ authors. Otherwise the markers
105-
are noise on a single-author / single-affiliation paper. */}
104+
{/* Suppress meaningless markers: each superscript only renders when it actually
105+
disambiguates something. Single-author / single-affiliation entries collapse
106+
to clean text. Marker order on each author follows academic convention:
107+
symbol markers (* † ‡) first, then numeric affiliation indices. */}
106108
{(() => {
109+
const hasMultipleAuthors = props.authors.length > 1
110+
const equalContribCount = props.authors.filter((a) => a.equalContribution).length
111+
107112
const showAffSup = (props.affiliations?.length ?? 0) > 1
108-
const showCorrespondingSup = props.authors.length > 1 && props.authors.some((a) => a.corresponding)
113+
const showCorrespondingSup = hasMultipleAuthors && props.authors.some((a) => a.corresponding)
114+
const showEqualContribSup = hasMultipleAuthors && equalContribCount >= 2
115+
const showPISup = hasMultipleAuthors && props.authors.some((a) => a.principalInvestigator)
116+
117+
const captions: { glyph: string; label: string }[] = []
118+
if (showCorrespondingSup) captions.push({ glyph: '*', label: 'Corresponding author' })
119+
if (showEqualContribSup) captions.push({ glyph: '†', label: 'Equal contribution' })
120+
if (showPISup) captions.push({ glyph: '‡', label: 'Principal investigator' })
109121

110122
return (
111123
<>
@@ -147,6 +159,16 @@ export const HeadingResearch: React.FunctionComponent<HeadingResearchProps> = (p
147159
*
148160
</sup>
149161
)}
162+
{author.equalContribution && showEqualContribSup && (
163+
<sup className={twclsx(nameClass, 'cursor-help')} title='Equal contribution'>
164+
165+
</sup>
166+
)}
167+
{author.principalInvestigator && showPISup && (
168+
<sup className={twclsx(nameClass, 'cursor-help')} title='Principal investigator'>
169+
170+
</sup>
171+
)}
150172
{supText && showAffSup && (
151173
<sup className={twclsx(nameClass, 'cursor-help')} title={affTitle || undefined}>
152174
{supText}
@@ -185,9 +207,17 @@ export const HeadingResearch: React.FunctionComponent<HeadingResearchProps> = (p
185207
</p>
186208
)}
187209

188-
{showCorrespondingSup && (
210+
{captions.length > 0 && (
189211
<p className={twclsx('mt-1 text-center text-xs text-gray-500 dark:text-gray-400')}>
190-
<sup>*</sup>Corresponding author
212+
{captions.map((cap, i) => (
213+
<Fragment key={cap.glyph}>
214+
{i > 0 && <span aria-hidden='true'>{' · '}</span>}
215+
<span>
216+
<sup>{cap.glyph}</sup>
217+
{cap.label}
218+
</span>
219+
</Fragment>
220+
))}
191221
</p>
192222
)}
193223
</>

src/types/index.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,16 @@ declare module 'me' {
4343
name: string
4444
url?: string
4545
affiliations?: Array<number>
46+
/** Renders a `*` superscript next to the name + a "*Corresponding author" caption.
47+
* Suppressed on single-author papers (the marker has nothing to disambiguate). */
4648
corresponding?: boolean
49+
/** Marks shared first-authorship. Renders a `†` superscript on every author with the
50+
* flag set + a "†Equal contribution" caption. Requires at least 2 authors flagged
51+
* (the concept of "equal" is meaningless with one). */
52+
equalContribution?: boolean
53+
/** Marks the senior / PI author. Renders a `‡` superscript + a "‡Principal
54+
* investigator" caption. Suppressed on single-author papers. */
55+
principalInvestigator?: boolean
4756
email?: string
4857
orcid?: string
4958
}

0 commit comments

Comments
 (0)