Skip to content

Commit

Permalink
🧱 Drop ContentBlocks and move functionality to MyST (#536)
Browse files Browse the repository at this point in the history
Co-authored-by: Rowan Cockett <[email protected]>
  • Loading branch information
agoose77 and rowanc1 authored Feb 28, 2025
1 parent 0ae2575 commit 0c5f40a
Show file tree
Hide file tree
Showing 28 changed files with 321 additions and 246 deletions.
5 changes: 5 additions & 0 deletions .changeset/cool-onions-admire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@myst-theme/site': patch
---

Remove unused function `isACodeCell`
5 changes: 5 additions & 0 deletions .changeset/famous-cows-sleep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@myst-theme/site': patch
---

Remove deprecated `ArticlePage`
5 changes: 5 additions & 0 deletions .changeset/fuzzy-plums-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@myst-theme/site': patch
---

Remove dependence on `@myst-theme/jupyter`
11 changes: 11 additions & 0 deletions .changeset/honest-sheep-compare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@myst-theme/site': minor
'myst-to-react': patch
'myst-demo': patch
'@myst-theme/providers': patch
'@myst-theme/diagrams': patch
'@myst-theme/article': patch
'@myst-theme/book': patch
---

Move ContentBlocks to MyST
5 changes: 5 additions & 0 deletions .changeset/red-lies-taste.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@myst-theme/providers': patch
---

Move `ReferencesProvider` to `ArticleProvider`
1 change: 0 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

88 changes: 88 additions & 0 deletions packages/jupyter/src/block.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Details, MyST } from 'myst-to-react';
import { SourceFileKind } from 'myst-spec-ext';
import type { GenericParent } from 'myst-common';
import classNames from 'classnames';
import {
NotebookClearCell,
NotebookRunCell,
NotebookRunCellSpinnerOnly,
} from './controls/index.js';
import { useGridSystemProvider, usePageKind } from '@myst-theme/providers';
import type { NodeRenderers, NodeRenderer } from '@myst-theme/providers';

export function NotebookBlock({
id,
node,
className,
}: {
id: string;
node: GenericParent;
className?: string;
}) {
const pageKind = usePageKind();
const grid = useGridSystemProvider();
const subGrid = node.visibility === 'hide' ? '' : `${grid} subgrid-gap col-screen`;
const dataClassName = typeof node.data?.class === 'string' ? node.data?.class : undefined;
// Hide the subgrid if either the dataClass or the className exists and includes `col-`
const noSubGrid =
(dataClassName && dataClassName.includes('col-')) || (className && className.includes('col-'));
const block = (
<div
key={`block-${id}`}
id={id}
className={classNames('relative group/block', className, dataClassName, {
[subGrid]: !noSubGrid,
hidden: node.visibility === 'remove',
})}
>
{pageKind === SourceFileKind.Notebook && node.kind === 'notebook-code' && (
<>
<div className="flex sticky top-[80px] z-10 opacity-70 group-hover/block:opacity-100 group-hover/block:hidden">
<div className="absolute top-0 -right-[28px] flex md:flex-col">
<NotebookRunCellSpinnerOnly id={id} />
</div>
</div>
<div className="hidden sticky top-[80px] z-10 opacity-70 group-hover/block:opacity-100 group-hover/block:flex">
<div className="absolute top-0 -right-[28px] flex md:flex-col">
<NotebookRunCell id={id} />
<NotebookClearCell id={id} />
</div>
</div>
</>
)}
<MyST ast={node.children} />
</div>
);
if (node.visibility === 'hide') {
return <Details title="Notebook Cell">{block}</Details>;
}
return block;
}

export const NotebookBlockRenderer: NodeRenderer = ({ node, className }) => {
return (
<NotebookBlock
key={node.key}
id={node.key}
node={node}
className={classNames(node.class, className)}
/>
);
};

/**
* The logic for the selector is complex:
*
* - MD files have `notebook-code` and otherwise blocks with no kind.
* - IPyNB files have both `notebook-code` and `notebook-content` blocks.
* - An article may contain `notebook-code` blocks from the `code-cell` directive even though it is not considered a notebook (i.e., no frontmatter kernelspec).
*
* This component therefore only renders for `code-cells` (both ipynb and .md) and `content-cells` (ipynb).
*
* The benefit of this is that we can use the block-kind to figure out if e.g. the cell is executable.
*/
export const NOTEBOOK_BLOCK_RENDERERS: NodeRenderers = {
block: {
'block[kind=notebook-code],block[kind=notebook-content]': NotebookBlockRenderer,
},
};
13 changes: 1 addition & 12 deletions packages/jupyter/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
import { Embed } from './embed.js';
import { Output } from './output.js';
import { Figure } from './figure.js';

const OUTPUT_RENDERERS = {
output: Output,
embed: Embed,
container: Figure,
};

export * from './BinderBadge.js';
export * from './ErrorTray.js';
export * from './ConnectionStatusTray.js';
Expand All @@ -16,5 +6,4 @@ export * from './execute/index.js';
export * from './controls/index.js';
export * from './utils.js';
export { useLaunchBinder } from './hooks.js';

export default OUTPUT_RENDERERS;
export { JUPYTER_RENDERERS, NOTEBOOK_BLOCK_RENDERERS, OUTPUT_RENDERERS } from './renderers.js';
13 changes: 13 additions & 0 deletions packages/jupyter/src/renderers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Embed } from './embed.js';
import { Output } from './output.js';
import { Figure } from './figure.js';
import { mergeRenderers } from '@myst-theme/providers';
import { NOTEBOOK_BLOCK_RENDERERS } from './block.js';

export { NOTEBOOK_BLOCK_RENDERERS } from './block.js';
export const OUTPUT_RENDERERS = {
output: Output,
embed: Embed,
container: Figure,
};
export const JUPYTER_RENDERERS = mergeRenderers([OUTPUT_RENDERERS, NOTEBOOK_BLOCK_RENDERERS]);
16 changes: 11 additions & 5 deletions packages/myst-demo/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type { DocxResult } from 'myst-to-docx';
import { validatePageFrontmatter } from 'myst-frontmatter';
import type { PageFrontmatter } from 'myst-frontmatter';
import type { NodeRenderer } from '@myst-theme/providers';
import { ReferencesProvider } from '@myst-theme/providers';
import { ArticleProvider, GridSystemProvider } from '@myst-theme/providers';
import { CopyIcon, CodeBlock, MyST } from 'myst-to-react';
import { useEffect, useRef, useState } from 'react';
import classnames from 'classnames';
Expand Down Expand Up @@ -445,10 +445,16 @@ export function MySTRenderer({
>
{previewType === 'DEMO' && (
<>
<ReferencesProvider references={references} frontmatter={reducedFrontmatter}>
{TitleBlock && <TitleBlock frontmatter={frontmatter}></TitleBlock>}
<MyST ast={references.article?.children as GenericNode[]} />
</ReferencesProvider>
<ArticleProvider
kind={SourceFileKind.Article}
references={references}
frontmatter={reducedFrontmatter}
>
<GridSystemProvider gridSystem="demo-grid">
{TitleBlock && <TitleBlock frontmatter={frontmatter}></TitleBlock>}
<MyST ast={references.article?.children as GenericNode[]} />
</GridSystemProvider>
</ArticleProvider>
</>
)}
{previewType === 'AST' && (
Expand Down
51 changes: 51 additions & 0 deletions packages/myst-to-react/src/block.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Details } from './dropdown.js';
import { MyST } from './MyST.js';
import type { GenericParent } from 'myst-common';
import classNames from 'classnames';
import { useGridSystemProvider } from '@myst-theme/providers';
import type { NodeRenderer } from '@myst-theme/providers';

export function Block({
id,
node,
className,
}: {
id: string;
node: GenericParent;
className?: string;
}) {
const grid = useGridSystemProvider();
const subGrid = node.visibility === 'hide' ? '' : `${grid} subgrid-gap col-screen`;
const dataClassName = typeof node.data?.class === 'string' ? node.data?.class : undefined;
// Hide the subgrid if either the dataClass or the className exists and includes `col-`
const noSubGrid =
(dataClassName && dataClassName.includes('col-')) || (className && className.includes('col-'));
const block = (
<div
key={`block-${id}`}
id={id}
className={classNames('relative group/block', className, dataClassName, {
[subGrid]: !noSubGrid,
hidden: node.visibility === 'remove',
})}
>
<MyST ast={node.children} />
</div>
);
if (node.visibility === 'hide') {
return <Details title="Block">{block}</Details>;
}
return block;
}

export const BlockRenderer: NodeRenderer = ({ node, className }) => {
return (
<Block key={node.key} id={node.key} node={node} className={classNames(node.class, className)} />
);
};

const BLOCK_RENDERERS: Record<string, NodeRenderer> = {
block: BlockRenderer,
};

export default BLOCK_RENDERERS;
3 changes: 3 additions & 0 deletions packages/myst-to-react/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { mergeRenderers } from '@myst-theme/providers';
import BASIC_RENDERERS from './basic.js';
import ADMONITION_RENDERERS from './admonitions.js';
import DROPDOWN_RENDERERS from './dropdown.js';
import BLOCK_RENDERERS from './block.js';
import CARD_RENDERERS from './card.js';
import GRID_RENDERERS from './grid.js';
import CITE_RENDERERS from './cite.js';
Expand All @@ -22,6 +23,7 @@ import EXERCISE_RENDERERS from './exercise.js';
import ASIDE_RENDERERS from './aside.js';
import UNKNOWN_MYST_RENDERERS from './unknown.js';

export { Block } from './block.js';
export { CopyIcon, HoverPopover, Tooltip, LinkCard } from './components/index.js';
export { CodeBlock } from './code.js';
export { HashLink, scrollToElement } from './hashLink.js';
Expand All @@ -34,6 +36,7 @@ export const DEFAULT_RENDERERS = mergeRenderers(
[
BASIC_RENDERERS,
UNKNOWN_MYST_RENDERERS,
BLOCK_RENDERERS,
IMAGE_RENDERERS,
LINK_RENDERERS,
CODE_RENDERERS,
Expand Down
62 changes: 62 additions & 0 deletions packages/providers/src/article.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, { useContext } from 'react';
import type { References } from 'myst-common';
import type { PageLoader } from '@myst-theme/common';
import { SourceFileKind } from 'myst-spec-ext';

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

export function ArticleProvider({
kind,
references,
frontmatter,
children,
}: {
kind: SourceFileKind;
frontmatter?: PageLoader['frontmatter'];
references?: References;
children: React.ReactNode;
}) {
return (
<ArticleContext.Provider value={{ kind, references, frontmatter }}>
{children}
</ArticleContext.Provider>
);
}

export function useReferences() {
const data = useContext(ArticleContext);
return data?.references;
}

export function useFrontmatter() {
const data = useContext(ArticleContext);
return data?.frontmatter;
}

export function usePageKind() {
const data = useContext(ArticleContext);
return data?.kind ?? SourceFileKind.Article;
}

/**
* @deprecated This component is not maintained, in favor of the reworked `ArticleProvider` component
*/
export function ReferencesProvider({
references,
frontmatter,
children,
}: {
frontmatter?: PageLoader['frontmatter'];
references?: References;
children: React.ReactNode;
}) {
return (
<ArticleContext.Provider value={{ references, frontmatter }}>
{children}
</ArticleContext.Provider>
);
}
2 changes: 1 addition & 1 deletion packages/providers/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export * from './hooks.js';
export * from './theme.js';
export * from './grid.js';
export * from './references.js';
export * from './article.js';
export * from './baseurl.js';
export * from './ui.js';
export * from './site.js';
Expand Down
34 changes: 0 additions & 34 deletions packages/providers/src/references.tsx

This file was deleted.

9 changes: 9 additions & 0 deletions packages/providers/src/renderers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ export function validateRenderers(renderers?: NodeRenderers): NodeRenderersValid
return validatedRenderers;
}

/**
* Combines a list of renderers. Put more specific renderers **later** in the list.
*
* When a renderer is selected, it will look for a match in **reversed** order.
*
* ```typescript
* mergeRenderers([defaultRenderers, specificRenderers])
* ```
*/
export function mergeRenderers(renderers: NodeRenderers[], validate: true): NodeRenderersValidated;
export function mergeRenderers(renderers: NodeRenderers[], validate?: false): NodeRenderers;
export function mergeRenderers(renderers: NodeRenderers[], validate?: boolean): NodeRenderers {
Expand Down
Loading

0 comments on commit 0c5f40a

Please sign in to comment.