Add opt-in .ipynb round-trip (preserve original format on save)#58
Merged
Conversation
Introduce a preserve-original-format feature and Jupyter (.ipynb) export support. Adds PreserveFormat option across the CLI (repl/serve), Blazor host, and REPL session so implicit .save behavior can preserve an opened .ipynb instead of converting to .verso. ServerNotebookService now chooses a serializer based on the file path and PreserveFormat; NotebookHandler accepts an optional format param and routes post-processors and serializers accordingly (falling back to Verso). JupyterSerializer is extended to support serialization (nbformat v4) with write helpers and DTOs, and many serializer tests were added/updated to cover round-trips and outputs. The VS Code extension gains a setting to preserve original formats and the editor provider sends the requested format when saving. Unit tests were added/adjusted to validate the new behaviors.
Introduce opt-in support for round-tripping Jupyter .ipynb files instead of always converting to .verso. Update serializer metadata to mark Jupyter as writable, add a VS Code setting (verso.preserveOriginalFormat) and CLI flags (--preserve-format) for verso repl/serve to enable in-place .ipynb saves, and make front-ends send an optional format parameter on notebook/save. Documentation and READMEs updated to explain default behavior (sibling .verso created) and the opt-in preservation semantics, including limitations and how non-native Verso features are represented when round-tripping.
SummarySummary
CoverageVerso - 76.6%
Verso.Abstractions - 84.7%
Verso.Ado - 82.6%
Verso.Blazor - 18.9%
Verso.Blazor.Shared - 45.2%
Verso.Cli - 38.6%
Verso.FSharp - 82.6%
Verso.Host - 29.3%
Verso.Http - 75.7%
Verso.JavaScript - 43.9%
Verso.PowerShell - 65.1%
Verso.Python - 59.3%
Verso.Sample.Diagram - 80.1%
Verso.Sample.Dice - 82.1%
Verso.Sample.Slides - 79.5%
Verso.Testing - 80.3%
|
Prevent TryGetProperty from running on non-object JsonElement values in NotebookHandler.HandleSaveAsync by pattern-matching params as an object first, ensuring non-object (null/array/primitive) params fall back to the default "verso" format. Also update JupyterSerializer to treat null/empty MimeType as "text/plain" (avoiding invalid empty MIME keys) and use the coerced mime type when emitting display_data. Added unit tests to cover non-object save params and empty MimeType behavior.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements discussion #44: opt-in support for saving
.ipynbnotebooks back to.ipynbinstead of force-converting to.verso. Cell outputs round-trip. Default behavior is unchanged.JupyterSerializer.SerializeAsyncnow writes nbformat v4 (kernelspec, source as list-of-strings, execution counts, stream/error/display_data outputs). Hostnotebook/saveaccepts an optionalformatparam, resolved againstExtensionHost.GetSerializers()with aversofallback.verso.preserveOriginalFormatsetting (defaultfalse). When on and the document ends in.ipynb, the editor sendsformat: "jupyter"to the host instead of auto-converting to a sibling.versofile..dibstill auto-converts.--preserve-formatflag onverso replandverso serve(defaultfalse).SaveMetabranches on it for implicit-target saves; explicit.save foo.ipynbis always honored.ServerNotebookServiceselectsJupyterSerializerwhenPreserveFormat=trueand the loaded path is.ipynb.vscode/README.md,src/Verso.Cli/README.md,docs/architecture/engine.md,docs/architecture/front-ends.md,docs/migration/from-jupyter.mdupdated to describe the opt-in and its round-trip semantics (Verso-specific cell types collapse to Jupyterrawwith the original type stashed incell.metadata.verso_type; layouts, parameter definitions, and theme preferences do not have a Jupyter representation).Test plan
dotnet test tests/Verso.Tests/Verso.Tests.csproj— 1018 passeddotnet test tests/Verso.Host.Tests/Verso.Host.Tests.csproj— 50 passeddotnet test tests/Verso.Cli.Tests/Verso.Cli.Tests.csproj— 243 passed.ipynbin VS Code with the setting off → sibling.versocreated (existing behavior); with the setting on → file stays.ipynband reopens cleanlyOut of scope
.dibwriter (DibSerializer.SerializeAsync). Same plumbing applies whenever added.--preserve-formatflag plumbs through; per-session UI control is a follow-up.