Skip to content

feat: validate marimo notebooks with styling improvements#7

Closed
lucharo wants to merge 27 commits intomainfrom
validate/marimo-notebooks
Closed

feat: validate marimo notebooks with styling improvements#7
lucharo wants to merge 27 commits intomainfrom
validate/marimo-notebooks

Conversation

@lucharo
Copy link
Copy Markdown
Owner

@lucharo lucharo commented Feb 3, 2026

Summary

Validation and styling improvements for the marimo-live addon.

Changes

  • Enable interactive UI elements (sliders, dropdowns) via marimo frontend
  • Redesign code blocks with One Dark Pro theme
  • Fix code review feedback (debug logging, XSS safety, empty line handling)

Testing

  • Start marimo kernel: marimo edit notebook.py --headless --port 2718
  • Start slidev: bunx slidev examples/marimo-live-test.md --port 3033
  • Verify slider renders and code styling looks polished

🤖 Generated with Claude Code

lucharo and others added 27 commits January 31, 2026 02:44
The watch callbacks with { immediate: true } were calling unwatch()
before the watch() function returned, causing a ReferenceError.
Fixed by checking initial state first, then setting up watchers
without immediate flag.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Marimo requires a Marimo-Server-Token header for API requests.
This token is embedded in the HTML page and used for CSRF protection.
Fetch the token on connect and include it in all HTTP requests.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Interactive slider with live value display
- Dropdown selecting Titanic dataset columns
- Altair chart visualization
- Data explorer (dataframe UI)
- Checkbox and switch toggles
- Text input with greeting

Added PEP 723 script header for sandbox mode dependencies.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fill in TODO sections in main README
- Add sandbox mode instructions with --sandbox flag
- Document PEP 723 dependency header for notebooks
- Add bun.lock

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Clear autoRunTimeout in cleanup function to prevent orphaned timers
- Add null check for dropdown.value with fallback default
- Load Titanic dataset once in dedicated slide, reuse across slides
- Add --sandbox flag to Get Started instructions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use ternary expression instead of if/else branches so marimo can
display the result properly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Import marimo, polars, and altair only once. Subsequent cells
reuse the imported modules since marimo shares state across cells.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Slides now reference notebook cells by name (cell=slider_demo) instead
of containing inline Python. This is the intended architecture:
- notebook.py: contains all Python code with named cells
- slides.md: references cells by function name

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Cells must return their display values for marimo to render them.
Fixed all cells that had mo.md(), mo.ui.altair_chart(), etc.
without returning the result.

Addresses roborev #75.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace awkward code fence syntax:
  ```marimo-live cell=plot_chart
  ```

With cleaner component syntax:
  <MarimoCell cell="plot_chart" />
  <MarimoCell cell="2" :displayCode="false" />

Changes:
- Add MarimoCell.vue as semantic alias for MarimoLive
- Export MarimoCell from addon index
- Simplify preparser to only handle inline code (remove cell= handling)
- Update README with new component syntax as primary usage
- Migrate examples to new MarimoCell syntax

Also created GitHub issue #5 for interchangeable format vision.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1. Add backward compatibility for deprecated code fence cell= syntax
   - Old syntax still works but adds deprecation comment in output
   - Prevents silent breakage for existing slides

2. Fix MarimoCell props passing to avoid overriding MarimoLive defaults
   - Only pass props that are explicitly set
   - Prevents undefined values from overriding withDefaults

3. Clarify README documentation for boolean props
   - Add note about : prefix for false values
   - Explain that true is the default and can be omitted

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Address findings from roborev #87:

1. Extract formatFlag() helper for consistent flag handling
   - Both cell reference and inline code paths now use same logic
   - Fixes hideLines, codePosition, cellId handling for deprecated syntax

2. Replace HTML comment with console.warn for deprecation
   - More visible to developers at build time
   - Reduces output bloat

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The marimo kernel sends error tracebacks as HTML with syntax highlighting.
Detect HTML content and render using v-html instead of plain text.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Address findings from roborev #108:

1. Add DOMPurify to sanitize HTML content before rendering
   - Prevents XSS attacks via malicious print() statements
   - Sanitizes both main output and console output

2. Improve HTML detection regex to avoid false positives
   - Now looks for specific marimo HTML patterns (span/div/pre/code with class)
   - Won't match comparison operators like "x < a" anymore

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Don't re-run notebook cells that already have output from the
initial instantiation. This prevents overwriting valid outputs
with failed executions that lack dependency context.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix reactivity in notebookCell computed to re-evaluate when kernel ready
- Add DOMPurify configuration to allow marimo custom web components
- Fix instantiate API call to include required objectIds/values arrays
- Add reactive dependency helper in getNotebookCellByName
- Remove verbose debug logging from kernel-connection
- Clean up kernel-ready logging output

Note: Marimo UI web components (slider, dropdown, etc.) are now in the
DOM but need marimo's frontend JavaScript bundle to render visually.
Text and error outputs render correctly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix XSS vulnerability by replacing permissive attributeNameCheck with
  a proper whitelist of safe attributes for marimo custom elements
- Remove invalid data-* wildcard from MARIMO_ATTRS (handled in check fn)
- Add empty string check to hasExistingOutput to fix race condition
- Replace fragile setTimeout with event-based instantiate in kernel-ready
- Consolidate redundant kernel-ready log statements
- Add explanatory comment for Vue reactivity hack in getNotebookCellByName
- Add pandas to notebook dependencies (required for Altair .to_pandas())
- Add greeting_input/greeting_output cells with marimonaut default
- Add Greeting Demo slide to presentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Key fixes:
- MarimoCell: Add withDefaults for boolean props to prevent Vue from
  defaulting displayCode/autoRun to false instead of undefined
- MarimoLive: Add null-safe access to notebookCellsVersion to prevent
  TypeError when kernel isn't fully initialized
- useKernelState: Add notebookCellsVersion ref to trigger reactive
  updates when notebook cells are registered
- notebook.py: Fix greeting_output cell to display markdown directly
  instead of returning it (prevents docstring being shown as output)
- Add justfile with cache clearing and service restart commands

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add clarifying comment for bare return in greeting_output cell
- Replace fragile sleep-based process management in justfile with
  nohup and curl-based health checks for more robust startup detection

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change cells from `return mo.md(...)` to `mo.md(...)` without return.
This ensures marimo sends proper cell outputs instead of docstrings.

Updated cells:
- slider_output
- checkbox_output
- text_output

Also reverted justfile to use edit mode (run mode doesn't expose cell names).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add marimo-frontend.ts to load @marimo-team/islands CSS/JS from CDN
- Add message-bridge.ts to intercept UI calls and redirect to WebSocket
- Add slider-styles.ts for shadow DOM CSS injection on sliders
- Add marimo-overrides.css for theming CSS variables
- Add Prism.js syntax highlighting for Python code blocks
- Hide status bar by default (showStatusBar prop, default false)
- Add dark mode styling support
- Update MarimoOutput.vue to trigger slider styling after render

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Sanitize Prism.js highlighted output with DOMPurify to prevent XSS
- Fix setTimeout cleanup in MarimoOutput.vue watch using onCleanup
- Move prism-ready event listener to onMounted with cleanup in onUnmounted
- Fix unused pollingInterval variable (renamed to pollingTimeoutId, track timeouts)
- Add TODO comment for hardcoded dev version of marimo-islands
- Fix redundant dark mode theme selection (remove unused conditional)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add console.log statements throughout main.ts and marimo-frontend.ts to
diagnose why the marimo frontend (slider UI) is not loading:

- MAIN.TS ENTRY POINT CALLED - when setup function starts
- Installing message bridge... - before bridge installation
- About to call loadMarimoFrontend() - before frontend load
- loadMarimoFrontend() CALLED - when function enters
- loadMarimoFrontend() starting load - when actually loading

This helps identify which part of the initialization fails silently.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Address code review #135 feedback:

1. Remove verbose debug console.log statements that were added for
   diagnosing frontend loading. Keep only the useful logs for success
   and failure states that users might need.

2. Remove redundant try-catch around loadMarimoFrontend() - the function
   returns a Promise and the .catch() handler is sufficient since it
   doesn't throw synchronously.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Completely redesign the MarimoLive component styling:

- Separate line number gutter from code content for proper alignment
- Implement One Dark Pro color scheme with CSS custom properties
- Add JetBrains Mono / Fira Code font stack for crisp monospace text
- Improve visual hierarchy with subtle shadows and borders
- Add proper spacing and padding throughout
- Include light mode variant with One Light colors
- Use tabular-nums for consistent line number width
- Add hover states and transitions for polish

The new design is inspired by VS Code's One Dark Pro theme with
enhanced readability for presentation contexts.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Address code review #138 feedback:

Use '\u00A0' (Unicode non-breaking space) instead of regular space
for empty line content. Regular spaces collapse in HTML, causing
empty lines to lose their height. The non-breaking space preserves
the line height while avoiding HTML entity syntax.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@lucharo
Copy link
Copy Markdown
Owner Author

lucharo commented Feb 4, 2026

Superseded by #8 which consolidates into a single slidev-addon-marimo package

@lucharo lucharo closed this Feb 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant