Skip to content

Commit

Permalink
🏗 Support parts mdast trees in page frontmatter
Browse files Browse the repository at this point in the history
  • Loading branch information
fwkoch committed Oct 16, 2024
1 parent 50c6258 commit 9be9470
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 35 deletions.
12 changes: 12 additions & 0 deletions .changeset/itchy-doors-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'myst-to-react': patch
'@myst-theme/frontmatter': patch
'myst-demo': patch
'@myst-theme/providers': patch
'@myst-theme/common': patch
'@myst-theme/article': patch
'@myst-theme/site': patch
'@myst-theme/book': patch
---

Support parts mdast trees in page frontmatter
3 changes: 2 additions & 1 deletion packages/common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export type FooterLinks = {
};
};

type PageFrontmatterWithDownloads = Omit<PageFrontmatter, 'downloads' | 'exports'> & {
type PageFrontmatterWithDownloads = Omit<PageFrontmatter, 'parts' | 'downloads' | 'exports'> & {
parts?: Record<string, GenericParent>;
downloads?: SiteAction[];
exports?: SiteExport[];
};
Expand Down
47 changes: 25 additions & 22 deletions packages/common/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,28 +188,31 @@ export function updatePageStaticLinksInplace(data: PageLoader, updateUrl: Update
return { ...exp, url: updateUrl(exp.url) };
});
}
// Fix all of the images to point to the CDN
const images = selectAll('image', data.mdast) as Image[];
images.forEach((node) => {
node.url = updateUrl(node.url);
if (node.urlOptimized) {
node.urlOptimized = updateUrl(node.urlOptimized);
}
});
const links = selectAll('link,linkBlock,card', data.mdast) as Link[];
const staticLinks = links.filter((node) => node.static);
staticLinks.forEach((node) => {
// These are static links to thinks like PDFs or other referenced files
node.url = updateUrl(node.url);
});
const outputs = selectAll('output', data.mdast) as Output[];
outputs.forEach((node) => {
if (!node.data) return;
walkOutputs(node.data, (obj) => {
// The path will be defined from output of myst
// Here we are re-assigning it to the current domain
if (!obj.path) return;
obj.path = updateUrl(obj.path);
const allMdastTrees = [data.mdast, ...Object.values(data.frontmatter?.parts ?? {})];
allMdastTrees.forEach((tree) => {
// Fix all of the images to point to the CDN
const images = selectAll('image', tree) as Image[];
images.forEach((node) => {
node.url = updateUrl(node.url);
if (node.urlOptimized) {
node.urlOptimized = updateUrl(node.urlOptimized);
}
});
const links = selectAll('link,linkBlock,card', tree) as Link[];
const staticLinks = links.filter((node) => node.static);
staticLinks.forEach((node) => {
// These are static links to thinks like PDFs or other referenced files
node.url = updateUrl(node.url);
});
const outputs = selectAll('output', tree) as Output[];
outputs.forEach((node) => {
if (!node.data) return;
walkOutputs(node.data, (obj) => {
// The path will be defined from output of myst
// Here we are re-assigning it to the current domain
if (!obj.path) return;
obj.path = updateUrl(obj.path);
});
});
});
return data;
Expand Down
2 changes: 1 addition & 1 deletion packages/frontmatter/src/FrontmatterBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ export function FrontmatterBlock({
hideExports,
className,
}: {
frontmatter: PageFrontmatter;
frontmatter: Omit<PageFrontmatter, 'parts'>;
kind?: SourceFileKind;
authorStyle?: 'block' | 'list';
hideBadges?: boolean;
Expand Down
3 changes: 2 additions & 1 deletion packages/myst-demo/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ export function MySTRenderer({
);

const mdastStage = astStage === 'pre' ? mdastPre : mdastPost;
const { downloads, exports, parts, ...reducedFrontmatter } = frontmatter;

return (
<figure
Expand Down Expand Up @@ -437,7 +438,7 @@ export function MySTRenderer({
>
{previewType === 'DEMO' && (
<>
<ReferencesProvider references={references} frontmatter={frontmatter}>
<ReferencesProvider references={references} frontmatter={reducedFrontmatter}>
{TitleBlock && <TitleBlock frontmatter={frontmatter}></TitleBlock>}
<MyST ast={references.article?.children as GenericNode[]} />
</ReferencesProvider>
Expand Down
19 changes: 15 additions & 4 deletions packages/myst-to-react/src/crossReference.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import {
XRefProvider,
useXRefState,
type NodeRenderer,
useFrontmatter,
} from '@myst-theme/providers';
import { InlineError } from './inlineError.js';
import { default as useSWR } from 'swr';
import { HoverPopover } from './components/index.js';
import { MyST } from './MyST.js';
import type { GenericNode } from 'myst-common';
import { selectMdastNodes } from 'myst-common';
import { scrollToElement } from './hashLink.js';

Expand Down Expand Up @@ -100,11 +102,20 @@ export function useFetchMdast({

function useSelectNodes({ load, identifier }: { load?: boolean; identifier: string }) {
const references = useReferences();
const frontmatter = useFrontmatter();
const { remote, url, remoteBaseUrl, dataUrl } = useXRefState();
if (!load) return;
const { data, error } = useFetchMdast({ remote, url, remoteBaseUrl, dataUrl });
const mdast = data?.mdast ?? references?.article;
const { nodes, htmlId } = selectMdastNodes(mdast, identifier, 3);
const mdast = data ? data.mdast : references?.article;
const parts = data ? data.frontmatter?.parts : frontmatter?.parts;
let nodes: GenericNode[] = [];
let htmlId: string | undefined;
[mdast, ...Object.values(parts ?? {})].forEach((tree) => {
if (!tree || nodes.length > 0) return;
const selected = selectMdastNodes(tree, identifier, 3);
nodes = selected.nodes;
htmlId = selected.htmlId;
});
return { htmlId, nodes, loading: remote && !data, error: remote && error };
}

Expand All @@ -130,8 +141,8 @@ export function CrossReferenceHover({
const parent = useXRefState();
const remoteBaseUrl = remoteBaseUrlIn ?? parent.remoteBaseUrl;
const remote = !!remoteBaseUrl || parent.remote || remoteIn;
const url = parent.remote ? (urlIn ?? parent.url) : urlIn;
const dataUrl = parent.remote ? (dataUrlIn ?? parent.dataUrl) : dataUrlIn;
const url = parent.remote ? urlIn ?? parent.url : urlIn;
const dataUrl = parent.remote ? dataUrlIn ?? parent.dataUrl : dataUrlIn;
const external = !!remoteBaseUrl || (url?.startsWith('http') ?? false);
const scroll: React.MouseEventHandler<HTMLAnchorElement> = (e) => {
e.preventDefault();
Expand Down
6 changes: 3 additions & 3 deletions packages/providers/src/references.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useContext } from 'react';
import type { References } from 'myst-common';
import type { PageFrontmatter } from 'myst-frontmatter';
import type { PageLoader } from '@myst-theme/common';

const ReferencesContext = React.createContext<{
frontmatter?: PageFrontmatter;
frontmatter?: PageLoader['frontmatter'];
references?: References;
}>({});

Expand All @@ -12,7 +12,7 @@ export function ReferencesProvider({
frontmatter,
children,
}: {
frontmatter?: PageFrontmatter;
frontmatter?: PageLoader['frontmatter'];
references?: References;
children: React.ReactNode;
}) {
Expand Down
2 changes: 1 addition & 1 deletion packages/site/src/pages/Article.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const ArticlePage = React.memo(function ({
const downloads = combineDownloads(manifest?.downloads, article.frontmatter);
const tree = copyNode(article.mdast);
const keywords = article.frontmatter?.keywords ?? [];
const parts = extractKnownParts(tree);
const parts = { ...extractKnownParts(tree), ...article.frontmatter?.parts };

return (
<ReferencesProvider
Expand Down
2 changes: 1 addition & 1 deletion themes/article/app/components/Article.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function Article({
}) {
const keywords = article.frontmatter?.keywords ?? [];
const tree = copyNode(article.mdast);
const parts = extractKnownParts(tree);
const parts = { ...extractKnownParts(tree), ...article.frontmatter?.parts };
const { title, subtitle } = article.frontmatter;
const compute = useComputeOptions();
const top = useThemeTop();
Expand Down
2 changes: 1 addition & 1 deletion themes/book/app/components/ArticlePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const ArticlePage = React.memo(function ({
const downloads = combineDownloads(manifest?.downloads, article.frontmatter);
const tree = copyNode(article.mdast);
const keywords = article.frontmatter?.keywords ?? [];
const parts = extractKnownParts(tree);
const parts = { ...extractKnownParts(tree), ...article.frontmatter?.parts };
const isOutlineMargin = useMediaQuery('(min-width: 1024px)');
return (
<ReferencesProvider
Expand Down

0 comments on commit 9be9470

Please sign in to comment.