Skip to content

Commit

Permalink
First cut of CKEditor5
Browse files Browse the repository at this point in the history
  • Loading branch information
jackhiggs committed May 7, 2020
1 parent a048175 commit 1148539
Show file tree
Hide file tree
Showing 2,912 changed files with 212,063 additions and 273 deletions.
276 changes: 5 additions & 271 deletions couch/field.php
Expand Up @@ -316,7 +316,7 @@ function store_posted_changes( $post_val ){
if( $this->trust_mode==0 && in_array($this->k_type, array('text', 'textarea', 'richtext')) ){
// if value submitted from front-end form, input is untrusted and so only a limited subset of HTML tags will be allowed
if( $this->k_type=='richtext' ){
$allowed_tags = '<a><br><strong><b><em><i><u><blockquote><pre><code><ul><ol><li><del><strike><div><p><h1><h2><h3><h4><h5><h6>';
$allowed_tags = '<a><br><strong><b><em><i><u><blockquote><pre><code><ul><ol><li><del><strike><div><p><h1><h2><h3><h4><h5><h6><oembed><figure>';
$this->data = trim( $FUNCS->cleanXSS(strip_tags($post_val, $allowed_tags), 2) );
}
else{
Expand Down Expand Up @@ -591,277 +591,11 @@ static function _render_richtext( $f, $input_name, $input_id, $extra, $dynamic_i

$html = '';
$value = $f->get_data();
$separator = ( $f->k_separator ) ? $f->k_separator : '|';
$val_separator = ( $f->val_separator ) ? $f->val_separator : '=';
$rtl = ( $f->rtl ) ? 'dir="RTL"' : '';

if( !$f->page->CKEditor ){
require_once( K_COUCH_DIR.'includes/ckeditor/ckeditor.php' );

$f->page->CKEditor = new CKEditor();
$f->page->CKEditor->returnOutput = true;
$f->page->CKEditor->basePath = K_ADMIN_URL . 'includes/ckeditor/';

if( $f->trust_mode ){
if( K_USE_KC_FINDER ){
$f->page->CKEditor->config['filebrowserBrowseUrl'] = K_ADMIN_URL . 'includes/kcfinder/browse.php?nonce='.$FUNCS->create_nonce( 'kc_finder' ).'&type=file';
$f->page->CKEditor->config['filebrowserImageBrowseUrl'] = K_ADMIN_URL . 'includes/kcfinder/browse.php?nonce='.$FUNCS->create_nonce( 'kc_finder' ).'&type=image';
$f->page->CKEditor->config['filebrowserFlashBrowseUrl'] = K_ADMIN_URL . 'includes/kcfinder/browse.php?nonce='.$FUNCS->create_nonce( 'kc_finder' ).'&type=flash';
$f->page->CKEditor->config['filebrowserWindowWidth'] = '670';
}
else{
$f->page->CKEditor->config['filebrowserBrowseUrl'] = K_ADMIN_URL . 'includes/fileuploader/browser/browser.html';
$f->page->CKEditor->config['filebrowserImageBrowseUrl'] = K_ADMIN_URL . 'includes/fileuploader/browser/browser.html?Type=Image';
$f->page->CKEditor->config['filebrowserFlashBrowseUrl'] = K_ADMIN_URL . 'includes/fileuploader/browser/browser.html?Type=Flash';
$f->page->CKEditor->config['filebrowserWindowWidth'] = '600';
}
}
$f->page->CKEditor->config['width'] = '100%';
$f->page->CKEditor->config['height'] = 240;

}
$f->page->CKEditor->textareaAttributes = array("style" => "visibility:hidden", "id" => $input_id, "cols" => 80, "rows" => 15);

//$config['baseHref'] = K_SITE_URL;
// RTL
if( $rtl ) $config['contentsLangDirection'] = 'rtl';

// body class and body id
if( $f->body_class ) $config['bodyClass'] = $f->body_class;
if( $f->body_id ) $config['bodyId'] = $f->body_id;

// height
if( $f->height && $f->height > 0 ){
$config['height'] = $f->height .'px';
}

// width
if( $f->width && $f->width > 0 ){
$config['width'] = $f->width .'px';
}

// content css
// Multiple css files can be loaded and non-local files are supported too.
$arr_css[] = $f->page->CKEditor->basePath . 'contents.css';
if( $f->css ){
$arr_custom_css = array_map( "trim", explode( $separator, $f->css ) );
foreach( $arr_custom_css as $css ){
if( strpos($css, '://')===false ){
$css = K_SITE_URL . (( $css[0]=='/' ) ? substr($css, 1) : $css);
}
$arr_css[] = $css;
}
}
$config['contentsCss'] = $arr_css;

// custom styles dropdown
// Only a single file can be added. Non local file supported.
if( $f->custom_styles ){
list( $custom_style_name, $custom_style_file ) = array_map( "trim", explode( $val_separator, $f->custom_styles ) );
if( strpos($custom_style_file, '://')===false ){
$custom_style_file = K_SITE_URL . (( $custom_style_file[0]=='/' ) ? substr($custom_style_file, 1) : $custom_style_file);
}
$config['stylesCombo_stylesSet'] = $custom_style_name . ':' . $custom_style_file;
}

// rendered within repeatable region?
$repeatable = 0;
if( $dynamic_insertion || $dynamic_insertion===false ){
// NOTE: With v2.0, for regions *within* repeatable-regions, when the need arose to differentiate between regions that already exist (from previous saves)
// and those being added on-the-fly by clicking 'new', to preserve backward compatibility the $dynamic_insertion is set to boolean 'false' for
// existing regions (and '1', as previously, for dynamically added).

$repeatable = 1;
}

// toolbars
$toolbar = $f->toolbar; // basic, medium, full.
if( $repeatable && $toolbar=='' ) $toolbar = 'basic';

if( $toolbar == 'full' ){
$config['toolbar'] = array(
array( 'Bold', 'Italic', 'Underline', 'Strike', '-', 'Subscript', 'Superscript'),
array( 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ),
array( 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', 'Blockquote' ),
array( 'Undo', 'Redo', 'RemoveFormat' ),
'/',
array( 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord' ),
array( 'Image', 'Flash', 'Table', 'HorizontalRule', 'Smiley', 'SpecialChar', 'PageBreak' ),
array( 'Link', 'Unlink', 'Anchor' ),
'/',
array( 'Styles', 'Format', 'Font', 'FontSize' ),
array( 'TextColor', 'BGColor' ),
array( 'ShowBlocks', 'Preview', 'Maximize', '-', 'Source' )
);
}
elseif( $toolbar == 'basic' ){
$config['toolbar'] = array(
array( 'Bold', 'Italic', 'Underline', 'Strike' ),
array( 'Format' ),
array( 'NumberedList', 'BulletedList', 'Blockquote', 'Link', 'Unlink' ),
array( 'Undo', 'Redo', 'RemoveFormat' ),
array( 'Preview', 'Maximize', '-', 'Source' )
);
}
elseif( $toolbar == 'custom' ){
$str_toolbar = $f->custom_toolbar;
if( $str_toolbar ){
$arr_toolbars = array_map( "trim", explode( $separator, $str_toolbar ) );
foreach( $arr_toolbars as $toolbar ){
$arr_buttons = array_map( "trim", explode( ',', $toolbar ) );
if( count($arr_buttons)==1 && $arr_buttons[0]=='' ){
$arr_tb_buttons[] = '/';
}
else{
$arr_tmp = array();
foreach( $arr_buttons as $btn ){
if( array_key_exists( strtolower($btn), $f->available_buttons ) ){
$arr_tmp[] = $f->available_buttons[strtolower($btn)];
}
// Check if a custom button specified (starts with a #)
elseif( substr($btn, 0, 1)=='#' ){
$arr_tmp[] = substr( $btn, 1 );
}
}
if( count($arr_tmp) ) $arr_tb_buttons[] = $arr_tmp;
}
}
if( count($arr_tb_buttons) ) $config['toolbar'] = $arr_tb_buttons;
}
}
else{ //medium (defult)
$config['toolbar'] = array(
array( 'Bold', 'Italic', 'Underline', 'Strike', '-', 'Subscript', 'Superscript'),
array( 'Format' ),
array( 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ),
array( 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', 'Blockquote' ),
array( 'Undo', 'Redo', 'RemoveFormat' ),
'/',
array( 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord' ),
array( 'Image', 'Flash', 'Table', 'HorizontalRule', 'Smiley', 'SpecialChar', 'PageBreak' ),
array( 'Link', 'Unlink', 'Anchor' ),
array( 'ShowBlocks', 'Preview', 'Maximize', '-', 'Source' )
);
}

if( $repeatable ){
ob_start();
?>
var parentRow = $("#"+eid).closest("tr");
if(parentRow.length){
parentRow.bind("row_delete", function(event){
var ed = CKEDITOR.instances[ eid ];
if( typeof ed != "undefined" ){
ed.destroy();
CKEDITOR.remove( ed );
}
});
parentRow.bind("_reorder_start", function(event){
var ed = CKEDITOR.instances[ eid ];
if( typeof ed != "undefined" ){
if( typeof CKEDITOR.k_config_cks == "undefined" ) CKEDITOR.k_config_cks = [];
CKEDITOR.k_config_cks[eid] = ed.config;
var txtarea = $("#"+eid);
var dummy = txtarea.next(".cke").clone().addClass("dummy");
ed.destroy();
CKEDITOR.remove( ed );
txtarea.hide().after(dummy);
}
});
parentRow.bind("_reorder_stop", function(event){
CKEDITOR.replace( eid, CKEDITOR.k_config_cks[eid] );
var txtarea = $("#"+eid);
txtarea.next(".dummy").remove();
});
}
<?php
$dyn_js = ob_get_contents();
ob_end_clean();

if( $dynamic_insertion ){ // being added on-the-fly.. output template markup that will be duplicated for each dynamically added new row
$tmp = $f->page->CKEditor->editor( $input_name, $value, $config );

if( preg_match('/<textarea.*?<\/textarea>/i', $tmp, $matches) ){
$html .= $matches[0];
}

if( strpos($tmp, 'window.CKEDITOR_BASEPATH')!==false ){
if( preg_match_all('/<script[^>]*>.*?<\/script>/s', $tmp, $matches, PREG_PATTERN_ORDER) ){
$matches = $matches[0]; // scripts
$tmp = array_pop( $matches );

$html0 = '';
foreach ($matches as $match) {
$html0 .= $match;
}
if( strlen($html0) ){ $FUNCS->add_html( $html0 ); };
}
}

if( preg_match('/CKEDITOR\\.replace\\(.*\\);/sim', $tmp, $matches) ){
$html1 = str_replace( '\'', '"', $matches[0] );
}

// Being dynamically inserted (e.g. through 'repeatable' tag).
// Simply outputting script will not work.
// Have to use a workaround (http://24ways.org/2005/have-your-dom-and-script-it-too).
// Additionally, we are adding an id - the logic is that the id gets duplicated into 'idx' for the 'template' row code.
// This 'idx' will not be present in the cloned rows. We use this property to avoid executing JavaScript in template row.
ob_start();
?>
<img src="<?php echo K_SYSTEM_THEME_URL; ?>assets/blank.gif" alt="" id="<?php echo $input_id ?>_dummyimg" onload='
el=$("#<?php echo $input_id ?>_dummyimg");
if(!el.attr("idx")){
<?php echo $html1 ?>
var eid = "<?php echo $input_id ?>";
<?php echo $dyn_js ?>
el.css("display", "none");
}
' />
<?php
$html .= ob_get_contents();
ob_end_clean();

return $html;

}
else{ /* not dynamically inserted but is being rendered within repeatable regions */
$config['removePlugins']='resize';

static $done=0;
if( !$done ){
$done=1;
ob_start();
?>
$(function(){
if( CKEDITOR && CKEDITOR.k_repeatable_cks ){
$.each(CKEDITOR.k_repeatable_cks, function(index, value){
try{
var eid = value;
<?php echo $dyn_js ?>
}
catch(e){}
});
}
});
<?php
$js = ob_get_contents();
ob_end_clean();
$FUNCS->add_js( $js );
}

$html .= $f->page->CKEditor->editor( $input_name, $value, $config );
$html .= "<script type=\"text/javascript\">//<![CDATA[\n";
$html .= "if( !CKEDITOR.k_repeatable_cks ) CKEDITOR.k_repeatable_cks = []; CKEDITOR.k_repeatable_cks.push( '". $input_id ."' );";
$html .= "\n//]]></script>\n";

return $html;
}
}

$html .= $f->page->CKEditor->editor( $input_name, $value, $config );
$html .= '<script src="includes/ckeditor5/ckeditor.js"></script>';
$html .= '<script src="includes/ckfinder/ckfinder.js"></script>';
$html .= '<textarea name="'.$input_name.'" id="'.$input_id.'">'.$value.'</textarea>';
$html .= '<script> ClassicEditor.create( document.querySelector("#'.$input_id.'"), { ckfinder: {uploadUrl: "includes/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Images&responseType=json"} } ).catch( error => { console.error( error );});</script>';

return $html;
}
Expand Down
21 changes: 21 additions & 0 deletions couch/includes/ckeditor5/LICENSE.md
@@ -0,0 +1,21 @@
Software License Agreement
==========================

**CKEditor 5 classic editor build**https://github.com/ckeditor/ckeditor5-build-classic <br>
Copyright (c) 2003-2020, [CKSource](http://cksource.com) Frederico Knabben. All rights reserved.

Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).

Sources of Intellectual Property Included in CKEditor
-----------------------------------------------------

Where not otherwise indicated, all CKEditor content is authored by CKSource engineers and consists of CKSource-owned intellectual property. In some specific instances, CKEditor will incorporate work done by developers outside of CKSource with their express permission.

The following libraries are included in CKEditor under the [MIT license](https://opensource.org/licenses/MIT):

* Lo-Dash - Copyright (c) JS Foundation and other contributors https://js.foundation/. Based on Underscore.js, copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors http://underscorejs.org/.

Trademarks
----------

**CKEditor** is a trademark of [CKSource](http://cksource.com) Frederico Knabben. All other brand and product names are trademarks, registered trademarks or service marks of their respective holders.
9 changes: 9 additions & 0 deletions couch/includes/ckeditor5/README.md
@@ -0,0 +1,9 @@
CKEditor 5 classic editor build v19.0.0
=======================================

In order to start using CKEditor 5 Builds, configure or customize them, please visit http://docs.ckeditor.com/ckeditor5/latest/builds/index.html

## License

Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).
For full details about the license, please check the LICENSE.md file.
6 changes: 6 additions & 0 deletions couch/includes/ckeditor5/ckeditor.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions couch/includes/ckeditor5/ckeditor.js.map

Large diffs are not rendered by default.

0 comments on commit 1148539

Please sign in to comment.