tdiary 5.6.0 → 5.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c52912654a8c3f8dcbef538b3ca818e71a46adea1416c691d76792747cf3d9a8
4
- data.tar.gz: 2f578f65c5c636012a3971508916a1f463f37c4039d4bb8d9654c24720b6eb8f
3
+ metadata.gz: 0152dd908530b141b305017532d2fdbee7d61cacb8eeb955e7da169504b68604
4
+ data.tar.gz: 0ad54ddca02502bae29ba3d69cf7b972c6ecd5c4cec62800f21600f98d016a62
5
5
  SHA512:
6
- metadata.gz: 66fd5778cfbe863790cda5a64a3cd8812b28d6dd3434f08ce710fec49044986cb0677599d8f58055d05f4001734b2374ec7397b4ed04f7e0ea7b912b76d372ee
7
- data.tar.gz: a2ddcc2c75d34cc2cd2cbbb669395b900b5a930dc129312ee325a960652995d0af04d2511f0f039e332fe461ed3dbcf4efd148abdf29ba5b167a8a99598fa28f
6
+ metadata.gz: 8d1655ec19c3d0079bd353cbd83593d5ecacbe15d75087daf08d9ecc5b747e4fc5ec61297dbd3a5722dcadc89c6a85745f2a6e7497cf0ac390daf3cd9b4ca6dd
7
+ data.tar.gz: 8192a8f3fe135f261f3cb942addf64bf6aabc8b9300fe6102e71053105c87f6ff73457e7e98ca9d60a677289011399327552a6d433951e30fa8fc53256854519
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  GIT
2
2
  remote: https://github.com/tdiary/tdiary-contrib.git
3
- revision: 79c4f1909a8941a9f7feb856b8213af74a8e6cf3
3
+ revision: 1c265fc47175dbe7573b166fc865b5893036c771
4
4
  specs:
5
- tdiary-contrib (5.4.0)
5
+ tdiary-contrib (5.6.0)
6
6
  coderay
7
7
  holiday_japan
8
8
  pushbullet_ruby
@@ -69,10 +69,10 @@ GEM
69
69
  commonmarker (2.9.0-x86_64-linux-musl)
70
70
  concurrent-ruby (1.3.8)
71
71
  connection_pool (3.0.2)
72
- cuprite (0.17)
72
+ cuprite (0.18)
73
73
  capybara (~> 3.0)
74
- ferrum (~> 0.17.0)
75
- dalli (5.1.0)
74
+ ferrum (~> 0.18.0)
75
+ dalli (5.1.1)
76
76
  logger
77
77
  date (3.5.1)
78
78
  diff-lcs (1.6.2)
@@ -82,11 +82,10 @@ GEM
82
82
  faraday (0.17.6)
83
83
  multipart-post (>= 1.2, < 3)
84
84
  fastimage (2.4.1)
85
- ferrum (0.17.2)
85
+ ferrum (0.18.0)
86
86
  addressable (~> 2.5)
87
87
  base64 (~> 0.2)
88
88
  concurrent-ruby (~> 1.1)
89
- webrick (~> 1.7)
90
89
  websocket-driver (~> 0.7)
91
90
  hashie (5.1.0)
92
91
  logger
@@ -108,7 +107,7 @@ GEM
108
107
  net-imap
109
108
  net-pop
110
109
  net-smtp
111
- matrix (0.4.2)
110
+ matrix (0.4.3)
112
111
  memcachier (0.0.2)
113
112
  mime-types (3.7.0)
114
113
  logger
@@ -214,7 +213,7 @@ GEM
214
213
  rdtool (0.6.39)
215
214
  nkf (>= 0.1, < 1.0)
216
215
  redcarpet (3.6.1)
217
- regexp_parser (2.10.0)
216
+ regexp_parser (2.12.0)
218
217
  rexml (3.4.4)
219
218
  rspec (3.13.2)
220
219
  rspec-core (~> 3.13.0)
@@ -231,9 +230,9 @@ GEM
231
230
  rspec-support (3.13.6)
232
231
  ruby2_keywords (0.0.5)
233
232
  securerandom (0.4.1)
234
- sequel (5.107.0)
233
+ sequel (5.108.0)
235
234
  bigdecimal
236
- simplecov (1.1.1)
235
+ simplecov (1.3.1)
237
236
  snaky_hash (2.0.7)
238
237
  hashie (>= 0.1.0, < 6)
239
238
  version_gem (~> 1.1, >= 1.1.14)
@@ -249,7 +248,7 @@ GEM
249
248
  sqlite3 (2.9.6-x86_64-darwin)
250
249
  sqlite3 (2.9.6-x86_64-linux-gnu)
251
250
  sqlite3 (2.9.6-x86_64-linux-musl)
252
- tdiary (5.5.1)
251
+ tdiary (5.6.0)
253
252
  cgi
254
253
  emot
255
254
  fastimage
@@ -36,7 +36,7 @@ tDiaryテーマには、以下のような基本的な約束事があります
36
36
  テーマ・ギャラリー用の説明
37
37
  -------------
38
38
 
39
- tDiary.Netには、[テーマ・ギャラリー](http://www.tdiary.org/20021001.html)というページがあります。テーマ集に登録されたテーマはここでスクリーンショットともども一覧することができます。ここに表示されている作者名やコメントは、テーマ付属のREADME(1.4の時の名残でcssファイルも利用されている)に一定のフォーマットで書かれているものを自動的に抜き出しているものです。
39
+ テーマ集に登録されたテーマは、[テーマ・ギャラリー](https://github.com/tdiary/tdiary-theme)で一覧できます。テーマ集のテーマには、作者名やコメントを一定のフォーマットで書いたREADMEが付いています。
40
40
 
41
41
  最初からこのフォーマットで書いておくと、テーマ集に入った時に見栄えがします。以下にそのフォーマットについて解説します。
42
42
 
@@ -50,7 +50,7 @@ Comment: 四つ葉のクローバーの葉をあしらった、シンプルで
50
50
 
51
51
  この説明は、READMEの最初の行から記述します。「キー」と「値」を「: 」で挟んだ形式で、1項目1行で書きます。日本語を書くときは、文字コードをUTF-8にして下さい。英語の説明があれば、README.enというファイルにしてください。
52
52
 
53
- 各項目の意味は以下のとおりです。なお、現在ギャラリーで利用されている項目はTitle、Author、License、Commentだけです。
53
+ 各項目の意味は以下のとおりです。
54
54
 
55
55
  - Title: テーマのタイトルです。ファイル名だけでは味気ないと思ったら、この項目を書いてください。なくてもかまいません。
56
56
  - Author: 作者名
@@ -63,5 +63,5 @@ Comment: 四つ葉のクローバーの葉をあしらった、シンプルで
63
63
  テーマ・テストベンチ
64
64
  ----------
65
65
 
66
- テーマの見え方を確認するための、[テストベンチ](http://www.tdiary.org/theme.sample.html)というページがあります。ギャラリーのスクリーンショットと異なり、こちらでは様々なエレメントの見え方や、代表的なプラグインの表示を確認することができます。テーマ作成時に利用してください。
66
+ テーマの見え方を確認するための、[テストベンチ](https://tdiary.org/tdiary-theme/themebench.html)というページがあります。こちらでは様々なエレメントの見え方や、代表的なプラグインの表示を確認することができます。テーマ作成時に利用してください。
67
67
 
data/js/draft.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /*
2
2
  * draft.js: save draft data to Web Storage automatically
3
- *
3
+ * and keep a copy of them on the server
4
+ *
4
5
  * Copyright (c) MATSUOKA Kohei <http://www.machu.jp/>
5
6
  * Distributed under the GPL2 or any later version.
6
7
  */
@@ -8,70 +9,122 @@ $(function() {
8
9
 
9
10
  if (!localStorage) { return; }
10
11
 
11
- var Draft = function(storage, text) {
12
+ var Draft = function(storage, text, server) {
12
13
  // 保存先のストレージ
13
14
  this.storage = storage;
14
15
  // 下書きの保存件数
15
- this.maxCount = 10;
16
+ this.maxCount = server.max;
16
17
  // 下書き一覧
17
18
  this.items = [];
18
-
19
- this.initialize(text);
19
+ // このページで編集している下書きの ID
20
+ this.current = null;
21
+ // 最後に保存したテキストエリアの内容
22
+ this.text = text;
23
+ // サーバーにある下書きの ID と更新日時
24
+ this.synced = {};
25
+
26
+ this.initialize(text, server);
20
27
  };
21
28
 
22
29
  Draft.prototype = {
23
- // ローカルストレージから下書きを読み込む
24
- initialize: function(text) {
25
- this.items = this.storage.drafts ? JSON.parse(this.storage.drafts) : new Array();
26
- // 下書きに空の日記・テキストエリアと同じ日記が存在すれば削除する
27
- this.items = $.grep(this.items, function(item, index) {
28
- // 改行と空白文字を無視して比較(プレビュー時に末尾へ改行が付加されるため)
29
- if (item.value == "" || DraftUtils.trim(item.value) == DraftUtils.trim(text)) {
30
- return false;
30
+ // ローカルストレージの下書きにサーバーの下書きを統合する
31
+ initialize: function(text, server) {
32
+ var items = this.storage.drafts ? JSON.parse(this.storage.drafts) : new Array();
33
+ var synced = this.synced;
34
+ $.each(items, function(index, item) {
35
+ if (!item.id) { item.id = DraftUtils.newId(); }
36
+ });
37
+ $.each(server.drafts, function(index, remote) {
38
+ synced[remote.id] = remote.date;
39
+ var local = DraftUtils.find(items, remote.id);
40
+ if (!local) {
41
+ items.push(remote);
42
+ } else if (local.date < remote.date) {
43
+ local.date = remote.date;
44
+ local.value = remote.value;
31
45
  }
32
- return true;
33
46
  });
34
- this.save(text, true);
47
+ // 空の下書きと、日記として投稿済みの下書きを削除する
48
+ this.items = $.grep(items, function(item) {
49
+ return typeof item.value == "string" && DraftUtils.trim(item.value) != "" &&
50
+ $.inArray(item.id, server.deleted) < 0;
51
+ });
52
+ this.truncate();
53
+ // テキストエリアと同じ下書きがあれば、それを続けて編集する
54
+ // 改行と空白文字を無視して比較(プレビュー時に末尾へ改行が付加されるため)
55
+ var trimmed = DraftUtils.trim(text);
56
+ var same = $.grep(this.items, function(item) {
57
+ return DraftUtils.trim(item.value) == trimmed;
58
+ });
59
+ if (trimmed != "" && same.length > 0) {
60
+ this.current = same.pop().id;
61
+ }
62
+ this.store();
35
63
  // console.log("Draft.initialized");
36
64
  },
37
65
 
38
- // ローカルストレージに下書きを保存する
39
- // append が true の場合は、下書き一覧の末尾に追加する
40
- // append が false の場合は、最後の下書きに上書きする
41
- save: function(text, append) {
42
- if (!append) {
43
- this.items.pop();
44
- }
45
- this.items.push({
46
- date: new Date().getTime(),
47
- value: text
48
- });
49
- // 最大でmaxCount件数の履歴を保持
50
- if (this.items.length > this.maxCount) {
51
- this.items.shift();
66
+ // 編集している下書きを更新する
67
+ // テキストエリアの内容が変わっていなければ何もしない
68
+ save: function(text) {
69
+ if (text == this.text) { return; }
70
+ this.text = text;
71
+ if (DraftUtils.trim(text) == "") { return; }
72
+ var item = DraftUtils.find(this.items, this.current);
73
+ if (item) {
74
+ this.items.splice($.inArray(item, this.items), 1);
75
+ } else {
76
+ item = { id: DraftUtils.newId() };
77
+ this.current = item.id;
52
78
  }
53
- this.storage.drafts = JSON.stringify(this.items);
79
+ item.date = new Date().getTime();
80
+ item.value = text;
81
+ this.items.push(item);
82
+ this.truncate();
83
+ this.store();
54
84
  },
55
85
 
56
- // 下書き一覧から index 番目の下書きを取得する
57
- // 取得した下書きは一覧の末尾に移動する
58
- load: function(index) {
59
- var item = this.items.splice(index, 1)[0];
60
- this.items.push(item);
86
+ // 指定した下書きを読み込み、それを続けて編集する
87
+ load: function(id) {
88
+ var item = DraftUtils.find(this.items, id);
89
+ if (!item) { return null; }
90
+ this.current = item.id;
91
+ this.text = item.value;
61
92
  return item.value;
62
93
  },
63
94
 
64
- // 下書きのタイトル一覧の配列を返す(表示用)
95
+ // サーバーにまだ無い版の下書き一覧を返す
96
+ pending: function() {
97
+ var synced = this.synced;
98
+ return $.grep(this.items, function(item) {
99
+ return !(synced[item.id] >= item.date);
100
+ });
101
+ },
102
+
103
+ // サーバーへ保存した下書きを記録する
104
+ markSynced: function(items) {
105
+ var synced = this.synced;
106
+ $.each(items, function(index, item) {
107
+ synced[item.id] = item.date;
108
+ });
109
+ },
110
+
111
+ // 最大でmaxCount件数の履歴を保持
112
+ truncate: function() {
113
+ this.items.sort(function(a, b) { return a.date - b.date; });
114
+ this.items = this.items.slice(-this.maxCount);
115
+ },
116
+
117
+ store: function() {
118
+ this.storage.drafts = JSON.stringify(this.items);
119
+ },
120
+
121
+ // 下書きの ID とタイトルの一覧を返す(表示用)
65
122
  // タイトルは textarea の先頭1行目 + 更新日時
66
123
  titles: function() {
67
124
  return $.map(this.items, function(item) {
68
- var date = new Date(item.date);
69
- date = DraftUtils.dateToString(date);
70
- var title = "No-Name";
71
- if (item.value && typeof item.value == "string") {
72
- title = item.value.match(/.*/)[0];
73
- }
74
- return title + " (" + date + ")";
125
+ var date = DraftUtils.dateToString(new Date(item.date));
126
+ var title = item.value.match(/.*/)[0] || "No-Name";
127
+ return { id: item.id, title: title + " (" + date + ")" };
75
128
  });
76
129
  }
77
130
 
@@ -99,6 +152,13 @@ var DraftUtils = {
99
152
  // 文字列から改行と空白文字を取り除く
100
153
  trim: function(str) {
101
154
  return str.replace(/\s+/g, "");
155
+ },
156
+ // 下書きの ID を作る(サーバーが受け付けるのは英小文字と数字のみ)
157
+ newId: function() {
158
+ return new Date().getTime().toString(36) + Math.random().toString(36).slice(2, 10);
159
+ },
160
+ find: function(items, id) {
161
+ return $.grep(items, function(item) { return item.id == id; })[0];
102
162
  }
103
163
  };
104
164
 
@@ -108,12 +168,17 @@ var DraftUtils = {
108
168
 
109
169
  // 保存対象のテキストエリア
110
170
  var textarea = $("[name=body]");
171
+ // 日記の更新フォーム
172
+ var form = textarea.closest("form");
111
173
  // 下書き一覧を表示するセレクトボックス
112
174
  var select = $("[name=drafts]");
113
175
  // 自動保存の間隔(ミリ秒)
114
176
  var autoSaveInterval = 5 * 1000;
177
+ // サーバーへ保存する間隔(ミリ秒)
178
+ var syncInterval = $tDiary.plugin.draft.interval * 1000;
115
179
 
116
- var draft = new Draft(localStorage, textarea.val());
180
+ var draft = new Draft(localStorage, textarea.val(), $tDiary.plugin.draft.server);
181
+ var syncing = false;
117
182
 
118
183
  // 下書き保存
119
184
  saveDraft = function() {
@@ -122,26 +187,61 @@ saveDraft = function() {
122
187
  };
123
188
  // 下書き読み込み
124
189
  loadDraft = function() {
125
- textarea.val(draft.load(select.val()));
190
+ var value = draft.load(select.val());
191
+ if (value != null) {
192
+ textarea.val(value);
193
+ }
126
194
  showSelectForm(false);
127
195
  };
196
+ // サーバーに無い下書きをサーバーへ保存
197
+ syncDraft = function(keepalive) {
198
+ var items = $.map(draft.pending(), function(item) {
199
+ return { id: item.id, date: item.date, value: item.value };
200
+ });
201
+ if (syncing || items.length == 0) { return; }
202
+ var params = new URLSearchParams();
203
+ params.append("plugin", "draft");
204
+ params.append("plugin_draft_sync", JSON.stringify(items));
205
+ form.find("[name=csrf_protection_key]").each(function() {
206
+ params.append("csrf_protection_key", $(this).val());
207
+ });
208
+ syncing = true;
209
+ fetch(form.attr("action"), { method: "POST", body: params, keepalive: keepalive })
210
+ .then(function(response) {
211
+ if (response.ok) { draft.markSynced(items); }
212
+ }, function() {})
213
+ .then(function() { syncing = false; });
214
+ };
128
215
  // 下書き選択用のセレクトボックスを描画
129
- showSelectForm = function(keepIndex) {
130
- var index = select.val();
216
+ showSelectForm = function(keepSelection) {
217
+ var selected = select.val();
131
218
  select.empty();
132
- $.each(draft.titles(), function(i, title) {
133
- select.append($("<option/>").attr("value", i).text(title));
134
- select.val(i);
219
+ $.each(draft.titles(), function(i, item) {
220
+ select.append($("<option/>").attr("value", item.id).text(item.title));
135
221
  });
136
- if (keepIndex) {
137
- select.val(index);
222
+ if (!(keepSelection && selected)) {
223
+ selected = draft.current || select.children().last().val();
138
224
  }
225
+ select.val(selected);
139
226
  };
140
227
 
141
228
  // DOMイベント設定
142
229
  $("#draft_load").click(loadDraft);
143
230
  setInterval(saveDraft, autoSaveInterval);
231
+ setInterval(function() { syncDraft(false); }, syncInterval);
144
232
  textarea.change(saveDraft);
233
+ // タブを閉じる・切り替える前に保存する
234
+ $(document).on("visibilitychange", function() {
235
+ if (document.visibilityState == "hidden") {
236
+ saveDraft();
237
+ syncDraft(true);
238
+ }
239
+ });
240
+ // 日記として投稿する下書きをサーバーに知らせる
241
+ form.submit(function() {
242
+ saveDraft();
243
+ $("[name=plugin_draft_id]").val(draft.current || "");
244
+ });
145
245
 
146
246
  showSelectForm(false);
147
247
  // console.log("ready");
data/js/image.js CHANGED
@@ -18,20 +18,57 @@ $(function(){
18
18
  $(this).css('cursor', 'default');
19
19
  })
20
20
  .on('click', '.image-img', function(){
21
- var idx = this.id.replace('image-index-', '');
22
- var w = $('#image-info-' + idx + ' .image-width').text();
23
- var h = $('#image-info-' + idx + ' .image-height').text();
24
- $('#body').insertAtCaret($.makePluginTag('image', function(){
25
- return [idx, "'" + $tDiary.plugin.image.alt + "'", 'nil', '[' + w + ',' + h + ']']
26
- }));
21
+ $('#body').insertAtCaret(imageTag(this));
27
22
  });
28
-
23
+
24
+ var imageTag = function(img, context){
25
+ var idx = img.id.replace('image-index-', '');
26
+ var w = $('#image-info-' + idx + ' .image-width', context).text();
27
+ var h = $('#image-info-' + idx + ' .image-height', context).text();
28
+ return $.makePluginTag('image', function(){
29
+ return [idx, "'" + $tDiary.plugin.image.alt + "'", 'nil', '[' + w + ',' + h + ']']
30
+ });
31
+ };
32
+
33
+ var imageFiles = function(files){
34
+ return $.grep(files, function(file){
35
+ return /^image\//.test(file.type);
36
+ });
37
+ };
38
+
39
+ var shrink = function(file){
40
+ if(!window.createImageBitmap || file.type == 'image/gif'){
41
+ return Promise.resolve(file);
42
+ }
43
+ return createImageBitmap(file, {imageOrientation: 'from-image'}).then(function(bitmap){
44
+ var scale = Math.min(1, $tDiary.plugin.image.resize / Math.max(bitmap.width, bitmap.height));
45
+ var type = file.type == 'image/png' && scale == 1 ? 'image/png' : 'image/jpeg';
46
+ var canvas = document.createElement('canvas');
47
+ canvas.width = Math.max(1, Math.round(bitmap.width * scale));
48
+ canvas.height = Math.max(1, Math.round(bitmap.height * scale));
49
+ var context = canvas.getContext('2d');
50
+ if(type == 'image/jpeg'){
51
+ context.fillStyle = '#fff';
52
+ context.fillRect(0, 0, canvas.width, canvas.height);
53
+ }
54
+ context.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
55
+ bitmap.close();
56
+ return new Promise(function(resolve){
57
+ canvas.toBlob(function(blob){
58
+ resolve(blob || file);
59
+ }, type, 0.85);
60
+ });
61
+ }).catch(function(){
62
+ return file;
63
+ });
64
+ };
65
+
29
66
  var ImagePlugin = function(url){
30
67
  this.url =url;
31
68
  };
32
69
  ImagePlugin.prototype = {
33
- upload: function(formData, callback){
34
- $.ajax({
70
+ upload: function(formData){
71
+ return $.ajax({
35
72
  url: this.url,
36
73
  type: 'post',
37
74
  data: formData,
@@ -41,9 +78,6 @@ $(function(){
41
78
  $('#plugin-image-addimage input[type="submit"]').attr('disabled', 'disabled');
42
79
  $('#plugin-image-uploading').show();
43
80
  },
44
- success: function(data){
45
- callback(data);
46
- },
47
81
  complete: function(){
48
82
  $('#plugin-image-addimage input[type="submit"]').removeAttr('disabled');
49
83
  $('#plugin-image-uploading').hide();
@@ -74,40 +108,96 @@ $(function(){
74
108
  }
75
109
  e.preventDefault();
76
110
 
77
- uploadFiles(this.plugin_image_file.files);
111
+ uploadFiles($.makeArray(this.plugin_image_file.files));
78
112
  this.reset();
79
113
  return false;
80
114
  });
81
115
 
116
+ var replaceMarker = function(marker, text){
117
+ var body = $('#body').get(0);
118
+ var start = body.value.indexOf(marker);
119
+ if(start < 0){
120
+ if(text){
121
+ $('#body').insertAtCaret(text);
122
+ }
123
+ return;
124
+ }
125
+ var end = start + marker.length;
126
+ body.setRangeText(text, start, end, body.selectionStart == end ? 'end' : 'preserve');
127
+ };
128
+
129
+ var uploads = 0;
130
+ var uploading = Promise.resolve();
82
131
  var uploadFiles = function(files) {
83
- var formData = new FormData();
84
- formData.append('plugin', 'image');
85
- $.each($('#plugin-image-addimage input[type="hidden"]'), function(){
86
- formData.append($(this).attr('name'), $(this).val());
87
- });
88
- $.each(files, function(i, file){
89
- formData.append('plugin_image_file', file);
90
- });
132
+ if(!files.length){
133
+ return false;
134
+ }
135
+ var marker = '[Uploading image ' + (++uploads) + '...]';
136
+ $('#body').insertAtCaret(marker);
137
+ uploading = uploading.then(function(){
138
+ return files.reduce(function(shrunk, file){
139
+ return shrunk.then(function(images){
140
+ return shrink(file).then(function(image){
141
+ return images.concat([image]);
142
+ });
143
+ });
144
+ }, Promise.resolve([]));
145
+ }).then(function(images){
146
+ var formData = new FormData();
147
+ formData.append('plugin', 'image');
148
+ formData.append('plugin_image_addimage', 'true');
149
+ formData.append('date', $tDiary.plugin.image.date);
150
+ $('form.update [name=csrf_protection_key]').first().each(function(){
151
+ formData.append(this.name, this.value);
152
+ });
153
+ $.each(images, function(i, image){
154
+ formData.append('plugin_image_file', image, image.name || (image.type == 'image/png' ? 'image.png' : 'image.jpg'));
155
+ });
91
156
 
92
- var imagePlugin = new ImagePlugin($(this).attr('action'));
93
- imagePlugin.upload(formData, function(result){
157
+ var imagePlugin = new ImagePlugin($('form.update').attr('action'));
158
+ return imagePlugin.upload(formData);
159
+ }).then(function(result){
160
+ var list = $('#plugin-image-delimage', result).parents('div.form');
161
+ var tags = $.map(list.find('.image-img[data-added]'), function(img){
162
+ return imageTag(img, list);
163
+ });
164
+ if(!tags.length){
165
+ throw new Error('no image was saved');
166
+ }
94
167
  $('#plugin-image-delimage').parents('div.form').remove();
95
168
  $('<div>')
96
169
  .attr({
97
170
  'class': 'form'
98
171
  })
99
- .append($('#plugin-image-delimage', result).parents('div.form').html())
172
+ .append(list.html())
100
173
  .insertBefore('#plugin-image-addimage');
101
174
  var timestamp = new Date().getTime();
102
175
  $.each($('#plugin-image-delimage img'), function(){
103
176
  $(this).attr('src', $(this).attr('src') + '?' + timestamp);
104
177
  });
178
+ replaceMarker(marker, tags.join("\n"));
179
+ }).catch(function(error){
180
+ replaceMarker(marker, '');
181
+ console.error(error);
182
+ alert($tDiary.plugin.image.failed);
105
183
  });
106
184
  return false;
107
185
  };
108
186
 
109
- $('#plugin-image-delimage')
110
- .on('submit', function(e){
187
+ $('#body').on('paste', function(e){
188
+ var clipboard = e.originalEvent.clipboardData;
189
+ if(!clipboard || $.inArray('text/plain', clipboard.types) >= 0){
190
+ return;
191
+ }
192
+ var files = imageFiles(clipboard.files);
193
+ if(files.length){
194
+ e.preventDefault();
195
+ this.setRangeText('', this.selectionStart, this.selectionEnd, 'end');
196
+ uploadFiles(files);
197
+ }
198
+ });
199
+
200
+ $(document).on('submit', '#plugin-image-delimage', function(e){
111
201
  e.preventDefault();
112
202
 
113
203
  var ids = $.map($('#image-table input[name="plugin_image_id"]:checked'), function(i){
@@ -147,14 +237,23 @@ $(function(){
147
237
  $('#plugin_image_dnd').hide();
148
238
  $(this).css('border', 'dashed 3px #CCC');
149
239
  $('#plugin-image-addimage form').show();
150
- var files = e.originalEvent.dataTransfer.files;
151
- uploadFiles(files);
240
+ uploadFiles($.makeArray(e.originalEvent.dataTransfer.files));
152
241
  return false;
153
242
  })
154
243
  .text($tDiary.plugin.image.drop_here)
155
244
  .hide()
156
245
  .appendTo('#plugin-image-addimage');
157
246
 
247
+ $('#body').on('drop', function(e){
248
+ var files = imageFiles(e.originalEvent.dataTransfer.files);
249
+ if(files.length){
250
+ e.preventDefault();
251
+ $('#plugin_image_dnd').hide();
252
+ $('#plugin-image-addimage form').show();
253
+ uploadFiles(files);
254
+ }
255
+ });
256
+
158
257
  var dnd_timer = false;
159
258
  $('body')
160
259
  .on('dragenter', function() {
@@ -1,3 +1,3 @@
1
1
  module TDiary
2
- VERSION = "5.6.0"
2
+ VERSION = "5.6.1"
3
3
  end