Наводим порядок в редакторе TinyMCE 4

Простите, но я зае, намучался с этим встроенным TinyMCE 4.0.
Поэтому разрешите выложить решения проблем, которые мучали лично меня, возможно и кого-то ещё.

Какие были проблемы:
1) При вставке текста из другого сайта получалась каша, перенимались все стили, естественно. Плавали переходы строк, параграфы и т.д.
2) Было не понятно, когда добавляется новая строка (br), когда новый параграф (p).
Для начала, общие понятия.
Конфиг редактора лежит тут:
common/templates/frontend/libs/js/engine/settings.js
(Вопрос попутный к более опытным, почему почти такой же конфиг лежит тут:
common/templates/frontend/ls/js/settings.js и для чего он ?)

Получается, что все настройки редактора выстраиваются тут (если всё по умолчанию).
Тут же можно добавить новые кнопки, плагины и другие настройки.
Кнопки можно взять с оф.сайта https://www.tinymce.com/


Начнём с последнего вопроса, т.к. тупо легче и привычнее нажимать Enter и понимать, что у тебя вставляется новая строчка этого же параграфа.

Что делаем?
В настройках выставляем:
В блок « this.presets.tinymce['default'] = function(){ »
                
force_br_newlines: true,
forced_root_block: '', // Needed for 3.x
force_p_newlines: false,


Теперь порядок такой:
Enter, Enter+CTRL — новая строчка
Enter+Shift — Новый параграф

Вопрос первый, объёмнее.
Проблема:
При вставке текста из другого сайта получалась каша, перенимались все стили, естественно. Плавали переходы строк, параграфы и т.д. Убивалось куча времени на редактирование этого добра. Хотя должен быть простой копи-паст.

Решение:
В 2х словах: используем https://github.com/WEACOMRU/html-formatting для обработки входящего текста для TinyMCE на лету. Написано программерами для какого-то новостного портала. Решение не моё, но очень удобное.
Можно самостоятельно писать правила обработки входящего текста, который идёт с html тегами. Убирать все стили, оставлять что-то конкретное. Мануал написал неудачно, но штука работает.

Процесс:
1) Для начала зальём файл html-formatting.min.js (из репозитория) сюда
\common\templates\skin\experience\assets\js\experience\ (каждый заливает в свой шаблон)
2) Далее подключаем файл в шаблоне:
common/templates/skin/experience/settings/config/assets.php
Добавлем ниже всех js файлов:
$config['assets']['default']['js'][] = «___path.skin.dir___/assets/js/experience/html-formatting.min.js»;

3) Далее настройки параметров редактора.
Файл: common/templates/frontend/libs/js/engine/settings.js
В этот блок: this.presets.tinymce['default'] = function(){
Вставляем следующее:
а) В Параметр plugins добавляем «paste» (т.е. добавляем включение плагина paste в TinyMCE)
б) добавляем Параметр paste_auto_cleanup_on_paste : truе,
в) и обработчик paste_postprocess

Вот как по итогу выглядит новый код:
            
plugins: "paste advlist autolink autosave link lists media pagebreak autoresize table code altoimage snippets photoset username spoiler",
            paste_auto_cleanup_on_paste : true,

            paste_postprocess : function(pl, o) {
                // Content DOM node containing the DOM structure of the clipboard
                var headerRule = {
                    'br': {
                        process: function (node) {
                            var parent = node.parentNode,
                                space = document.createTextNode(' ');

                            parent.replaceChild(space, node);
                        }
                    }
                };

               var valid_elements = {
                    'h1': {
                        convert_to: 'h2',
                        valid_styles: '',
                        valid_classes: '',
                        no_empty: true,
                        valid_elements: headerRule
                    },
                    'h2,h3,h4': {
                        valid_styles: '',
                        valid_classes: '',
                        no_empty: true,
                        valid_elements: headerRule
                    },
                    'p': {
                        valid_styles: 'text-align',
                        valid_classes: '',
                        no_empty: true
                    },
                    a: {
                        valid_styles: '',
                        valid_classes: '',
                        no_empty: true,

                        process: function (node) {
                            var host = 'http://' + window.location.host + '/';
                            if (node.href.indexOf(host) !== 0) {
                                node.target = '_blank';
                            }
                        }
                    },
                    'br': {
                        valid_styles: '',
                        valid_classes: ''
                    },
                    'blockquote,b,strong,i,em,s,strike,sub,sup,kbd,ul,ol,li,dl,dt,dd,time,address,thead,tbody,tfoot': {
                        valid_styles: '',
                        valid_classes: '',
                        no_empty: true
                    },
                    'table,tr,th,td': {
                        valid_styles: 'text-align,vertical-align',
                        valid_classes: '',
                        no_empty: true
                    },
                    'embed,iframe': {
                        valid_classes: ''
                    }
                };

                htmlFormatting(o.node, valid_elements);
            },


Опустим описание правил. Это написано на гит-репозитории плагина.

Вот как по итогу выглядит у меня блок параметров
   this.presets.tinymce['default'] = function(){
        return {
            selector:           '.js-editor-wysiwyg',
            theme:              'modern',
            skin:              'custom',
            relative_urls:      false,
            menubar:            false,
            toolbar: "undo redo styleselect | bold italic strikethrough underline blockquote snippets | alignleft aligncenter alignright | bullist numlist table | link unlink | altoimage media | code pagebreak removeformat",
            toolbar_items_size: 'small',
            image_advtab: false,
            style_formats: [
                {title:  'H1', block: 'h1'},
                {title: 'H2', block: 'h2'},
                {title: 'H3', block: 'h3'},
                {title: ls.lang.get('panel_title_h4'), block: 'h4'},
                {title: ls.lang.get('panel_title_h5'), block: 'h5'},
                {title: ls.lang.get('panel_title_h6'), block: 'h6'}
            ],
            object_resizing:    true,
            forced_root_block:  '', // Needed for 3.x
            force_br_newlines: true,
            force_p_newlines: false,

            custom_elements : "alto:photoset",
            self_closing_elements: "alto:photoset",

            //convert_urls: false,
            extended_valid_elements: "embed[src|type|allowscriptaccess|allowfullscreen|width|height],alto:photoset[from|to|style|position|topic],alto:user[login|style],alto:spoiler[style|title]",
            pagebreak_separator: "<cut>",
            media_strict: false,
            language: TINYMCE_LANG ? TINYMCE_LANG : 'ru',
            inline_styles: false,
            plugins: "paste advlist autolink autosave link lists media pagebreak autoresize table code altoimage snippets photoset username spoiler",
            paste_auto_cleanup_on_paste : true,

            paste_postprocess : function(pl, o) {
                // Content DOM node containing the DOM structure of the clipboard
                var headerRule = {
                    'br': {
                        process: function (node) {
                            var parent = node.parentNode,
                                space = document.createTextNode(' ');

                            parent.replaceChild(space, node);
                        }
                    }
                };

               var valid_elements = {
                    'h1': {
                        convert_to: 'h2',
                        valid_styles: '',
                        valid_classes: '',
                        no_empty: true,
                        valid_elements: headerRule
                    },
                    'h2,h3,h4': {
                        valid_styles: '',
                        valid_classes: '',
                        no_empty: true,
                        valid_elements: headerRule
                    },
                    'p': {
                        valid_styles: 'text-align',
                        valid_classes: '',
                        no_empty: true
                    },
                    a: {
                        valid_styles: '',
                        valid_classes: '',
                        no_empty: true,

                        process: function (node) {
                            var host = 'http://' + window.location.host + '/';
                            if (node.href.indexOf(host) !== 0) {
                                node.target = '_blank';
                            }
                        }
                    },
                    'br': {
                        valid_styles: '',
                        valid_classes: ''
                    },
                    'blockquote,b,strong,i,em,s,strike,sub,sup,kbd,ul,ol,li,dl,dt,dd,time,address,thead,tbody,tfoot': {
                        valid_styles: '',
                        valid_classes: '',
                        no_empty: true
                    },
                    'table,tr,th,td': {
                        valid_styles: 'text-align,vertical-align',
                        valid_classes: '',
                        no_empty: true
                    },
                    'embed,iframe': {
                        valid_classes: ''
                    }
                };

                htmlFormatting(o.node, valid_elements);
            },


            setup: function (editor) {
                editor.on('change', function() {
                    tinyMCE.triggerSave();
                });

            },
            formats: {
                underline:      {inline: 'u', exact: true},
                strikethrough:  {inline: 's', exact: true}
            },

        }
    };


Далее чистим кэш (http:// site.ru /admin/tools-reset/) и проверяем. Это сделано для редактора Топиков. То же самое можно сделать и для редактора комментов.

Похожие статьи

  • Как задать высоту в редакторе?
    Привет всем! Подскажите, пожалуйста. Немного смущает тот факт, что редактор tinymce при написании текста уезжает вниз, то есть нет никаких полос прокрутки и при необходимости вставить изображения чтобы дотянуться до ...
  • Встраивание карт в заметки (топики).
    Введение. Кратко, без лишних слов, чтобы не забыть в будущем. Сервис карт можно использовать в принципе любой, но мне больше по душе основанный на Leaflet MapBBCode. По умолчанию в Альто (как и в Livestreet) в...
  • Проблемы с редактором Tinymce
    — При создании топиков в Tinymce, на версии 1.1.29, не работает выравнивание текста после сохранения. — Если задать цвет текста, после сохранения, цвет не задается. <p style="color: #cc0000; text-align:...
  • Размер загружаемой картинки через редактор
    Всех приветствую! Когда загружаешь картинку в редакторе, то в ссылку автоматически добавляется параметр width="100%" <img src="http://moysait....

1 комментарий

0
почему почти такой же конфиг лежит тут
Для обратной совместимости с ЛС-шаблонами и плагинами. Но недолго ему осталось там лежать :)

тупо легче и привычнее нажимать Enter и понимать, что у тебя вставляется новая строчка этого же параграфа
Тут у разных людей мнения расходятся. Кто-то, как ты, считает, что должен быть перевод строки. Кто-то категорично утверждает, что однозначно должен быть новый параграф. Было и такое мнение: одиночный перевод строки — это <br>, а две пустых строки подряд — параграф.

Идеально было бы, конечно, это все во внешние настройки вынести.

При вставке текста из другого сайта получалась каша...
Идеально, конечно, было бы так: при вставке текста делать аякс-запрос и прогонять через штатный типограф движка. Но и этот вариант вполне рабочий, думаю, многим сгодится.

Спасибо, что поделился!
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.