Skip to content

Commit

Permalink
🔢 Support numbered references (#370)
Browse files Browse the repository at this point in the history
  • Loading branch information
rowanc1 authored Apr 24, 2024
1 parent de86232 commit c8000fa
Show file tree
Hide file tree
Showing 13 changed files with 101 additions and 13 deletions.
9 changes: 9 additions & 0 deletions .changeset/chatty-trees-repair.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'myst-to-react': patch
'@myst-theme/article': patch
'@myst-theme/site': patch
'@myst-theme/book': patch
'@myst-theme/styles': patch
---

Support numbered references
29 changes: 20 additions & 9 deletions packages/myst-to-react/src/cite.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import classNames from 'classnames';
import { useReferences } from '@myst-theme/providers';
import { useReferences, useSiteManifest } from '@myst-theme/providers';
import type { NodeRenderer } from '@myst-theme/providers';
import { doi } from 'doi-utils';
import { InlineError } from './inlineError.js';
import { HoverPopover } from './components/index.js';
import { MyST } from './MyST.js';
import type { GenericParent } from 'myst-common';

function useNumberedReferences(): boolean {
const config = useSiteManifest();
const numbered_references = !!config?.options?.numbered_references;
return numbered_references;
}

function CiteChild({ html }: { html?: string }) {
return (
Expand All @@ -15,10 +22,13 @@ function CiteChild({ html }: { html?: string }) {
);
}

export const CiteGroup: NodeRenderer = ({ node }) => {
export const CiteGroup: NodeRenderer<GenericParent> = ({ node }) => {
const allCite = node.children?.every((child) => child.type === 'cite') ?? false;
return (
<span
className={classNames('cite-group', {
className={classNames({
'cite-group': allCite,
'xref-group': !allCite,
narrative: node.kind === 'narrative',
parenthetical: node.kind === 'parenthetical',
})}
Expand All @@ -41,29 +51,30 @@ export const Cite = ({
if (!label) {
return <InlineError value="cite (no label)" message={'Citation Has No Label'} />;
}
const { html, doi: doiString } = references?.cite?.data[label] ?? {};
const { html, doi: doiString, url: refUrl } = references?.cite?.data[label] ?? {};
if (error) {
return <InlineError value={label} message={'Citation Not Found'} />;
}
const doiUrl = doiString ? doi.buildUrl(doiString as string) : null;
const url = doiString ? doi.buildUrl(doiString as string) : refUrl;
return (
<HoverPopover openDelay={300} card={<CiteChild html={html} />}>
<cite>
{doiUrl && (
<a href={doiUrl} target="_blank" rel="noreferrer" className="hover-link">
{url && (
<a href={url} target="_blank" rel="noreferrer" className="hover-link">
{children}
</a>
)}
{!doiUrl && <span className="hover-link">{children}</span>}
{!url && <span className="hover-link">{children}</span>}
</cite>
</HoverPopover>
);
};

export const CiteRenderer: NodeRenderer = ({ node }) => {
const numbered = useNumberedReferences();
return (
<Cite label={node.label} error={node.error}>
<MyST ast={node.children} />
{numbered && node.kind === 'parenthetical' ? node.enumerator : <MyST ast={node.children} />}
</Cite>
);
};
Expand Down
1 change: 1 addition & 0 deletions packages/site/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './loaders/index.js';
export * from './components/index.js';
export * from './pages/index.js';
export * from './seo/index.js';
export * from './themeCSS.js';
33 changes: 33 additions & 0 deletions packages/site/src/themeCSS.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export type ThemeCssOptions = {
numbered_references?: boolean;
};

type MystThemeVariables = {
'cite-group-open'?: '(' | '[' | string;
'cite-group-close'?: ')' | ']' | string;
};

function variables(vars: MystThemeVariables) {
const css = Object.entries(vars)
.map(([name, value]) => `--${name}: '${value}';`)
.join('\n ');
if (!css) return '';
return `:root {\n ${css}}`;
}

export function themeCSS(options?: ThemeCssOptions) {
const numbered_references = !!options?.numbered_references;
const citationCss = numbered_references
? { 'cite-group-open': '[', 'cite-group-close': ']' }
: {};
return variables({ ...citationCss });
}

export function cssResponse(css: string): Response {
return new Response(css, {
headers: {
'Content-Type': 'text/css',
'Cache-Control': 'no-cache',
},
});
}
12 changes: 10 additions & 2 deletions styles/citations.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ cite {
.cite-group.parenthetical > *::after {
content: ';\00a0';
}
.xref-group > *::after,
.cite-group.narrative > *::after {
content: ',\00a0';
}
.xref-group > *:last-of-type::after,
.cite-group > *:last-of-type::after {
content: '';
}
.cite-group.parenthetical:before {
content: '(';
content: var(--cite-group-open, '(');
}
.cite-group.parenthetical:after {
content: ')';
content: var(--cite-group-close, ')');
}
.xref-group.parenthetical:before {
content: var(--xref-group-open, '(');
}
.xref-group.parenthetical:after {
content: var(--xref-group-close, ')');
}
3 changes: 2 additions & 1 deletion themes/article/app/components/ArticlePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import { BusyScopeProvider, ExecuteScopeProvider } from '@myst-theme/jupyter';
import { DownloadLinksArea } from './Downloads';
import { Article } from './Article';

interface ArticleTemplateOptions {
export interface ArticleTemplateOptions {
hide_toc?: boolean;
hide_footer_links?: boolean;
numbered_references?: boolean;
}

export function ArticlePage({ article }: { article: PageLoader }) {
Expand Down
1 change: 1 addition & 0 deletions themes/article/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const links: LinksFunction = () => {
},
{ rel: 'stylesheet', href: tailwind },
{ rel: 'stylesheet', href: thebeCoreCss },
{ rel: 'stylesheet', href: '/myst-theme.css' },
{
rel: 'stylesheet',
href: 'https://cdn.jsdelivr.net/npm/[email protected]/css/mpl_widget.css',
Expand Down
8 changes: 8 additions & 0 deletions themes/article/app/routes/myst-theme[.css].ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { type LoaderFunction } from '@remix-run/node';
import { type ThemeCssOptions, themeCSS, cssResponse } from '@myst-theme/site';
import { getConfig } from '~/utils/loaders.server';

export const loader: LoaderFunction = async (): Promise<Response> => {
const site = await getConfig();
return cssResponse(themeCSS(site?.options as ThemeCssOptions));
};
3 changes: 3 additions & 0 deletions themes/article/template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ options:
- type: string
id: analytics_plausible
description: Plausible analytics key
- type: boolean
id: numbered_references
description: Show references as numbered, rather than in APA-style. Only applies to parenthetical citations.
build:
install: npm install
start: npm run start
Expand Down
1 change: 1 addition & 0 deletions themes/book/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const links: LinksFunction = () => {
},
{ rel: 'stylesheet', href: tailwind },
{ rel: 'stylesheet', href: thebeCoreCss },
{ rel: 'stylesheet', href: '/myst-theme.css' },
{
rel: 'stylesheet',
href: 'https://cdn.jsdelivr.net/npm/[email protected]/css/mpl_widget.css',
Expand Down
3 changes: 2 additions & 1 deletion themes/book/app/routes/$.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,12 @@ export function ArticlePageAndNavigation({
);
}

interface BookThemeTemplateOptions {
export interface BookThemeTemplateOptions {
hide_toc?: boolean;
hide_outline?: boolean;
hide_footer_links?: boolean;
outline_maxdepth?: number;
numbered_references?: boolean;
}

export default function Page() {
Expand Down
8 changes: 8 additions & 0 deletions themes/book/app/routes/myst-theme[.css].ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { type LoaderFunction } from '@remix-run/node';
import { type ThemeCssOptions, themeCSS, cssResponse } from '@myst-theme/site';
import { getConfig } from '~/utils/loaders.server';

export const loader: LoaderFunction = async (): Promise<Response> => {
const site = await getConfig();
return cssResponse(themeCSS(site?.options as ThemeCssOptions));
};
3 changes: 3 additions & 0 deletions themes/book/template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ options:
- type: string
id: analytics_plausible
description: Plausible analytics key
- type: boolean
id: numbered_references
description: Show references as numbered, rather than in APA-style. Only applies to parenthetical citations.
build:
install: npm install
start: npm run start
Expand Down

0 comments on commit c8000fa

Please sign in to comment.