From 2f26afb36f05716bfd26d09be3b763a2e9287a10 Mon Sep 17 00:00:00 2001 From: Sean O'Connor Date: Mon, 28 Oct 2024 19:08:33 -0700 Subject: [PATCH] Citation generator added --- public/publications.bib | 2 +- src/app/publications/page.tsx | 55 ++++++++++++++++++++++++++++++----- src/lib/bibtex.ts | 29 ++++++++++++++---- 3 files changed, 72 insertions(+), 14 deletions(-) diff --git a/public/publications.bib b/public/publications.bib index ccd9e85..6150fd6 100644 --- a/public/publications.bib +++ b/public/publications.bib @@ -2,7 +2,7 @@ abstract = {Human-robot interaction (HRI) research plays a pivotal role in shaping how robots communicate and collaborate with humans. However, conducting HRI studies, particularly those employing the Wizard-of-Oz (WoZ) technique, can be challenging. WoZ user studies can have complexities at the technical and methodological levels that may render the results irreproducible. We propose to address these challenges with HRIStudio, a novel web-based platform designed to streamline the design, execution, and analysis of WoZ experiments. HRIStudio offers an intuitive interface for experiment creation, real-time control and monitoring during experimental runs, and comprehensive data logging and playback tools for analysis and reproducibility. By lowering technical barriers, promoting collaboration, and offering methodological guidelines, HRIStudio aims to make human-centered robotics research easier, and at the same time, empower researchers to develop scientifically rigorous user studies.}, author = {O'Connor, Sean and Perrone, L. Felipe}, title = {HRIStudio: A Framework for Wizard-of-Oz Experiments in Human-Robot Interaction Studies (Late Breaking Report)}, - booktitle={33rd IEEE International Conference on Robot and Human Interactive Communication (RO-MAN)}, + booktitle={33rd IEEE International Conference on Robot and Human Interactive Communication}, year = {2024} url = {https://soconnor.dev/publications/hristudio-lbr.pdf}, paperUrl = {/publications/hristudio-lbr.pdf}, diff --git a/src/app/publications/page.tsx b/src/app/publications/page.tsx index 0bc0c74..11e302e 100644 --- a/src/app/publications/page.tsx +++ b/src/app/publications/page.tsx @@ -1,17 +1,18 @@ 'use client'; -import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "~/components/ui/card"; -import { Badge } from "~/components/ui/badge"; -import { ArrowUpRight, FileText, Presentation } from "lucide-react"; +import { ArrowUpRight, BookOpenText, FileText, Presentation } from "lucide-react"; import Link from "next/link"; -import { parseBibtex } from "~/lib/bibtex"; import { useEffect, useState } from "react"; -import type { Publication } from "~/lib/bibtex"; +import { Badge } from "~/components/ui/badge"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/components/ui/card"; import { Skeleton } from "~/components/ui/skeleton"; +import type { Publication } from "~/lib/bibtex"; +import { parseBibtex } from "~/lib/bibtex"; export default function PublicationsPage() { const [publications, setPublications] = useState([]); const [loading, setLoading] = useState(true); + const tagsToStrip = ['paperUrl', 'posterUrl']; useEffect(() => { fetch('/publications.bib') @@ -23,6 +24,38 @@ export default function PublicationsPage() { }); }, []); + const downloadBibtex = (pub: Publication) => { + const { title, authors, venue, year, doi, abstract, type, citationType, citationKey } = pub; + let bibtexEntry = `@${citationType}{${citationKey},\n`; + bibtexEntry += ` title = {${title}},\n`; + bibtexEntry += ` author = {${authors.join(' and ')}},\n`; + bibtexEntry += ` year = {${year}},\n`; + if (type === 'conference' || type === 'workshop') { + bibtexEntry += ` organization = {${venue}},\n`; + } else if (type === 'journal') { + bibtexEntry += ` journal = {${venue}},\n`; + } else if (type === 'thesis') { + bibtexEntry += ` school = {${venue}},\n`; + } + if (doi) { + bibtexEntry += ` doi = {${doi}},\n`; + } + if (abstract) { + bibtexEntry += ` abstract = {${abstract}},\n`; + } + bibtexEntry += `}\n`; + + const blob = new Blob([bibtexEntry], { type: 'text/plain' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `refs.bib`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + }; + return (
@@ -49,9 +82,9 @@ export default function PublicationsPage() {
{pub.title} - {pub.url && ( + {pub.paperUrl && ( )} + downloadBibtex(pub)} + className="cursor-pointer capitalize" + variant="outline" + > + + BibTeX +
diff --git a/src/lib/bibtex.ts b/src/lib/bibtex.ts index 14c2449..0f6729b 100644 --- a/src/lib/bibtex.ts +++ b/src/lib/bibtex.ts @@ -8,12 +8,15 @@ export type Publication = { paperUrl?: string; posterUrl?: string; abstract?: string; + citationType?: string; + citationKey?: string; type: 'conference' | 'journal' | 'workshop' | 'thesis'; }; type BibTeXEntry = { type: string; fields: Record; + citationKey: string; }; function parseAuthors(authorString: string): string[] { @@ -31,10 +34,11 @@ function parseAuthors(authorString: string): string[] { function parseBibTeXEntry(entry: string): BibTeXEntry | null { // Match the entry type and content - const typeMatch = entry.match(/^(\w+)\s*{\s*[\w\d-_]+\s*,/); + const typeMatch = entry.match(/^(\w+)\s*{\s*([\w\d-_]+)\s*,/); if (!typeMatch) return null; const type = typeMatch[1]!.toLowerCase(); + const citationKey = typeMatch[2]; const content = entry.slice(typeMatch[0].length); const fields: Record = {}; @@ -68,7 +72,7 @@ function parseBibTeXEntry(entry: string): BibTeXEntry | null { fields[currentField] = buffer.trim(); } - return { type, fields }; + return { type, fields, citationKey: citationKey! }; } export function parseBibtex(bibtex: string): Publication[] { @@ -79,10 +83,21 @@ export function parseBibtex(bibtex: string): Publication[] { .filter((entry): entry is BibTeXEntry => entry !== null); return entries.map(entry => { - const publicationType = - entry.type === 'inproceedings' ? 'conference' : - entry.type === 'article' ? 'journal' : - entry.type === 'mastersthesis' ? 'thesis' : 'workshop'; + const publicationType = (() => { + switch (entry.type) { + case 'inproceedings': + case 'conference': + return 'conference'; + case 'article': + return 'journal'; + case 'mastersthesis': + return 'thesis'; + case 'workshop': + return 'workshop'; + default: + return 'journal'; + } + })(); return { title: entry.fields.title?.replace(/[{}]/g, '') || '', @@ -94,6 +109,8 @@ export function parseBibtex(bibtex: string): Publication[] { paperUrl: entry.fields.paperurl, posterUrl: entry.fields.posterurl, abstract: entry.fields.abstract, + citationType: entry.type, + citationKey: entry.citationKey, type: publicationType }; });