narou 2.8.3.1 → 2.9.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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +77 -0
  3. data/Gemfile +2 -1
  4. data/README.md +69 -86
  5. data/lib/command/convert.rb +10 -11
  6. data/lib/command/init.rb +2 -2
  7. data/lib/command/list.rb +12 -3
  8. data/lib/command/setting.rb +20 -5
  9. data/lib/command/update.rb +0 -3
  10. data/lib/command/version.rb +2 -3
  11. data/lib/command/web.rb +58 -7
  12. data/lib/converterbase.rb +7 -24
  13. data/lib/database.rb +7 -6
  14. data/lib/device.rb +15 -1
  15. data/lib/device/ibunko.rb +1 -2
  16. data/lib/device/library/mac.rb +7 -0
  17. data/lib/downloader.rb +44 -21
  18. data/lib/extension.rb +25 -0
  19. data/lib/helper.rb +4 -3
  20. data/lib/html.rb +18 -2
  21. data/lib/narou.rb +20 -0
  22. data/lib/novelconverter.rb +11 -35
  23. data/lib/novelinfo.rb +19 -8
  24. data/lib/novelsetting.rb +0 -6
  25. data/lib/version.rb +1 -1
  26. data/lib/web/appserver.rb +134 -15
  27. data/lib/web/public/favicon.ico +0 -0
  28. data/lib/web/public/resources/common.ui.js +2 -2
  29. data/lib/web/public/resources/narou.library.js +657 -91
  30. data/lib/web/public/resources/narou.queue.js +1 -1
  31. data/lib/web/public/resources/narou.ui.js +253 -102
  32. data/lib/web/public/resources/sprintf.js +245 -0
  33. data/lib/web/pushserver.rb +14 -3
  34. data/lib/web/views/_about.haml +188 -0
  35. data/lib/web/views/{diff_list.haml → _diff_list.haml} +0 -0
  36. data/lib/web/views/{edit_replace_txt.haml → _edit_replace_txt.haml} +4 -4
  37. data/lib/web/views/_rebooting.haml +18 -0
  38. data/lib/web/views/bookmarklet/download.js.erb +2 -2
  39. data/lib/web/views/bookmarklet/insert_button.js.erb +1 -1
  40. data/lib/web/views/edit_menu.haml +223 -0
  41. data/lib/web/views/help.haml +29 -12
  42. data/lib/web/views/index.haml +99 -88
  43. data/lib/web/views/layout.haml +5 -3
  44. data/lib/web/views/notepad.haml +39 -0
  45. data/lib/web/views/novels/setting.haml +15 -5
  46. data/lib/web/views/settings.haml +2 -2
  47. data/lib/web/views/style.scss +72 -21
  48. data/lib/web/views/widget/download.haml +3 -2
  49. data/lib/web/views/widget/drag_and_drop.haml +3 -2
  50. data/lib/web/views/widget/notepad.haml +44 -0
  51. data/narou.gemspec +75 -6
  52. data/narou.rb +8 -14
  53. data/preset/ncode.syosetu.com/n5115cq/converter.rb +30 -0
  54. data/preset/ncode.syosetu.com/n7594ct/converter.rb +37 -0
  55. data/preset/ncode.syosetu.com/n8725k/converter.rb +1 -1
  56. data/preset/vertical_font.css +0 -10
  57. data/spec/generator/convert_spec_gen.rb +2 -0
  58. data/template/novel.txt.erb +3 -0
  59. data/webnovel/https.syosetu.org.yaml +1 -1
  60. data/webnovel/kakuyomu.jp.yaml +82 -0
  61. data/webnovel/ncode.syosetu.com.yaml +1 -0
  62. data/webnovel/syosetu.org.yaml +1 -1
  63. metadata +89 -12
  64. data/lib/web/views/about.haml +0 -85
  65. data/preset/DMincho.ttf +0 -0
@@ -21,6 +21,7 @@ module Narou
21
21
  GLOBAL_REPLACE_NAME = "replace.txt"
22
22
  EXIT_ERROR_CODE = 127
23
23
  EXIT_INTERRUPT = 126
24
+ EXIT_REQUEST_REBOOT = 125
24
25
 
25
26
  UPDATE_SORT_KEYS = {
26
27
  "id" => "ID", "last_update" => "更新日", "title" => "タイトル", "author" => "作者名",
@@ -275,5 +276,24 @@ module Narou
275
276
  type == 2 ? "短編" : "連載"
276
277
  end
277
278
 
279
+ #
280
+ # Narou.rb gem の最新バージョン番号を取得する
281
+ #
282
+ # rubygems公式APIによる取得は、WindowsでのSSL証明書問題で取得出来ない
283
+ # 環境があるため、gemコマンド経由で取得する
284
+ #
285
+ def latest_version
286
+ response = `gem search ^narou$`.split("\n")
287
+ if response.last =~ /\Anarou \((.+?)\)\z/
288
+ $1
289
+ end
290
+ end
291
+
292
+ def commit_version
293
+ cv_path = File.expand_path("commitversion", get_script_dir)
294
+ File.read(cv_path) if File.exist?(cv_path)
295
+ end
296
+ memoize :commit_version
297
+
278
298
  end
279
299
  end
@@ -23,8 +23,6 @@ class NovelConverter
23
23
  NOVEL_TEXT_TEMPLATE_NAME = "novel.txt"
24
24
  NOVEL_TEXT_TEMPLATE_NAME_FOR_IBUNKO = "ibunko_novel.txt"
25
25
 
26
- attr_reader :use_dakuten_font
27
-
28
26
  if Narou.already_init?
29
27
  @@site_settings = Downloader.load_settings
30
28
  end
@@ -41,10 +39,7 @@ class NovelConverter
41
39
  setting = NovelSetting.load(target, options[:ignore_force], options[:ignore_default])
42
40
  if setting
43
41
  novel_converter = new(setting, options[:output_filename], options[:display_inspector])
44
- return {
45
- converted_txt_path: novel_converter.convert_main,
46
- use_dakuten_font: novel_converter.use_dakuten_font
47
- }
42
+ return novel_converter.convert_main
48
43
  end
49
44
  nil
50
45
  end
@@ -72,22 +67,8 @@ class NovelConverter
72
67
  if options[:encoding]
73
68
  text.force_encoding(options[:encoding]).encode!(Encoding::UTF_8)
74
69
  end
75
- {
76
- converted_txt_path: novel_converter.convert_main(text),
77
- use_dakuten_font: novel_converter.use_dakuten_font
78
- }
79
- end
80
-
81
- def self.stash_aozora_fonts_directory
82
- fonts_path = File.join(File.dirname(Narou.get_aozoraepub3_path), "template/OPS/fonts")
83
- return unless File.exist?(fonts_path)
84
- FileUtils.mv(fonts_path, fonts_path + "_hide")
85
- end
86
70
 
87
- def self.visible_aozora_fonts_directory
88
- fonts_path = File.join(File.dirname(Narou.get_aozoraepub3_path), "template/OPS/fonts")
89
- return unless File.exist?(fonts_path + "_hide")
90
- FileUtils.mv(fonts_path + "_hide", fonts_path)
71
+ novel_converter.convert_main(text)
91
72
  end
92
73
 
93
74
  #
@@ -100,7 +81,7 @@ class NovelConverter
100
81
  #
101
82
  # 返り値:正常終了 :success、エラー終了 :error、AozoraEpub3が見つからなかった nil
102
83
  #
103
- def self.txt_to_epub(filename, use_dakuten_font = false, dst_dir = nil, device = nil, verbose = false)
84
+ def self.txt_to_epub(filename, dst_dir = nil, device = nil, verbose = false)
104
85
  abs_srcpath = File.expand_path(filename)
105
86
  src_dir = File.dirname(abs_srcpath)
106
87
 
@@ -149,14 +130,12 @@ class NovelConverter
149
130
  if Helper.os_windows?
150
131
  command = "cmd /c " + command.encode(Encoding::Windows_31J)
151
132
  end
152
- stash_aozora_fonts_directory unless use_dakuten_font
153
133
  print "AozoraEpub3でEPUBに変換しています"
154
134
  begin
155
135
  res = Helper::AsyncCommand.exec(command) do
156
136
  print "."
157
137
  end
158
138
  ensure
159
- visible_aozora_fonts_directory unless use_dakuten_font
160
139
  Dir.chdir(pwd)
161
140
  end
162
141
 
@@ -267,7 +246,6 @@ class NovelConverter
267
246
  #
268
247
  def self.convert_txt_to_ebook_file(txt_path, options)
269
248
  options = {
270
- use_dakuten_font: false,
271
249
  dst_dir: nil,
272
250
  device: nil,
273
251
  verbose: false,
@@ -283,8 +261,7 @@ class NovelConverter
283
261
  return false if options[:no_epub]
284
262
  clean_up_file_list << txt_path unless options[:no_cleanup_txt]
285
263
  # epub
286
- status = NovelConverter.txt_to_epub(txt_path, options[:use_dakuten_font],
287
- options[:dst_dir], device, options[:verbose])
264
+ status = NovelConverter.txt_to_epub(txt_path, options[:dst_dir], device, options[:verbose])
288
265
  return nil if status != :success
289
266
  if device && device.kobo?
290
267
  epub_ext = device.ebook_file_ext
@@ -340,7 +317,6 @@ class NovelConverter
340
317
  @inspector = Inspector.new(@setting)
341
318
  @illustration = Illustration.new(@setting, @inspector)
342
319
  @display_inspector = display_inspector
343
- @use_dakuten_font = false
344
320
  @converter = create_converter
345
321
  @converter.output_text_dir = output_text_dir
346
322
  @data = @novel_id ? Database.instance.get_data("id", @novel_id) : {}
@@ -415,11 +391,13 @@ class NovelConverter
415
391
  end
416
392
 
417
393
  #
418
- # 2045年くらいまでの残り時間を10分単位の36進数で取得する
394
+ # 2035年くらいまでの残り時間を10分単位の36進数で取得する
419
395
  # hyff のような文字列が取得可能
396
+ # 小説家になろうで、もっとも古い作品が2004年5月1日11時49分なので、
397
+ # その小説がちょうど4桁の zzzz となるように調整してある
420
398
  #
421
399
  def calc_reverse_short_time(time)
422
- ((2396736000 - time.to_i) / (10 * 60)).to_s(36).rjust(4, "0")
400
+ ((2091149000 - time.to_i) / (10 * 60)).to_s(36).rjust(4, "0")
423
401
  end
424
402
 
425
403
  #
@@ -427,7 +405,7 @@ class NovelConverter
427
405
  # 日付の種類は title_date_target で指定する
428
406
  #
429
407
  # strftime の書式の他に拡張書式として $s, $t をサポートする
430
- # $s 2045年くらいまでの残り時間を10分単位の36進数(4桁)
408
+ # $s 2035年くらいまでの残り時間を10分単位の36進数(4桁)
431
409
  # $t タイトル自身。書式の中で自由な位置にタイトルを埋め込める
432
410
  # $ns 小説が掲載されているサイト名
433
411
  # $nt 小説種別(短編 or 連載)
@@ -562,8 +540,6 @@ class NovelConverter
562
540
  # 表紙の挿絵注記を3行目に挟み込む
563
541
  converted_text = [splited[0], splited[1], create_cover_chuki, splited[2]].join("\n")
564
542
 
565
- @use_dakuten_font = @converter.use_dakuten_font
566
-
567
543
  converted_text
568
544
  end
569
545
 
@@ -623,8 +599,10 @@ class NovelConverter
623
599
  section["chapter"] = @converter.convert(section["chapter"], "chapter")
624
600
  end
625
601
  @inspector.subtitle = section["subtitle"]
602
+ section["subtitle"] = @converter.convert(section["subtitle"], "subtitle")
626
603
  element = section["element"]
627
604
  data_type = element.delete("data_type") || "text"
605
+ @converter.data_type = data_type
628
606
  element.each do |text_type, elm_text|
629
607
  if data_type == "html"
630
608
  html.string = elm_text
@@ -632,10 +610,8 @@ class NovelConverter
632
610
  end
633
611
  element[text_type] = @converter.convert(elm_text, text_type)
634
612
  end
635
- section["subtitle"] = @converter.convert(section["subtitle"], "subtitle")
636
613
  sections << section
637
614
  end
638
- @use_dakuten_font = @converter.use_dakuten_font
639
615
  sections
640
616
  ensure
641
617
  trigger(:"convert_main.finish")
@@ -11,36 +11,47 @@ class NovelInfo
11
11
  REFRESH_INTERVAL = 10 * 60 # キャッシュを捨てて再取得するまでの時間(s)
12
12
  @@novel_info_parameters = {}
13
13
 
14
- def self.load(setting)
15
- info = new(setting)
14
+ def self.load(setting, toc_source = nil)
15
+ info = new(setting, toc_source)
16
16
  info.parse_novel_info
17
17
  end
18
18
 
19
- def initialize(setting)
19
+ def initialize(setting, toc_source = nil)
20
20
  @setting = setting
21
21
  @ncode = @setting["ncode"]
22
+ @toc_source = toc_source
22
23
  @@novel_info_parameters[@setting["name"]] ||= {}
23
24
  end
24
25
 
25
26
  def parse_novel_info
26
27
  info_url = @setting["novel_info_url"] or return nil
27
28
  result = @@novel_info_parameters[@setting["name"]][@ncode] ||= {}
29
+ need_reload = false
28
30
  unless result.empty?
29
31
  # WEB UI でプロセスが常駐している間に小説情報(タイトルやあらすじ等)が
30
32
  # 変更される場合があるので、一定時間過ぎたら再取得をする必要がある
31
33
  if Time.now < result["last_load_time"] + REFRESH_INTERVAL
32
34
  return result # まだ一定時間過ぎていないのでキャッシュを返す
33
35
  end
36
+ need_reload = true
34
37
  end
35
38
  of = "t-nt-ga-s-gf-nu-gl-w"
36
39
  request_output_parameters = of.split("-")
37
40
  info_source = ""
38
- cookie = @setting["cookie"] || ""
39
- open_uri_options = make_open_uri_options("Cookie" => cookie, allow_redirections: :safe)
40
- open(info_url, open_uri_options) do |fp|
41
- info_source = Helper.restor_entity(Helper.pretreatment_source(fp.read, @setting["encoding"]))
42
- raise Downloader::DownloaderNotFoundError if Downloader.detect_error_message(@setting, info_source)
41
+
42
+ if @setting["novel_info_url"] == @setting["toc_url"] && @toc_source && !need_reload
43
+ # 目次ページのHTML(オプション)。目次と小説情報が同じページにある場合、
44
+ # 同じページを二度取得するのは非効率なので、使い回す
45
+ info_source = @toc_source
46
+ else
47
+ cookie = @setting["cookie"] || ""
48
+ open_uri_options = make_open_uri_options("Cookie" => cookie, allow_redirections: :safe)
49
+ open(info_url, open_uri_options) do |fp|
50
+ info_source = Helper.restor_entity(Helper.pretreatment_source(fp.read, @setting["encoding"]))
51
+ raise Downloader::DownloaderNotFoundError if Downloader.detect_error_message(@setting, info_source)
52
+ end
43
53
  end
54
+
44
55
  @setting.multi_match(info_source, *request_output_parameters)
45
56
  result["last_load_time"] = Time.now
46
57
  result["title"] = @setting["title"]
@@ -354,12 +354,6 @@ class NovelSetting
354
354
  value: 10,
355
355
  help: "ここで設定した値が `enable_convert_page_break` に反映される"
356
356
  },
357
- {
358
- name: "enable_dakuten_font",
359
- type: :boolean,
360
- value: true,
361
- help: "濁点フォントを使用する。false の場合は縦中横による擬似表現を使用する"
362
- },
363
357
  {
364
358
  name: "enable_display_end_of_book",
365
359
  type: :boolean,
@@ -3,4 +3,4 @@
3
3
  # Copyright 2013 whiteleaf. All rights reserved.
4
4
  #
5
5
 
6
- Version = "2.8.3.1"
6
+ Version = "2.9.0"
@@ -6,10 +6,8 @@
6
6
  require "socket"
7
7
  require "sinatra/base"
8
8
  require "sinatra/json"
9
- if $debug
10
- require "sinatra/reloader"
11
- require "pry"
12
- end
9
+ require "sinatra/reloader" if $development
10
+ require "better_errors" if $debug
13
11
  require "tilt/erubis"
14
12
  require "tilt/haml"
15
13
  require "tilt/sass"
@@ -25,7 +23,7 @@ module Narou::ServerHelpers
25
23
  # タグをHTMLで装飾する
26
24
  #
27
25
  def decorate_tags(tags)
28
- tags.map do |tag|
26
+ tags.sort.map do |tag|
29
27
  %!<span class="tag label label-#{Command::Tag.get_color(tag)}" data-tag="#{escape_html(tag)}">#{escape_html(tag)}</span>!
30
28
  end.join(" ")
31
29
  end
@@ -103,12 +101,20 @@ module Narou::ServerHelpers
103
101
  value
104
102
  end
105
103
  end
104
+
105
+ def notepad_text_path
106
+ File.join(Narou.get_local_setting_dir, "notepad.txt")
107
+ end
106
108
  end
107
109
 
108
110
  class Narou::AppServer < Sinatra::Base
109
- register Sinatra::Reloader if $debug
111
+ register Sinatra::Reloader if $development
110
112
  helpers Narou::ServerHelpers
111
113
 
114
+ @@request_reboot = false
115
+ @@already_update_system = false
116
+ @@gem_update_last_log = ""
117
+
112
118
  configure do
113
119
  set :app_file, __FILE__
114
120
  set :erb, trim: "-"
@@ -119,13 +125,31 @@ class Narou::AppServer < Sinatra::Base
119
125
  Command::Version.create_version_string
120
126
  end
121
127
 
122
- set :environment, :production unless $debug
128
+ set :environment, :production unless $development
129
+ set :server, :webrick
130
+
131
+ if $debug
132
+ use BetterErrors::Middleware
133
+ BetterErrors.application_root = Narou.get_script_dir
134
+ end
123
135
  end
124
136
 
125
137
  def self.push_server=(server)
126
138
  @@push_server = server
127
139
  end
128
140
 
141
+ def self.push_server
142
+ @@push_server
143
+ end
144
+
145
+ def self.request_reboot
146
+ @@request_reboot = true
147
+ end
148
+
149
+ def self.request_reboot?
150
+ @@request_reboot
151
+ end
152
+
129
153
  #
130
154
  # サーバのアドレスを生成
131
155
  #
@@ -173,6 +197,30 @@ class Narou::AppServer < Sinatra::Base
173
197
  }.call
174
198
  end
175
199
 
200
+ def initialize
201
+ super
202
+ puts_hello_messages
203
+ start_device_ejectable_event
204
+ end
205
+
206
+ def puts_hello_messages
207
+ puts "<white>Narou.rb version #{::Version}</white>".termcolor
208
+ end
209
+
210
+ def start_device_ejectable_event
211
+ return unless Device.support_eject?
212
+ Thread.new do
213
+ loop do
214
+ if @@push_server.connections.count > 0
215
+ device = Narou.get_device
216
+ @@push_server.send_all(:"device.ejectable" => device && device.ejectable?)
217
+ end
218
+
219
+ sleep 2
220
+ end
221
+ end
222
+ end
223
+
176
224
  # ===================================================================
177
225
  # ルーティング
178
226
  # ===================================================================
@@ -291,7 +339,7 @@ class Narou::AppServer < Sinatra::Base
291
339
  get "/about" do
292
340
  @narourb_version = settings.version
293
341
  @ruby_version = build_ruby_version
294
- haml :about, layout: false
342
+ haml :_about, layout: false
295
343
  end
296
344
 
297
345
  post "/shutdown" do
@@ -299,6 +347,36 @@ class Narou::AppServer < Sinatra::Base
299
347
  "シャットダウンしました。再起動するまで操作は出来ません"
300
348
  end
301
349
 
350
+ post "/reboot" do
351
+ self.class.request_reboot
352
+ self.class.quit!
353
+ haml :_rebooting, layout: false
354
+ end
355
+
356
+ post "/update_system" do
357
+ Thread.new do
358
+ buffer = `gem update --no-document narou`
359
+ @@gem_update_last_log = buffer.strip!
360
+ if buffer =~ /Nothing to update\z/
361
+ @@push_server.send_all("server.update.nothing" => buffer)
362
+ elsif buffer.include?("Gems updated: narou")
363
+ @@already_update_system = true
364
+ @@push_server.send_all("server.update.success" => buffer)
365
+ else
366
+ @@push_server.send_all("server.update.failure" => buffer)
367
+ end
368
+ end
369
+ end
370
+
371
+ post "/gem_update_last_log" do
372
+ content_type "text/plain"
373
+ @@gem_update_last_log
374
+ end
375
+
376
+ post "/check_already_update_system" do
377
+ json({ result: @@already_update_system })
378
+ end
379
+
302
380
  before "/novels/:id/*" do
303
381
  @id = params[:id]
304
382
  not_found unless @id =~ /^\d+$/
@@ -376,12 +454,26 @@ class Narou::AppServer < Sinatra::Base
376
454
  ext = device ? device.ebook_file_ext : ".epub"
377
455
  path = Narou.get_ebook_file_path(@id, ext)
378
456
  if File.exist?(path)
379
- send_file(path, filename: File.basename(path))
457
+ send_file(path, filename: File.basename(path), type: "application/octet-stream")
380
458
  else
381
459
  not_found
382
460
  end
383
461
  end
384
462
 
463
+ get "/notepad" do
464
+ @title = "メモ帳"
465
+ haml :notepad
466
+ end
467
+
468
+ get "/edit_menu" do
469
+ @title = "個別メニューの編集"
470
+ haml :edit_menu
471
+ end
472
+
473
+ not_found do
474
+ "not found"
475
+ end
476
+
385
477
  # -------------------------------------------------------------------------------
386
478
  # API's
387
479
  # -------------------------------------------------------------------------------
@@ -411,7 +503,7 @@ class Narou::AppServer < Sinatra::Base
411
503
  tags.include?("end") ? "完結" : nil,
412
504
  tags.include?("404") ? "削除" : nil,
413
505
  ].compact.join(", "),
414
- download: %!<a href="/novels/#{id}/download" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-book"></span></a>!,
506
+ download: %!<a href="/novels/#{id}/download" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-download-alt"></span></a>!,
415
507
  frozen: Narou.novel_frozen?(id),
416
508
  new_arrivals_date: data["new_arrivals_date"].tap { |m| break m.to_i if m },
417
509
  general_lastup: data["general_lastup"].tap { |m| break m.to_i if m }
@@ -529,7 +621,7 @@ class Narou::AppServer < Sinatra::Base
529
621
  target = params["target"] or return ""
530
622
  id = Downloader.get_id_by_target(target) or return ""
531
623
  @list = Command::Diff.new.get_diff_list(id)
532
- haml :diff_list, layout: false
624
+ haml :_diff_list, layout: false
533
625
  end
534
626
 
535
627
  post "/api/diff_clean" do
@@ -564,9 +656,11 @@ class Narou::AppServer < Sinatra::Base
564
656
  end
565
657
 
566
658
  get "/api/tag_list" do
567
- result = '<div><span class="tag label label-default" data-tag="">タグ検索を解除</span></div>'
659
+ result =
660
+ '<div><span class="tag label label-default" data-tag="">タグ検索を解除</span></div>' \
661
+ '<div class="text-muted" style="font-size:10px">Altキーを押しながらで除外検索</div>'
568
662
  tagname_list = Command::Tag.get_tag_list.keys
569
- tagname_list.each do |tagname|
663
+ tagname_list.sort.each do |tagname|
570
664
  result << "<div>#{decorate_tags([tagname])} " \
571
665
  "<span class='select-color-button' data-target-tag='#{h tagname}'>" \
572
666
  "<span class='#{Command::Tag.get_color(tagname)}'>a</span></span></div>"
@@ -683,11 +777,32 @@ class Narou::AppServer < Sinatra::Base
683
777
  end
684
778
 
685
779
  get "/api/version/latest.json" do
686
- open("https://rubygems.org/api/v1/versions/narou/latest.json?#{Time.now.to_i}") do |fp|
687
- fp.read
780
+ json({ version: Narou.latest_version })
781
+ end
782
+
783
+ get "/api/notepad/read" do
784
+ content_type "text/plain"
785
+ if File.exist?(notepad_text_path)
786
+ File.read(notepad_text_path)
787
+ else
788
+ ""
688
789
  end
689
790
  end
690
791
 
792
+ post "/api/notepad/save" do
793
+ File.write(notepad_text_path, params["text"])
794
+ @@push_server.send_all("notepad.change" => {
795
+ text: params["text"], object_id: params["object_id"]
796
+ })
797
+ ""
798
+ end
799
+
800
+ post "/api/eject" do
801
+ device = Narou.get_device
802
+ device.eject if device
803
+ ""
804
+ end
805
+
691
806
  # -------------------------------------------------------------------------------
692
807
  # 一部分に表示するためのHTMLを取得する(パーシャル)
693
808
  # -------------------------------------------------------------------------------
@@ -741,5 +856,9 @@ class Narou::AppServer < Sinatra::Base
741
856
  get "/widget/drag_and_drop" do
742
857
  haml :"widget/drag_and_drop", layout: nil
743
858
  end
859
+
860
+ get "/widget/notepad" do
861
+ haml :"widget/notepad", layout: nil
862
+ end
744
863
  end
745
864