MCPcopy Create free account
hub / github.com/deepnote/deepnote / convertCellToBlock

Function convertCellToBlock

packages/convert/src/jupyter-to-deepnote.ts:203–277  ·  view source on GitHub ↗
(cell: JupyterCell, index: number, idGenerator: () => string)

Source from the content-addressed store, hash-verified

201}
202
203function convertCellToBlock(cell: JupyterCell, index: number, idGenerator: () => string): DeepnoteBlock {
204 let source = Array.isArray(cell.source) ? cell.source.join('') : cell.source
205
206 // Check if this cell has Deepnote metadata (from a previous conversion)
207 const cellId = cell.metadata?.cell_id as string | undefined
208 const deepnoteCellType = cell.metadata?.deepnote_cell_type as string | undefined
209 const sortingKey = cell.metadata?.deepnote_sorting_key as string | undefined
210
211 // Restore snapshot fields from metadata
212 const contentHash = cell.metadata?.deepnote_content_hash as string | undefined
213 const executionStartedAt = cell.metadata?.deepnote_execution_started_at as string | undefined
214 const executionFinishedAt = cell.metadata?.deepnote_execution_finished_at as string | undefined
215
216 // Determine blockGroup: prefer metadata, fall back to top-level field, then generate
217 // Cloud-exported notebooks may have block_group at top level
218 const blockGroup = cell.metadata?.deepnote_block_group ?? cell.block_group ?? idGenerator()
219
220 // Restore original content from metadata if available (for lossless roundtrip)
221 // For plain code blocks, only use deepnote_source if it matches the current source
222 // (this respects user edits while preserving roundtrip for unchanged content)
223 // For non-code blocks (sql, text-cell-h2, etc.), always use deepnote_source since
224 // transformations are applied during export (e.g., "Data Cleaning" → "## Data Cleaning")
225 const deepnoteSource = cell.metadata?.deepnote_source as string | undefined
226 const isPlainCodeBlock = cell.cell_type === 'code' && (!deepnoteCellType || deepnoteCellType === 'code')
227 if (deepnoteSource !== undefined) {
228 if (isPlainCodeBlock) {
229 // Plain code blocks: only use deepnote_source if content is unchanged
230 if (deepnoteSource === source) {
231 source = deepnoteSource
232 }
233 // Otherwise, user has edited - keep the actual source
234 } else {
235 // Non-code blocks: always use deepnote_source (content is transformed during export)
236 source = deepnoteSource
237 }
238 }
239
240 const blockType = (deepnoteCellType ?? (cell.cell_type === 'code' ? 'code' : 'markdown')) as DeepnoteBlock['type']
241
242 // Extract original metadata (exclude Deepnote-specific fields)
243 const originalMetadata = { ...cell.metadata }
244 delete originalMetadata.cell_id
245 delete originalMetadata.deepnote_cell_type
246 delete originalMetadata.deepnote_block_group
247 delete originalMetadata.deepnote_sorting_key
248 delete originalMetadata.deepnote_source
249 delete originalMetadata.deepnote_content_hash
250 delete originalMetadata.deepnote_execution_started_at
251 delete originalMetadata.deepnote_execution_finished_at
252 // Also remove top-level block_group from metadata to avoid duplication
253 delete (cell as { block_group?: unknown }).block_group
254
255 // Build block object - order doesn't matter here since we sort alphabetically after parsing
256 // Only include executionCount and outputs when they have values
257 const executionCount = cell.execution_count ?? undefined
258 const hasExecutionCount = executionCount !== undefined
259 const hasOutputs = cell.cell_type === 'code' && cell.outputs !== undefined
260

Callers 1

Calls 2

generateSortingKeyFunction · 0.90
sortKeysAlphabeticallyFunction · 0.90

Tested by

no test coverage detected