TinyMCE でペースト時に不要なスタイルを削除する

TinyMCE | Content Filtering によると、TinyMCE を初期化する際に valid_styles または invalid_styles オプションを指定することで、不要なスタイルを削除できると書かれている。

tinymce.init({
	selector: 'textarea',  // change this value according to your HTML
	valid_styles: {
		'*': 'border,font-size',
		'div': 'width,height'
	}
});

しかしながらこの機能、エディタの初期化にしか効かないようで、Web ページや文書作成アプリケーションから貼り付けたときには不要なスタイルがついたままになってしまう。

これを解決するには TinyMCE の API を使用して

  1. ペーストイベントを補足
  2. コンテンツを走査
  3. それぞれの要素に対して不要なスタイルを除去

という手順が必要になる。

具体的には初期化時に setup オプションを指定し、エディタごとにこの処理を登録してやればよい。

tinymce.init({
	selector: 'textarea',  // change this value according to your HTML
	valid_styles: {
		'*': 'border,font-size',
		'div': 'width,height'
	},
	setup: function(editor) {
		editor.on("paste", function(e) {
			// ペースト後に実行
			setTimeout(function() {
				// Styles クラスの機能に不要スタイルの除去がある
				var Styles = new tinymce.html.Styles({}, editor.schema);

				// TreeWalker を使用してすべての要素に対して操作を行う
				var walker = new tinymce.dom.TreeWalker(editor.getBody());
				do {
					var el = walker.current();
					if (!el.getAttribute) {
						continue;
					}
					// 各要素の style 属性を Styles クラスで解析すると
					// valid_styles, invalid_styles が適用されるので、
					// それをふたたび style 属性に書き込む
					var styleString = el.getAttribute("style");
					if (!styleString) {
						continue;
					}
					var s = Styles.parse(styleString);
					el.setAttribute("style", Styles.serialize(s, el.nodeName));
				} while (walker.next());
			});
		});
	},
});