Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: marimo islands (Windows-related) + doc touchups #3242

Merged
merged 14 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ venv/
ENV/
env.bak/
venv.bak/
uv.lock

# editors
*.swp
Expand Down
72 changes: 69 additions & 3 deletions docs/guides/exporting.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,75 @@ marimo islands are a way to embed marimo outputs and/or python code in your HTML

Check out an [example island-powered document](./island_example.md).

### Generating islands
akshayka marked this conversation as resolved.
Show resolved Hide resolved

Use `MarimoIslandGenerator` to generate HTML for islands

!!! example
/// tab | From code blocks

```python
import asyncio
import sys
from marimo import MarimoIslandGenerator

if sys.platform == 'win32':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

async def main():
generator = MarimoIslandGenerator()
block1 = generator.add_code("import marimo as mo")
block2 = generator.add_code("mo.md('Hello, islands!')")

# Build the app
app = await generator.build()

# Render the app
output = f"""
<html>
<head>
{generator.render_head()}
</head>
<body>
{block1.render(display_output=False)}
{block2.render()}
</body>
</html>
"""
print(output)
# Save the HTML to a file
output_file = "output.html"
with open(output_file, "w", encoding="utf-8") as f:
f.write(output)

if __name__ == '__main__':
asyncio.run(main())
```

///

/// tab | From notebook files

```python
from marimo import MarimoIslandGenerator

# Create the generator from file
generator = MarimoIslandGenerator.from_file("./<notebook-name>.py", display_code=False)

# Generate and print the HTML without building
# This will still work for basic rendering, though without running the cells
html = generator.render_html(include_init_island=False)
print(html)
# Save the HTML to a file
output_file = "output.html"
with open(output_file, "w", encoding="utf-8") as f:
f.write(html)
```

///

Any relevant `.html` that gets generated can be run through the [`development.md`](https://github.com/marimo-team/marimo/blob/main/frontend/islands/development.md) file instructions.

### Islands in action

!!! warning "Advanced topic!"
Expand Down Expand Up @@ -256,8 +325,5 @@ In order to use marimo islands, you need to import the necessary JS/CSS headers
</body>
```

### Generating islands

While you can generate the HTML code for islands yourself, it it recommend to use our `MarimoIslandGenerator` class to generate the HTML code for you.

::: marimo.MarimoIslandGenerator
2 changes: 1 addition & 1 deletion frontend/islands/development.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Marimo Islands

marimo islands are a way to render HTML "islands" each with static outputs and code. This differs from the normal "app mode" int that there is no top-level app. In "island mode", we do not have access to the HTML of the parent page.
marimo islands are a way to render HTML "islands" each with static outputs and code. This differs from the normal "app mode" in the sense that there is no top-level app. In "island mode", we do not have access to the HTML of the parent page.

## Development

Expand Down
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
"lint:stylelint": "stylelint src/**/*.css --fix",
"format": "biome format --write .",
"preview": "vite preview",
"dev:islands": "VITE_MARIMO_ISLANDS=true vite --config islands/vite.config.mts",
"dev:islands": "cross-env VITE_MARIMO_ISLANDS=true vite --config islands/vite.config.mts",
"build:islands": "VITE_MARIMO_ISLANDS=true vite --config islands/vite.config.mts build",
"preview:islands": "VITE_MARIMO_VERSION='0.4.6' VITE_MARIMO_ISLANDS=true vite --config islands/vite.config.mts build",
"storybook": "storybook dev -p 6006",
Expand Down Expand Up @@ -200,6 +200,7 @@
"autoprefixer": "^10.4.20",
"babel-plugin-react-compiler": "19.0.0-beta-8a03594-20241020",
"blob-polyfill": "^7.0.20220408",
"cross-env": "^7.0.3",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jsx-a11y": "^6.9.0",
Expand Down
12 changes: 12 additions & 0 deletions frontend/pnpm-lock.yaml

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

80 changes: 59 additions & 21 deletions marimo/_islands/island_generator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Copyright 2024 Marimo. All rights reserved.
from __future__ import annotations

import asyncio
import json
import sys
from textwrap import dedent
from typing import TYPE_CHECKING, List, Optional, Union, cast

Expand All @@ -18,6 +20,9 @@
from marimo._server.file_router import AppFileRouter
from marimo._utils.marimo_path import MarimoPath

if sys.platform == "win32": # handling for windows
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
Haleshot marked this conversation as resolved.
Show resolved Hide resolved

if TYPE_CHECKING:
from marimo._server.session.session_view import SessionView

Expand Down Expand Up @@ -152,29 +157,62 @@ class MarimoIslandGenerator:

# Example

Using the MarimoIslandGenerator class:
```python
import asyncio
import sys
from marimo import MarimoIslandGenerator

async def main():
generator = MarimoIslandGenerator()
block1 = generator.add_code("import marimo as mo")
block2 = generator.add_code("mo.md('Hello, islands!')")

# Build the app
app = await generator.build()

# Render the app
output = f\"\"\"
<html>
<head>
{generator.render_head()}
</head>
<body>
{block1.render(display_output=False)}
{block2.render()}
</body>
</html>
\"\"\"
print(output)
# Save the HTML to a file
output_file = "output.html"
with open(output_file, "w", encoding="utf-8") as f:
f.write(output)

if __name__ == '__main__':
asyncio.run(main())
```

You can also create the generator from a file:

```python
from marimo.islands import MarimoIslandGenerator

generator = MarimoIslandGenerator()
block1 = generator.add_code("import marimo as mo")
block2 = generator.add_code("mo.md('Hello, islands!')")

# Build the app
app = await generator.build()

# Render the app
output = f\"\"\"
<html>
<head>
{generator.render_head()}
</head>
<body>
{block1.render(display_output=False)}
{block2.render()}
</body>
</html>
\"\"\"
from marimo import MarimoIslandGenerator

# Create the generator from file
generator = MarimoIslandGenerator.from_file(
"./<notebook-name>.py", display_code=False
)

# Generate and print the HTML without building
# This will still work for basic rendering, though without running the cells
html = generator.render_html(include_init_island=False)
print(html)
# Save the HTML to a file
output_file = "output.html"
with open(output_file, "w", encoding="utf-8") as f:
f.write(html)
```

"""

def __init__(self, app_id: str = "main"):
Expand Down
Loading