narou 1.0.2 → 1.1.0.rc1

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.

@@ -1,6 +1,6 @@
1
-
2
- Changes
3
- -------
1
+ 
2
+ 更新履歴 - ChangeLog
3
+ --------------------
4
4
 
5
5
  1.0.2 : 2013/02/24
6
6
  - フォントのライセンスについて明確に記載した
data/README.md CHANGED
@@ -1,24 +1,43 @@
1
- Narou.rb ― 小説家になろうダウンローダ&縦書用整形スクリプト
2
- ============================================================
1
+ Narou.rb ― 小説家になろう読書支援アプリケーション
2
+ ==================================================
3
3
 
4
4
  説明 - Description
5
5
  ------------------
6
+ このアプリケーションは[小説家になろう](http://syosetu.com/)にある小説を電子書籍端末で快適に読むための支援ツールです。
6
7
 
7
- 小説家になろうから小説をダウンロードして、縦書で読みやすいようにテキストを整形し、AozoraEPUB3を使ってEPUB化します。
8
- 小説の更新管理もできます。
8
+ 全てコンソールで操作するCUIアプリケーションです。
9
+
10
+ 縦書に特化しており、どんな文章だろうとほぼ違和感なく縦書で読むことが出来るでしょう。また、若干の校正機能もありますので、
11
+ 小説としては許されない記述法などは矯正します。(例:感嘆符のあとにはスペースが必ずくる)
12
+
13
+ 簡単にまとめると以下の様なことが出来ます。
14
+
15
+ 1. 小説家になろうから小説をダウンロード
16
+ 2. ダウンロードした小説の更新管理(新規投稿、改稿された既存話をダウンロード)
17
+ 3. 縦書で読みやすい様にがっつり変換(校正、整形)
18
+ 4. AozoraEpub3でEPUB化
19
+ 5. KindlegenによるMOBI化
20
+ 6. 接続されている端末に送信
21
+
22
+ 1~6はすべて自動化されていて、利用者がほとんど操作をしなくても良いように設計されています。(各コマンドを使うことにより、ダウンロードのみ、変換のみ、送信のみ、なども可能です)
23
+
24
+ 上で説明していない機能もまだまだあります。(更新された小説のどこが変更されたかを目視するdiffなど)
9
25
 
10
26
  作った人 - Author
11
27
  -----------------
12
28
  * whiteleaf
13
29
  * Twitter: https://twitter.com/sasalove7
14
30
  * Blog: http://whiteleaf.hatenablog.com/
31
+ * GitHub: https://github.com/whiteleaf7/narou
15
32
 
16
33
  必須ツール - Require tools
17
34
  --------------------------
18
- * Ruby 1.9.3以上 (Windows: http://www.artonx.org/data/asr/, その他OS: 適当に)
19
- * AozoraEpub3 1.1.0系 (http://www18.atwiki.jp/hmdev/pages/21.html)
35
+ * Ruby 1.9.3 (2.0.0は動きますがまだ動作保証外です)
36
+ * Windows: [Ruby MSI Packages](http://www.artonx.org/data/asr/), その他OS: 適当に
37
+ * [AozoraEpub3 1.1.0系](http://www18.atwiki.jp/hmdev/pages/21.html)
20
38
  * Java 6以降(AozoraEpub3で必須)
21
- * kindlegen 2.7 (http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211)
39
+ * [kindlegen 2.7](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211)
40
+ * 最新版は2.8ですが、現在AozoraEpub3が吐き出すEPUBだとNCXが正常に出力されないというバグがあります。
22
41
 
23
42
  機能っぽい一覧 - Functions
24
43
  --------------------------
@@ -50,37 +69,169 @@ Narou.rb ― 小説家になろうダウンローダ&縦書用整形スクリ
50
69
 
51
70
  インストール - How to install
52
71
  -----------------------------
53
- * 事前に AozoraEpub3 をインストールしておきます。
54
- → http://www18.atwiki.jp/hmdev/pages/21.html
72
+ ### わかってる人向け:
73
+ ```
74
+ gem install narou
75
+ ```
76
+ でインストール出来ます。
77
+
78
+ *****
79
+
80
+ ### 初心者向け:
81
+ 必須ツールのインストールを含めて説明します。すでに導入済みの場合は読み飛ばして下さい。
82
+ ただし、AozoraEpub3 に関してだけは Narou.rb 用に別途新規インストールすることをオススメします。
83
+ それはこのアプリケーションが AozoraEpub3 用の構成ファイルを書き換えるからです。
84
+
85
+ > * Windows7ユーザを対象に説明します。他のOSの場合は適宜読み替えて下さい。
86
+ > * Windows以外の動作は確認していません。動作報告は歓迎いたします。
87
+ > * 3番のkindlegenのインストールはKindleを使わない方は必要ありません。
88
+
89
+ 1. Ruby をインストールします。
90
+ - [Windows用パッケージ](http://www.artonx.org/data/asr/)からインストールするのが簡単です。
91
+ - Ruby-1.9.3-p*** Microsoft Installer Package を選びましょう。
92
+ - インストールしたRubyにパスを通します → [参考ページ](http://www.rubylife.jp/install/install/index3.html)
93
+ 2. [AozoraEpub3](http://www18.atwiki.jp/hmdev/pages/21.html) をインストールします。
94
+ - インストールしたフォルダを覚えておきましょう。3.で必要になります。
95
+ 3. [kindlegen](http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211) を
96
+ AozoraEpub3 をインストールしたフォルダにコピーします。
97
+ 4. Narou.rb をインストールします。コンソールを立ち上げ(Winキー+R→cmd と入力すれば立ち上がります)、
98
+ ```
99
+ gem install narou
100
+ ```
101
+
102
+ と入力します。
103
+ 5. 小説を管理するために好きな場所にフォルダを作成し、そのフォルダを初期化します。
104
+ ここでは **C:\MyNovel** を管理用フォルダとして話を進めます。4.で立ち上げたコンソールで、
105
+ ```
106
+ cd c:/
107
+ mkdir MyNovel
108
+ cd MyNovel
109
+ narou init
110
+ ```
111
+
112
+ と順番に入力します。`narou init`を入力したら、AozoraEpub3 のフォルダの入力を求められますので、
113
+ 2.でインストールしたフォルダを入力して下さい(コンソールにエクスプローラからフォルダをドラッグで入力出来ます)。
114
+ ```
115
+ c:\MyNovel>narou init
116
+ .narou/ を作成しました
117
+ 小説データ/ を作成しました
118
+ ------------------------------
119
+ AozoraEpub3の設定を行います
120
+ !!!WARNING!!!
121
+ AozoraEpub3の構成ファイルを書き換えます。narouコマンド用に別途新規インストールし
122
+ ておくことをオススメします
123
+
124
+ AozoraEpub3のあるフォルダを入力して下さい
125
+ (未入力でスキップ):
126
+ >C:\Users\whiteleaf\Documents\GitHub\narou\AozoraEpub3
127
+
128
+ (次のファイルを書き換えました)
129
+ ~~ 以下略 ~~
130
+ ```
131
+
132
+ これで **C:\MyNovel** 以下のフォルダでNarou.rbの各種コマンドが使用できるようになります。
133
+
134
+ 使い方 - How to use
135
+ -------------------
136
+ 基本的な使い方を説明します。
137
+
138
+ *****
139
+
140
+ ### 小説のダウンロード (download)
141
+
142
+ ここでは[無職転生 - 異世界行ったら本気だす -](http://ncode.syosetu.com/n9669bk/)を例に説明します
143
+ (関係ないですが私のオススメ小説です)。また、使用している電子書籍端末を **Kindle Paperwhite** と仮定します。
144
+
145
+ 以下は全てコンソールでの作業です。
146
+
147
+ 1. まずは Kindle Paperwhite をUSBケーブルでパソコンに接続します。
148
+ 2. あなたの使用する電子書籍端末を設定します。ここでは Kindle Paperwhite なので、
149
+ ```
150
+ narou setting device=kindle
151
+ ```
152
+
153
+ と入力します。
154
+ 3. 小説をダウンロードしましょう! 次のコマンドを入力して下さい。
155
+ ```
156
+ narou download n9669bk
157
+ ```
158
+
159
+ 小説のダウンロードが始まるので終わるまで待ちます。
160
+
161
+ > *NOTICE*
162
+ > - `narou download` は `narou d` と省略することが出来ます。
163
+ > - `narou d http://ncode.syosetu.com/n9669bk/` とURLを直接入力することもできます。
164
+ > ブラウザからそのままコピーが楽でしょう(アドレスバーのアイコンをドラッグで入力出来ます)。
165
+ 4. 自動で変換されます。
166
+ 5. Kindle Paperwhiteへコピーされましたね? **これでもうKindle Paperwhiteで読むことが出来ます!**
167
+
168
+ このアプリケーションは **ダウンロード→変換→端末へ送信** までが全自動なのです。
169
+ > *NOTICE*
170
+ >
171
+ > ダウンロード時の変換は抑制することが出来ます。
172
+ >
173
+ > `narou d n9669bk -n` と `-n` オプションをつければダウンロードだけ実行します。
174
+
175
+ *****
176
+
177
+ ### ダウンロードした小説の管理
55
178
 
56
- * kindlegen を AozoraEpub3 をインストールしたフォルダにコピーします。
57
- → http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211
179
+ 一度小説をダウンロードすれば、パソコン上に保存され、次回以降は再度ダウンロードする必要はありません。
58
180
 
59
- * Narou.rb をインストールします。
60
- コンソールで
181
+ まずは現在保存されている小説の一覧を見てみましょう。
182
+
183
+ #### 一覧を表示する (list)
61
184
  ```
62
- gem install narou
185
+ > narou list
186
+ ID | 更新日 | タイトル
187
+ 0 | 13/02/26 | 無職転生 - 異世界行ったら本気だす -
63
188
  ```
189
+ 先ほどダウンロードした無職転生がリストに現れました。 **listコマンド** では現在管理している小説の一覧を表示することが出来ます。
190
+
191
+ このlistコマンドは非常によく使いますので、`narou l` (l は小文字のエル)と短縮コマンドを覚えましょう。短縮コマンドは各コマンドの頭文字の1文字、もしくは2文字を使います。
64
192
 
65
- * 小説の管理用として任意のフォルダで、
193
+ このリストで表示されているIDは、各コマンドで小説を特定するための数字です。
194
+ NコードやURL、タイトルでも各コマンドは動かすことが出来ますが、入力が面倒なのでIDを使いましょう。
195
+
196
+ #### 小説を更新する (update)
66
197
  ```
67
- narou init
198
+ > narou update
199
+ ID:0 無職転生 - 異世界行ったら本気だす - のDL開始
200
+ 第26部分 第二十三話「信用の理由」 (1/5)
201
+ 第30部分 第二十七話「冒険者の宿」 (2/5)
202
+ 第31部分 第二十八話「人の命と初仕事」 (3/5)
203
+ 第34部分 第三十一話「子供と戦士」 (4/5)
204
+ 第35部分 第三十二話「失敗と混乱と決意」 (5/5)
205
+ ID:0 無職転生 - 異世界行ったら本気だす - の変換を開始
206
+ 小説状態の調査結果を 調査ログ.txt に出力しました
207
+ [理不尽な孫の手] 無職転生 - 異世界行ったら本気だす -.txt を出力しました
208
+ AozoraEpub3でEPUBに変換しています.........変換しました
209
+ kindlegen実行中...............変換しました
210
+ kindlestrip実行中
211
+ MOBIファイルを出力しました
212
+ Kindleへ送信しています....
213
+ F:/documents/[理不尽な孫の手] 無職転生 - 異世界行ったら本気だす -.mobi へコピーしました
68
214
  ```
69
- あとは画面の説明に従って下さい。
215
+ これは更新があった時の表示例です。downloadコマンド実行直後は更新は当然ありませんので、『更新はありません』と表示されます。
70
216
 
71
- 使い方 - How to use
72
- -------------------
73
- 基本的な使い方
217
+ この **updateコマンド** は、現在管理している全ての小説の更新をチェックするコマンドです。これもまたよく使うコマンドなので、`narou u` という短縮コマンドを覚えましょう。
74
218
 
75
- narou init したフォルダで、narou <command> を適宜実行します。
219
+ updateコマンドは指定した小説のみアップデートする機能もあります。
76
220
  ```
77
- narou downlaod Nコード
78
- narou update Nコード
79
- narou convert Nコード
221
+ narou update 0
80
222
  ```
81
- 等と使います。
223
+ と先ほどlistコマンドで取得したIDをupdateに続いて指定しました。これで無職転生のみの更新を取得することが出来ます。
82
224
 
83
- (書きかけ)
225
+ (ここまで書いた)
226
+
227
+ #### 読み終わったら評価、感想を書こう
228
+
229
+ 小説家になろうの作品を読んだら評価や感想を書きましょう。
230
+
231
+ ```
232
+ narou browser 0 --vote
233
+ ```
234
+ ブラウザが開き、評価投票、感想を書くページが表示されます。--vote オプションを付けなかった場合は目次ページが表示されます。
84
235
 
85
236
  サポート - Support
86
237
  ------------------
@@ -88,13 +239,49 @@ https://twitter.com/sasalove7 , http://whiteleaf.hatenablog.com/
88
239
 
89
240
  上記のツイッター及びブログで今後要望等を取り扱いたいと思います。
90
241
 
242
+ 動作環境 - Platform
243
+ -------------------
244
+
245
+ ### OS別動作状況
246
+
247
+ |OS名 |Rubyバージョン|動作|備考 |
248
+ |---------------|--------------|:--:|----------------------------------------|
249
+ |Windows7 64 bit|Ruby 1.9.3 | ◎ |製作者と同じ環境 |
250
+ |Windows7 64 bit|Ruby 1.9.2 | × |1.9.2から前は対応していません |
251
+ |WindowsXP |Ruby 1.9.3 | ◎ | |
252
+ |Windows7 64 bit|Ruby 2.0.0 | ○ |動くが一部ライブラリで警告が出る |
253
+ |Mac OS X |Ruby x.x.x | △ |動作未確認 |
254
+ |Linux |Ruby 1.9.3 | ○ |SL6で軽く確認。folderとbrowserは動かない|
255
+
256
+ > ◎:動作確認済み、○:動くが一部に何か問題がありそう、△:多分動くかも、×:動きません
257
+
258
+ send コマンドに関しては現在 Windows 専用となっております。要望と情報があれば対応します。
259
+
260
+ ### 端末の自動認識での対応リスト
261
+
262
+ |電子書籍端末名 |対応状況|備考 |
263
+ |--------------------|:------:|--------------------------------------------------------------|
264
+ |Kindle Paperwhite | ◎ |表示の確認も動作確認も済。この端末を元にチューニングしています|
265
+ |Kindle Fire | △ |動くかもしれませんが未確認 |
266
+ |Kobo シリーズ | △ |情報を元に設定してありますが、動作未確認です。多分動きます |
267
+ |Sony Reader シリーズ| ? |情報が全くありません |
268
+ |他各種端末/アプリ | ? |USBにつながるタイプならまだ望みはあります |
269
+
270
+ Kobo については暫定で対応しておりますが、動作未確認です。
271
+ Kindle Paperwhite 以外の環境の対応については、以下の情報があれば対応可能です。(Windowsの場合)
272
+ - USB接続した場合のボリュームラベル
273
+ - 書籍データを保存するフォルダ名
274
+ - 対応電子書籍データの種類(.epubかどうか等)
275
+
276
+ 出力したEPUBを手動でコピーする分には動作対応などは全く関係は無いです。
277
+
91
278
  添付のDMincho.ttfについて - About DMincho font
92
279
  ----------------------------------------------
93
280
  WEB小説でよく見かける「あ゛」のような表現を、縦書でも再現するための濁点つきフォントです。
94
281
 
95
282
  青キン明朝フォントをカスタマイズして使用しています。
96
283
 
97
- オリジナルはIPA明朝フォントであり、ライセンスは IPAフォントライセンスv1.0 の元に「派生プログラム」として
284
+ オリジナルはIPA明朝フォントであり、ライセンスは **IPAフォントライセンスv1.0** の元に「派生プログラム」として
98
285
  再配布されています。
99
286
 
100
287
  ライセンスに基づく一般公開は以下のURLになります。また、
@@ -102,14 +289,13 @@ WEB小説でよく見かける「あ゛」のような表現を、縦書でも
102
289
 
103
290
  http://ux.getuploader.com/whiteleaf/download/23/ipam.rar
104
291
 
105
- Changes
106
- -------
292
+ 更新履歴 - ChangeLog
293
+ --------------------
107
294
 
108
- 1.0.2 : 2013/02/24
109
- - フォントのライセンスについて明確に記載した
110
-
111
- 1.0.1 : 2013/02/24
112
- - folder コマンドが正常に機能していないバグを修正
295
+ 1.1.0.rc1 : 2013/03/02
296
+ - 1.1.0の正式リリースに向けてのテストリリース
297
+ (1.0.x 系はテスト用非公開バージョン)
113
298
 
114
299
  1.0.0 : 2013/02/24
115
- - first release
300
+ - first release (create gem repository)
301
+
@@ -17,6 +17,10 @@ module Command
17
17
  narou browser n9669bk
18
18
  narou browser musyoku
19
19
  EOS
20
+
21
+ @opt.on("-v", "--vote", "指定した小説の投票・感想を投稿するページを表示する") {
22
+ @options["vote"] = true
23
+ }
20
24
  end
21
25
 
22
26
  def execute(argv)
@@ -26,13 +30,22 @@ module Command
26
30
  return
27
31
  end
28
32
  argv.each do |target|
29
- toc_url = Downloader.get_toc_url(target)
30
- unless toc_url
33
+ data = Downloader.get_data_by_target(target)
34
+ unless data
31
35
  warn "#{target} は存在しません"
32
36
  next
33
37
  end
34
- Helper.open_url_by_browser(toc_url)
35
- puts toc_url
38
+ toc_url = data["toc_url"]
39
+ if @options["vote"]
40
+ # TODO: 最新話の場所をAPIで取得する
41
+ data_dir = Downloader.get_novel_data_dir_by_target(data["id"])
42
+ latest_index = YAML.load_file(File.join(data_dir, Downloader::TOC_FILE_NAME))["subtitles"].last["index"]
43
+ open_url = "#{toc_url + latest_index}/#f_cr"
44
+ else
45
+ open_url = toc_url
46
+ end
47
+ Helper.open_url_by_browser(open_url)
48
+ puts open_url
36
49
  end
37
50
  end
38
51
 
@@ -65,6 +65,9 @@ module Command
65
65
  @opt.on("-i", "--inspect", "小説状態の調査結果を表示する") {
66
66
  @options["inspect"] = true
67
67
  }
68
+ @opt.on("-v", "--verbose", "AozoraEpub3, kindlegen の標準出力を全て表示します") {
69
+ @options["verbose"] = true
70
+ }
68
71
  @opt.separator <<-EOS
69
72
 
70
73
  Configuration:
@@ -84,14 +87,6 @@ module Command
84
87
  end
85
88
  end
86
89
 
87
- def get_device
88
- device_name = LocalSetting.get["local_setting"]["device"]
89
- if device_name && Device.exists?(device_name)
90
- return Device.new(device_name)
91
- end
92
- nil
93
- end
94
-
95
90
  def execute(argv)
96
91
  load_local_settings # @opt.on 実行前に設定ロードしたいので super 前で実行する
97
92
  super
@@ -113,7 +108,7 @@ module Command
113
108
  return
114
109
  end
115
110
  end
116
- @device = get_device
111
+ @device = Narou.get_device
117
112
  convert_novels(argv)
118
113
  end
119
114
 
@@ -132,9 +127,9 @@ module Command
132
127
  end
133
128
  res = NovelConverter.convert(target, @output_filename, @options["inspect"])
134
129
  end
130
+ next unless res
135
131
  @converted_txt_path = res[:converted_txt_path]
136
132
  @use_dakuten_font = res[:use_dakuten_font]
137
- next unless @converted_txt_path
138
133
 
139
134
  ebook_file = convert_txt_to_ebook_file
140
135
  next if ebook_file.nil?
@@ -180,7 +175,7 @@ module Command
180
175
  def convert_txt_to_ebook_file
181
176
  return false if @options["no-epub"]
182
177
  # epub
183
- status = NovelConverter.txt_to_epub(@converted_txt_path, @use_dakuten_font, nil, @device)
178
+ status = NovelConverter.txt_to_epub(@converted_txt_path, @use_dakuten_font, nil, @device, @options["verbose"])
184
179
  return nil if status != :success
185
180
  if @device && @device.kobo?
186
181
  epub_ext = @device.ebook_file_ext
@@ -194,7 +189,7 @@ module Command
194
189
  end
195
190
 
196
191
  # mobi
197
- status = NovelConverter.epub_to_mobi(epub_path)
192
+ status = NovelConverter.epub_to_mobi(epub_path, @options["verbose"])
198
193
  return nil if status != :success
199
194
  mobi_path = epub_path.sub(/\.epub$/, @device.ebook_file_ext)
200
195
 
@@ -42,23 +42,31 @@ module Command
42
42
  return
43
43
  end
44
44
  argv.each.with_index(1) do |target, i|
45
+ download_target ||= target
45
46
  Helper.print_horizontal_rule if i > 1
46
- data = Downloader.get_data_by_target(target)
47
- if Narou.novel_frozen?(target)
47
+ data = Downloader.get_data_by_target(download_target)
48
+ if Narou.novel_frozen?(download_target)
48
49
  puts "#{data["title"]} は凍結中です\nダウンロードを中止しました"
49
50
  next
50
51
  end
51
52
  if !@options["force"] && data
52
- puts "#{target} はダウンロード済みです。"
53
- puts "ID: #{data["id"]}"
54
- puts "title: #{data["title"]}"
53
+ if Downloader.get_novel_data_dir_by_target(download_target)
54
+ puts "#{download_target} はダウンロード済みです。"
55
+ puts "ID: #{data["id"]}"
56
+ puts "title: #{data["title"]}"
57
+ else
58
+ if Helper.confirm("再ダウンロードしますか")
59
+ download_target = data["toc_url"]
60
+ redo
61
+ end
62
+ end
55
63
  next
56
64
  end
57
- unless Downloader.start(target, @options["force"])
65
+ unless Downloader.start(download_target, @options["force"])
58
66
  next
59
67
  end
60
68
  unless @options["no-convert"]
61
- Convert.execute_and_rescue_exit([target])
69
+ Convert.execute_and_rescue_exit([download_target])
62
70
  end
63
71
  end
64
72
  end
@@ -27,8 +27,12 @@ module Command
27
27
  end
28
28
  argv.each do |target|
29
29
  dir = Downloader.get_novel_data_dir_by_target(target)
30
- Helper.open_directory_by_os_filer(dir)
31
- puts dir
30
+ if dir
31
+ Helper.open_directory_by_os_filer(dir)
32
+ puts dir
33
+ else
34
+ warn "#{target} は存在しません"
35
+ end
32
36
  end
33
37
  end
34
38
 
@@ -56,7 +56,7 @@ module Command
56
56
  init_aozoraepub3
57
57
  puts "初期化が完了しました!"
58
58
  puts "現在のフォルダ下で各種コマンドが使用出来るようになりました。"
59
- puts "まずは narou --help で簡単な説明を御覧ください。"
59
+ puts "まずは narou help で簡単な説明を御覧ください。"
60
60
  end
61
61
  end
62
62
 
@@ -33,13 +33,9 @@ module Command
33
33
 
34
34
  def get_device(argv)
35
35
  if Device.exists?(argv.first)
36
- return Device.new(argv.shift)
36
+ return Narou.get_device(argv.shift)
37
37
  end
38
- local_setting_device = LocalSetting.get["local_setting"]["device"]
39
- if local_setting_device
40
- return Device.new(local_setting_device)
41
- end
42
- nil
38
+ Narou.get_device
43
39
  end
44
40
 
45
41
  def execute(argv)
@@ -180,7 +180,7 @@ class ConverterBase
180
180
  data.gsub!(/([!?!?]+)([^!?!?])/) do
181
181
  m1, m2 = $1, $2
182
182
  m2 = " " if m2 == " "
183
- if m2 =~ /[^」]』】〉》〕>>≫))"”’ ☆★♪[]/
183
+ if m2 =~ /[^」]』】〉》〕>>≫))"”’ ☆★♪[―]/
184
184
  "#{m1} #{m2}"
185
185
  else
186
186
  "#{m1}#{m2}"
@@ -25,6 +25,14 @@ class Device
25
25
  DEVICES.include?(device.downcase)
26
26
  end
27
27
 
28
+ def self.create(device_name)
29
+ @@device_cache ||= {}
30
+ name = device_name.downcase
31
+ return @@device_cache[name] ||= new(name)
32
+ end
33
+
34
+ private_class_method :new
35
+
28
36
  def initialize(device_name)
29
37
  unless Device.exists?(device_name)
30
38
  raise UnknownDevice, "#{device_name} は存在しません"
@@ -84,7 +84,7 @@ class Downloader
84
84
  #
85
85
  # target の種別を判別する
86
86
  #
87
- # ncodeの場合は破壊的に小文字に変更する
87
+ # ncodeの場合、targetを破壊的に変更する
88
88
  #
89
89
  def self.get_target_type(target)
90
90
  case target
@@ -112,23 +112,22 @@ class Downloader
112
112
  when :url, :ncode
113
113
  toc_url = get_toc_url(target)
114
114
  data = @@database.get_data("toc_url", toc_url)
115
- id = data["id"]
116
115
  when :other
117
116
  data = @@database.get_data("title", target)
118
- id = data["id"]
119
117
  when :id
120
- id = target.to_i
121
- data = @@database[id]
118
+ data = @@database[target.to_i]
122
119
  end
123
120
  return nil unless data
124
- path = File.join(Database.archive_root_path, data["sitename"], data["title"])
121
+ id = data["id"]
122
+ file_title = data["file_title"] || data["title"] # 互換性維持のための処理
123
+ path = File.join(Database.archive_root_path, data["sitename"], file_title)
125
124
  if File.exists?(path)
126
125
  return path
127
126
  else
128
127
  @@database.delete(id)
129
128
  @@database.save_database
130
129
  warn "#{path} が見つかりません。"
131
- warn "保存ディレクトリが消去されていたため、管理リストから削除しました。"
130
+ warn "保存フォルダが消去されていたため、データベースのインデックスを削除しました。"
132
131
  return nil
133
132
  end
134
133
  end
@@ -331,6 +330,7 @@ class Downloader
331
330
  "id" => @id,
332
331
  "author" => @setting["author"],
333
332
  "title" => @setting["title"],
333
+ "file_title" => @file_title,
334
334
  "toc_url" => @setting["toc_url"],
335
335
  "sitename" => @setting["name"],
336
336
  "last_update" => Time.now
@@ -367,6 +367,7 @@ class Downloader
367
367
  end
368
368
  @setting.multi_match(toc_source, "title", "author", "story", "tcode")
369
369
  @title = @setting["title"]
370
+ @file_title = Helper.replace_filename_special_chars(@title)
370
371
  toc_objects = {
371
372
  "title" => @title,
372
373
  "author" => @setting["author"],
@@ -413,6 +414,7 @@ class Downloader
413
414
  "href" => @setting["href"],
414
415
  "chapter" => @setting["chapter"],
415
416
  "subtitle" => @setting["subtitle"],
417
+ "file_subtitle" => Helper.replace_filename_special_chars(@setting["subtitle"]),
416
418
  "subdate" => @setting["subdate"],
417
419
  "subupdate" => @setting["subupdate"]
418
420
  }
@@ -441,12 +443,12 @@ class Downloader
441
443
  else
442
444
  sleep(interval_sleep_time) if i > 0
443
445
  end
444
- index, subtitle = subtitle_info["index"], subtitle_info["subtitle"]
446
+ index, subtitle, file_subtitle = %w(index subtitle file_subtitle).map {|k| subtitle_info[k] }
445
447
  puts "第#{index}部分 #{subtitle} (#{i+1}/#{max})"
446
448
  section_element = a_section_download(subtitle_info)
447
449
  info = subtitle_info.dup
448
450
  info["element"] = section_element
449
- section_file_name = "#{index} #{subtitle}.yaml"
451
+ section_file_name = "#{index} #{file_subtitle}.yaml"
450
452
  section_file_path = File.join(SECTION_SAVE_DIR_NAME, section_file_name)
451
453
  move_to_cache_dir(section_file_path)
452
454
  save_novel_data(section_file_path, info)
@@ -546,8 +548,8 @@ class Downloader
546
548
  #
547
549
  # 小説データの格納ディレクトリパス
548
550
  def get_novel_data_dir
549
- raise "小説名がまだ設定されていません" unless @title
550
- File.join(Database.archive_root_path, @setting["name"], @title)
551
+ raise "小説名がまだ設定されていません" unless @file_title
552
+ File.join(Database.archive_root_path, @setting["name"], @file_title)
551
553
  end
552
554
 
553
555
  #
@@ -73,6 +73,10 @@ module Helper
73
73
  puts "―" * 35
74
74
  end
75
75
 
76
+ def self.replace_filename_special_chars(str)
77
+ str.tr("/:*?\"<>|.", "/:*?”〈〉|.").gsub("\\", "¥")
78
+ end
79
+
76
80
  #
77
81
  # 外部コマンド実行中の待機ループの処理を書けるクラス
78
82
  #
@@ -192,7 +192,9 @@ class Inspector
192
192
  #
193
193
  def inspect_indent(data)
194
194
  dont_indent_line_count = data.scan(/^[^#{IGNORE_INDENT_CHAR}]/).count
195
- line_count = data.lines.count
195
+ lines = data.lines
196
+ # MEMO: Enumerable#size (via http://jp.rubyist.net/magazine/?0041-200Special-note#l11)
197
+ line_count = (lines.respond_to?(:size) ? lines.size : lines.count)
196
198
  ratio = dont_indent_line_count / line_count.to_f
197
199
  return ratio > AUTO_INDENT_THRESHOLD_RATIO
198
200
  end
@@ -56,8 +56,7 @@ end
56
56
  # buffer
57
57
  # end
58
58
  # end
59
- def load_converter(archive_path)
60
- title = File.basename(archive_path)
59
+ def load_converter(title, archive_path)
61
60
  converter_path = File.join(archive_path, "converter.rb")
62
61
  if File.exists?(converter_path)
63
62
  if Helper.os_windows?
@@ -7,6 +7,7 @@ require "fileutils"
7
7
  require_relative "helper"
8
8
  require_relative "localsetting"
9
9
  require_relative "globalsetting"
10
+ require_relative "device"
10
11
 
11
12
  module Narou
12
13
  LOCAL_SETTING_DIR = ".narou"
@@ -129,8 +130,10 @@ module Narou
129
130
  end
130
131
 
131
132
  def self.create_novel_filename(novel_data, ext = "")
132
- info = Hash[novel_data.map { |k, v| [k, v.sub(/^[  ]*(.+?)[  ]*$/, "\\1")] }]
133
- "[#{info["author"]}] #{info["title"]}#{ext}"
133
+ author, title = %w(author title).map { |k|
134
+ Helper.replace_filename_special_chars(novel_data[k])
135
+ }
136
+ "[#{author}] #{title}#{ext}"
134
137
  end
135
138
 
136
139
  def self.get_mobi_path(target)
@@ -143,4 +146,12 @@ module Narou
143
146
  dir = Downloader.get_novel_data_dir_by_target(target)
144
147
  File.join(dir, create_novel_filename(data, ext))
145
148
  end
149
+
150
+ def self.get_device(device_name = nil)
151
+ device_name = LocalSetting.get["local_setting"]["device"] unless device_name
152
+ if device_name && Device.exists?(device_name)
153
+ return Device.create(device_name)
154
+ end
155
+ nil
156
+ end
146
157
  end
@@ -80,7 +80,7 @@ class NovelConverter
80
80
  #
81
81
  # 返り値:正常終了 :success、エラー終了 :error、AozoraEpub3が見つからなかった nil
82
82
  #
83
- def self.txt_to_epub(filename, use_dakuten_font = false, dst_dir = nil, device = nil)
83
+ def self.txt_to_epub(filename, use_dakuten_font = false, dst_dir = nil, device = nil, verbose = false)
84
84
  abs_srcpath = File.expand_path(filename)
85
85
  #cover_path = File.join(File.dirname(filename), "cover.jpg")
86
86
  cover_option = ""
@@ -103,15 +103,15 @@ class NovelConverter
103
103
  pwd = Dir.pwd
104
104
 
105
105
  aozoraepub3_path = Narou.get_aozoraepub3_path
106
- aozoraepub3_basename = File.basename(aozoraepub3_path)
107
- aozoraepub3_dir = File.dirname(aozoraepub3_path)
108
- unless File.exists?(aozoraepub3_path)
106
+ unless aozoraepub3_path
109
107
  warn "AozoraEpub3が見つからなかったので、EPUBが出力出来ませんでした"
110
108
  return nil
111
109
  end
110
+ aozoraepub3_basename = File.basename(aozoraepub3_path)
111
+ aozoraepub3_dir = File.dirname(aozoraepub3_path)
112
112
 
113
113
  Dir.chdir(aozoraepub3_dir)
114
- command = %!java -cp #{aozoraepub3_basename} AozoraEpub3 -enc UTF-8 ! +
114
+ command = %!java -cp #{aozoraepub3_basename} AozoraEpub3 -enc UTF-8 -of DUMMY ! +
115
115
  %!#{cover_option} #{dst_option} #{ext_option} "#{abs_srcpath}"!
116
116
  if Helper.os_windows?
117
117
  command = "cmd /c " + command.encode(Encoding::Windows_31J)
@@ -121,18 +121,25 @@ class NovelConverter
121
121
  res = Helper::AsyncCommand.exec(command) do
122
122
  print "."
123
123
  end
124
+ visible_aozora_fonts_directory unless use_dakuten_font
124
125
  # MEMO: Windows環境以外で出力される文字コードはSJISなのか?
125
126
  stdout_capture = res[0].force_encoding(Encoding::Shift_JIS).encode(Encoding::UTF_8)
126
127
 
127
128
  Dir.chdir(pwd)
128
- error_list = stdout_capture.scan(/^\[ERROR\].+$/)
129
+
130
+ if verbose
131
+ puts
132
+ puts "==== AozoraEpub3 stdout capture " + "=" * 47
133
+ puts stdout_capture.strip
134
+ puts "=" * 79
135
+ end
136
+
137
+ error_list = stdout_capture.scan(/^(?:\[ERROR\]|エラーが発生しました :).+$/)
129
138
  warn_list = stdout_capture.scan(/^\[WARN\].+$/)
130
139
  info_list = stdout_capture.scan(/^\[INFO\].+$/)
131
140
  if !error_list.empty? || !warn_list.empty? || !info_list.empty?
132
141
  puts
133
- puts error_list
134
- puts warn_list
135
- puts info_list
142
+ puts error_list, warn_list, info_list
136
143
  unless error_list.empty?
137
144
  # AozoraEpub3 のエラーにはEPUBが出力されないエラーとEPUBが出力されるエラーの2種類ある。
138
145
  # EPUBが出力される場合は「変換完了」という文字があるのでそれを検出する
@@ -144,8 +151,6 @@ class NovelConverter
144
151
  end
145
152
  puts "変換しました"
146
153
  :success
147
- ensure
148
- visible_aozora_fonts_directory unless use_dakuten_font
149
154
  end
150
155
 
151
156
  #
@@ -154,7 +159,7 @@ class NovelConverter
154
159
  #
155
160
  # 返り値:正常終了 :success、エラー終了 :error、中断終了 :abort、kindlegenがなかった nil
156
161
  #
157
- def self.epub_to_mobi(epub_path)
162
+ def self.epub_to_mobi(epub_path, verbose = false)
158
163
  kindlegen_path = File.join(File.dirname(Narou.get_aozoraepub3_path), "kindlegen")
159
164
  if Dir.glob(kindlegen_path + "*").empty?
160
165
  warn "kindlegenが見つかりませんでした。AozoraEpub3と同じディレクトリにインストールして下さい"
@@ -171,6 +176,14 @@ class NovelConverter
171
176
  end
172
177
  stdout_capture, _, proccess_status = res
173
178
  stdout_capture.force_encoding(Encoding::UTF_8)
179
+
180
+ if verbose
181
+ puts
182
+ puts "==== kindlegen stdout capture " + "=" * 49
183
+ puts stdout_capture.gsub("\n\n", "\n").strip
184
+ puts "=" * 79
185
+ end
186
+
174
187
  if proccess_status.exited?
175
188
  if proccess_status.exitstatus == 2
176
189
  puts ""
@@ -202,13 +215,15 @@ class NovelConverter
202
215
  end
203
216
 
204
217
  def load_novel_section(subtitle_info)
205
- path = File.join(@section_save_dir, "#{subtitle_info["index"]} #{subtitle_info["subtitle"]}.yaml")
218
+ file_subtitle = subtitle_info["file_subtitle"] || subtitle_info["subtitle"] # 互換性維持のため
219
+ path = File.join(@section_save_dir, "#{subtitle_info["index"]} #{file_subtitle}.yaml")
206
220
  YAML.load_file(path)
207
221
  end
208
222
 
209
223
  def create_novel_text_by_template(sections)
210
224
  toc = @toc
211
225
  cover_chuki = @cover_chuki
226
+ device = Narou.get_device
212
227
  Template.get(NOVEL_TEXT_TEMPLATE_NAME, binding)
213
228
  end
214
229
 
@@ -232,11 +247,11 @@ class NovelConverter
232
247
  # 変換処理メイン
233
248
  #
234
249
  def convert_main(text = nil)
235
- puts "ID:#{@novel_id} #{@novel_title} の変換を開始"
250
+ puts "ID:#{@novel_id} #{@novel_title} の変換を開始"
236
251
  sections = []
237
252
  @cover_chuki = create_cover_chuki
238
253
 
239
- conv = load_converter(@setting.archive_path).new(@setting, @inspector, @illustration)
254
+ conv = load_converter(@novel_title, @setting.archive_path).new(@setting, @inspector, @illustration)
240
255
  if text
241
256
  result = conv.convert(text, "textfile")
242
257
  unless @setting.enable_enchant_midashi
@@ -3,7 +3,11 @@
3
3
  # Copyright 2013 whiteleaf. All rights reserved.
4
4
  #
5
5
 
6
- Version = "1.0.2"
6
+ Version = "1.1.0.rc1"
7
7
 
8
8
  cv_path = File.expand_path(File.join(File.dirname(__FILE__), "../commitversion"))
9
- CommitVersion = File.read(cv_path)
9
+ if File.exists?(cv_path)
10
+ CommitVersion = File.read(cv_path)
11
+ else
12
+ CommitVersion = `git describe --always`.strip + "(develop)"
13
+ end
@@ -2,8 +2,11 @@
2
2
  # -*- coding: UTF-8 -*-
3
3
  lib = File.expand_path("../lib", __FILE__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
5
6
  require "version"
6
7
 
8
+ require "fileutils"
9
+
7
10
  module Narou
8
11
  def self.create_git_commit_version
9
12
  File.write("commitversion", `git describe --always`.strip)
@@ -11,6 +14,12 @@ module Narou
11
14
  end
12
15
  end
13
16
 
17
+ at_exit do
18
+ if File.exists?("commitversion")
19
+ FileUtils.rm("commitversion")
20
+ end
21
+ end
22
+
14
23
  Encoding.default_external = Encoding::UTF_8
15
24
 
16
25
  Gem::Specification.new do |gem|
@@ -27,9 +36,16 @@ Gem::Specification.new do |gem|
27
36
  }.split("\n").join
28
37
 
29
38
  gem.post_install_message = <<-EOS
30
- narou コマンドのインストールが完了しました。
31
- 小説を管理するための任意のフォルダで narou init コマンドを実行して下さい。
39
+ #{"*" * 79}
40
+
41
+ narou コマンドのインストール or アップデートが完了しました。
42
+ 詳しい説明は `narou help' コマンドをご覧下さい。
32
43
 
44
+ NOTICE
45
+ 初めてこのアプリケーションを使う場合、小説管理用のフォルダを初期化する必要があります。
46
+ 任意のフォルダで `narou init' を実行して下さい。
47
+
48
+ #{"*" * 79}
33
49
  EOS
34
50
 
35
51
  gem.required_ruby_version = ">=1.9.3"
@@ -39,4 +55,4 @@ narou コマンドのインストールが完了しました。
39
55
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
40
56
  #gem.require_paths = ["lib"]
41
57
  #gem.add_dependency ""
42
- end
58
+ end
data/narou.rb CHANGED
@@ -6,23 +6,28 @@
6
6
  # Copyright 2013 whiteleaf. All rights reserved.
7
7
  #
8
8
 
9
- $debug = File.exists?(File.join(File.expand_path(__FILE__), "debug"))
9
+ $debug = File.exists?(File.join(File.expand_path(File.dirname($0)), "debug"))
10
10
  Encoding.default_external = Encoding::UTF_8
11
11
 
12
- require_relative "lib/logger" # 標準出力と標準エラーのロギング開始
12
+ require_relative "lib/logger"
13
13
  require_relative "lib/version"
14
14
  require_relative "lib/commandline"
15
15
 
16
- if $debug
17
- begin
18
- CommandLine.run(ARGV)
19
- rescue Exception => e
20
- puts $@.shift + ": #{e.message} (#{e.class})"
16
+ rescue_level = $debug ? Exception : StandardError
17
+
18
+ begin
19
+ display_backtrace = ARGV.delete("--backtrace")
20
+ display_backtrace ||= $debug
21
+ CommandLine.run(ARGV)
22
+ rescue rescue_level => e
23
+ warn $@.shift + ": #{e.message} (#{e.class})"
24
+ if display_backtrace
21
25
  $@.each do |b|
22
26
  warn " from #{b}"
23
27
  end
24
- exit 1
28
+ else
29
+ puts " エラーが発生したため終了しました。"
30
+ puts " 詳細なエラーは --backtrace オプションを付けて再度実行して下さい。"
25
31
  end
26
- else
27
- CommandLine.run(ARGV)
32
+ exit 1
28
33
  end
@@ -13,13 +13,17 @@
13
13
  [#改ページ]
14
14
  <% if section["chapter"] != "" -%>
15
15
  [#ページの左右中央]
16
+ <% if device && device.name == "Kindle" -%>
16
17
  [#ここからキンドル左右中央]
18
+ <% end -%>
17
19
  <%= toc["title"] %>
18
20
 
19
21
  [#ここから大見出し]<%= section["chapter"] %>[#ここで大見出し終わり]
20
22
   
21
23
   
24
+ <% if device && device.name == "Kindle" -%>
22
25
  [#ここでキンドル左右中央終わり]
26
+ <% end -%>
23
27
  [#改ページ]
24
28
  <% end -%>
25
29
  [#3字下げ][#ここから中見出し]<%= section["subtitle"].rstrip %>[#ここで中見出し終わり]
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: narou
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
5
- prerelease:
4
+ version: 1.1.0.rc1
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - whiteleaf7
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-24 00:00:00.000000000 Z
12
+ date: 2013-03-02 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: 小説家になろうで公開されている小説の管理、及び電子書籍データへの変換を支援します。縦書用に特化されており、横書き用に特化されたWEB小説を違和感なく縦書で読むことが出来るようになります。
15
15
  email:
@@ -21,7 +21,7 @@ extra_rdoc_files: []
21
21
  files:
22
22
  - .gitattributes
23
23
  - .gitignore
24
- - Changes.md
24
+ - ChangeLog.txt
25
25
  - Gemfile
26
26
  - README.md
27
27
  - Rakefile
@@ -91,12 +91,9 @@ files:
91
91
  - commitversion
92
92
  homepage: http://whiteleaf.hatenablog.com/
93
93
  licenses: []
94
- post_install_message: ! 'narou コマンドのインストールが完了しました。
95
-
96
- 小説を管理するための任意のフォルダで narou init コマンドを実行して下さい。
97
-
98
-
99
- '
94
+ post_install_message: ! "*******************************************************************************\n\nnarou
95
+ コマンドのインストール or アップデートが完了しました。\n詳しい説明は `narou help' コマンドをご覧下さい。\n\n NOTICE\n 初めてこのアプリケーションを使う場合、小説管理用のフォルダを初期化する必要があります。\n
96
+ \ 任意のフォルダで `narou init' を実行して下さい。\n\n*******************************************************************************\n"
100
97
  rdoc_options: []
101
98
  require_paths:
102
99
  - lib
@@ -109,9 +106,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
109
106
  required_rubygems_version: !ruby/object:Gem::Requirement
110
107
  none: false
111
108
  requirements:
112
- - - ! '>='
109
+ - - ! '>'
113
110
  - !ruby/object:Gem::Version
114
- version: '0'
111
+ version: 1.3.1
115
112
  requirements: []
116
113
  rubyforge_project:
117
114
  rubygems_version: 1.8.25