Skip to content

Commit

Permalink
🌀 Refactor and simplify providers
Browse files Browse the repository at this point in the history
  • Loading branch information
rowanc1 committed Feb 21, 2023
1 parent 4471998 commit 270dc61
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 68 deletions.
35 changes: 0 additions & 35 deletions src/CellMetadataProvider.tsx

This file was deleted.

30 changes: 30 additions & 0 deletions src/JupyterCellProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { createContext, useContext } from 'react';
import type { MySTMarkdownCell } from './MySTMarkdownCell';

type JupyterCellState = {
cell?: MySTMarkdownCell;
};

const JupyterCellContext = createContext<JupyterCellState | undefined>(
undefined
);

// Create a provider for components to consume and subscribe to changes
export function JupyterCellProvider({
cell,
children
}: {
cell?: MySTMarkdownCell;
children: React.ReactNode;
}): JSX.Element {
return (
<JupyterCellContext.Provider value={{ cell }}>
{children}
</JupyterCellContext.Provider>
);
}

export function useJupyterCell(): JupyterCellState {
const state = useContext(JupyterCellContext) ?? {};
return state;
}
2 changes: 1 addition & 1 deletion src/MySTContentFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ export class MySTContentFactory extends NotebookPanel.ContentFactory {
if (!options.contentFactory) {
options.contentFactory = this;
}
return new MySTMarkdownCell(options, parent).initializeState();
return new MySTMarkdownCell(options).initializeState();
}
}
24 changes: 3 additions & 21 deletions src/MySTMarkdownCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,14 @@ import { linkFactory } from './links';
import { selectAll } from 'unist-util-select';

import { PromiseDelegate } from '@lumino/coreutils';
import { metadataSection, IUserExpressionMetadata } from './metadata';
import { CellMetadataProvider } from './CellMetadataProvider';
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
import { JupyterCellProvider } from './JupyterCellProvider';

export class MySTMarkdownCell
extends MarkdownCell
implements IMySTMarkdownCell
{
private _doneRendering = new PromiseDelegate<void>();

private __rendermime: IRenderMimeRegistry;

constructor(options: MarkdownCell.IOptions, parent: StaticNotebook) {
super(options);
// Note we cannot clone this, and it must be the parents (the notebooks)
this.__rendermime = parent.rendermime;
// this.__rendermime.addFactory(textRendererFactory);
}

myst: {
pre?: GenericParent;
post?: GenericParent;
Expand Down Expand Up @@ -94,20 +83,13 @@ export class MySTMarkdownCell
const { references, frontmatter } = notebook.myst;

const children = useParse(mdast as any, renderers);
const metadata = this.model.metadata.get(
metadataSection
) as IUserExpressionMetadata[];
render(
<ThemeProvider
theme={Theme.light}
Link={linkFactory(notebook)}
renderers={renderers}
>
<CellMetadataProvider
metadata={metadata}
trusted={this.model.trusted}
rendermime={this.__rendermime}
>
<JupyterCellProvider cell={this}>
<TabStateProvider>
<ReferencesProvider
references={references}
Expand All @@ -117,7 +99,7 @@ export class MySTMarkdownCell
{children}
</ReferencesProvider>
</TabStateProvider>
</CellMetadataProvider>
</JupyterCellProvider>
</ThemeProvider>,
this.myst.node
);
Expand Down
26 changes: 15 additions & 11 deletions src/inlineExpression.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React, { useRef, useEffect, useMemo } from 'react';
import { useCellMetadata } from './CellMetadataProvider';
import { useJupyterCell } from './JupyterCellProvider';
import { SingletonLayout, Widget } from '@lumino/widgets';
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
import { IExpressionResult, isOutput } from './userExpressions';
import { getUserExpressions } from './metadata';
import { StaticNotebook } from '@jupyterlab/notebook';

export interface IRenderedExpressionOptions {
expression: string;
Expand All @@ -14,7 +16,7 @@ export interface IRenderedExpressionOptions {
export class RenderedExpressionError extends Widget {
constructor() {
super();
this.addClass('im-RenderedExpressionError');
this.addClass('myst-RenderedExpressionError');
}
}

Expand All @@ -32,7 +34,7 @@ export class RenderedExpression extends Widget {
this.rendermime = options.rendermime;
this.safe = options.safe;

this.addClass('im-RenderedExpression');
this.addClass('myst-RenderedExpression');

// We can only hold one renderer at a time
const layout = (this.layout = new SingletonLayout());
Expand Down Expand Up @@ -85,14 +87,19 @@ export class RenderedExpression extends Widget {

export function InlineRenderer({ value }: { value?: string }): JSX.Element {
const ref = useRef<HTMLDivElement>(null);
const { metadata, trusted, rendermime } = useCellMetadata();
const { cell } = useJupyterCell();
// Load the information from the MystMarkdownCell
const metadata = getUserExpressions(cell);
const trusted = cell?.model.trusted ?? false;
// We use the notebook rendermime directly
const rendermime = (cell?.parent as StaticNotebook).rendermime;

// Create a single RenderedExpression when the rendermime is available
const renderer = useMemo<RenderedExpression | undefined>(() => {
if (!rendermime) return undefined;
return new RenderedExpression({
expression: value as string,
trusted: trusted ?? false,
trusted,
rendermime,
safe: 'any'
});
Expand All @@ -104,11 +111,7 @@ export function InlineRenderer({ value }: { value?: string }): JSX.Element {
// Attach and render the widget when the expression result changes
useEffect(() => {
if (!ref.current || !renderer || !expressionResult) return;
console.log('attaching', value);
if (!renderer.isAttached) {
Widget.attach(renderer, ref.current);
}
console.log('Render: ', expressionResult.result);
if (!renderer.isAttached) Widget.attach(renderer, ref.current);
renderer.renderExpression(expressionResult.result);
}, [ref, renderer, expressionResult]);

Expand All @@ -121,7 +124,8 @@ export function InlineRenderer({ value }: { value?: string }): JSX.Element {
// TODO: improve the renderer when no result is found in the metadata
if (!expressionResult) return <code>{value}</code>;
const mimeBundle = expressionResult.result.data as Record<string, string>;
// TODO: we can do a simple plain-text renderer here in react.
const text = mimeBundle?.['text/plain'];
console.log('Rendering react', value, '=', text);
console.debug('Rendering react', value, '=', text);
return <div ref={ref} className="not-prose inline-block" />;
}
10 changes: 10 additions & 0 deletions src/metadata.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import type { MySTMarkdownCell } from './MySTMarkdownCell';
import { PartialJSONObject } from '@lumino/coreutils';
import { IExpressionResult } from './userExpressions';

export const metadataSection = 'user_expressions';

export function getUserExpressions(
cell?: MySTMarkdownCell
): IUserExpressionMetadata[] | undefined {
const metadata = cell?.model.metadata.get(metadataSection) as
| IUserExpressionMetadata[]
| undefined;
return metadata;
}

export interface IUserExpressionMetadata extends PartialJSONObject {
expression: string;
result: IExpressionResult;
Expand Down

0 comments on commit 270dc61

Please sign in to comment.