import { ExtensionContext , NotebookCellsChangeEvent , NotebookDocument , notebooks , workspace , WorkspaceEdit } from 'vscode' ; import { v4 as uuid } from 'uuid' ; import { getCellMetadata } from './serializers' ; import { CellMetadata } from './common' ; import { getNotebookMetadata } from './notebookSerializer' ; import { nbformat } from '@jupyterlab/coreutils' ; /**
 * Ensure all new cells in notebooks with nbformat >= 4.5 have an id.
 * Details of the spec can be found here https://jupyter.org/enhancement-proposals/62-cell-id/cell-id.html#
 */ export function ensureAllNewCellsHaveCellIds ( context ) { notebooks . onDidChangeNotebookCells ( onDidChangeNotebookCells , undefined , context . subscriptions ) ; } function onDidChangeNotebookCells ( e ) { const nbMetadata = getNotebookMetadata ( e . document ) ; if ( ! isCellIdRequired ( nbMetadata ) ) { return ; } e . changes . forEach ( change => { change . items . forEach ( cell => { const cellMetadata = getCellMetadata ( cell ) ; if ( cellMetadata ?. id ) { return ; } const id = generateCellId ( e . document ) ; const edit = new WorkspaceEdit ( ) ; const updatedMetadata = { ... JSON . parse ( JSON . stringify ( cellMetadata || { } ) ) } ; updatedMetadata . id = id ; edit . replaceNotebookCellMetadata ( cell . notebook . uri , cell . index , { ... ( cell . metadata ) , custom : updatedMetadata } ) ; workspace . applyEdit ( edit ) ; } ) ; } ) ; } /**
 * Cell ids are required in notebooks only in notebooks with nbformat >= 4.5
 */ function isCellIdRequired ( metadata ) { if ( ( metadata . nbformat || 0 ) >= 5 ) { return true ; } if ( ( metadata . nbformat || 0 ) === 4 && ( metadata . nbformat_minor || 0 ) >= 5 ) { return true ; } return false ; } function generateCellId ( notebook ) { while ( true ) { const id = uuid ( ) . replace ( /-/g , '' ) . substring ( 0 , 8 ) ; let duplicate = false ; for ( let index = 0 ; index < notebook . cellCount ; index ++ ) { const cell = notebook . cellAt ( index ) ; const existingId = getCellMetadata ( cell ) ?. id ; if ( ! existingId ) { continue ; } if ( existingId === id ) { duplicate = true ; break ; } } if ( ! duplicate ) { return id ; } } }