【WYSIWYGエディタ】Summernoteでコピペした時プレーンテキストでコピーしたい

## はじめに
タイトルが長くなってしまいましたが、タイトルの通りなんですwww
前回、Summernoteのツールバーをカスタマイズしましたが、簡易な更新機能などを持たせたシステムのようなケースですと、WYSIWYG特有のコピペに対するスタイルの引継ぎ機能が余計な作業を発生させる原因になったりします。
プレーンなテキストでコピペしたいのにできないから、一旦メモ帳などにコピペして改めてエディタにコピペしたり、エディタにコピペした後クリーンボタンなどでプレーンテキストにしたりなど…
元からプレーンテキストでコピペされるのであればしなくていい作業が発生してしまいます。
（本格的なCMSの場合はあったほうが良い場合ももちろんあります）

今回はWordやブラウザからSummernoteのエディタ部分へコピペする際に、プレーンテキストでコピーされるようにカスタマイズしていこうと思います。

前回の記事の内容はこちら

https://qiita.com/chika_pon/items/27bc6b47ccf967ce573b

## 1. 基本のソース
前回ツールバーのカスタマイズまで完了したソースです。
```html:test.html
<!DOCTYPE html>
<html lang="ja">
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>Summernote Test</title>
 
	<!-- CSS -->
	<link rel="stylesheet" href="./js/snote/summernote-lite.min.css" type="text/css" />
	<!-- /CSS -->

	<!-- JavaScript -->
	<script src="./js/jquery-3.7.1.slim.min.js" type="text/javascript"></script>
	<script src="./js/snote/summernote-lite.min.js" type="text/javascript"></script>
	<script src="./js/snote/lang/summernote-ja-JP.min.js" type="text/javascript"></script>
	<!-- /JavaScript -->
<head>
<body>

	<lavel for="hoge">Summernote Test</label>
	<textarea id="hoge" value=""></textarea>

	<script type="text/javascript">
	$(function(){
		$('#hoge').summernote({
			lang: 'ja-JP',
			height: 400,
			toolbar: [
				['view', ['undo', 'redo']],
				['font', ['clear', 'hr']],
				['para', ['ul', 'ol']],
				['insert', ['link', 'picture']]
			]
		});
	});
	</script>

</body>
</html>
```

ここからカスタマイズしてみようと思います。
## 2. summernote-cleaner.js
今回はクリーナープラグインを利用していきます。
こういった便利なプラグインがわんさか転がっているのもオープンソースのいいところ。
まずはGitHubでクリーナープラグインをダウンロードしてきます。

https://github.com/DiemenDesign/summernote-cleaner

ダウンロードしたzipファイルの中からsummernote-cleaner.jsを適当な場所にポイっとします。
私の場合は以前投稿した「【WYSIWYGエディタ】Summernoteの使い方（日本語化）」の中で書いたファイル構成の中のsnoteディレクトリ中に入れました。
```
root
　├─ test.html ← Test表示用HTML
　└─ js
　    ├─ jquery-3.7.1.slim.min.js
　    └─ snote
          ├─ summernote-lite.min.js
          ├─ summernote-cleaner.js ← ここ！
          ├─ summernote-lite.min.css
          ├─ font
          │   ├─ summernote.ttf
          │   ├─ summernote.eot
          │   ├─ summernote.woff
          │   └─ summernote.woff2
          └─ lang
              └─ summernote-ja-JP.min.js
```
こんな感じ。

https://qiita.com/chika_pon/items/2f46411ba383fe345759

## 3. 実装の前にまずは中身を確認
私はこういったプラグインを実装する前には必ず中身を確認します。
理由は自分自身の勉強と、明らかに不自然な記述が無いかの確認のためです。
私のように素人に毛が生えた程度のスキルだと勉強が必要なんですw

ってことで、中身を見てみると…ふむふむ…専用のボタンもツールバーに表示できるみたいです。
私の場合は作業を減らしたいという目的なので必要ありませんが、ボタンも表示させたくなった時のために、ソースの13～22行目の部分に追記していきます。
念のため。
なので、summernote-cleaner.jsを開いて
```javascript
	$.extend(true, $.summernote.lang, {
		'en-US': {
			cleaner: {
				tooltip: 'Cleaner',
				not: 'Text has been cleaned!',
				limitText: 'Text',
				limitHTML: 'HTML'
			}
		}, // ← ここのカンマを忘れずに！
		'ja-JP': {
			cleaner: {
				tooltip: 'クリーナー',
				not: '文字がきれいになりました！',
				limitText: 'テキスト',
				limitHTML: 'HTML'
			}
		}
	});
```
こんな感じに追記すれば日本語化ができると思います。
これで万が一クリーナーボタンが必要になってもちゃんと日本語化されてくれます。
## 4. クリーナーのオプション設定を確認
まずは設定内容を紐解くためにプラグインのドキュメントを確認。

https://github.com/DiemenDesign/summernote-cleaner

ざっくり説明。

:::note info
__action__：どの行動をしたときに実行するか
* button　クリーナーボタンをクリックしたとき
* paste　コピペしたとき
* both　両方
:::

:::note info
__icon__：クリーナーボタンのアイコン
```javascript
'<i class="note-icon">好きなSVG</i>'
```
:::

:::note info
__keepHtml__：HTMLのマークアップを保持
* true　保持する
* false　保持しない（クリップボードから利用）
:::
↑↑↑コピペできなかった理由はこれか？

:::note info
__keepTagContents__：内容は保持して削除するタグ
:::

:::note info
__badTags__：内容を含んだ完全削除するタグ
:::

:::note info
__badAttributes__：属性を削除するタグ
:::

:::note info
__limitChars__：文字数の制限
* 0　最大入力を許可
* 数値　入力した数値で処理する文字数を制限
:::

:::note info
__limitDisplay__：下部に表示されるステータス領域の表示内容
* text　テキストの文字数のみ
* html　HTMLの文字数のみ
* Both　HTMLとテキストの両方
:::

:::note info
__limitStop__：limitCharsで設定された文字数に達した時どうするか
* true　入力を停止
* false　どうもしない
:::

:::note info
__limitType__：テキスト長さとHTML長さのどちらで制限をかけるか
* text　テキスト長さで制限
* html　HTML長さで制限
* Both　HTMLとテキストの両方
:::

:::note info
__notTimeOut__：ステータスメッセージが非表示になるまでの時間（ミリ秒）
:::

:::note info
__keepImages__：ペーストした画像を保持するか
* true　保持する
* false　imagePlaceholderで設定された画像に置き換え
:::

:::note info
__imagePlaceholder__：ペーストした画像を指定された画像に置き換え
:::

うん、要らないものがいっぱいあったなぁ…反省！
私の場合の要件をまとめると、
* テキストのみをコピぺさせるようにして、スタイル要素を省いた状態でペーストさせたい
* 画像のコピペはさせたくない
* 改行は残ってほしい

こうすることでお客様自身の作業が単純化されて、決まった形でのルーティンワークになりやすいと思います。（あくまでも私見です）
これこそが制限することで簡易な作業にしていく施策のように思います。
## 6. summernote-cleaner.jsの実装
オプション設定も確認できたのでまずはsummernote-cleaner.jsの読み込み。
head内のSummernoteのスクリプト読み込み部分の下に
```html
<script src="./js/snote/summernote-cleaner.js" type="text/javascript"></script>
```
を書き込んで、あとはSummernote実行部分に
```javascript
toolbar: [
	['cleaner',['cleaner']],
	//省略
],
cleaner: {
	action: 'paste',
	icon: '<i class="note-icon"><svg xmlns="http://www.w3.org/2000/svg" id="libre-paintbrush" viewBox="0 -3 14 14" width="14" height="14"><path d="m 11.821425,1 q 0.46875,0 0.82031,0.311384 0.35157,0.311384 0.35157,0.780134 0,0.421875 -0.30134,1.01116 -2.22322,4.212054 -3.11384,5.035715 -0.64956,0.609375 -1.45982,0.609375 -0.84375,0 -1.44978,-0.61942 -0.60603,-0.61942 -0.60603,-1.469866 0,-0.857143 0.61608,-1.419643 l 4.27232,-3.877232 Q 11.345985,1 11.821425,1 z m -6.08705,6.924107 q 0.26116,0.508928 0.71317,0.870536 0.45201,0.361607 1.00781,0.508928 l 0.007,0.475447 q 0.0268,1.426339 -0.86719,2.32366 Q 5.700895,13 4.261155,13 q -0.82366,0 -1.45982,-0.311384 -0.63616,-0.311384 -1.0212,-0.853795 -0.38505,-0.54241 -0.57924,-1.225446 -0.1942,-0.683036 -0.1942,-1.473214 0.0469,0.03348 0.27455,0.200893 0.22768,0.16741 0.41518,0.29799 0.1875,0.130581 0.39509,0.24442 0.20759,0.113839 0.30804,0.113839 0.27455,0 0.3683,-0.247767 0.16741,-0.441965 0.38505,-0.753349 0.21763,-0.311383 0.4654,-0.508928 0.24776,-0.197545 0.58928,-0.31808 0.34152,-0.120536 0.68974,-0.170759 0.34821,-0.05022 0.83705,-0.07031 z"/></svg></i>',
	keepHtml: false,
	limitChars: false,
	limitDisplay: 'both',
	limitStop: false,
	limitType: 'both',
	notTimeOut: 1000
}
```
を追記。
結構削ったソースになりました。
ちなみにアイコンのsvgがずれていたので、viewBox="0 0 14 14"をviewBox="0 -3 14 14"にプチ修正しています。

結果、ブラウザなどからコピペした時に、テキストのみが p タグに囲まれて、改行は再現された状態でペーストされるようになりました♪

後は見た目調整のためにCSSを追記します。
```css
/* 背景が白じゃなくてもSummernoteの背景が白くなるように */
.note-editing-area {
	background-color: #fff;
}

/* 下部に表示されるステータスエリアの高さと背景色の調整 */
.note-editor.note-frame .note-status-output {
	height: 15px;
	background-color: #f7f7f7;
}

/* ステータスエリアに表示されるテキストの調整 */
.note-editor.note-frame .note-status-output small {
	font-size: 80%;
	line-height: 1.3;
}
```
さらに私の場合ボタンは要らないのでボタンを非表示にして…
さて、これでいい感じになるはず。

ブラウザで早速確認！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762843/0779e865-20ff-7673-5b7f-81f3bee321c0.png)

うん、ステータスエリアも邪魔にならない感じになったし、コピペも改行ありのテキストのみになりました♪

## 7. HTMLまとめ
```html:test.html
<!DOCTYPE html>
<html lang="ja">
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>Summernote Test</title>
 
	<!-- CSS -->
	<link rel="stylesheet" href="./js/snote/summernote-lite.min.css" type="text/css" /><!-- Summernoteのcss -->
	<style type="text/css">
		/* 背景が白じゃなくてもSummernoteの背景が白くなるように */
		.note-editing-area {
			background-color: #fff;
		}

		/* 下部に表示されるステータスエリアの高さと背景色の調整 */
		.note-editor.note-frame .note-status-output {
			height: 15px;
			background-color: #f7f7f7;
		}

		/* ステータスエリアに表示されるテキストの調整 */
		.note-editor.note-frame .note-status-output small {
			font-size: 80%;
			line-height: 1.3;
		}
	</style>
	<!-- /CSS -->

	<!-- JavaScript -->
	<script src="./js/jquery-3.7.1.slim.min.js" type="text/javascript"></script><!-- JQuery -->
	<script src="./js/snote/summernote-lite.min.js" type="text/javascript"></script><!-- Summernoteの本体 -->
	<script src="./js/snote/lang/summernote-ja-JP.min.js" type="text/javascript"></script><!-- Summernoteの日本語化用 -->
	<script src="./js/snote/summernote-cleaner.js" type="text/javascript"></script><!-- クリーナープラグイン -->
	<!-- /JavaScript -->
<head>
<body>

	<lavel for="hoge">Summernote Test</label>
	<textarea id="hoge" value=""></textarea>

	<script type="text/javascript">
	$(function(){
		$('#hoge').summernote({
			lang: 'ja-JP',// 日本語化
			height: 400,// 初期表示の高さ
			toolbar: [
				//  ['cleaner',['cleaner']],とりあえず非表示
				['view', ['undo', 'redo']],
				['font', ['clear', 'hr']],
				['para', ['ul', 'ol']],
				['insert', ['link', 'picture']]
			],
			cleaner: {// クリーナー設定
				action: 'paste',// button | paste | both：クリーナー設定
				icon: '<i class="fa-solid fa-eraser"><svg xmlns="http://www.w3.org/2000/svg" id="libre-paintbrush" viewBox="0 -3 14 14" width="14" height="14"><path d="m 11.821425,1 q 0.46875,0 0.82031,0.311384 0.35157,0.311384 0.35157,0.780134 0,0.421875 -0.30134,1.01116 -2.22322,4.212054 -3.11384,5.035715 -0.64956,0.609375 -1.45982,0.609375 -0.84375,0 -1.44978,-0.61942 -0.60603,-0.61942 -0.60603,-1.469866 0,-0.857143 0.61608,-1.419643 l 4.27232,-3.877232 Q 11.345985,1 11.821425,1 z m -6.08705,6.924107 q 0.26116,0.508928 0.71317,0.870536 0.45201,0.361607 1.00781,0.508928 l 0.007,0.475447 q 0.0268,1.426339 -0.86719,2.32366 Q 5.700895,13 4.261155,13 q -0.82366,0 -1.45982,-0.311384 -0.63616,-0.311384 -1.0212,-0.853795 -0.38505,-0.54241 -0.57924,-1.225446 -0.1942,-0.683036 -0.1942,-1.473214 0.0469,0.03348 0.27455,0.200893 0.22768,0.16741 0.41518,0.29799 0.1875,0.130581 0.39509,0.24442 0.20759,0.113839 0.30804,0.113839 0.27455,0 0.3683,-0.247767 0.16741,-0.441965 0.38505,-0.753349 0.21763,-0.311383 0.4654,-0.508928 0.24776,-0.197545 0.58928,-0.31808 0.34152,-0.120536 0.68974,-0.170759 0.34821,-0.05022 0.83705,-0.07031 z"/></svg></i>',
				keepHtml: false,// true | false：HTMLのマークアップの保持設定
				limitChars: false,// 0 or false | #：文字数の制限
				limitDisplay: 'both',// text | html | both：ステータス領域の表示内容
				limitStop: false,// true | false：limitCharsで設定された文字数に達した時の設定
				limitType: 'both',// text | html | both：テキスト長さとHTML長さのどちらで制限をかけるか
				notTimeOut: 1000// ステータスメッセージが非表示になるまでの時間（ミリ秒）
			}
		});
	});
	</script>

</body>
</html>
```

## 最後に
さて、今回はコピペした時にプレーンテキストでコピーしたいというニッチな内容でしたが、これは人によって必要性が変わってくると思いますし、お客様や仕事の内容によっても必要有り無しが分かれると思います。
ただ単に私が必要だっただけという可能性もあるのですが、もし必要になる人が居れば参考にしてください。
次回はオリジナルボタンの作成方法についてメモっていこうと思います。

↓↓↓次の記事はこちら

https://qiita.com/chika_pon/items/0b083dcb9266d22fd851