По умолчанию 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/ свои статьи также писать весьма удобно.

Рассказать друзьям

Добавить комментарий


Защитный код
Обновить