1+ /// Internal model for generating Jupyter notebook (.ipynb) files from literate scripts and F# Interactive sessions.
2+ /// Types in this module mirror the JSON structure of the Jupyter nbformat 4 spec.
13module internal FSharp.Formatting.PynbModel
24
35open System.Web
46
7+ /// Escapes a string for use as a JSON string value (with surrounding quotes).
58let escapeAndQuote ( txt : string ) =
69 HttpUtility.JavaScriptStringEncode( txt, true )
710
11+ /// Ensures a string ends with a newline character, as required by the nbformat source line convention.
812let addLineEnd ( s : string ) = if s.EndsWith '\n' then s else s + " \n "
913
14+ /// Represents the output data payload of a notebook cell execution result, keyed by MIME type.
1015type OutputData =
1116 | OutputData of kind : string * lines : string array
1217
@@ -20,6 +25,7 @@ type OutputData =
2025 kind
2126 ( String.concat " ,\n " ( Array.map escapeAndQuote lines))
2227
28+ /// Represents a single output produced by executing a notebook code cell.
2329type Output =
2430 { data: OutputData
2531 execution_count: int option
@@ -42,6 +48,7 @@ type Output =
4248 this.metadata
4349 this.output_ type
4450
51+ /// Represents a single cell in a Jupyter notebook (code, markdown, or raw).
4552type Cell =
4653 { cell_type: string
4754 execution_count: int option
@@ -91,6 +98,7 @@ type Cell =
9198 |> Array.map ( addLineEnd >> escapeAndQuote)
9299 |> String.concat " ,\n " )
93100
101+ /// Metadata describing the kernel (language runtime) used to execute the notebook.
94102type Kernelspec =
95103 { display_name: string
96104 language: string
@@ -112,6 +120,7 @@ type Kernelspec =
112120 ( escapeAndQuote this.language)
113121 ( escapeAndQuote this.name)
114122
123+ /// Metadata describing the programming language used in the notebook (for syntax highlighting and MIME types).
115124type LanguageInfo =
116125 { file_extension: string
117126 mimetype: string
@@ -137,6 +146,7 @@ type LanguageInfo =
137146 ( escapeAndQuote this.name)
138147 ( escapeAndQuote this.pygments_ lexer)
139148
149+ /// Polyglot Notebooks kernel info, identifying the default kernel for the notebook.
140150type DefaultKernelInfo =
141151 { defaultKernelName: string
142152 languageName: string
@@ -165,6 +175,7 @@ type DefaultKernelInfo =
165175 ( escapeAndQuote this.languageName)
166176 ( escapeAndQuote this.name)
167177
178+ /// Top-level notebook metadata combining kernel spec, language info, and Polyglot Notebooks extension data.
168179type Metadata =
169180 { kernelspec: Kernelspec
170181 language_info: LanguageInfo
@@ -186,6 +197,7 @@ type Metadata =
186197 this.language_ info
187198 this.defaultKernelInfo
188199
200+ /// The root Jupyter notebook document, containing all cells and metadata.
189201type Notebook =
190202 { nbformat: int
191203 nbformat_minor: int
@@ -216,6 +228,7 @@ type Notebook =
216228let internal splitLines ( s : string ) =
217229 s.Replace( " \r\n " , " \n " ) .Split([| '\n' |])
218230
231+ /// Creates a code cell with the given source lines, execution count, and outputs.
219232let codeCell ( lines : string array ) executionCount outputs =
220233 let lines = lines |> Array.collect splitLines |> Array.map addLineEnd
221234
@@ -228,11 +241,13 @@ let codeCell (lines: string array) executionCount outputs =
228241
229242 cell
230243
244+ /// Creates a raw (non-executed) cell with the given content string.
231245let rawCell ( s : string ) =
232246 { Cell.Default with
233247 cell_ type = " raw"
234248 source = splitLines s }
235249
250+ /// Creates a markdown cell with the given source lines.
236251let markdownCell ( lines : string array ) =
237252 let lines = lines |> Array.collect splitLines |> Array.map addLineEnd
238253
0 commit comments