summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLester Caine <lester@lsces.co.uk>2026-05-16 14:08:36 +0100
committerLester Caine <lester@lsces.co.uk>2026-05-16 14:08:36 +0100
commit17cb4e47dfec18793a0848c66e9c9602e1a96394 (patch)
treebe9f0e04773ea69c1eb96e5a38f78eaf6eac7563
parentaac01aa419299f447a067873d7483bddc116821d (diff)
downloadckeditor-17cb4e47dfec18793a0848c66e9c9602e1a96394.tar.gz
ckeditor-17cb4e47dfec18793a0848c66e9c9602e1a96394.tar.bz2
ckeditor-17cb4e47dfec18793a0848c66e9c9602e1a96394.zip
Add filter to display {code} block is ckeditor
Caution, the {code} element is replaced by <pre class="bwcode"></pre>' wrapper in souce view
-rwxr-xr-xincludes/bit_setup_inc.php4
-rw-r--r--includes/code_blocks_inc.php62
-rwxr-xr-xtemplates/footer_inc.tpl1
3 files changed, 67 insertions, 0 deletions
diff --git a/includes/bit_setup_inc.php b/includes/bit_setup_inc.php
index 7448d4c..008ba90 100755
--- a/includes/bit_setup_inc.php
+++ b/includes/bit_setup_inc.php
@@ -16,6 +16,10 @@ define( "CKEDITOR_PKG_ADMIN_PATH", BIT_ROOT_PATH . basename( $pRegisterHash["pac
$gBitSystem->registerPackage( $pRegisterHash );
+if( $gBitSystem->isPackageActive( 'ckeditor' ) ) {
+ require_once CKEDITOR_PKG_INCLUDE_PATH . 'code_blocks_inc.php';
+}
+
if( $gBitSystem->isPackageActive( "ckeditor" ) && $gBitUser->isRegistered() && $gBitUser->hasPermission( "p_liberty_enter_html" ) ){
if( defined( "IS_LIVE" ) && IS_LIVE ) {
$gBitThemes->loadJavascript( CKEDITOR_PKG_PATH."ckeditor.js", false, 600, false );
diff --git a/includes/code_blocks_inc.php b/includes/code_blocks_inc.php
new file mode 100644
index 0000000..ec50fce
--- /dev/null
+++ b/includes/code_blocks_inc.php
@@ -0,0 +1,62 @@
+<?php
+
+define( 'PLUGIN_GUID_CK_CODEBLOCKS', 'ck_codeblocks' );
+
+global $gLibertySystem;
+
+$gLibertySystem->registerPlugin( PLUGIN_GUID_CK_CODEBLOCKS, [
+ 'title' => 'CKEditor Code Block Conversion',
+ 'description' => 'Converts {code} wiki blocks to <pre class="bwcode"> 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 <pre class="bwcode"> for CKEditor.
+ * HTML-encodes the content so CKEditor preserves it as text (protects <?php etc. from PI stripping).
+ * Stores the original {code} params in data-bwcode-params for lossless round-trip.
+ */
+function ckeditor_code_wiki_to_pre( string $content ): string {
+ return preg_replace_callback(
+ '/\{code([^}]*)\}([\s\S]*?)\{\/code\}/i',
+ function( array $m ): string {
+ $params = trim( $m[1] );
+ $code = htmlspecialchars( $m[2], ENT_COMPAT | ENT_HTML5, 'UTF-8' );
+ $dataAttr = $params !== ''
+ ? ' data-bwcode-params="' . htmlspecialchars( $params, ENT_COMPAT | ENT_HTML5, 'UTF-8' ) . '"'
+ : '';
+ return '<pre class="bwcode"' . $dataAttr . '>' . $code . '</pre>';
+ },
+ $content
+ );
+}
+
+/**
+ * Reverse of ckeditor_code_wiki_to_pre — called by the prestore filter.
+ * Converts <pre class="bwcode" data-bwcode-params="...">...</pre> back to {code ...}...{/code}.
+ */
+function ckeditor_code_pre_to_wiki( string $content ): string {
+ return preg_replace_callback(
+ '/<pre\b([^>]*?class="[^"]*\bbwcode\b[^"]*"[^>]*)>([\s\S]*?)<\/pre>/i',
+ function( array $m ): string {
+ $attrStr = $m[1];
+ // Strip any trailing <br> CKEditor appends inside <pre>
+ $raw = preg_replace( '/<br\s*\/?>\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 );
+ }
+}
diff --git a/templates/footer_inc.tpl b/templates/footer_inc.tpl
index feb79bd..9a801d6 100755
--- a/templates/footer_inc.tpl
+++ b/templates/footer_inc.tpl
@@ -2,6 +2,7 @@
{if $gBitUser->isRegistered() }
<script nonce="{$cspNonce}">
CKEDITOR.replace( '{$smarty.const.LIBERTY_TEXT_AREA}', {
+ extraAllowedContent: 'pre(bwcode)[data-bwcode-params]',
toolbarGroups: [
{if $gBitSystem->getConfig('ckedit_toolbars') eq 'Full'}
{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },