registerPlugin( PLUGIN_GUID_CK_CODEBLOCKS, [ 'title' => 'CKEditor Code Block Conversion', 'description' => 'Converts {code} wiki blocks to
 for CKEditor editing, and back on save.',
	'auto_activate'     => true,
	'plugin_type'       => FILTER_PLUGIN,
	'prestore_function' => 'ckeditor_code_pre_to_wiki_filter',
]);

/**
 * Convert {code params}...{/code} wiki markup to 
 for CKEditor.
 * HTML-encodes the content so CKEditor preserves it as text (protects ' . $code . '
'; }, $content ); } /** * Reverse of ckeditor_code_wiki_to_pre — called by the prestore filter. * Converts
...
back to {code ...}...{/code}. */ function ckeditor_code_pre_to_wiki( string $content ): string { return preg_replace_callback( '/]*?class="[^"]*\bbwcode\b[^"]*"[^>]*)>([\s\S]*?)<\/pre>/i', function( array $m ): string { $attrStr = $m[1]; // Strip any trailing
CKEditor appends inside
			$raw  = preg_replace( '/\s*$/i', '', $m[2] );
			$code = html_entity_decode( $raw, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
			$params = '';
			if( preg_match( '/data-bwcode-params="([^"]*)"/', $attrStr, $pm ) ) {
				$params = html_entity_decode( $pm[1], ENT_QUOTES | ENT_HTML5, 'UTF-8' );
			}
			$open = $params !== '' ? "{code $params}" : '{code}';
			return $open . $code . '{/code}';
		},
		$content
	);
}

function ckeditor_code_pre_to_wiki_filter( &$pData, &$pFilterHash, $pObject = null ): void {
	if( !empty( $pData ) ) {
		$pData = ckeditor_code_pre_to_wiki( $pData );
	}
}