Skip to content

Instantly share code, notes, and snippets.

@bfintal
Created September 29, 2021 12:54
Show Gist options
  • Select an option

  • Save bfintal/be97d3182a69747ee937cad3b6bc98b3 to your computer and use it in GitHub Desktop.

Select an option

Save bfintal/be97d3182a69747ee937cad3b6bc98b3 to your computer and use it in GitHub Desktop.

Revisions

  1. bfintal created this gist Sep 29, 2021.
    85 changes: 85 additions & 0 deletions auto-block-recovery.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,85 @@
    var recursivelyRecoverInvalidBlockList = blocks => {
    const _blocks = [ ...blocks ]
    let recoveryCalled = false
    const recursivelyRecoverBlocks = willRecoverBlocks => {
    willRecoverBlocks.forEach( _block => {
    if ( isInvalid( _block ) ) {
    recoveryCalled = true
    const newBlock = recoverBlock( _block )
    for ( const key in newBlock ) {
    _block[ key ] = newBlock[ key ]
    }
    }

    if ( _block.innerBlocks.length ) {
    recursivelyRecoverBlocks( _block.innerBlocks )
    }
    } )
    }

    recursivelyRecoverBlocks( _blocks )
    return [ _blocks, recoveryCalled ]
    }

    var recoverBlock = ( { name, attributes, innerBlocks } ) =>
    wp.blocks.createBlock( name, attributes, innerBlocks );

    var recoverBlocks = blocks => {
    return blocks.map( _block => {
    const block = _block

    // If the block is a reusable block, recover the Stackable blocks inside it.
    if ( _block.name === 'core/block' ) {
    const { attributes: { ref } } = _block
    const parsedBlocks = wp.blocks.parse( wp.data.select( 'core' ).getEntityRecords( 'postType', 'wp_block', { include: [ ref ] } )?.[ 0 ]?.content?.raw ) || []

    const [ recoveredBlocks, recoveryCalled ] = recursivelyRecoverInvalidBlockList( parsedBlocks )

    if ( recoveryCalled ) {
    console.log( 'Stackable notice: block ' + block.name + ' (' + block.clientId + ') was auto-recovered, you should not see this after saving your page.' ) // eslint-disable-line no-console
    return {
    blocks: recoveredBlocks,
    isReusable: true,
    ref,
    }
    }
    }

    if ( block.innerBlocks && block.innerBlocks.length ) {
    const newInnerBlocks = recoverBlocks( block.innerBlocks )
    if ( newInnerBlocks.some( block => block.recovered ) ) {
    block.innerBlocks = newInnerBlocks
    block.replacedClientId = block.clientId
    block.recovered = true
    }
    }

    if ( ! block.isValid ) {
    const newBlock = recoverBlock( block )
    newBlock.replacedClientId = block.clientId
    newBlock.recovered = true
    console.log( 'Stackable notice: block ' + block.name + ' (' + block.clientId + ') was auto-recovered, you should not see this after saving your page.' ) // eslint-disable-line no-console

    return newBlock
    }

    return block
    } )
    }

    // Recover all the blocks that we can find.
    var mainBlocks = recoverBlocks( wp.data.select( 'core/editor' ).getEditorBlocks() )
    // Replace the recovered blocks with the new ones.
    mainBlocks.forEach( block => {
    if ( block.isReusable && block.ref ) {
    // Update the reusable blocks.
    wp.data.dispatch( 'core' ).editEntityRecord( 'postType', 'wp_block', block.ref, { content: wp.blocks.serialize( block.blocks ) } ).then( () => {
    // But don't save them, let the user do the saving themselves. Our goal is to get rid of the block error visually.
    // dispatch( 'core' ).saveEditedEntityRecord( 'postType', 'wp_block', block.ref )
    } )
    }

    if ( block.recovered && block.replacedClientId ) {
    wp.data.dispatch( 'core/block-editor' ).replaceBlock( block.replacedClientId, block )
    }
    } )