narou 2.5.2 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of narou might be problematic. Click here for more details.

Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/ChangeLog.md +54 -0
  4. data/LICENSE.txt +26 -0
  5. data/README.md +70 -84
  6. data/lib/command/alias.rb +7 -0
  7. data/lib/command/convert.rb +40 -61
  8. data/lib/command/download.rb +9 -1
  9. data/lib/command/mail.rb +24 -13
  10. data/lib/command/send.rb +18 -2
  11. data/lib/command/setting.rb +152 -34
  12. data/lib/command/tag.rb +5 -0
  13. data/lib/command/update.rb +137 -4
  14. data/lib/converterbase.rb +12 -6
  15. data/lib/database.rb +1 -1
  16. data/lib/device/ibooks.rb +6 -5
  17. data/lib/downloader.rb +85 -83
  18. data/lib/helper.rb +3 -2
  19. data/lib/html.rb +3 -0
  20. data/lib/logger.rb +20 -12
  21. data/lib/narou.rb +16 -0
  22. data/lib/novelconverter.rb +209 -75
  23. data/lib/novelinfo.rb +1 -1
  24. data/lib/novelsetting.rb +53 -29
  25. data/lib/template.rb +4 -3
  26. data/lib/version.rb +1 -1
  27. data/lib/web/appserver.rb +46 -32
  28. data/lib/web/public/resources/common.ui.js +2 -4
  29. data/lib/web/public/resources/default-style.css +37 -0
  30. data/lib/web/public/resources/narou.library.js +48 -57
  31. data/lib/web/public/resources/narou.ui.js +71 -39
  32. data/lib/web/public/theme/Cerulean/bootstrap.min.css +11 -0
  33. data/lib/web/public/theme/Cerulean/style.css +49 -0
  34. data/lib/web/public/theme/Darkly/bootstrap.min.css +11 -0
  35. data/lib/web/public/theme/Darkly/style.css +53 -0
  36. data/lib/web/public/theme/Readable/bootstrap.min.css +11 -0
  37. data/lib/web/public/theme/Readable/style.css +53 -0
  38. data/lib/web/public/theme/Slate/bootstrap.min.css +11 -0
  39. data/lib/web/public/theme/Slate/style.css +40 -0
  40. data/lib/web/public/theme/Superhero/bootstrap.min.css +11 -0
  41. data/lib/web/public/theme/Superhero/style.css +40 -0
  42. data/lib/web/public/theme/United/bootstrap.min.css +11 -0
  43. data/lib/web/public/theme/United/style.css +47 -0
  44. data/lib/web/public/theme/fonts/glyphicons-halflings-regular.eot +0 -0
  45. data/lib/web/public/theme/fonts/glyphicons-halflings-regular.svg +288 -0
  46. data/lib/web/public/theme/fonts/glyphicons-halflings-regular.ttf +0 -0
  47. data/lib/web/public/theme/fonts/glyphicons-halflings-regular.woff +0 -0
  48. data/lib/web/public/theme/fonts/glyphicons-halflings-regular.woff2 +0 -0
  49. data/lib/web/settingmessages.rb +5 -0
  50. data/lib/web/views/index.haml +15 -19
  51. data/lib/web/views/layout.haml +6 -1
  52. data/lib/web/views/novels/setting.haml +76 -75
  53. data/lib/web/views/settings.haml +111 -107
  54. data/lib/web/views/style.scss +6 -21
  55. data/narou.gemspec +49 -6
  56. data/narou.rb +3 -1
  57. data/preset/ncode.syosetu.com/n7975cr/setting.ini +7 -0
  58. data/spec/README.txt +4 -0
  59. data/spec/data/convert_test/ruby/correct_test_ruby.txt +4 -4
  60. data/template/hotentry.txt.erb +28 -0
  61. data/template/ibunko_novel.txt.erb +4 -2
  62. data/template/novel.txt.erb +6 -3
  63. data/template/setting.ini.erb +18 -2
  64. metadata +73 -8
@@ -0,0 +1,37 @@
1
+
2
+ .navbar {
3
+ background-color: rgba(248,248,248,0.93);
4
+ }
5
+ @media (max-width:767px) {
6
+ .navbar.navbar-collapse {
7
+ background-color: rgba(248,248,248,0.93);
8
+ }
9
+ }
10
+
11
+ .navbar ul.dropdown-menu li.active a {
12
+ background-color: inherit !important;
13
+ color: inherit !important;
14
+ }
15
+ .navbar ul.dropdown-menu li.active a:hover {
16
+ background-color: #f5f5f5 !important;
17
+ color: inherit !important;
18
+ }
19
+ @media (max-width:767px) {
20
+ .navbar ul.dropdown-menu li.active a:hover {
21
+ background-color: inherit !important;
22
+ }
23
+ }
24
+
25
+ .queue-plus {
26
+ color: #d9534f;
27
+ font-weight: bold;
28
+ }
29
+
30
+ #queue-text.active {
31
+ color: #d9534f !important;
32
+ }
33
+
34
+ #queue-text.active #queue {
35
+ background-color: #d9534f !important;
36
+ }
37
+
@@ -20,7 +20,10 @@ var Narou = (function() {
20
20
  $.extend(Storage.prototype, {
21
21
  storage_name: "Narou.rb_WEB_UI_saved",
22
22
  initialize: function() {
23
- this.objects = storage_cache ? storage_cache : this.load();
23
+ if (!storage_cache) {
24
+ storage_cache = this.load();
25
+ }
26
+ this.objects = storage_cache;
24
27
  },
25
28
 
26
29
  load: function() {
@@ -210,7 +213,7 @@ var Narou = (function() {
210
213
  openConsoleDialog: function(callback) {
211
214
  if (typeof callback !== "function") return;
212
215
  var $console_dialog = $("#console-dialog");
213
- $console_dialog.one("show.bs.modal", callback);
216
+ $console_dialog.one("shown.bs.modal", callback);
214
217
  $(document).one("cancel.narou.remove", function() {
215
218
  $console_dialog.modal("hide");
216
219
  });
@@ -280,12 +283,6 @@ var Narou = (function() {
280
283
  self.action.remove(self.target_id);
281
284
  });
282
285
  });
283
- $("#context-menu-remove-with-file").on("click", function(e) {
284
- e.preventDefault();
285
- self.openConsoleDialog(function() {
286
- self.action.removeWithFile(self.target_id);
287
- });
288
- });
289
286
  $("#context-menu-edit-tag").on("click", function(e) {
290
287
  e.preventDefault();
291
288
  self.tag.openEditor(self.target_id);
@@ -354,10 +351,27 @@ var Narou = (function() {
354
351
  },
355
352
 
356
353
  download: function() {
357
- bootbox.prompt("ダウンロードする小説のURL、もしくはNコードを入力", function(target) {
358
- if (!target) return;
359
- $.post("/api/download", { "target": target });
360
- console.log("new downloading %o", target);
354
+ var download_modal = bootbox.dialog({
355
+ title: "ダウンロードする小説のURL、もしくはNコードを入力(複数可)",
356
+ message: '<textarea id="download-input" class="form-control" rows="3"></textarea>',
357
+ backdrop: true,
358
+ buttons: {
359
+ cancel: {
360
+ label: "キャンセル",
361
+ className: "btn-default"
362
+ },
363
+ main: {
364
+ label: "OK",
365
+ className: "btn-primary",
366
+ callback: function() {
367
+ var targets = $("#download-input").val();
368
+ $.post("/api/download", { targets: targets });
369
+ }
370
+ }
371
+ }
372
+ });
373
+ download_modal.one("shown.bs.modal", function () {
374
+ $("#download-input").focus();
361
375
  });
362
376
  },
363
377
 
@@ -365,19 +379,11 @@ var Narou = (function() {
365
379
  var ids = this._getSelectedIds(arguments);
366
380
  if (ids.length === 0) return;
367
381
  $.post("/api/download_force", { "ids": ids });
368
- console.log("force downloading " + ids.join(", "));
369
382
  },
370
383
 
371
384
  update: function() {
372
385
  var ids = this._getSelectedIds(arguments);
373
- if (ids.length === 0) {
374
- $.post("/api/update");
375
- console.log("updating all");
376
- }
377
- else {
378
- $.post("/api/update_select", { "ids": ids });
379
- console.log("updating " + ids.join(", "));
380
- }
386
+ $.post("/api/update", { "ids": ids });
381
387
  },
382
388
 
383
389
  updateView: function() {
@@ -390,8 +396,7 @@ var Narou = (function() {
390
396
  }
391
397
  });
392
398
  if (ids.length > 0) {
393
- $.post("/api/update_select", { "ids": ids });
394
- console.log("updating " + ids.join(", "));
399
+ $.post("/api/update", { "ids": ids });
395
400
  }
396
401
  },
397
402
 
@@ -412,44 +417,38 @@ var Narou = (function() {
412
417
  className: "btn-primary",
413
418
  callback: function() {
414
419
  $.post("/api/update_general_lastup");
415
- console.log("updating general lastup");
416
420
  }
417
421
  },
418
422
  }
419
423
  });
420
424
  },
421
425
 
426
+ updateForce: function() {
427
+ var ids = this._getSelectedIds(arguments);
428
+ $.post("/api/update", { ids: ids, force: true });
429
+ },
430
+
422
431
  send: function() {
423
432
  var ids = this._getSelectedIds(arguments);
424
- if (ids.length === 0) {
425
- $.post("/api/send");
426
- console.log("sending all");
427
- }
428
- else {
429
- $.post("/api/send_select", { "ids": ids });
430
- console.log("sending " + ids.join(", "));
431
- }
433
+ $.post("/api/send", { "ids": ids });
432
434
  },
433
435
 
434
436
  freeze: function() {
435
437
  var ids = this._getSelectedIds(arguments);
436
438
  if (ids.length === 0) return;
437
439
  $.post("/api/freeze", { "ids": ids });
438
- console.log("freezing(toggle) " + ids.join(", "));
439
440
  },
440
441
 
441
442
  freezeOn: function() {
442
443
  var ids = this._getSelectedIds(arguments);
443
444
  if (ids.length === 0) return;
444
445
  $.post("/api/freeze_on", { "ids": ids });
445
- console.log("freezing " + ids.join(", "));
446
446
  },
447
447
 
448
448
  freezeOff: function() {
449
449
  var ids = this._getSelectedIds(arguments);
450
450
  if (ids.length === 0) return;
451
451
  $.post("/api/freeze_off", { "ids": ids });
452
- console.log("thawing " + ids.join(", "));
453
452
  },
454
453
 
455
454
  _removeConfirmDialog: function(title, ids, callback) {
@@ -459,7 +458,9 @@ var Narou = (function() {
459
458
  message += "<li>" + data.title + "</li>";
460
459
  }
461
460
  });
462
- message = '<div style="max-height:300px;overflow:auto"><ul>' + message + '</ul></div>';
461
+ message = '<div style="max-height:300px;overflow:auto"><ul>' + message + '</ul></div>' +
462
+ '<div class="checkbox pull-right"><label><input type="checkbox" id="check-remove-with-file">' +
463
+ '保存フォルダ・ファイルも一緒に削除する</label></div><div class="clearfix"></div>';
463
464
  bootbox.dialog({
464
465
  title: title,
465
466
  message: message,
@@ -468,7 +469,7 @@ var Narou = (function() {
468
469
  label: "削除する",
469
470
  className: "btn-danger",
470
471
  callback: function() {
471
- callback(true);
472
+ callback(true, $("#check-remove-with-file").prop("checked"));
472
473
  $(document).trigger("ok.narou.remove");
473
474
  }
474
475
  },
@@ -476,7 +477,7 @@ var Narou = (function() {
476
477
  label: "キャンセル",
477
478
  className: "btn-default",
478
479
  callback: function() {
479
- callback(false);
480
+ callback(false, false);
480
481
  $(document).trigger("cancel.narou.remove");
481
482
  }
482
483
  }
@@ -487,20 +488,9 @@ var Narou = (function() {
487
488
  remove: function() {
488
489
  var ids = this._getSelectedIds(arguments);
489
490
  if (ids.length === 0) return;
490
- this._removeConfirmDialog("選択した小説を削除しますか?", ids, function(result) {
491
- if (!result) return;
492
- $.post("/api/remove", { "ids": ids });
493
- console.log("removing " + ids.join(", "));
494
- });
495
- },
496
-
497
- removeWithFile: function() {
498
- var ids = this._getSelectedIds(arguments);
499
- if (ids.length === 0) return;
500
- this._removeConfirmDialog("選択した小説を“完全に”削除しますか?", ids, function(result) {
491
+ this._removeConfirmDialog("選択した小説を削除しますか?", ids, function(result, with_file) {
501
492
  if (!result) return;
502
- $.post("/api/remove_with_file", { "ids": ids });
503
- console.log("removing with file " + ids.join(", "));
493
+ $.post("/api/remove", { ids: ids, with_file: with_file });
504
494
  });
505
495
  },
506
496
 
@@ -508,35 +498,36 @@ var Narou = (function() {
508
498
  var ids = this._getSelectedIds(arguments);
509
499
  if (ids.length === 0) return;
510
500
  $.post("/api/convert", { "ids": ids });
511
- console.log("converting " + ids.join(", "));
512
501
  },
513
502
 
514
503
  diff: function() {
515
504
  var ids = this._getSelectedIds(arguments);
516
505
  if (ids.length === 0) return;
517
506
  $.post("/api/diff", { "ids": ids });
518
- console.log("diffing " + ids.join(", "));
519
507
  },
520
508
 
521
509
  inspect: function() {
522
510
  var ids = this._getSelectedIds(arguments);
523
511
  if (ids.length === 0) return;
524
512
  $.post("/api/inspect", { "ids": ids });
525
- console.log("inspecting " + ids.join(", "));
526
513
  },
527
514
 
528
515
  folder: function() {
529
516
  var ids = this._getSelectedIds(arguments);
530
517
  if (ids.length === 0) return;
531
518
  $.post("/api/folder", { "ids": ids });
532
- console.log("opening folder " + ids.join(", "));
533
519
  },
534
520
 
535
521
  backup: function() {
536
522
  var ids = this._getSelectedIds(arguments);
537
523
  if (ids.length === 0) return;
538
524
  $.post("/api/backup", { "ids": ids });
539
- console.log("backup " + ids.join(", "));
525
+ },
526
+
527
+ settingBurn: function() {
528
+ var ids = this._getSelectedIds(arguments);
529
+ if (ids.length === 0) return;
530
+ $.post("/api/setting_burn", { "ids": ids });
540
531
  },
541
532
  });
542
533
 
@@ -679,7 +670,7 @@ var Narou = (function() {
679
670
 
680
671
  position_is_bottom: function() {
681
672
  var con = this.console;
682
- return (con.scrollTop() === con.prop("scrollHeight") - con.outerHeight());
673
+ return (con.scrollTop() >= con.prop("scrollHeight") - con.outerHeight() - 10);
683
674
  },
684
675
 
685
676
  print: function(str) {
@@ -52,7 +52,6 @@ $(document).ready(function() {
52
52
  return tags.match(new RegExp('data-tag="' + tag_name + '"'));
53
53
  });
54
54
 
55
-
56
55
  var ANNOTATION_COLOR_TIME_LIMIT = 6 * 60 * 60; // 6時間(秒)
57
56
  var GENERAL_LASTUP_CLASSES = [
58
57
  [60 * 60, "gl-60minutes"],
@@ -287,11 +286,6 @@ $(document).ready(function() {
287
286
  },
288
287
  });
289
288
 
290
- $.fn.dataTableExt.afnFiltering.push(function(oSettings, aData, iDataIndex) {
291
- var row = table.row(iDataIndex);
292
- return !$(row.node()).hasClass("exclude");
293
- });
294
-
295
289
  var storage = new Narou.Storage();
296
290
  var action = new Narou.Action(table);
297
291
  var notification = Narou.Notification.instance();
@@ -299,17 +293,61 @@ $(document).ready(function() {
299
293
  var tag = new Narou.Tag(table);
300
294
  var context_menu = new Narou.ContextMenu(action, notification, tag);
301
295
 
296
+ /*
297
+ * 凍結の表示状態制御
298
+ */
299
+ var visibility_frozen_novel, visibility_nonfrozen_novel;
300
+
301
+ $.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
302
+ var state_frozen = table.row(dataIndex).data().frozen;
303
+ if (state_frozen) {
304
+ return visibility_frozen_novel;
305
+ }
306
+ else {
307
+ return visibility_nonfrozen_novel;
308
+ }
309
+ });
310
+
311
+ function restoreVisibilityForFrozen() {
312
+ visibility_frozen_novel = storage.get("visibility_frozen_novel");
313
+ visibility_nonfrozen_novel = storage.get("visibility_nonfrozen_novel");
314
+ if (typeof visibility_frozen_novel === "undefined")
315
+ visibility_frozen_novel = true;
316
+ if (typeof visibility_nonfrozen_novel === "undefined")
317
+ visibility_nonfrozen_novel = true;
318
+ // メニューのチェック状態も復元
319
+ var method = ["removeClass", "addClass"];
320
+ $("#action-view-frozen")[method[visibility_frozen_novel | 0]]("active");
321
+ $("#action-view-nonfrozen")[method[visibility_nonfrozen_novel | 0]]("active");
322
+ }
323
+
324
+ restoreVisibilityForFrozen();
325
+
326
+ function saveVisibilityFrozen() {
327
+ storage.set("visibility_frozen_novel", visibility_frozen_novel);
328
+ storage.set("visibility_nonfrozen_novel", visibility_nonfrozen_novel);
329
+ storage.save();
330
+ }
331
+
332
+ function toggleVisibilityFrozen() {
333
+ visibility_frozen_novel = visibility_frozen_novel ? false : true;
334
+ }
335
+
336
+ function toggleVisibilityNonFrozen() {
337
+ visibility_nonfrozen_novel = visibility_nonfrozen_novel ? false : true;
338
+ }
339
+
340
+ /*
341
+ * テーブルリロードイベント定義
342
+ */
302
343
  notification.on("table.reload", function() {
303
344
  // リロードする前に現在の状態を保存
304
- var selected_ids = [], excluded_ids = [];
345
+ var selected_ids = [];
305
346
  table.eachRow(function(row, data) {
306
347
  var $node = $(row.node());
307
348
  if ($node.hasClass("selected")) {
308
349
  selected_ids.push(data.id);
309
350
  }
310
- if ($node.hasClass("exclude")) {
311
- excluded_ids.push(data.id);
312
- }
313
351
  });
314
352
  table.ajax.reload(function() {
315
353
  // リロードしたら状態は解除されているので復元
@@ -321,9 +359,6 @@ $(document).ready(function() {
321
359
  if ($.inArray(data.id, selected_ids) !== -1) {
322
360
  $(row.node()).addClass("selected");
323
361
  }
324
- if ($.inArray(data.id, excluded_ids) !== -1) {
325
- $(row.node()).addClass("exclude");
326
- }
327
362
  });
328
363
  table.fireChangeSelect();
329
364
  table.draw(false);
@@ -680,18 +715,12 @@ $(document).ready(function() {
680
715
  * メニュー
681
716
  * 表示>凍結中以外を表示
682
717
  */
683
- var nonfrozen_rows = [];
684
- $("#action-view-without-frozen").on(click_event_name, function(e) {
718
+ $("#action-view-nonfrozen").on(click_event_name, function(e) {
685
719
  e.preventDefault();
686
720
  slideNavbar.slide();
687
721
  $(this).toggleClass("active");
688
- table.rows().eq(0).each(function(idx) {
689
- var row = table.row(idx);
690
- var data = row.data();
691
- if (!data.frozen) {
692
- $(row.node()).toggleClass("exclude");
693
- }
694
- });
722
+ toggleVisibilityNonFrozen();
723
+ saveVisibilityFrozen();
695
724
  table.draw();
696
725
  });
697
726
 
@@ -699,18 +728,12 @@ $(document).ready(function() {
699
728
  * メニュー
700
729
  * 表示>凍結中を表示
701
730
  */
702
- var frozen_list = [];
703
731
  $("#action-view-frozen").on(click_event_name, function(e) {
704
732
  e.preventDefault();
705
733
  slideNavbar.slide();
706
734
  $(this).toggleClass("active");
707
- table.rows().eq(0).each(function(idx) {
708
- var row = table.row(idx);
709
- var data = row.data();
710
- if (data.frozen) {
711
- $(row.node()).toggleClass("exclude");
712
- }
713
- });
735
+ toggleVisibilityFrozen();
736
+ saveVisibilityFrozen();
714
737
  table.draw();
715
738
  });
716
739
 
@@ -929,6 +952,15 @@ $(document).ready(function() {
929
952
  action.updateGeneralLastup();
930
953
  });
931
954
 
955
+ /*
956
+ * ボタン
957
+ * Update > 凍結済みも更新
958
+ */
959
+ $("#button-update-force").on("click", function(e) {
960
+ e.preventDefault();
961
+ action.updateForce();
962
+ });
963
+
932
964
  /*
933
965
  * ボタン
934
966
  * Send
@@ -966,15 +998,6 @@ $(document).ready(function() {
966
998
  action.remove();
967
999
  });
968
1000
 
969
- /*
970
- * ボタン
971
- * Remove > 選択した小説をファイルも含めて削除
972
- */
973
- $("#button-remove-with-file").on("click", function(e) {
974
- e.preventDefault();
975
- action.removeWithFile();
976
- });
977
-
978
1001
  /*
979
1002
  * ボタン
980
1003
  * Convert
@@ -1021,6 +1044,15 @@ $(document).ready(function() {
1021
1044
  action.backup();
1022
1045
  });
1023
1046
 
1047
+ /*
1048
+ * ボタン
1049
+ * Other > 選択した小説の設定の未設定項目に共通設定を焼付ける
1050
+ */
1051
+ $("#button-setting-burn").on("click", function(e) {
1052
+ e.preventDefault();
1053
+ action.settingBurn();
1054
+ });
1055
+
1024
1056
  /*
1025
1057
  * アイコン
1026
1058
  * ○件表示の横のリロードアイコン