From c8000facb09fdd223c195721aaf640443f4f2d12 Mon Sep 17 00:00:00 2001 From: Rowan Cockett Date: Wed, 24 Apr 2024 12:59:16 -0600 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A2=20Support=20numbered=20references?= =?UTF-8?q?=20(#370)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/chatty-trees-repair.md | 9 +++++ packages/myst-to-react/src/cite.tsx | 29 +++++++++++----- packages/site/src/index.ts | 1 + packages/site/src/themeCSS.ts | 33 +++++++++++++++++++ styles/citations.css | 12 +++++-- themes/article/app/components/ArticlePage.tsx | 3 +- themes/article/app/root.tsx | 1 + themes/article/app/routes/myst-theme[.css].ts | 8 +++++ themes/article/template.yml | 3 ++ themes/book/app/root.tsx | 1 + themes/book/app/routes/$.tsx | 3 +- themes/book/app/routes/myst-theme[.css].ts | 8 +++++ themes/book/template.yml | 3 ++ 13 files changed, 101 insertions(+), 13 deletions(-) create mode 100644 .changeset/chatty-trees-repair.md create mode 100644 packages/site/src/themeCSS.ts create mode 100644 themes/article/app/routes/myst-theme[.css].ts create mode 100644 themes/book/app/routes/myst-theme[.css].ts diff --git a/.changeset/chatty-trees-repair.md b/.changeset/chatty-trees-repair.md new file mode 100644 index 000000000..4165bb112 --- /dev/null +++ b/.changeset/chatty-trees-repair.md @@ -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 diff --git a/packages/myst-to-react/src/cite.tsx b/packages/myst-to-react/src/cite.tsx index 95677b56b..2ab37865a 100644 --- a/packages/myst-to-react/src/cite.tsx +++ b/packages/myst-to-react/src/cite.tsx @@ -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 ( @@ -15,10 +22,13 @@ function CiteChild({ html }: { html?: string }) { ); } -export const CiteGroup: NodeRenderer = ({ node }) => { +export const CiteGroup: NodeRenderer = ({ node }) => { + const allCite = node.children?.every((child) => child.type === 'cite') ?? false; return ( ; } - const { html, doi: doiString } = references?.cite?.data[label] ?? {}; + const { html, doi: doiString, url: refUrl } = references?.cite?.data[label] ?? {}; if (error) { return ; } - const doiUrl = doiString ? doi.buildUrl(doiString as string) : null; + const url = doiString ? doi.buildUrl(doiString as string) : refUrl; return ( }> - {doiUrl && ( - + {url && ( + {children} )} - {!doiUrl && {children}} + {!url && {children}} ); }; export const CiteRenderer: NodeRenderer = ({ node }) => { + const numbered = useNumberedReferences(); return ( - + {numbered && node.kind === 'parenthetical' ? node.enumerator : } ); }; diff --git a/packages/site/src/index.ts b/packages/site/src/index.ts index 1bc9eb000..20ffd2080 100644 --- a/packages/site/src/index.ts +++ b/packages/site/src/index.ts @@ -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'; diff --git a/packages/site/src/themeCSS.ts b/packages/site/src/themeCSS.ts new file mode 100644 index 000000000..a4efc3f67 --- /dev/null +++ b/packages/site/src/themeCSS.ts @@ -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', + }, + }); +} diff --git a/styles/citations.css b/styles/citations.css index fc8ea1a42..9f6514d6c 100644 --- a/styles/citations.css +++ b/styles/citations.css @@ -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, ')'); } diff --git a/themes/article/app/components/ArticlePage.tsx b/themes/article/app/components/ArticlePage.tsx index e147d0649..617f51aff 100644 --- a/themes/article/app/components/ArticlePage.tsx +++ b/themes/article/app/components/ArticlePage.tsx @@ -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 }) { diff --git a/themes/article/app/root.tsx b/themes/article/app/root.tsx index 5bd309697..f307fbde7 100644 --- a/themes/article/app/root.tsx +++ b/themes/article/app/root.tsx @@ -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/jupyter-matplotlib@0.11.3/css/mpl_widget.css', diff --git a/themes/article/app/routes/myst-theme[.css].ts b/themes/article/app/routes/myst-theme[.css].ts new file mode 100644 index 000000000..d53b5913e --- /dev/null +++ b/themes/article/app/routes/myst-theme[.css].ts @@ -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 => { + const site = await getConfig(); + return cssResponse(themeCSS(site?.options as ThemeCssOptions)); +}; diff --git a/themes/article/template.yml b/themes/article/template.yml index e0e01a98f..d25473c64 100644 --- a/themes/article/template.yml +++ b/themes/article/template.yml @@ -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 diff --git a/themes/book/app/root.tsx b/themes/book/app/root.tsx index c7f20d6df..1c397c039 100644 --- a/themes/book/app/root.tsx +++ b/themes/book/app/root.tsx @@ -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/jupyter-matplotlib@0.11.3/css/mpl_widget.css', diff --git a/themes/book/app/routes/$.tsx b/themes/book/app/routes/$.tsx index c37719185..7d6743205 100644 --- a/themes/book/app/routes/$.tsx +++ b/themes/book/app/routes/$.tsx @@ -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() { diff --git a/themes/book/app/routes/myst-theme[.css].ts b/themes/book/app/routes/myst-theme[.css].ts new file mode 100644 index 000000000..d53b5913e --- /dev/null +++ b/themes/book/app/routes/myst-theme[.css].ts @@ -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 => { + const site = await getConfig(); + return cssResponse(themeCSS(site?.options as ThemeCssOptions)); +}; diff --git a/themes/book/template.yml b/themes/book/template.yml index 324994637..bbbd5f336 100644 --- a/themes/book/template.yml +++ b/themes/book/template.yml @@ -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