Custom CSS classes for styling elements

Define allowed tags, allowed empty, do not wrap, remove tags
Refs #2005
This commit is contained in:
Samuel Georges 2016-05-24 05:33:32 +10:00
parent 7563670c49
commit ef290df3af
9 changed files with 443 additions and 87 deletions

View File

@ -5,6 +5,7 @@ use File;
use Event; use Event;
use Request; use Request;
use Backend\Classes\FormWidgetBase; use Backend\Classes\FormWidgetBase;
use Backend\Models\EditorSetting;
/** /**
* Rich Editor * Rich Editor
@ -71,6 +72,17 @@ class RichEditor extends FormWidgetBase
$this->vars['name'] = $this->formField->getName(); $this->vars['name'] = $this->formField->getName();
$this->vars['value'] = $this->getLoadValue(); $this->vars['value'] = $this->getLoadValue();
$this->vars['toolbarButtons'] = $this->evalToolbarButtons(); $this->vars['toolbarButtons'] = $this->evalToolbarButtons();
$this->vars['allowEmptyTags'] = EditorSetting::getConfigured('html_allow_empty_tags');
$this->vars['allowTags'] = EditorSetting::getConfigured('html_allow_tags');
$this->vars['noWrapTags'] = EditorSetting::getConfigured('html_no_wrap_tags');
$this->vars['removeTags'] = EditorSetting::getConfigured('html_remove_tags');
$this->vars['imageStyles'] = EditorSetting::getConfiguredStyles('html_style_image');
$this->vars['linkStyles'] = EditorSetting::getConfiguredStyles('html_style_link');
$this->vars['paragraphStyles'] = EditorSetting::getConfiguredStyles('html_style_paragraph');
$this->vars['tableStyles'] = EditorSetting::getConfiguredStyles('html_style_table');
$this->vars['tableCellStyles'] = EditorSetting::getConfiguredStyles('html_style_table_cell');
} }
/** /**

View File

@ -149,60 +149,6 @@ iframe.fr-iframe{width:100%;border:none;position:relative;display:block;z-index:
.fr-sticky-on.fr-sticky-ios{position:absolute;left:0;right:0;width:auto !important} .fr-sticky-on.fr-sticky-ios{position:absolute;left:0;right:0;width:auto !important}
.fr-sticky-dummy{display:none} .fr-sticky-dummy{display:none}
.fr-sticky-on + .fr-sticky-dummy,.fr-sticky-box > .fr-sticky-dummy{display:block} .fr-sticky-on + .fr-sticky-dummy,.fr-sticky-box > .fr-sticky-dummy{display:block}
.fr-view strong{font-weight:700}
.fr-view table{border:none;border-collapse:collapse;empty-cells:show;max-width:100%}
.fr-view table.fr-dashed-borders td,.fr-view table.fr-dashed-borders th{border-style:dashed}
.fr-view table.fr-alternate-rows tbody tr:nth-child(2n){background:#f5f5f5}
.fr-view table td,.fr-view table th{border:1px solid #dddddd}
.fr-view table td:empty,.fr-view table th:empty{height:20px}
.fr-view table td.fr-highlighted,.fr-view table th.fr-highlighted{border:1px double red}
.fr-view table td.fr-thick,.fr-view table th.fr-thick{border-width:2px}
.fr-view table th{background:#e6e6e6}
.fr-view hr{clear:both;user-select:none;-o-user-select:none;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none;page-break-after:always}
.fr-view .fr-file{position:relative}
.fr-view .fr-file::after{position:relative;content:"\1F4CE";font-weight:normal}
.fr-view pre{white-space:pre-wrap;word-wrap:break-word}
.fr-view blockquote{border-left:solid 2px #5e35b1;margin-left:0;padding-left:5px;color:#5e35b1}
.fr-view blockquote blockquote{border-color:#00bcd4;color:#00bcd4}
.fr-view blockquote blockquote blockquote{border-color:#43a047;color:#43a047}
.fr-view span.fr-emoticon{font-weight:normal;font-family:"Apple Color Emoji","Segoe UI Emoji","NotoColorEmoji","Segoe UI Symbol","Android Emoji","EmojiSymbols";display:inline;line-height:0}
.fr-view span.fr-emoticon.fr-emoticon-img{background-repeat:no-repeat !important;font-size:inherit;height:1em;width:1em;min-height:20px;min-width:20px;display:inline-block;margin:-0.1em 0.1em 0.1em;line-height:1;vertical-align:middle}
.fr-view .fr-text-gray{color:#AAA !important}
.fr-view .fr-text-bordered{border-top:solid 1px #222;border-bottom:solid 1px #222;padding:10px 0}
.fr-view .fr-text-spaced{letter-spacing:1px}
.fr-view .fr-text-uppercase{text-transform:uppercase}
.fr-view img{position:relative;max-width:100%}
.fr-view img.fr-dib{margin:5px auto;display:block;float:none;vertical-align:top}
.fr-view img.fr-dib.fr-fil{margin-left:0}
.fr-view img.fr-dib.fr-fir{margin-right:0}
.fr-view img.fr-dii{display:inline-block;float:none;vertical-align:bottom;margin-left:5px;margin-right:5px;max-width:calc(90%)}
.fr-view img.fr-dii.fr-fil{float:left;margin:5px 5px 5px 0;max-width:calc(95%)}
.fr-view img.fr-dii.fr-fir{float:right;margin:5px 0 5px 5px;max-width:calc(95%)}
.fr-view img.fr-rounded{border-radius:100%;-moz-border-radius:100%;-webkit-border-radius:100%;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box}
.fr-view img.fr-bordered{border:solid 10px #CCC;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}
.fr-view .fr-video{text-align:center;position:relative}
.fr-view .fr-video > *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;max-width:100%;border:none}
.fr-view .fr-video.fr-dvb{display:block;clear:both}
.fr-view .fr-video.fr-dvb.fr-fvl{text-align:left}
.fr-view .fr-video.fr-dvb.fr-fvr{text-align:right}
.fr-view .fr-video.fr-dvi{display:inline-block}
.fr-view .fr-video.fr-dvi.fr-fvl{float:left}
.fr-view .fr-video.fr-dvi.fr-fvr{float:right}
.fr-view a.fr-strong{font-weight:700}
.fr-view a.fr-green{color:green}
.fr-view button.fr-rounded,.fr-view input.fr-rounded,.fr-view textarea.fr-rounded{border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box}
.fr-view button.fr-large,.fr-view input.fr-large,.fr-view textarea.fr-large{font-size:24px}
a.fr-view.fr-strong{font-weight:700}
a.fr-view.fr-green{color:green}
img.fr-view{position:relative;max-width:100%}
img.fr-view.fr-dib{margin:5px auto;display:block;float:none;vertical-align:top}
img.fr-view.fr-dib.fr-fil{margin-left:0}
img.fr-view.fr-dib.fr-fir{margin-right:0}
img.fr-view.fr-dii{display:inline-block;float:none;vertical-align:bottom;margin-left:5px;margin-right:5px;max-width:calc(90%)}
img.fr-view.fr-dii.fr-fil{float:left;margin:5px 5px 5px 0;max-width:calc(95%)}
img.fr-view.fr-dii.fr-fir{float:right;margin:5px 0 5px 5px;max-width:calc(95%)}
img.fr-view.fr-rounded{border-radius:100%;-moz-border-radius:100%;-webkit-border-radius:100%;-moz-background-clip:padding;-webkit-background-clip:padding-box;background-clip:padding-box}
img.fr-view.fr-bordered{border:solid 10px #CCC;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}
body.fr-fullscreen{overflow:hidden;height:100%;width:100%;position:fixed} body.fr-fullscreen{overflow:hidden;height:100%;width:100%;position:fixed}
.fr-box.fr-fullscreen{margin:0 !important;position:fixed;top:0;left:0;bottom:0;right:0;z-index:9990 !important;width:auto !important} .fr-box.fr-fullscreen{margin:0 !important;position:fixed;top:0;left:0;bottom:0;right:0;z-index:9990 !important;width:auto !important}
.fr-box.fr-fullscreen .fr-toolbar.fr-top{top:0 !important} .fr-box.fr-fullscreen .fr-toolbar.fr-top{top:0 !important}
@ -363,6 +309,48 @@ to{left:100%}
.fr-drag-helper{background:#1e88e5;height:2px;margin-top:-1px;filter:alpha(opacity=20);-webkit-opacity:0.2;-moz-opacity:0.2;opacity:0.2;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";position:absolute;z-index:9999;display:none} .fr-drag-helper{background:#1e88e5;height:2px;margin-top:-1px;filter:alpha(opacity=20);-webkit-opacity:0.2;-moz-opacity:0.2;opacity:0.2;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";position:absolute;z-index:9999;display:none}
.fr-drag-helper.fr-visible{display:block} .fr-drag-helper.fr-visible{display:block}
.fr-dragging{filter:alpha(opacity=40);-webkit-opacity:0.4;-moz-opacity:0.4;opacity:0.4;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"} .fr-dragging{filter:alpha(opacity=40);-webkit-opacity:0.4;-moz-opacity:0.4;opacity:0.4;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"}
.fr-view strong{font-weight:700}
.fr-view table{border:none;border-collapse:collapse;empty-cells:show;max-width:100%}
.fr-view table td,.fr-view table th{border:1px solid #dddddd}
.fr-view table td:empty,.fr-view table th:empty{height:20px}
.fr-view table th{background:#e6e6e6}
.fr-view hr{clear:both;user-select:none;-o-user-select:none;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none;page-break-after:always}
.fr-view .fr-file{position:relative}
.fr-view .fr-file::after{position:relative;content:"\1F4CE";font-weight:normal}
.fr-view pre{white-space:pre-wrap;word-wrap:break-word}
.fr-view blockquote{border-left:solid 2px #5e35b1;margin-left:0;padding-left:5px;color:#5e35b1}
.fr-view blockquote blockquote{border-color:#00bcd4;color:#00bcd4}
.fr-view blockquote blockquote blockquote{border-color:#43a047;color:#43a047}
.fr-view span.fr-emoticon{font-weight:normal;font-family:"Apple Color Emoji","Segoe UI Emoji","NotoColorEmoji","Segoe UI Symbol","Android Emoji","EmojiSymbols";display:inline;line-height:0}
.fr-view span.fr-emoticon.fr-emoticon-img{background-repeat:no-repeat !important;font-size:inherit;height:1em;width:1em;min-height:20px;min-width:20px;display:inline-block;margin:-0.1em 0.1em 0.1em;line-height:1;vertical-align:middle}
.fr-view img{position:relative;max-width:100%}
.fr-view img.fr-dib{margin:5px auto;display:block;float:none;vertical-align:top}
.fr-view img.fr-dib.fr-fil{margin-left:0}
.fr-view img.fr-dib.fr-fir{margin-right:0}
.fr-view img.fr-dii{display:inline-block;float:none;vertical-align:bottom;margin-left:5px;margin-right:5px;max-width:calc(90%)}
.fr-view img.fr-dii.fr-fil{float:left;margin:5px 5px 5px 0;max-width:calc(95%)}
.fr-view img.fr-dii.fr-fir{float:right;margin:5px 0 5px 5px;max-width:calc(95%)}
.fr-view .fr-video{text-align:center;position:relative}
.fr-view .fr-video > *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;max-width:100%;border:none}
.fr-view .fr-video.fr-dvb{display:block;clear:both}
.fr-view .fr-video.fr-dvb.fr-fvl{text-align:left}
.fr-view .fr-video.fr-dvb.fr-fvr{text-align:right}
.fr-view .fr-video.fr-dvi{display:inline-block}
.fr-view .fr-video.fr-dvi.fr-fvl{float:left}
.fr-view .fr-video.fr-dvi.fr-fvr{float:right}
.fr-view{ }
.fr-view .oc-text-gray{color:#AAA !important}
.fr-view .oc-text-bordered{border-top:solid 1px #222;border-bottom:solid 1px #222;padding:10px 0}
.fr-view .oc-text-spaced{letter-spacing:1px}
.fr-view .oc-text-uppercase{text-transform:uppercase}
.fr-view a.oc-link-strong{font-weight:700}
.fr-view a.oc-link-green{color:green}
.fr-view table.oc-dashed-borders td,.fr-view table.oc-dashed-borders th{border-style:dashed}
.fr-view table.oc-alternate-rows tbody tr:nth-child(2n){background:#f5f5f5}
.fr-view table td.oc-cell-highlighted,.fr-view table th.oc-cell-highlighted{border:1px double red}
.fr-view table td.oc-cell-thick-border,.fr-view table th.oc-cell-thick-border{border-width:2px}
.fr-view img.oc-img-rounded{border-radius:100%;background-clip:padding-box}
.fr-view img.oc-img-bordered{border:solid 10px #CCC;box-sizing:content-box}
body .fr-box.fr-basic.fr-top .fr-wrapper,body .fr-box.fr-basic.fr-bottom .fr-wrapper{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none} body .fr-box.fr-basic.fr-top .fr-wrapper,body .fr-box.fr-basic.fr-bottom .fr-wrapper{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}
body .fr-box .ace_editor{display:none} body .fr-box .ace_editor{display:none}
body .fr-box .ace_editor{position:absolute;top:0;bottom:0;left:0;right:0;margin:0} body .fr-box .ace_editor{position:absolute;top:0;bottom:0;left:0;right:0;margin:0}

View File

@ -464,18 +464,25 @@ Base.call(this)
this.init()} this.init()}
RichEditor.prototype=Object.create(BaseProto) RichEditor.prototype=Object.create(BaseProto)
RichEditor.prototype.constructor=RichEditor RichEditor.prototype.constructor=RichEditor
RichEditor.DEFAULTS={linksHandler:null,stylesheet:null,fullpage:false,editorLang:'en',toolbarButtons:null} RichEditor.DEFAULTS={linksHandler:null,stylesheet:null,fullpage:false,editorLang:'en',toolbarButtons:null,allowEmptyTags:null,allowTags:null,noWrapTags:null,removeTags:null,imageStyles:null,linkStyles:null,paragraphStyles:null,tableStyles:null,tableCellStyles:null}
RichEditor.prototype.init=function(){var self=this;this.$el.one('dispose-control',this.proxy(this.dispose)) RichEditor.prototype.init=function(){var self=this;this.$el.one('dispose-control',this.proxy(this.dispose))
if(!this.$textarea.attr('id')){this.$textarea.attr('id','element-'+Math.random().toString(36).substring(7))} if(!this.$textarea.attr('id')){this.$textarea.attr('id','element-'+Math.random().toString(36).substring(7))}
this.initFroala()} this.initFroala()}
RichEditor.prototype.initFroala=function(){var froalaOptions={editorClass:'control-richeditor',language:this.options.editorLang} RichEditor.prototype.initFroala=function(){var froalaOptions={editorClass:'control-richeditor',language:this.options.editorLang,fullPage:this.options.fullpage}
if(this.options.toolbarButtons){froalaOptions.toolbarButtons=this.options.toolbarButtons.split(',')} if(this.options.toolbarButtons){froalaOptions.toolbarButtons=this.options.toolbarButtons.split(',')}
else{froalaOptions.toolbarButtons=['paragraphFormat','paragraphStyle','quote','bold','italic','align','formatOL','formatUL','insertTable','insertLink','insertImage','insertVideo','insertAudio','insertFile','insertHR','fullscreen','html']} else{froalaOptions.toolbarButtons=['paragraphFormat','paragraphStyle','quote','bold','italic','align','formatOL','formatUL','insertTable','insertLink','insertImage','insertVideo','insertAudio','insertFile','insertHR','fullscreen','html']}
froalaOptions.imageStyles=this.options.imageStyles?this.options.imageStyles:{'oc-img-rounded':'Rounded','oc-img-bordered':'Bordered'}
froalaOptions.linkStyles=this.options.linkStyles?this.options.linkStyles:{'oc-link-green':'Green','oc-link-strong':'Thick'}
froalaOptions.paragraphStyles=this.options.paragraphStyles?this.options.paragraphStyles:{'oc-text-gray':'Gray','oc-text-bordered':'Bordered','oc-text-spaced':'Spaced','oc-text-uppercase':'Uppercase'}
froalaOptions.tableStyles=this.options.tableStyles?this.options.tableStyles:{'oc-dashed-borders':'Dashed Borders','oc-alternate-rows':'Alternate Rows'}
froalaOptions.tableCellStyles=this.options.tableCellStyles?this.options.tableCellStyles:{'oc-cell-highlighted':'Highlighted','oc-cell-thick-border':'Thick'}
froalaOptions.toolbarButtonsMD=froalaOptions.toolbarButtons froalaOptions.toolbarButtonsMD=froalaOptions.toolbarButtons
froalaOptions.toolbarButtonsSM=froalaOptions.toolbarButtons froalaOptions.toolbarButtonsSM=froalaOptions.toolbarButtons
froalaOptions.toolbarButtonsXS=froalaOptions.toolbarButtons froalaOptions.toolbarButtonsXS=froalaOptions.toolbarButtons
froalaOptions.htmlAllowedEmptyTags=['figure','textarea','a','iframe','object','video','style','script'] if(this.options.htmlAllowedEmptyTags){froalaOptions.allowEmptyTags=this.options.htmlAllowedEmptyTags.split(/[\s,]+/)}
froalaOptions.htmlDoNotWrapTags=['figure','script','style'] if(this.options.allowTags){froalaOptions.htmlAllowedTags=this.options.allowTags.split(/[\s,]+/)}
froalaOptions.htmlDoNotWrapTags=this.options.noWrapTags?this.options.noWrapTags.split(/[\s,]+/):['figure','script','style']
if(this.options.removeTags){froalaOptions.htmlRemoveTags=this.options.removeTags.split(/[\s,]+/)}
froalaOptions.lineBreakerTags=['figure','table','hr','iframe','form','dl'] froalaOptions.lineBreakerTags=['figure','table','hr','iframe','form','dl']
froalaOptions.shortcutsEnabled=['show','bold','italic','underline','indent','outdent','undo','redo'] froalaOptions.shortcutsEnabled=['show','bold','italic','underline','indent','outdent','undo','redo']
froalaOptions.linkInsertButtons=['linkBack','|'] froalaOptions.linkInsertButtons=['linkBack','|']

View File

@ -39,7 +39,16 @@
stylesheet: null, stylesheet: null,
fullpage: false, fullpage: false,
editorLang: 'en', editorLang: 'en',
toolbarButtons: null toolbarButtons: null,
allowEmptyTags: null,
allowTags: null,
noWrapTags: null,
removeTags: null,
imageStyles: null,
linkStyles: null,
paragraphStyles: null,
tableStyles: null,
tableCellStyles: null
} }
RichEditor.prototype.init = function() { RichEditor.prototype.init = function() {
@ -63,7 +72,8 @@
RichEditor.prototype.initFroala = function() { RichEditor.prototype.initFroala = function() {
var froalaOptions = { var froalaOptions = {
editorClass: 'control-richeditor', editorClass: 'control-richeditor',
language: this.options.editorLang language: this.options.editorLang,
fullPage: this.options.fullpage
} }
if (this.options.toolbarButtons) { if (this.options.toolbarButtons) {
@ -91,11 +101,63 @@
] ]
} }
froalaOptions.imageStyles = this.options.imageStyles
? this.options.imageStyles
: {
'oc-img-rounded': 'Rounded',
'oc-img-bordered': 'Bordered'
}
froalaOptions.linkStyles = this.options.linkStyles
? this.options.linkStyles
: {
'oc-link-green': 'Green',
'oc-link-strong': 'Thick'
}
froalaOptions.paragraphStyles = this.options.paragraphStyles
? this.options.paragraphStyles
: {
'oc-text-gray': 'Gray',
'oc-text-bordered': 'Bordered',
'oc-text-spaced': 'Spaced',
'oc-text-uppercase': 'Uppercase'
}
froalaOptions.tableStyles = this.options.tableStyles
? this.options.tableStyles
: {
'oc-dashed-borders': 'Dashed Borders',
'oc-alternate-rows': 'Alternate Rows'
}
froalaOptions.tableCellStyles = this.options.tableCellStyles
? this.options.tableCellStyles
: {
'oc-cell-highlighted': 'Highlighted',
'oc-cell-thick-border': 'Thick'
}
froalaOptions.toolbarButtonsMD = froalaOptions.toolbarButtons froalaOptions.toolbarButtonsMD = froalaOptions.toolbarButtons
froalaOptions.toolbarButtonsSM = froalaOptions.toolbarButtons froalaOptions.toolbarButtonsSM = froalaOptions.toolbarButtons
froalaOptions.toolbarButtonsXS = froalaOptions.toolbarButtons froalaOptions.toolbarButtonsXS = froalaOptions.toolbarButtons
froalaOptions.htmlAllowedEmptyTags = ['figure', 'textarea', 'a', 'iframe', 'object', 'video', 'style', 'script']
froalaOptions.htmlDoNotWrapTags = ['figure', 'script', 'style'] if (this.options.htmlAllowedEmptyTags) {
froalaOptions.allowEmptyTags = this.options.htmlAllowedEmptyTags.split(/[\s,]+/)
}
if (this.options.allowTags) {
froalaOptions.htmlAllowedTags = this.options.allowTags.split(/[\s,]+/)
}
froalaOptions.htmlDoNotWrapTags = this.options.noWrapTags
? this.options.noWrapTags.split(/[\s,]+/)
: ['figure', 'script', 'style']
if (this.options.removeTags) {
froalaOptions.htmlRemoveTags = this.options.removeTags.split(/[\s,]+/)
}
froalaOptions.lineBreakerTags = ['figure', 'table', 'hr', 'iframe', 'form', 'dl'] froalaOptions.lineBreakerTags = ['figure', 'table', 'hr', 'iframe', 'form', 'dl']
froalaOptions.shortcutsEnabled = ['show', 'bold', 'italic', 'underline', 'indent', 'outdent', 'undo', 'redo'] froalaOptions.shortcutsEnabled = ['show', 'bold', 'italic', 'underline', 'indent', 'outdent', 'undo', 'redo']
froalaOptions.linkInsertButtons = ['linkBack', '|'] froalaOptions.linkInsertButtons = ['linkBack', '|']

View File

@ -0,0 +1,175 @@
// Vars
@image-margin: 5px;
@table-border: 1px solid #DDD;
@blockquote-level1-color: #5E35B1;
@blockquote-level2-color: #00BCD4;
@blockquote-level3-color: #43A047;
@editor-text: #000;
.image-style() {
img {
position: relative;
max-width: 100%;
&.fr-dib {
margin: @image-margin auto;
display: block;
float: none;
vertical-align: top;
&.fr-fil {
margin-left: 0;
}
&.fr-fir {
margin-right: 0;
}
}
&.fr-dii {
display: inline-block;
float: none;
vertical-align: bottom;
margin-left: @image-margin;
margin-right: @image-margin;
max-width: calc(100% - (2 * @image-margin));
&.fr-fil {
float: left;
margin: @image-margin @image-margin @image-margin 0;
max-width: calc(100% - @image-margin);
}
&.fr-fir {
float: right;
margin: @image-margin 0 @image-margin @image-margin;
max-width: calc(100% - @image-margin);
}
}
}
}
.video-style() {
.fr-video {
text-align: center;
position: relative;
> * {
.box-sizing(content-box);
max-width: 100%;
border: none;
}
&.fr-dvb {
display: block;
clear: both;
&.fr-fvl {
text-align: left;
}
&.fr-fvr {
text-align: right;
}
}
&.fr-dvi {
display: inline-block;
&.fr-fvl {
float: left;
}
&.fr-fvr {
float: right;
}
}
}
}
.fr-view {
strong {
font-weight: 700;
}
table {
border: none;
border-collapse: collapse;
empty-cells: show;
max-width: 100%;
td, th {
border: @table-border;
&:empty {
height: 20px;
}
}
th {
background: mix(white, @editor-text, 90%);;
}
}
hr {
clear: both;
.user-select(none);
page-break-after: always;
}
.fr-file {
position: relative;
&::after {
position: relative;
content: "\1F4CE";
font-weight: normal;
}
}
pre {
white-space: pre-wrap;
word-wrap: break-word;
}
blockquote {
border-left: solid 2px @blockquote-level1-color;
margin-left: 0;
padding-left: 5px;
color: @blockquote-level1-color;
blockquote {
border-color: @blockquote-level2-color;
color: @blockquote-level2-color;
blockquote {
border-color: @blockquote-level3-color;
color: @blockquote-level3-color;
}
}
}
span.fr-emoticon {
font-weight: normal;
font-family: "Apple Color Emoji","Segoe UI Emoji","NotoColorEmoji","Segoe UI Symbol","Android Emoji","EmojiSymbols";
display: inline;
line-height: 0;
&.fr-emoticon-img {
background-repeat: no-repeat !important;
font-size: inherit;
height: 1em;
width: 1em;
min-height: 20px;
min-width: 20px;
display: inline-block;
margin: -.1em .1em .1em;
line-height: 1;
vertical-align: middle;
}
}
.image-style();
.video-style();
}

View File

@ -11,7 +11,6 @@
@color-richeditor-toolbar-btn-color-hover: #ffffff; @color-richeditor-toolbar-btn-color-hover: #ffffff;
@import "../vendor/froala_drm/less/froala.less"; @import "../vendor/froala_drm/less/froala.less";
@import "../vendor/froala_drm/less/style.less";
// Buttons // Buttons
@import "../vendor/froala_drm/less/plugins/fullscreen.less"; @import "../vendor/froala_drm/less/plugins/fullscreen.less";
@ -27,6 +26,12 @@
@import "../vendor/froala_drm/less/plugins/line_breaker.less"; @import "../vendor/froala_drm/less/plugins/line_breaker.less";
@import "../vendor/froala_drm/less/plugins/draggable.less"; @import "../vendor/froala_drm/less/plugins/draggable.less";
// Base styles
@import "_base_styles.less";
.fr-view {
@import "../../../../models/editorsetting/default_styles.less";
}
// Modifications // Modifications
@import "_froala.less"; @import "_froala.less";

View File

@ -5,9 +5,18 @@
<div <div
id="<?= $this->getId() ?>" id="<?= $this->getId() ?>"
class="field-richeditor size-<?= $size ?> <?= $stretch?'layout-relative stretch':'' ?>" class="field-richeditor size-<?= $size ?> <?= $stretch?'layout-relative stretch':'' ?>"
<?php if ($editorLang): ?>data-editor-lang="<?= $editorLang ?>"<?php endif ?>
<?php if ($fullPage): ?>data-fullpage="true"<?php endif ?> <?php if ($fullPage): ?>data-fullpage="true"<?php endif ?>
<?php if ($editorLang): ?>data-editor-lang="<?= $editorLang ?>"<?php endif ?>
<?php if ($toolbarButtons): ?>data-toolbar-buttons="<?= implode(',', $toolbarButtons) ?>"<?php endif ?> <?php if ($toolbarButtons): ?>data-toolbar-buttons="<?= implode(',', $toolbarButtons) ?>"<?php endif ?>
<?php if ($allowEmptyTags): ?>data-allow-empty-tags="<?= e($allowEmptyTags) ?>"<?php endif ?>
<?php if ($allowTags): ?>data-allow-tags="<?= e($allowTags) ?>"<?php endif ?>
<?php if ($noWrapTags): ?>data-no-wrap-tags="<?= e($noWrapTags) ?>"<?php endif ?>
<?php if ($removeTags): ?>data-remove-tags="<?= e($removeTags) ?>"<?php endif ?>
<?php if ($imageStyles): ?>data-image-styles="<?= e(json_encode($imageStyles)) ?>"<?php endif ?>
<?php if ($linkStyles): ?>data-link-styles="<?= e(json_encode($linkStyles)) ?>"<?php endif ?>
<?php if ($paragraphStyles): ?>data-paragraph-styles="<?= e(json_encode($paragraphStyles)) ?>"<?php endif ?>
<?php if ($tableStyles): ?>data-table-styles="<?= e(json_encode($tableStyles)) ?>"<?php endif ?>
<?php if ($tableCellStyles): ?>data-table-cell-styles="<?= e(json_encode($tableCellStyles)) ?>"<?php endif ?>
data-links-handler="<?= $this->getEventHandler('onGetPageLinks') ?>" data-links-handler="<?= $this->getEventHandler('onGetPageLinks') ?>"
placeholder="<?= e(trans($field->placeholder)) ?>" placeholder="<?= e(trans($field->placeholder)) ?>"
data-control="richeditor"> data-control="richeditor">

View File

@ -1,8 +1,14 @@
<?php <?php
use Backend\Models\BrandSettings; use Backend\Models\BrandSettings;
use Backend\Models\EditorSetting;
?> ?>
<?php if (BrandSettings::isConfigured()): ?> <?php if (BrandSettings::isConfigured()): ?>
<style> <style>
<?= BrandSettings::renderCss() ?> <?= BrandSettings::renderCss() ?>
</style> </style>
<?php endif ?> <?php endif ?>
<?php if (EditorSetting::isConfigured()): ?>
<style>
<?= EditorSetting::renderCss() ?>
</style>
<?php endif ?>

View File

@ -1,7 +1,9 @@
<?php namespace Backend\Models; <?php namespace Backend\Models;
use File; use File;
use Cache;
use Model; use Model;
use Less_Parser;
use Exception; use Exception;
/** /**
@ -21,33 +23,43 @@ class EditorSetting extends Model
public $settingsFields = 'fields.yaml'; public $settingsFields = 'fields.yaml';
protected $defaultParagraphStyles = [ const CACHE_KEY = 'backend::editor.custom_css';
protected $defaultHtmlAllowEmptyTags = 'textarea, a, iframe, object, video, style, script';
protected $defaultHtmlAllowTags = 'a, abbr, address, area, article, aside, audio, b, base, bdi, bdo, blockquote, br, button, canvas, caption, cite, code, col, colgroup, datalist, dd, del, details, dfn, dialog, div, dl, dt, em, embed, fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, hr, i, iframe, img, input, ins, kbd, keygen, label, legend, li, link, main, map, mark, menu, menuitem, meter, nav, noscript, object, ol, optgroup, option, output, p, param, pre, progress, queue, rp, rt, ruby, s, samp, script, style, section, select, small, source, span, strike, strong, sub, summary, sup, table, tbody, td, textarea, tfoot, th, thead, time, title, tr, track, u, ul, var, video, wbr';
protected $defaultHtmlNoWrapTags = 'figure, script, style';
protected $defaultHtmlRemoveTags = 'script, style';
protected $defaultHtmlStyleImage = [
'oc-img-rounded' => 'Rounded',
'oc-img-bordered' => 'Bordered',
];
protected $defaultHtmlStyleLink = [
'oc-link-green' => 'Green',
'oc-link-strong' => 'Strong',
];
protected $defaultHtmlStyleParagraph = [
'oc-text-bordered' => 'Bordered', 'oc-text-bordered' => 'Bordered',
'oc-text-gray' => 'Gray', 'oc-text-gray' => 'Gray',
'oc-text-spaced' => 'Spaced', 'oc-text-spaced' => 'Spaced',
'oc-text-uppercase' => 'Uppercase', 'oc-text-uppercase' => 'Uppercase',
]; ];
protected $defaultTableStyles = [ protected $defaultHtmlStyleTable = [
'oc-table-dashed-borders' => 'Dashed Borders', 'oc-table-dashed-borders' => 'Dashed Borders',
'oc-table-alternate-rows' => 'Alternate Rows', 'oc-table-alternate-rows' => 'Alternate Rows',
]; ];
protected $defaultTableCellStyles = [ protected $defaultHtmlStyleTableCell = [
'oc-cell-highlighted' => 'Highlighted', 'oc-cell-highlighted' => 'Highlighted',
'oc-cell-thick-border' => 'Thick Border', 'oc-cell-thick-border' => 'Thick Border',
]; ];
protected $defaultImageStyles = [
'oc-img-rounded' => 'Rounded',
'oc-img-bordered' => 'Bordered',
];
protected $defaultLinkStyles = [
'oc-link-green' => 'Green',
'oc-link-strong' => 'Strong',
];
/** /**
* Validation rules * Validation rules
*/ */
@ -55,24 +67,104 @@ class EditorSetting extends Model
public function initSettingsData() public function initSettingsData()
{ {
$this->html_allow_empty_tags = 'figure, textarea, a, iframe, object, video, style, script'; $this->html_allow_empty_tags = $this->defaultHtmlAllowEmptyTags;
$this->html_allow_tags = 'a, abbr, address, area, article, aside, audio, b, base, bdi, bdo, blockquote, br, button, canvas, caption, cite, code, col, colgroup, datalist, dd, del, details, dfn, dialog, div, dl, dt, em, embed, fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, hr, i, iframe, img, input, ins, kbd, keygen, label, legend, li, link, main, map, mark, menu, menuitem, meter, nav, noscript, object, ol, optgroup, option, output, p, param, pre, progress, queue, rp, rt, ruby, s, samp, script, style, section, select, small, source, span, strike, strong, sub, summary, sup, table, tbody, td, textarea, tfoot, th, thead, time, title, tr, track, u, ul, var, video, wbr'; $this->html_allow_tags = $this->defaultHtmlAllowTags;
$this->html_no_wrap_tags = 'figure, script, style'; $this->html_no_wrap_tags = $this->defaultHtmlNoWrapTags;
$this->html_remove_tags = 'script,style'; $this->html_remove_tags = $this->defaultHtmlRemoveTags;
$this->html_custom_styles = File::get(base_path().'/modules/backend/models/editorsetting/default_styles.less'); $this->html_custom_styles = File::get(base_path().'/modules/backend/models/editorsetting/default_styles.less');
$this->html_style_paragraph = $this->makeStylesForTable($this->defaultParagraphStyles); $this->html_style_image = $this->makeStylesForTable($this->defaultHtmlStyleImage);
$this->html_style_table = $this->makeStylesForTable($this->defaultTableStyles); $this->html_style_link = $this->makeStylesForTable($this->defaultHtmlStyleLink);
$this->html_style_table_cell = $this->makeStylesForTable($this->defaultTableCellStyles); $this->html_style_paragraph = $this->makeStylesForTable($this->defaultHtmlStyleParagraph);
$this->html_style_image = $this->makeStylesForTable($this->defaultImageStyles); $this->html_style_table = $this->makeStylesForTable($this->defaultHtmlStyleTable);
$this->html_style_link = $this->makeStylesForTable($this->defaultLinkStyles); $this->html_style_table_cell = $this->makeStylesForTable($this->defaultHtmlStyleTableCell);
}
public function afterSave()
{
Cache::forget(self::CACHE_KEY);
} }
protected function makeStylesForTable($arr) protected function makeStylesForTable($arr)
{ {
$count = 0; $count = 0;
return array_build($arr, function($key, $value) use (&$count) { return array_build($arr, function($key, $value) use (&$count) {
return [$count++, ['class_label' => $value, 'class_name' => $key]]; return [$count++, ['class_label' => $value, 'class_name' => $key]];
}); });
} }
/**
* Same as getConfigured but uses special style structure.
* @return mixed
*/
public static function getConfiguredStyles($key, $default = null)
{
$instance = static::instance();
$value = $instance->get($key);
$defaultValue = $instance->getDefaultValue($key);
if (is_array($value)) {
$value = array_build($value, function($key, $value) {
return [array_get($value, 'class_name'), array_get($value, 'class_label')];
});
}
return $value != $defaultValue ? $value : $default;
}
/**
* Returns the value only if it differs from the default value.
* @return mixed
*/
public static function getConfigured($key, $default = null)
{
$instance = static::instance();
$value = $instance->get($key);
$defaultValue = $instance->getDefaultValue($key);
return $value != $defaultValue ? $value : $default;
}
public function getDefaultValue($attribute)
{
$property = 'default'.studly_case($attribute);
return $this->$property;
}
public static function renderCss()
{
if (Cache::has(self::CACHE_KEY)) {
return Cache::get(self::CACHE_KEY);
}
try {
$customCss = self::compileCss();
Cache::forever(self::CACHE_KEY, $customCss);
}
catch (Exception $ex) {
$customCss = '/* ' . $ex->getMessage() . ' */';
}
return $customCss;
}
public static function compileCss()
{
$parser = new Less_Parser(['compress' => true]);
$customStyles = '.fr-view {';
$customStyles .= self::get('html_custom_styles');
$customStyles .= '}';
$parser->parse($customStyles);
$css = $parser->getCss();
return $css;
}
} }