diff --git a/.changeset/great-weeks-sit.md b/.changeset/great-weeks-sit.md
new file mode 100644
index 000000000..0da955fb7
--- /dev/null
+++ b/.changeset/great-weeks-sit.md
@@ -0,0 +1,5 @@
+---
+'@myst-theme/site': patch
+---
+
+Mark ArticlePage as deprecated
diff --git a/.changeset/healthy-waves-sell.md b/.changeset/healthy-waves-sell.md
new file mode 100644
index 000000000..cd1feefaf
--- /dev/null
+++ b/.changeset/healthy-waves-sell.md
@@ -0,0 +1,6 @@
+---
+'@myst-theme/article': patch
+'@myst-theme/book': patch
+---
+
+Support inline navigation
diff --git a/packages/site/src/pages/Article.tsx b/packages/site/src/pages/Article.tsx
index 0c3e49228..94be713c5 100644
--- a/packages/site/src/pages/Article.tsx
+++ b/packages/site/src/pages/Article.tsx
@@ -41,6 +41,11 @@ function combineDownloads(
return pageFrontmatter.exports;
}
+/**
+ * @deprecated This component is not maintained, in favor of theme-specific ArticlePages
+ *
+ * As examples, MyST book and article themes define their own ArticlePage components.
+ */
export const ArticlePage = React.memo(function ({
article,
hide_all_footer_links,
diff --git a/themes/article/app/components/Article.tsx b/themes/article/app/components/Article.tsx
index 2c35f250b..853b99c8b 100644
--- a/themes/article/app/components/Article.tsx
+++ b/themes/article/app/components/Article.tsx
@@ -21,11 +21,13 @@ export function Article({
hideKeywords,
hideOutline,
hideTitle,
+ outlineMaxDepth,
}: {
article: PageLoader;
hideKeywords?: boolean;
hideOutline?: boolean;
hideTitle?: boolean;
+ outlineMaxDepth?: number;
}) {
const keywords = article.frontmatter?.keywords ?? [];
const tree = copyNode(article.mdast);
@@ -42,12 +44,13 @@ export function Article({
{!hideTitle && }
{!hideOutline && (
-
-
+
+
)}
+
{compute?.enabled &&
compute?.features.notebookCompute &&
article.kind === SourceFileKind.Notebook && }
diff --git a/themes/article/app/components/ArticlePage.tsx b/themes/article/app/components/ArticlePage.tsx
index 617f51aff..cb1ceab68 100644
--- a/themes/article/app/components/ArticlePage.tsx
+++ b/themes/article/app/components/ArticlePage.tsx
@@ -1,5 +1,9 @@
import type { PageLoader } from '@myst-theme/common';
-import { FooterLinksBlock, ArticleHeader, Error404 } from '@myst-theme/site';
+import {
+ FooterLinksBlock,
+ ArticleHeader,
+ Error404,
+} from '@myst-theme/site';
import { LaunchBinder, useComputeOptions } from '@myst-theme/jupyter';
import { ArrowLeftIcon } from '@heroicons/react/24/outline';
import { DocumentArrowDownIcon } from '@heroicons/react/24/outline';
@@ -15,17 +19,20 @@ import classNames from 'classnames';
import { BusyScopeProvider, ExecuteScopeProvider } from '@myst-theme/jupyter';
import { DownloadLinksArea } from './Downloads';
import { Article } from './Article';
-
-export interface ArticleTemplateOptions {
- hide_toc?: boolean;
- hide_footer_links?: boolean;
- numbered_references?: boolean;
-}
+import type { TemplateOptions } from '../types.js';
export function ArticlePage({ article }: { article: PageLoader }) {
const grid = useGridSystemProvider();
- const { projects, hide_footer_links } = (useSiteManifest() ?? {}) as SiteManifest &
- ArticleTemplateOptions;
+
+ const siteManifest = useSiteManifest() as SiteManifest;
+ const pageDesign: TemplateOptions = (article.frontmatter as any)?.options ?? {};
+ const siteDesign: TemplateOptions = siteManifest?.options ?? {};
+
+ const { projects } = siteManifest;
+ const { hide_footer_links, hide_outline, outline_maxdepth } = {
+ ...siteDesign,
+ ...pageDesign,
+ };
const Link = useLinkProvider();
const baseurl = useBaseurl();
const compute = useComputeOptions();
@@ -91,7 +98,13 @@ export function ArticlePage({ article }: { article: PageLoader }) {
)}
-
+
{!hide_footer_links && }
@@ -99,3 +112,4 @@ export function ArticlePage({ article }: { article: PageLoader }) {
);
}
+
diff --git a/themes/article/app/routes/_index.tsx b/themes/article/app/routes/_index.tsx
index 2c5446466..a1f67919c 100644
--- a/themes/article/app/routes/_index.tsx
+++ b/themes/article/app/routes/_index.tsx
@@ -1,9 +1,4 @@
-import {
- ProjectPageCatchBoundary,
- getMetaTagsForArticle,
- responseNoArticle,
- responseNoSite,
-} from '@myst-theme/site';
+import { getMetaTagsForArticle, responseNoArticle, responseNoSite, ProjectPageCatchBoundary} from '@myst-theme/site';
import Page from './$';
import { ArticlePageAndNavigation } from '../components/ArticlePageAndNavigation';
import { getConfig, getPage } from '../utils/loaders.server';
diff --git a/themes/article/app/types.ts b/themes/article/app/types.ts
new file mode 100644
index 000000000..1416b4172
--- /dev/null
+++ b/themes/article/app/types.ts
@@ -0,0 +1,6 @@
+export interface TemplateOptions {
+ hide_toc?: boolean;
+ hide_outline?: boolean;
+ hide_footer_links?: boolean;
+ outline_maxdepth?: number;
+}
diff --git a/themes/article/template.yml b/themes/article/template.yml
index d25473c64..d53d5e2dd 100644
--- a/themes/article/template.yml
+++ b/themes/article/template.yml
@@ -19,6 +19,15 @@ options:
- type: boolean
id: hide_footer_links
description: Hide the previous/next links in the footer
+ - type: boolean
+ id: hide_outline
+ description: Hide the document outline on all pages
+ - type: number
+ id: outline_maxdepth
+ description: The maximum depth to show on the document outline, for example, `2` would show only two depths of headings (e.g. `
` and ``).
+ min: 1
+ max: 6
+ integer: true
- type: string
id: twitter
description: Twitter handle related to the site
diff --git a/themes/book/app/components/ArticlePage.tsx b/themes/book/app/components/ArticlePage.tsx
new file mode 100644
index 000000000..755a21abb
--- /dev/null
+++ b/themes/book/app/components/ArticlePage.tsx
@@ -0,0 +1,108 @@
+import React from 'react';
+import { ReferencesProvider, useProjectManifest, useSiteManifest } from '@myst-theme/providers';
+import {
+ Bibliography,
+ ContentBlocks,
+ FooterLinksBlock,
+ FrontmatterParts,
+ BackmatterParts,
+ DocumentOutline,
+ extractKnownParts,
+} from '@myst-theme/site';
+import type { SiteManifest } from 'myst-config';
+import type { PageLoader } from '@myst-theme/common';
+import { copyNode, type GenericParent } from 'myst-common';
+import { SourceFileKind } from 'myst-spec-ext';
+import {
+ ExecuteScopeProvider,
+ BusyScopeProvider,
+ NotebookToolbar,
+ ConnectionStatusTray,
+ ErrorTray,
+ useComputeOptions,
+} from '@myst-theme/jupyter';
+import { FrontmatterBlock } from '@myst-theme/frontmatter';
+import type { SiteAction } from 'myst-config';
+import type { TemplateOptions } from '../types.js';
+
+/**
+ * Combines the project downloads and the export options
+ */
+function combineDownloads(
+ siteDownloads: SiteAction[] | undefined,
+ pageFrontmatter: PageLoader['frontmatter'],
+) {
+ if (pageFrontmatter.downloads) {
+ return pageFrontmatter.downloads;
+ }
+ // No downloads on the page, combine the exports if they exist
+ if (siteDownloads) {
+ return [...(pageFrontmatter.exports ?? []), ...siteDownloads];
+ }
+ return pageFrontmatter.exports;
+}
+
+export const ArticlePage = React.memo(function ({
+ article,
+ hide_all_footer_links,
+ hideKeywords,
+}: {
+ article: PageLoader;
+ hide_all_footer_links?: boolean;
+ hideKeywords?: boolean;
+}) {
+ const manifest = useProjectManifest();
+ const compute = useComputeOptions();
+
+ const pageDesign: TemplateOptions = (article.frontmatter as any)?.options ?? {};
+ const siteDesign: TemplateOptions =
+ (useSiteManifest() as SiteManifest & TemplateOptions)?.options ?? {};
+ const { hide_title_block, hide_footer_links, hide_outline, outline_maxdepth } = {
+ ...siteDesign,
+ ...pageDesign,
+ };
+ const downloads = combineDownloads(manifest?.downloads, article.frontmatter);
+ const tree = copyNode(article.mdast);
+ const keywords = article.frontmatter?.keywords ?? [];
+ const parts = extractKnownParts(tree);
+
+ return (
+
+
+
+ {!hide_title_block && (
+
+ )}
+ {!hide_outline && (
+
+
+
+ )}
+ {compute?.enabled &&
+ compute.features.notebookCompute &&
+ article.kind === SourceFileKind.Notebook && }
+ {compute?.enabled && article.kind === SourceFileKind.Article && (
+
+ )}
+
+
+
+
+
+
+ {!hide_footer_links && !hide_all_footer_links && (
+
+ )}
+
+
+
+ );
+});
+
diff --git a/themes/book/app/routes/$.tsx b/themes/book/app/routes/$.tsx
index 7d6743205..a12345dc2 100644
--- a/themes/book/app/routes/$.tsx
+++ b/themes/book/app/routes/$.tsx
@@ -7,14 +7,12 @@ import {
import { getProject, isFlatSite, type PageLoader } from '@myst-theme/common';
import {
KatexCSS,
- ArticlePage,
useOutlineHeight,
useTocHeight,
- DocumentOutline,
Navigation,
TopNav,
- ArticlePageCatchBoundary,
getMetaTagsForArticle,
+ ArticlePageCatchBoundary,
} from '@myst-theme/site';
import { getConfig, getPage } from '~/utils/loaders.server';
import { useLoaderData } from '@remix-run/react';
@@ -29,7 +27,8 @@ import {
} from '@myst-theme/providers';
import { MadeWithMyst } from '@myst-theme/icons';
import { ComputeOptionsProvider, ThebeLoaderAndServer } from '@myst-theme/jupyter';
-
+import { ArticlePage } from '../components/ArticlePage.js';
+import type { TemplateOptions } from '../types.js';
type ManifestProject = Required['projects'][0];
export const meta: V2_MetaFunction = ({ data, matches, location }) => {
@@ -107,24 +106,15 @@ export function ArticlePageAndNavigation({
);
}
-export interface BookThemeTemplateOptions {
- hide_toc?: boolean;
- hide_outline?: boolean;
- hide_footer_links?: boolean;
- outline_maxdepth?: number;
- numbered_references?: boolean;
-}
export default function Page() {
- const { container, outline } = useOutlineHeight();
- const top = useThemeTop();
+ const { container } = useOutlineHeight();
const data = useLoaderData() as { page: PageLoader; project: ManifestProject };
-
const baseurl = useBaseurl();
- const pageDesign: BookThemeTemplateOptions = (data.page.frontmatter as any)?.options ?? {};
- const siteDesign: BookThemeTemplateOptions =
- (useSiteManifest() as SiteManifest & BookThemeTemplateOptions)?.options ?? {};
- const { hide_toc, hide_outline, hide_footer_links, outline_maxdepth } = {
+ const pageDesign: TemplateOptions = (data.page.frontmatter as any)?.options ?? {};
+ const siteDesign: TemplateOptions =
+ (useSiteManifest() as SiteManifest & TemplateOptions)?.options ?? {};
+ const { hide_toc, hide_footer_links } = {
...siteDesign,
...pageDesign,
};
@@ -137,19 +127,6 @@ export default function Page() {
>
- {!hide_outline && (
-
-
-
- )}
diff --git a/themes/book/app/types.ts b/themes/book/app/types.ts
new file mode 100644
index 000000000..edb9dd21a
--- /dev/null
+++ b/themes/book/app/types.ts
@@ -0,0 +1,7 @@
+export interface TemplateOptions {
+ hide_toc?: boolean;
+ hide_outline?: boolean;
+ hide_footer_links?: boolean;
+ outline_maxdepth?: number;
+ hide_title_block?: boolean;
+}
diff --git a/themes/book/template.yml b/themes/book/template.yml
index bbbd5f336..0347032f5 100644
--- a/themes/book/template.yml
+++ b/themes/book/template.yml
@@ -22,6 +22,9 @@ options:
- type: boolean
id: hide_outline
description: Hide the document outline on all pages
+ - type: boolean
+ id: hide_title_block
+ description: Hide the document title on all pages
- type: number
id: outline_maxdepth
description: The maximum depth to show on the document outline, for example, `2` would show only two depths of headings (e.g. `` and ``).