narou 3.2.5.1 → 3.3.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 (131) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -5
  3. data/.haml-lint.yml +7 -0
  4. data/.rubocop.yml +23 -5
  5. data/.scss-lint.yml +9 -0
  6. data/ChangeLog.md +86 -0
  7. data/Gemfile.lock +35 -35
  8. data/README.md +80 -64
  9. data/lib/backtracer.rb +2 -2
  10. data/lib/color.rb +5 -1
  11. data/lib/command.rb +7 -2
  12. data/lib/command/alias.rb +3 -5
  13. data/lib/command/backup.rb +3 -5
  14. data/lib/command/browser.rb +3 -5
  15. data/lib/command/clean.rb +5 -1
  16. data/lib/command/console.rb +33 -0
  17. data/lib/command/convert.rb +143 -117
  18. data/lib/command/csv.rb +2 -1
  19. data/lib/command/diff.rb +20 -18
  20. data/lib/command/download.rb +25 -14
  21. data/lib/command/folder.rb +3 -5
  22. data/lib/command/freeze.rb +3 -5
  23. data/lib/command/help.rb +20 -18
  24. data/lib/command/init.rb +4 -3
  25. data/lib/command/inspect.rb +2 -1
  26. data/lib/command/list.rb +10 -8
  27. data/lib/command/list/novel_decorator.rb +2 -1
  28. data/lib/command/log.rb +100 -0
  29. data/lib/command/log/tail.rb +76 -0
  30. data/lib/command/mail.rb +20 -17
  31. data/lib/command/remove.rb +7 -6
  32. data/lib/command/send.rb +23 -20
  33. data/lib/command/setting.rb +74 -40
  34. data/lib/command/tag.rb +16 -15
  35. data/lib/command/trace.rb +2 -2
  36. data/lib/command/update.rb +78 -128
  37. data/lib/command/update/general_lastup_updater.rb +3 -2
  38. data/lib/command/update/hotentry_manager.rb +2 -1
  39. data/lib/command/update/interval.rb +2 -1
  40. data/lib/command/version.rb +2 -1
  41. data/lib/command/web.rb +17 -3
  42. data/lib/commandbase.rb +34 -7
  43. data/lib/commandline.rb +54 -35
  44. data/lib/converterbase.rb +21 -15
  45. data/lib/database.rb +3 -2
  46. data/lib/device.rb +5 -4
  47. data/lib/device/epub.rb +2 -1
  48. data/lib/device/ibooks.rb +2 -1
  49. data/lib/device/ibunko.rb +2 -1
  50. data/lib/device/kindle.rb +2 -1
  51. data/lib/device/kobo.rb +2 -1
  52. data/lib/device/library/cygwin.rb +2 -1
  53. data/lib/device/library/linux.rb +2 -1
  54. data/lib/device/library/mac.rb +2 -1
  55. data/lib/device/library/windows.rb +2 -1
  56. data/lib/device/library/windows/eject.rb +2 -1
  57. data/lib/device/reader.rb +2 -1
  58. data/lib/diffviewer.rb +8 -11
  59. data/lib/downloader.rb +159 -151
  60. data/lib/eventable.rb +2 -1
  61. data/lib/extension.rb +16 -14
  62. data/lib/extensions/jruby.rb +2 -1
  63. data/lib/extensions/monkey_patches.rb +7 -0
  64. data/lib/extensions/monkey_patches/pathname.rb +22 -0
  65. data/lib/extensions/windows.rb +2 -1
  66. data/lib/extensions/windows_write_color.rb +2 -1
  67. data/lib/helper.rb +35 -20
  68. data/lib/html.rb +2 -1
  69. data/lib/illustration.rb +2 -1
  70. data/lib/ini.rb +2 -1
  71. data/lib/input.rb +2 -1
  72. data/lib/inspector.rb +3 -2
  73. data/lib/inventory.rb +3 -3
  74. data/lib/mailer.rb +3 -2
  75. data/lib/mixin/all.rb +8 -0
  76. data/lib/mixin/locker.rb +40 -0
  77. data/lib/mixin/output_error.rb +28 -0
  78. data/lib/narou.rb +69 -51
  79. data/lib/narou/api.rb +2 -4
  80. data/lib/narou_logger.rb +236 -108
  81. data/lib/novelconverter.rb +77 -69
  82. data/lib/novelinfo.rb +4 -2
  83. data/lib/novelsetting.rb +15 -12
  84. data/lib/progressbar.rb +13 -9
  85. data/lib/sitesetting.rb +39 -18
  86. data/lib/template.rb +5 -4
  87. data/lib/version.rb +3 -2
  88. data/lib/web/all.rb +2 -1
  89. data/lib/web/appserver.rb +83 -65
  90. data/lib/web/helper4web.rb +10 -5
  91. data/lib/web/progressbar4web.rb +8 -4
  92. data/lib/web/public/resources/default-style.css +2 -3
  93. data/lib/web/public/resources/narou.library.js +86 -60
  94. data/lib/web/public/resources/narou.queue.js +24 -30
  95. data/lib/web/public/resources/narou.ui.js +22 -3
  96. data/lib/web/public/theme/Cerulean/style.css +5 -5
  97. data/lib/web/public/theme/Darkly/style.css +5 -5
  98. data/lib/web/public/theme/Readable/style.css +5 -5
  99. data/lib/web/public/theme/Slate/style.css +2 -3
  100. data/lib/web/public/theme/Superhero/style.css +2 -3
  101. data/lib/web/public/theme/United/style.css +5 -5
  102. data/lib/web/pushserver.rb +10 -7
  103. data/lib/web/server_helpers.rb +16 -1
  104. data/lib/web/settingmessages.rb +10 -7
  105. data/lib/web/streaminginput.rb +2 -1
  106. data/lib/web/streaminglogger.rb +45 -32
  107. data/lib/web/views/_about.haml +6 -3
  108. data/lib/web/views/_header.haml +2 -3
  109. data/lib/web/views/_move_to_top.haml +2 -0
  110. data/lib/web/views/_queue.haml +7 -0
  111. data/lib/web/views/bookmarklet/insert_button.js.erb +1 -1
  112. data/lib/web/views/index.haml +30 -27
  113. data/lib/web/views/layout.haml +2 -0
  114. data/lib/web/views/novels/setting.haml +3 -4
  115. data/lib/web/views/settings.haml +22 -8
  116. data/lib/web/views/style.scss +54 -3
  117. data/lib/web/views/widget/download.haml +9 -3
  118. data/lib/web/views/widget/drag_and_drop.haml +10 -4
  119. data/lib/web/web_worker.rb +132 -0
  120. data/lib/worker.rb +142 -0
  121. data/narou.gemspec +80 -45
  122. data/narou.rb +6 -4
  123. data/template/novel.txt.erb +1 -0
  124. data/webnovel/kakuyomu.jp.yaml +9 -13
  125. data/webnovel/ncode.syosetu.com.yaml +3 -1
  126. data/webnovel/novel18.syosetu.com.yaml +8 -1
  127. data/webnovel/syosetu.org.yaml +3 -1
  128. data/webnovel/www.akatsuki-novels.com.yaml +4 -2
  129. data/webnovel/www.mai-net.net.yaml +3 -1
  130. metadata +109 -48
  131. data/lib/web/worker.rb +0 -126
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Copyright 2013 whiteleaf. All rights reserved.
4
5
  #
@@ -8,18 +9,22 @@ require_relative "../helper"
8
9
  module Helper
9
10
  module_function
10
11
 
12
+ HR_TAG = "<hr>"
13
+
11
14
  class << self
12
15
  alias :original_print_horizontal_rule :print_horizontal_rule
13
16
  end
14
17
 
15
- def print_horizontal_rule
18
+ def print_horizontal_rule(io = $stdout)
16
19
  # タグがキャプチャーされると困るので、キャプチャ専用の出力とWEBへの出力は分ける
17
20
  if $stdout.capturing
18
21
  $stdout.silence do
19
- original_print_horizontal_rule
22
+ original_print_horizontal_rule($stdout)
20
23
  end
24
+ else
25
+ io.append_log("#{HR_TEXT}\n")
21
26
  end
22
- $stdout.push_server.send_all(echo: "<hr>")
27
+ io.push_streaming(HR_TAG)
28
+ io.original_write(HR_TAG)
23
29
  end
24
30
  end
25
-
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Copyright 2013 whiteleaf. All rights reserved.
4
5
  #
@@ -17,16 +18,19 @@ class ProgressBar
17
18
 
18
19
  def initialize(*args)
19
20
  original_initialize(*args)
20
- @@push_server.send_all("progressbar.init" => true)
21
+ @@push_server.send_all("progressbar.init" => { target_console: io.target_console })
21
22
  end
22
23
 
23
24
  def output(num)
24
25
  percent = calc_ratio(num) * 100
25
- @@push_server.send_all("progressbar.step" => percent)
26
+ @@push_server.send_all("progressbar.step" => {
27
+ percent: percent,
28
+ target_console: io.target_console
29
+ })
26
30
  end
27
31
 
28
32
  def clear
29
- @@push_server.send_all("progressbar.clear" => true)
33
+ @@push_server.send_all("progressbar.clear" => { target_console: io.target_console })
30
34
  end
31
35
  end
32
36
 
@@ -27,11 +27,10 @@
27
27
  font-weight: bold;
28
28
  }
29
29
 
30
- #queue-text.active {
30
+ .queue.active {
31
31
  color: #d9534f !important;
32
32
  }
33
33
 
34
- #queue-text.active #queue {
34
+ .queue.active .queue__sizes {
35
35
  background-color: #d9534f !important;
36
36
  }
37
-
@@ -149,6 +149,13 @@ var Narou = (function() {
149
149
  tableReload: function() {
150
150
  Notification.instance().trigger("table.reload");
151
151
  },
152
+
153
+ concurrencyIsEnabled: function() {
154
+ if (typeof this.__concurrencyIsEnabled === "undefined") {
155
+ this.__concurrencyIsEnabled = $("#concurrency-enabled").val() === "true";
156
+ }
157
+ return this.__concurrencyIsEnabled;
158
+ },
152
159
  });
153
160
 
154
161
  /*************************************************************************
@@ -419,21 +426,15 @@ var Narou = (function() {
419
426
  },
420
427
 
421
428
  update: function() {
422
- this.openConsoleDialog(function() {
423
- this.action.update(this.target_id);
424
- }.bind(this));
429
+ this.action.update(this.target_id);
425
430
  },
426
431
 
427
432
  update_force: function() {
428
- this.openConsoleDialog(function() {
429
- this.action.updateForce(this.target_id);
430
- }.bind(this));
433
+ this.action.updateForce(this.target_id);
431
434
  },
432
435
 
433
436
  send: function() {
434
- this.openConsoleDialog(function() {
435
- this.action.send(this.target_id);
436
- }.bind(this));
437
+ this.action.send(this.target_id);
437
438
  },
438
439
 
439
440
  freeze_toggle: function() {
@@ -441,9 +442,7 @@ var Narou = (function() {
441
442
  },
442
443
 
443
444
  remove: function() {
444
- this.openConsoleDialog(function() {
445
- this.action.remove(this.target_id);
446
- }.bind(this));
445
+ this.action.remove(this.target_id);
447
446
  },
448
447
 
449
448
  edit_tag: function() {
@@ -451,9 +450,7 @@ var Narou = (function() {
451
450
  },
452
451
 
453
452
  convert: function() {
454
- this.openConsoleDialog(function() {
455
- this.action.convert(this.target_id);
456
- }.bind(this));
453
+ this.action.convert(this.target_id);
457
454
  },
458
455
 
459
456
  diff: function() {
@@ -461,9 +458,7 @@ var Narou = (function() {
461
458
  },
462
459
 
463
460
  inspect: function() {
464
- this.openConsoleDialog(function() {
465
- this.action.inspect(this.target_id);
466
- }.bind(this));
461
+ this.action.inspect(this.target_id);
467
462
  },
468
463
 
469
464
  folder: function() {
@@ -471,21 +466,15 @@ var Narou = (function() {
471
466
  },
472
467
 
473
468
  backup: function() {
474
- this.openConsoleDialog(function() {
475
- this.action.backup(this.target_id);
476
- }.bind(this));
469
+ this.action.backup(this.target_id);
477
470
  },
478
471
 
479
472
  download_force: function() {
480
- this.openConsoleDialog(function() {
481
- this.action.downloadForce(this.target_id);
482
- }.bind(this));
473
+ this.action.downloadForce(this.target_id);
483
474
  },
484
475
 
485
476
  mail: function() {
486
- this.openConsoleDialog(function() {
487
- this.action.mail(this.target_id);
488
- }.bind(this));
477
+ this.action.mail(this.target_id);
489
478
  },
490
479
 
491
480
  author_comments: function() {
@@ -914,6 +903,10 @@ var Narou = (function() {
914
903
  button.popover("show");
915
904
  });
916
905
  },
906
+
907
+ backupBookmark: function() {
908
+ $.post("/api/backup_bookmark");
909
+ },
917
910
  });
918
911
 
919
912
  /*************************************************************************
@@ -946,7 +939,9 @@ var Narou = (function() {
946
939
  restore: true, // コンソールの大きさを復元・保存するか
947
940
  buttons: true, // 拡大縮小等のコントロールボタンを使用するか
948
941
  id: "#console", // コンソールのID名
949
- buttons_id: "#console-buttons" // コントロールボタンを格納している要素のID名
942
+ buttons_id: "#console-buttons", // コントロールボタンを格納している要素のID名
943
+ sync_shape_console: null,
944
+ stream_id: "stdout"
950
945
  }, options);
951
946
  this.initialize();
952
947
  };
@@ -958,6 +953,7 @@ var Narou = (function() {
958
953
  this.notification = Notification.instance();
959
954
  this.last_char_was_return = true;
960
955
  this.console = $(this.options.id);
956
+ this.sync_shape_console = this.options.sync_shape_console;
961
957
  this.init_scrollbar();
962
958
  if (this.options.buttons) this.init_buttons();
963
959
  this.init_events();
@@ -976,14 +972,18 @@ var Narou = (function() {
976
972
 
977
973
  init_buttons: function() {
978
974
  var self = this;
975
+ var buttons = $(this.options.buttons_id);
979
976
  this.console.css("min-height", this.original_height);
980
- $(this.options.buttons_id + " .console-expand").on("click", function(e) {
977
+ buttons.find(".console-expand").on("click", function(e) {
981
978
  self.expand_console();
982
979
  });
983
- $(this.options.buttons_id + " .console-trash").on("click", function(e) {
980
+ buttons.find(".console-history").on("click", function(e) {
981
+ self.reloadHistory();
982
+ });
983
+ buttons.find(".console-trash").on("click", function(e) {
984
984
  self.trash_console();
985
985
  });
986
- $(this.options.buttons_id + " .queue-cancel").on("click", function(e) {
986
+ buttons.find(".queue-cancel").on("click", function(e) {
987
987
  $.post("/api/cancel");
988
988
  });
989
989
  },
@@ -1006,41 +1006,48 @@ var Narou = (function() {
1006
1006
  });
1007
1007
  },
1008
1008
 
1009
+ createProgressHtml: function(percent) {
1010
+ return '<div class="progress"><div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" style="width:' + percent + '%"></div></div>';
1011
+ },
1012
+
1013
+ initializeProgressBar: function(percent) {
1014
+ this.puts(this.createProgressHtml(percent));
1015
+ this.progress = this.console.find(".progress-bar");
1016
+ },
1017
+
1018
+ setProgressValue: function(percent) {
1019
+ if (!this.progress)
1020
+ this.initializeProgressBar(percent);
1021
+ this.progress.width(percent + "%");
1022
+ },
1023
+
1024
+ removeProgressBar: function() {
1025
+ if (!this.progress) return;
1026
+ this.progress.parent().parent().remove();
1027
+ this.progress = null;
1028
+ },
1029
+
1009
1030
  init_events_progressbar: function() {
1010
1031
  var self = this;
1011
- var $progress = null;
1012
- var createProgressHtml = function(percent) {
1013
- return '<div class="progress"><div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" style="width:' + percent + '%"></div></div>';
1014
- };
1015
- var initializeProgressbar = function(percent) {
1016
- self.puts(createProgressHtml(percent));
1017
- $progress = self.console.find(".progress > div");
1018
- };
1019
- var setProgressValue = function(step) {
1020
- $progress.width(step + "%");
1021
- };
1022
- this.notification.on("progressbar.init", function() {
1023
- initializeProgressbar(0);
1032
+ this.notification.on("progressbar.init", function(json) {
1033
+ if (json.target_console !== self.options.stream_id) return;
1034
+ self.initializeProgressBar(0);
1024
1035
  });
1025
- this.notification.on("progressbar.step", function(value) {
1026
- if ($progress) {
1027
- setProgressValue(value);
1028
- }
1029
- else {
1030
- initializeProgressbar(value);
1031
- }
1036
+ this.notification.on("progressbar.step", function(json) {
1037
+ if (json.target_console !== self.options.stream_id) return;
1038
+ self.setProgressValue(json.percent);
1032
1039
  });
1033
- this.notification.on("progressbar.clear", function() {
1034
- if (!$progress) return;
1035
- $progress = null;
1036
- $(".progress").parent("div").remove();
1040
+ this.notification.on("progressbar.clear", function(json) {
1041
+ if (json.target_console !== self.options.stream_id) return;
1042
+ self.removeProgressBar();
1037
1043
  });
1038
1044
  },
1039
1045
 
1040
1046
  init_notification: function() {
1041
1047
  var self = this;
1042
- this.notification.on("echo", function(message) {
1043
- self.print(message);
1048
+ this.notification.on("echo", function(echo) {
1049
+ if (echo.target_console === self.options.stream_id)
1050
+ self.print(echo.body);
1044
1051
  });
1045
1052
  },
1046
1053
 
@@ -1063,6 +1070,8 @@ var Narou = (function() {
1063
1070
  var data = storage.get("console");
1064
1071
  if (data) {
1065
1072
  this.console.height(data.height);
1073
+ if (this.sync_shape_console)
1074
+ this.sync_shape_console.restore_console_shape();
1066
1075
  if (data.expanded) this.toggle_expanded();
1067
1076
  }
1068
1077
  },
@@ -1123,6 +1132,8 @@ var Narou = (function() {
1123
1132
  calced_height = ($(window).height() - top) * 0.8;
1124
1133
  }
1125
1134
  var was_bottom = this.position_is_bottom();
1135
+ if (this.sync_shape_console)
1136
+ this.sync_shape_console.expand_console();
1126
1137
  this.console.stop().animate({ height: calced_height }, this.animate_duration,
1127
1138
  // after do
1128
1139
  function() {
@@ -1135,18 +1146,33 @@ var Narou = (function() {
1135
1146
 
1136
1147
  toggle_expanded: function() {
1137
1148
  this.console.toggleClass("expanded");
1138
- $(".console-expand > span").toggleClass("hide");
1149
+ if (this.options.buttons) {
1150
+ var buttons = $(this.options.buttons_id);
1151
+ buttons.find(".console-expand > span").toggleClass("hide");
1152
+ }
1153
+ },
1154
+
1155
+ reloadHistory: function() {
1156
+ $.get("/api/history", { stream: this.options.stream_id }, function(history) {
1157
+ this.clear();
1158
+ this.puts(history);
1159
+ }.bind(this));
1160
+ if (this.sync_shape_console)
1161
+ this.sync_shape_console.reloadHistory();
1139
1162
  },
1140
1163
 
1141
1164
  // コンソールのログを削除すると同時に、サーバの履歴も削除する
1142
1165
  trash_console: function() {
1143
1166
  this.clear();
1167
+ if (this.sync_shape_console) this.sync_shape_console.clear();
1144
1168
  $.post("/api/clear_history");
1145
1169
  },
1146
1170
 
1147
1171
  // コンソールの内容をクリア
1148
1172
  clear: function() {
1149
1173
  this.console.find("div.console-line").remove();
1174
+ this.last_char_was_return = true;
1175
+ this.progress = null;
1150
1176
  }
1151
1177
  });
1152
1178
 
@@ -1442,7 +1468,7 @@ var Narou = (function() {
1442
1468
  }
1443
1469
  }
1444
1470
 
1445
- $.get("/api/taginfo.json", { ids: ids }, function(taginfo) {
1471
+ $.post("/api/taginfo.json", { ids: ids }, function(taginfo) {
1446
1472
  _.each(taginfo, function(info) {
1447
1473
  var label = $('<label><input type="checkbox" data-tagname="' + info.tag.replace(/"/g, "&quot;") +
1448
1474
  '" data-default-checkstate=' + calcState(info.count) + '> ' + info.html + '&nbsp;&nbsp;</label>');
@@ -1591,7 +1617,7 @@ var Narou = (function() {
1591
1617
 
1592
1618
  _createEditorField: function(callback) {
1593
1619
  var field = $("<div id=update-by-tag-field class=form-group>");
1594
- $.get("/api/taginfo.json", { ids: [0], with_exclusion: true }, function(taginfo) {
1620
+ $.post("/api/taginfo.json", { ids: [0], with_exclusion: true }, function(taginfo) {
1595
1621
  var div = $("<div><p>更新したい小説のタグにチェックを入れて下さい。</p>");
1596
1622
  _.each(taginfo, function(info) {
1597
1623
  var label = $('<label><input type="checkbox" data-tagname="' + info.tag.replace(/"/g, "&quot;") + '"> ' +
@@ -6,46 +6,40 @@
6
6
  /*
7
7
  * キュー関係のコード
8
8
  */
9
- $(document).ready(function() {
9
+ $(function() {
10
10
  "use strict";
11
11
 
12
12
  /*
13
13
  * キューに積まれた数を表示
14
14
  */
15
15
  var notification = Narou.Notification.instance();
16
- var $queue = $("#queue");
17
- function highlightQueuBoxIcon(size) {
18
- if (size > 0) {
19
- $("#queue-text").addClass("active");
16
+ var $queue = $(".queue");
17
+ var $queueSizes = $(".queue__sizes");
18
+ var $queueSizeDefault = $(".queue__size--default");
19
+ var $queueSizeConvert = $(".queue__size--convert");
20
+
21
+ function highlightQueuBoxIcon(sizes) {
22
+ if (sizes[0] || sizes[1]) {
23
+ $queue.addClass("active");
20
24
  }
21
25
  else {
22
- $("#queue-text").removeClass("active");
26
+ $queue.removeClass("active");
27
+ }
28
+ }
29
+
30
+ function setQueueSizesText(sizes) {
31
+ $queueSizeDefault.text(sizes[0]);
32
+ if (Narou.concurrencyIsEnabled()) {
33
+ $queueSizeConvert.text(sizes[1]);
23
34
  }
35
+ highlightQueuBoxIcon(sizes);
24
36
  }
25
- notification.on("notification.queue", function(data) {
26
- var before_size = $queue.text();
27
- $queue.text(data);
28
- highlightQueuBoxIcon(data);
29
- // キューのスタック数の横に +1 が浮かび上がって消えるアニメーション
30
- var diff = data - before_size;
31
- if (diff <= 0) return;
32
- var $plus = $("<span>+" + diff + "</span>");
33
- $plus.addClass("queue-plus").css({
34
- position: "absolute",
35
- left: $queue.offset().left + $queue.outerWidth() + 1 - $(document).scrollLeft(),
36
- top: $queue.offset().top - 3 - $(document).scrollTop(),
37
- });
38
- $("#header-navbar").append($plus);
39
- $plus.delay(100).animate({
40
- top: - $plus.outerHeight(),
41
- opacity: 0,
42
- }, 3000, function() {
43
- $(this).remove();
44
- });
37
+
38
+ notification.on("notification.queue", function(sizes) {
39
+ setQueueSizesText(sizes);
45
40
  });
46
- $.get("/api/get_queue_size", function(json) {
47
- $queue.text(json.size);
48
- highlightQueuBoxIcon(json.size);
41
+
42
+ $.get("/api/get_queue_size", function(sizes) {
43
+ setQueueSizesText(sizes);
49
44
  });
50
45
  });
51
-
@@ -3,7 +3,7 @@
3
3
  * Copyright 2013 whiteleaf. All rights reserved.
4
4
  */
5
5
  var t; // for debugging
6
- $(document).ready(function() {
6
+ $(function() {
7
7
  "use strict";
8
8
 
9
9
  var touchable_device = "ontouchstart" in window;
@@ -364,7 +364,7 @@ $(document).ready(function() {
364
364
  switch (type) {
365
365
  case "display":
366
366
  return sprintf(
367
- '<a href="%(url)s" class="btn btn-default btn-xs" target="_blank" ' +
367
+ '<a href="%(url)s" class="btn btn-default btn-xs" target="_blank" rel="noreferrer" ' +
368
368
  'data-toggle="tooltip" data-placement="top" title="%(url)s">' +
369
369
  '<span class="glyphicon glyphicon-link"></span></a>',
370
370
  { url: data }
@@ -552,7 +552,17 @@ $(document).ready(function() {
552
552
  var action = new Narou.Action(table);
553
553
  var menuAction = new Narou.MenuAction();
554
554
  var notification = Narou.Notification.instance();
555
- var stream_console = new Narou.Console;
555
+ var consoleStdout2 = null;
556
+ if (Narou.concurrencyIsEnabled()) {
557
+ consoleStdout2 = new Narou.Console({
558
+ id: "#console-stdout2",
559
+ restore: false,
560
+ buttons: false,
561
+ buttons_id: "#console-convert-buttons",
562
+ stream_id: "stdout2"
563
+ });
564
+ }
565
+ new Narou.Console({ sync_shape_console: consoleStdout2 });
556
566
  var search = Narou.Search.get(table);
557
567
  var tag = new Narou.Tag(table);
558
568
  var context_menu = new Narou.ContextMenu(action, tag);
@@ -1451,6 +1461,15 @@ Mac スタイル:<br>メニューが画面外にはみ出そうとしたら、
1451
1461
  action.send("hotentry");
1452
1462
  });
1453
1463
 
1464
+ /*
1465
+ * ボタン
1466
+ * Send > 端末の栞データをバックアップする
1467
+ */
1468
+ $(".button-send-backup-bookmark").on("click", function(e) {
1469
+ e.preventDefault();
1470
+ action.backupBookmark();
1471
+ });
1472
+
1454
1473
  /*
1455
1474
  * ボタン
1456
1475
  * Freeze > 選択した小説を凍結