diff --git a/spec/converter-spec.js b/spec/converter-spec.js index 770cb1982..5c8cad47c 100644 --- a/spec/converter-spec.js +++ b/spec/converter-spec.js @@ -61,7 +61,7 @@ describe('Template converter', function() { }, { optionalName: 'simpleBlock', templateMode: 'show', - html: '
tags are rendered 0px height.
- getContentOptions: { format: 'raw' },
+ // We used to have a "getContentOptions" with a default value "{ format: 'raw' }" used to read the content from TinyMCE
+ // We used it to try to move to a more clean output (passing "{}" instead of raw), but this introduced issues with Firefox
+ // https://github.com/voidlabs/mosaico/issues/446
+ // We now don't use this option anymore: the options are decided internally depending on the mode (inline/single line vs block/multiline).
+ // getContentOptions: { format: 'raw' },
useTarget: false,
currentIndex: 0,
standardOptions: {},
@@ -244,14 +246,14 @@ ko.bindingHandlers.wysiwyg = {
toolbar1: 'bold italic forecolor backcolor hr styleselect removeformat | link unlink | pastetext code',
//toolbar1: "bold italic | forecolor backcolor | link unlink | hr | pastetext code", // | newsletter_profile newsletter_optlink newsletter_unsubscribe newsletter_showlink";
//toolbar2: "formatselect fontselect fontsizeselect | alignleft aligncenter alignright alignjustify | bullist numlist",
- plugins: ["link hr paste lists textcolor code"],
+ plugins: ["link", "hr", "paste", "lists", "textcolor", "code"],
// valid_elements: 'strong/b,em/i,*[*]',
// extended_valid_elements: 'strong/b,em/i,*[*]',
// Removed: image fullscreen contextmenu
// download custom:
// jquery version con legacyoutput, anchor, code, importcss, link, paste, textcolor, hr, lists
},
- init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+ init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// TODO ugly, but works...
ko.bindingHandlers.focusable.init(element);
@@ -284,7 +286,12 @@ ko.bindingHandlers.wysiwyg = {
if (!ko.isObservable(value)) throw "Wysiwyg binding called with non observable";
if (element.nodeType === 8) throw "Wysiwyg binding called on virtual node, ignoring...." + element.innerHTML;
- var fullEditor = element.tagName == 'DIV' || element.tagName == 'TD';
+ var fullEditor = true;
+
+ var editorStyle = allBindings['has']('wysiwygStyle') ? allBindings.get('wysiwygStyle') : false;
+ if (editorStyle == 'singleline') fullEditor = false;
+ else if (editorStyle === false) fullEditor = element.tagName == 'DIV' || element.tagName == 'TD';
+
var isSubscriberChange = false;
var thisEditor;
var isEditorChange = false;
@@ -296,18 +303,32 @@ ko.bindingHandlers.wysiwyg = {
plugins: ["paste"],
toolbar1: "bold italic",
toolbar2: "",
- // we have to disable preview_styles otherwise tinymce push inline every style he things will be applied and this makes the style menu to inherit color/font-family and more.
+ // we have to disable preview_styles otherwise tinymce push inline every style he thinks will be applied and
+ // this makes the style menu to inherit color/font-family and more.
preview_styles: false,
paste_as_text: true,
language: 'en',
schema: "html5",
- extended_valid_elements: 'strong/b,em/i,*[*]',
+
+ // 2022-05 remove *[*] from the extended_valid_elements to let tinymce do content filtering and, for example,
+ // protect from XSS.
+ // extended_valid_elements: 'strong/b,em/i,*[*]',
+ extended_valid_elements: 'strong/b,em/i',
menubar: false,
skin: 'gray-flat',
+
+ // 2022-05: we found that 'raw' format is mainly needed for "single line" (inline, not block multiline) editing
+ // NOTE: this is not a tinymce option!
+ // set "ko.bindingHandlers.wysiwyg.fullOptions._use_raw_format" to "true" to fallback to mosaico 0.17 behaviour
+ _use_raw_format: fullEditor ? false : true,
+
// 2018-03-07: the force_*_newlines are not effective. force_root_block is the property dealing with newlines, now.
// force_br_newlines: !fullEditor, // we force BR as newline when NOT in full editor
// force_p_newlines: fullEditor,
+ // 2022-05: tinymce 6 dropped support for forced_root_block false or empty. Using 'x' or another unknown tag is a
+ // workaround but then further handling is needed if you want the enter to create
newslines (like shift-enter).
forced_root_block: fullEditor ? 'p' : '',
+
init_instance_callback : function(editor) {
if (doDebug) console.debug("Editor for selector", selectorId, "is now initialized.");
if (ko.bindingHandlers.wysiwyg.initializingClass) {
@@ -351,7 +372,7 @@ ko.bindingHandlers.wysiwyg = {
// not emptied and full of tags used by tinymce as workaround.
// In future we'll probably change the default to "non raw", but at this time we keep this as an option
// in order to keep backward compatibility.
- value(editor.getContent(ko.bindingHandlers.wysiwyg.getContentOptions));
+ value(editor.getContent(editor.getParam('_use_raw_format') ? { format: 'raw' } : {}));
} catch (e) {
console.warn("Unexpected error setting content value for", selectorId, e);
} finally {
@@ -383,10 +404,14 @@ ko.bindingHandlers.wysiwyg = {
});
}
- // NOTE: this fixes issue with "leading spaces" in default content that were lost during initialization.
- editor.on('BeforeSetContent', function(args) {
- if (args.initial) args.format = 'raw';
- });
+ // 2022-05-04: use format raw only for inline contents (the ones with no force_root_block)
+ // for better compatibility with Tinymce 4.7+,5+
+ if (editor.getParam('_use_raw_format')) {
+ // NOTE: this fixes issue with "leading spaces" in default content that were lost during initialization.
+ editor.on('BeforeSetContent', function(args) {
+ if (args.initial) args.format = 'raw';
+ });
+ }
// 20180307: Newer TinyMCE versions (4.7.x for sure, maybe early versions too) stopped accepting ENTER on single paragraph elements
// We try to use the "force_br_newlines : true," in non full version (see options)
@@ -420,6 +445,13 @@ ko.bindingHandlers.wysiwyg = {
ko.utils.extend(options, ko.bindingHandlers.wysiwyg.standardOptions);
if (fullEditor) ko.utils.extend(options, ko.bindingHandlers.wysiwyg.fullOptions);
+ // this way you can have custom editing styles
+ // default ones are: singleline and multiline
+ // everyone already inherit "standardOptions" + every non "singleline" style inherit the "fullOptions"
+ if (ko.bindingHandlers.wysiwyg[editorStyle+'Options']) {
+ ko.utils.extend(options, ko.bindingHandlers.wysiwyg[editorStyle+'Options']);
+ }
+
// we have to put initialization in a settimeout, otherwise switching from "1" to "2" columns blocks
// will start the new editors before disposing the old ones and IDs get temporarily duplicated.
// using setTimeout the dispose/create order is correct on every browser tested.
@@ -442,7 +474,8 @@ ko.bindingHandlers.wysiwyg = {
// we failed setting contents in other ways...
// $(element).html(content);
if (typeof thisEditor !== 'undefined') {
- thisEditor.setContent(content, { format: 'raw' });
+ // 2022-05-04 changed so to use format raw only for single line editor
+ thisEditor.setContent(content, options._use_raw_format ? { format: 'raw' } : {});
} else {
ko.utils.setHtml(element, content);
}
diff --git a/src/js/converter/parser.js b/src/js/converter/parser.js
index 1fda1b82a..5b8b98a97 100644
--- a/src/js/converter/parser.js
+++ b/src/js/converter/parser.js
@@ -233,8 +233,29 @@ var processBlock = function(element, defs, themeUpdater, blockPusher, templateUr
newBinding += "wysiwygOrHtml: " + modelBindValue;
- if (domutils.getLowerTagName(element) == 'td') {
- var wrappingDiv = $('