По умолчанию ckeditor помещает все скрипты в документе в комментарий, и кодирует код скрипта через encodeURIComponent. Это политика безопасности. Чтобы скрипт не выполнялся при редактировании контента. В умелых руках это очень удобная фича. Заменяться могут не только скрипты, но и embed, iframe и object. К примеру текстовый парсер используется плагином flash для того, чтобы вставлять в документ flash объекты. При этом такой объект не инициализируется при редактировании, а место него видна лишь иконка. Такую замену осуществляет editor.dataProcessor. Вот как он это делает
afterInit: function( editor ) { var dataProcessor = editor.dataProcessor, dataFilter = dataProcessor && dataProcessor.dataFilter; if ( dataFilter ) { dataFilter.addRules({ elements: { 'p(span2)': function( element ) { return editor.createFakeParserElement( element, 'cke_p_span', 'p_span', true );; }, } }, 5 ); } }
createFakeParserElement создает "фейковый" (не настоящий) элемент, картинку и заменяет на него все теги <p> с классом span2. Так работает текстовый dataProcessor.
Цифра 5 тут не случайна. Это порядок в котором происходит замена. Вот тут и возникает проблема замены script. Дело в том, что их экранирует сама система ckeditor, т.е. они в этот круговорот dataProcessor.dataFilter не входят. Как же заменить <script> на свой фейковый элемент, или просто получить его значение.
Пришлось изрядно потрудиться, чтобы добраться до сути. Оказалось, что этим занимается плагин htmldataprocessor, а сама замена на комментарий и обратная замена происходит при вызове двух событий toHtml и toDataFormat соответственно. Эти события, в свою очередь, вызываются при смене режима редактирования. Когда мы редактируем в обычном режиме wysiwyg то вызывается событие toHtml, т.е. происходит замена всех скриптов на их за комментированные аналоги. Как только Вы нажимаете кнопку Источник, происходит вызов toDataFormat и все комментированные скрипты, чудесным образом, обратно превращаются в обычные.
dataFilter.addRules также влияет на замену, но он не может работать с script, потому, что его вызов происходит позже, когда скрипты уже за комментированы. Значит нужно добавить свои обработчики этих событий, но так чтобы их вызов был раньше чем в плагине htmldataprocessor
Вот тут нам и пригодится пятерка. В своем плагине пишем
editor.on( 'toDataFormat', function( evt ) { var sdl= unprotectSource(evt.data.dataValue); }, null, null, 16 ); editor.on( 'toHtml', function( evt ) { evt.data.dataValue = protectSource(evt.data.dataValue); }, null, null, 1 );
Где 16 и 1 это порядки вызова. Так обработчик toHtml надо вызывать раньше всех, чтобы работать с еще не измененными другими обработчиками данными. А toDataFormat надо вызывать последним, так как другие обработчики могли, что-то сделать с нашей заменой и необходимо, чтобы они все вернули на свои места. Осталось только написать код unprotectSource и protectSource
var protectSource = function( data, editor ) { return data.replace( /<script[^>]*>([^<]+)<\/script>/gi, function( match,script ) { return '<!--script-'+encodeURIComponent(script)+'-->' }) }; var unprotectSource = function( data, editor ) { return data.replace( /<!--script-([\S]+)-->/gi, function( match,script ) { return '<script>'+decodeURIComponent(script)+'</scritp>' }) };
вот и все. Далее можно производить, какие угодно манипуляции. К примеру в моем плагине, код для рисования Google Maps в документе заменялся на статичную картинку, с изображением результата работы этого самого кода. Не суть, как я это сделал, Google Maps API позволяет и не такое.
CKEDITOR отличный помощник в рерайте статей http://blog-craft.ru/rabota-kopirajting-rerajting/ свои статьи также писать весьма удобно.