Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions frontend/src/plugins/layout/OutlinePlugin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* Copyright 2024 Marimo. All rights reserved. */
import type { JSX } from "react";
import { z } from "zod";
import { notebookOutline } from "@/core/cells/cells";
import { store } from "@/core/state/jotai";
import { OutlineList } from "../../components/editor/chrome/panels/outline/floating-outline";
import {
findOutlineElements,
useActiveOutline,
} from "../../components/editor/chrome/panels/outline/useActiveOutline";
import type { IStatelessPlugin, IStatelessPluginProps } from "../stateless-plugin";

interface Data {
label?: string;
}

export class OutlinePlugin implements IStatelessPlugin<Data> {
tagName = "marimo-outline";

validator = z.object({
label: z.string().optional(),
});

render(props: IStatelessPluginProps<Data>): JSX.Element {
const { label } = props.data;
const { items } = store.get(notebookOutline);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this won't re-render on changes. you will need to create a new react component and then call useAtomValue(notebookOutline)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you will want to wrap the component in a <Provider store={store} too

const headerElements = findOutlineElements(items);

const { activeHeaderId, activeOccurrences } = useActiveOutline(headerElements);

Check failure on line 29 in frontend/src/plugins/layout/OutlinePlugin.tsx

View workflow job for this annotation

GitHub Actions / 🧹 Lint frontend

React Hook "useActiveOutline" cannot be called in a class component. React Hooks must be called in a React function component or a custom React Hook function

if (items.length === 0) {
return (
<div className="text-muted-foreground text-sm p-4 border border-dashed border-border rounded-lg">
No outline found. Add markdown headings to your notebook to create an outline.
</div>
);
}

return (
<div className="border border-border rounded-lg">
{label && (
<div className="px-4 py-2 border-b border-border font-medium text-sm">
{label}
</div>
)}
<OutlineList
className="max-h-[400px]"
items={items}
activeHeaderId={activeHeaderId}
activeOccurrences={activeOccurrences}
/>
</div>
);
}
}
2 changes: 2 additions & 0 deletions frontend/src/plugins/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import { NavigationMenuPlugin } from "@/plugins/layout/NavigationMenuPlugin";
import { OutlinePlugin } from "./layout/OutlinePlugin";
import { initializeUIElement } from "../core/dom/ui-element";
import { registerReactComponent } from "./core/registerReactComponent";
import { initializeSidebarElement } from "./core/sidebar-element";
Expand Down Expand Up @@ -99,6 +100,7 @@ const LAYOUT_PLUGINS: Array<IStatelessPlugin<unknown>> = [
new MimeRendererPlugin(),
new MermaidPlugin(),
new NavigationMenuPlugin(),
new OutlinePlugin(),
new ProgressPlugin(),
new RoutesPlugin(),
new StatPlugin(),
Expand Down
2 changes: 2 additions & 0 deletions marimo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"nav_menu",
"notebook_dir",
"notebook_location",
"outline",
"output",
"pdf",
"persistent_cache",
Expand Down Expand Up @@ -98,6 +99,7 @@
from marimo._output.hypertext import Html
from marimo._output.justify import center, left, right
from marimo._output.md import latex, md
from marimo._output.outline import outline
from marimo._output.show_code import show_code
from marimo._plugins import ui
from marimo._plugins.stateless import mpl, status
Expand Down
38 changes: 38 additions & 0 deletions marimo/_output/outline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright 2024 Marimo. All rights reserved.
from __future__ import annotations

from marimo._output.hypertext import Html
from marimo._output.rich_help import mddoc
from marimo._plugins.core.web_component import build_stateless_plugin


@mddoc
def outline(*, label: str = "") -> Html:
"""Display a table of contents outline showing all markdown headers in the notebook.

The outline automatically extracts all markdown headers from executed cells
and displays them in a hierarchical structure with clickable navigation.

Examples:
Basic outline:
```python
mo.outline()
```

With custom label:
```python
mo.outline(label="Table of Contents")
```

Args:
label (str, optional): A descriptive label for the outline. Defaults to "".

Returns:
Html: An HTML object that renders the outline component.
"""
return Html(
build_stateless_plugin(
component_name="marimo-outline",
args={"label": label},
)
)
Loading