makimono 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ab2d90e60b3c40579bb3a00023e0d1b4d9d2dbdeeb2f6646ba966bc2cf83dda
4
- data.tar.gz: 28854075a1ea080b97038464b90ff37e6ec42a6ffc9b9646fa27ab3989650670
3
+ metadata.gz: 92d6d41d6c631de78c30e6ad85736cb83b8424f08d66bb71ff0be880dbd36390
4
+ data.tar.gz: 5fce9f2686b48071bdec692c7e5de2e43ac3b2b2f9ab29aa7e4037bfbb46037a
5
5
  SHA512:
6
- metadata.gz: 77ff25682614bea8d5c3c2444b53ad07e8b702f9c6063e84f639b790b773001b230961cac9796a94018d5cc0440a6072f56a551e787d89bec3af097ae08605a2
7
- data.tar.gz: 11cf570ef3a45c9127f0a81741a84d68bd97ce62a7f6709c11de6a27fac24439764414f7249522e273eec68e2a3eda9bbf4d9d4d48a0f57d9a611abd4e0475f8
6
+ metadata.gz: '08163bc86fa01c7db77ad93bae0124e692e6722e15d2fbb0bdf5670d24f62785df1517b682d6511e83c041e72c22a9fa61c0928b5bef7ae5922da6c438ba402e'
7
+ data.tar.gz: c971e8899e7dc09fd8fb17acf3cb4ff8243625d29aa8e09875e2ac47741de498ca2834116844a788efaf2e2d3e698025758a1de4118783898116cb455b5c6cc3
@@ -0,0 +1 @@
1
+ github: fuji-nakahara
@@ -3,6 +3,7 @@ require:
3
3
 
4
4
  AllCops:
5
5
  NewCops: enable
6
+ TargetRubyVersion: 2.6
6
7
 
7
8
  # rubocop
8
9
 
@@ -10,9 +11,6 @@ Metrics/BlockLength:
10
11
  Exclude:
11
12
  - spec/**/*
12
13
 
13
- Style/ClassAndModuleChildren:
14
- Enabled: false
15
-
16
14
  Style/Documentation:
17
15
  Enabled: false
18
16
 
@@ -6,6 +6,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.2.0] - 2020-10-24
10
+
11
+ ### Added
12
+
13
+ - Add "Getting Started" section to README.
14
+ - Add Japanese README.
15
+
16
+ ### Changed
17
+
18
+ - Update `makimono.yml` generated by `makimono new` command.
19
+ - Stop generating `out` directory by `makimono new` command.
20
+ - Enable to give non-array options for CommonMarker config.
21
+
9
22
  ## [0.1.1] - 2020-10-12
10
23
 
11
24
  ### Fixed
@@ -16,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
29
 
17
30
  - First release!
18
31
 
19
- [Unreleased]: https://github.com/fuji-nakahara/makimono/compare/v0.1.1...HEAD
32
+ [Unreleased]: https://github.com/fuji-nakahara/makimono/compare/v0.2.0...HEAD
33
+ [0.2.0]: https://github.com/fuji-nakahara/makimono/compare/v0.1.1...v0.2.0
20
34
  [0.1.1]: https://github.com/fuji-nakahara/makimono/compare/v0.1.0...v0.1.1
21
35
  [0.1.0]: https://github.com/fuji-nakahara/makimono/releases/tag/v0.1.0
@@ -0,0 +1,187 @@
1
+ # Makimono
2
+
3
+ [English](README.md)
4
+
5
+ Makimono はマークダウンで書かれたファイル群から電子書籍を生成するコマンドラインツールを提供します。
6
+
7
+ ## はじめに
8
+
9
+ まず、Makimono をインストールします。
10
+
11
+ $ gem install makimono
12
+
13
+ 次に、`mybook` ディレクトリに Makimono プロジェクトを作成し、移動します。
14
+
15
+ $ makimono new mybook
16
+ $ cd mybook
17
+
18
+ `src` ディレクトリにあるマークダウンファイルに電子書籍にしたいテキストを書きます。
19
+
20
+ $ vi src/01-mybook.md
21
+
22
+ 編集が完了したら、電子書籍を作成します。
23
+
24
+ $ makimono build
25
+
26
+ すると、`out/book.epub` に EPUB ファイルが作成されます。
27
+
28
+ ## ファイル名の規約
29
+
30
+ Makimono では、ソースディレクトリ(デフォルトではカレントディレクトリの `src`)内のファイルで、正規表現 `^(\d+)-(.+)$` にマッチするファイル名のものを電子書籍に含めるべきコンテンツとみなします。
31
+ たとえば `01-プロローグ.md` や `99-エピローグ.md` などです。
32
+ また、`-` 以前の数値をコンテンツ順序の決定に利用し、`-` 以降拡張子までの文字列をタイトルとみなします。
33
+
34
+ 正規表現にマッチしない場合は電子書籍の順序だったコンテンツを構成する要素とはみなしませんが、相対パスで参照することができます。
35
+ たとえば、`01-プロローグ.md` の中で画像 `sample.png` を表示したい場合、マークダウン記法を使って、
36
+
37
+ ```
38
+ ![サンプル](sample.png)
39
+ ```
40
+
41
+ のように記述し、`src` ディレクトリに `sample.png` を配置すれば、電子書籍でも画像を表示することができます。
42
+
43
+ ## 設定
44
+
45
+ Makimono はデフォルトでカレントディレクトリの `makimono.yml` を設定ファイルとみなします。
46
+ `--config` オプションで別のファイルを指定することもできます。
47
+
48
+ 利用可能な設定項目とデフォルト値は以下のとおりです。
49
+
50
+ ```yaml
51
+ # EPUB のメタデータ
52
+ # 詳しくは https://imagedrive.github.io/Submission/epub32/epub-packages.html を参照
53
+ identifier: # 指定しなかった場合は実行時に生成した UUID が設定される
54
+ modified: # 指定しなかった場合は現在時刻が設定される
55
+ title: 'No title'
56
+ language: 'ja'
57
+ creator: # 配列でも指定可能
58
+ contributor: # 配列でも指定可能
59
+ date:
60
+ page_progression_direction:
61
+
62
+ # Makimono 固有のビルド設定
63
+ source: 'src' # 電子書籍にするファイル群を置くディレクトリ
64
+ output: 'out' # 出力したファイルを置くディレクトリ
65
+ library: 'lib' # Makimono 拡張用のユーザーライブラリを置くディレクトリ
66
+ converters: [ 'Markdown' ] # 使用するコンバーターの配列。この順で変換が行われる
67
+ markdown: 'CommonMarker' # Markdown コンバーターで使用するマークダウンの種類。デフォルトは CommonMarker で FujiMarkdown も利用可能
68
+ CommonMarker: # CommonMarker の設定
69
+ options: 'DEFAULT' # 配列でも指定可
70
+ extensions: []
71
+ template: 'default.xhtml' # 使用する ERB テンプレートのパス。default.xhtml を指定した場合はプリセットが適用される
72
+ style: null # 使用する CSS のパス。fuji または fuji_tategaki を指定した場合はプリセットが適用される
73
+ generator: 'EPUB' # 使用するジェネレーター
74
+ ebook_file_name: 'book' # 電子書籍を出力するときのファイル名
75
+ ```
76
+
77
+ #### markdown
78
+
79
+ Makimono は [CommonMark](https://commonmark.org/) の Ruby 実装である [CommonMarker](https://github.com/gjtorikian/commonmarker) をデフォルトのマークダウンコンバーターとして使用します。
80
+ また、日本語小説用の拡張マークダウンである [FujiMarkdown](https://github.com/fuji-nakahara/fuji_markdown) を仕様するよう変更することも可能です。
81
+ 以下は、縦書き日本語小説用の設定例です。
82
+
83
+ ```yaml
84
+ page_progression_direction: rtl # ページ送りを右から左(right to left)にする
85
+ markdown: FujiMarkdown # マークダウンコンバーターとして FujiMarkdown を使用する
86
+ style: fuji_tategaki # プリセットの縦書きスタイルを用いる
87
+ ```
88
+
89
+ 後述のユーザーライブラリ機能を用いれば、kramdown など任意のマークダウンコンバーターを使用することもできます。
90
+
91
+ #### template
92
+
93
+ 設定 `template` にファイルパスを渡せば、マークダウン変換時に利用するテンプレートを変更可能です。
94
+ テンプレートとして指定されたファイルは ERB として処理されます。
95
+ 変数として、設定のハッシュオブジェクト `config`、[`Resource`](lib/makimono/resource.rb) クラスのインスタンス `resource`、マークダウン変換後の文字列 `body` の3つが渡されます。
96
+ 詳しい書き方はデフォルトの XHTML テンプレート [`default.xhtml`](lib/templates/default.xhtml.erb) を参考にしてください。
97
+
98
+ #### style
99
+
100
+ 設定 `style` に CSS ファイルのパスを渡せば、電子書籍で利用するスタイルを変更できます。
101
+ また、プリセットとして横書き日本語小説に適した [`fuji`](lib/styles/fuji.css) と縦書き日本語小説に適した [`fuji_tategaki`](lib/styles/fuji_tategaki.css) が用意されています。
102
+
103
+ ## ユーザーライブラリ
104
+
105
+ Makimono は Makimono 自体のコードを変更することなく Ruby で拡張できます。
106
+
107
+ 拡張用の Ruby ファイルはライブラリディレクトリ以下に配置すれば実行時に自動でロードされます。
108
+ デフォルトのライブラリディレクトリは `lib` ですが、設定 `library` でディレクトリパスを変更可能です。
109
+
110
+ また、gem として配布されている場合は、`Gemfile` で `makimono` group に含めれば実行時に自動でロードされます。
111
+
112
+ ```ruby
113
+ gem 'my_makimono_library', group: :makimono
114
+ ```
115
+
116
+ ### マークダウン
117
+
118
+ 独自のマークダウンコンバーターを使用するには、`Makimono::Converter::Markdown` 以下に `#render` メソッドを持つ新しいクラスを定義し、設定 `markdown` でクラス名を指定します。
119
+ 実装は [`CommonMarker`](lib/makimono/converter/markdown/commonmarker.rb) や [`FujiMarkdown`](lib/makimono/converter/markdown/fuji_markdown.rb) を参考にしてください。
120
+
121
+ たとえば、[kramdown](https://github.com/gettalong/kramdown) をマークダウンコンバーターとして利用するには、まず以下のようなクラス `Makimono::Converter::Markdown::Kramdown` を定義します。
122
+
123
+ ```ruby
124
+ require 'kramdown'
125
+
126
+ module Makimono
127
+ class Converter
128
+ class Markdown
129
+ class Kramdown
130
+ def initialize(config)
131
+ @config = config
132
+ end
133
+
134
+ def render(markdown)
135
+ ::Kramdown::Document.new(markdown).to_html
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+ ```
142
+
143
+ 次に設定 `markdown` でクラス名 `Kramdown` を指定します。
144
+
145
+ ```yaml
146
+ markdown: Kramdown
147
+ ```
148
+
149
+ ### コンバーター
150
+
151
+ 独自のコンバーターを使用するには、`Makimono::Converter` 以下に `#convertible?` と `#convert` メソッドを持つ新しいクラスを定義し、設定 `converters` でクラス名を指定します。
152
+ 実装は [`Markdown`](lib/makimono/converter/markdown.rb) を参考にしてください。
153
+
154
+ たとえば、タイトルのアンダースコア (`_`) を空白に変換するコンバーターを追加するには、まず以下のようなクラス `Makimono::Converter::UnderscoreToSpace` を定義します。
155
+
156
+ ```ruby
157
+ module Makimono
158
+ class Converter
159
+ class UnderscoreToSpace
160
+ def initialize(config)
161
+ @config = config
162
+ end
163
+
164
+ def convertible?(resource)
165
+ resource.ordered?
166
+ end
167
+
168
+ def convert(resource)
169
+ converted = resource.dup
170
+ converted.title = resource.title.gsub('_', ' ')
171
+ converted
172
+ end
173
+ end
174
+ end
175
+ end
176
+ ```
177
+
178
+ 次に設定 `converters` にクラス名 `UnderscoreToSpace` を追加します。
179
+
180
+ ```yaml
181
+ converters: [ 'Markdown', 'UnderscoreToSpace' ]
182
+ ```
183
+
184
+ ### ジェネレーター
185
+
186
+ 独自のジェネレーターを使用するには、`Makimono::Generator` 以下に `#generate` メソッドを持つ新しいクラスを定義し、設定 `generator` でクラス名を指定します。
187
+ 実装は [`Epub`](lib/makimono/generator/epub.rb) や [`SimpleFile`](lib/makimono/generator/simple_file.rb) を参考にしてください。
data/README.md CHANGED
@@ -1,26 +1,29 @@
1
1
  # Makimono
2
2
 
3
- Makimono is a simple ebook generator.
3
+ [日本語](README-ja.md)
4
4
 
5
- ## Installation
5
+ Makimono provides a command line tool to generate an ebook from a set of markdown files.
6
6
 
7
- Add this line to your application's Gemfile:
7
+ ## Getting Started
8
8
 
9
- ```ruby
10
- gem 'makimono'
11
- ```
9
+ First, install Makimono.
12
10
 
13
- And then execute:
11
+ $ gem install makimono
14
12
 
15
- $ bundle install
13
+ Next, create a Makimono project in the `mybook` directory.
16
14
 
17
- Or install it yourself as:
15
+ $ makimono new mybook
16
+ $ cd mybook
18
17
 
19
- $ gem install makimono
18
+ Write text on a markdown file in the `src` directory.
19
+
20
+ $ vi src/01-mybook.md
21
+
22
+ When you are done writing, create an ebook.
20
23
 
21
- ## Usage
24
+ $ makimono build
22
25
 
23
- TODO: Write usage instructions here
26
+ This will create an EPUB file in `out/book.epub`.
24
27
 
25
28
  ## Development
26
29
 
@@ -22,7 +22,6 @@ module Makimono
22
22
  copy_file('Gemfile')
23
23
  template('makimono.yml', { name: name })
24
24
  copy_file('src/01-Title.md', "src/01-#{name.capitalize}.md")
25
- create_file('out/.keep')
26
25
  end
27
26
 
28
27
  def run_bundle_install
@@ -11,23 +11,32 @@ module Makimono
11
11
 
12
12
  DEFAULTS = {
13
13
  # Makimono
14
- source: File.expand_path('src'),
15
- output: File.expand_path('out'),
16
- style: nil,
17
- template: 'default.xhtml',
18
- markdown: 'CommonMarker',
14
+ source: 'src',
15
+ output: 'out',
16
+ library: 'lib',
19
17
  converters: %w[Markdown],
18
+ markdown: 'CommonMarker',
19
+ CommonMarker: {
20
+ options: 'DEFAULT',
21
+ extensions: []
22
+ },
23
+ template: 'default.xhtml',
24
+ style: nil,
20
25
  generator: 'EPUB',
21
26
  ebook_file_name: 'book',
22
- library: File.expand_path('lib'),
23
27
 
24
28
  # EPUB
25
29
  identifier: "urn:uuid:#{SecureRandom.uuid}",
30
+ modified: Time.now,
26
31
  title: 'No title',
27
- language: 'ja'
32
+ language: 'ja',
33
+ creator: nil,
34
+ contributor: nil,
35
+ date: nil,
36
+ page_progression_direction: nil
28
37
  }.freeze
29
38
 
30
- def_delegators :@config, :[], :fetch, :dig, :slice
39
+ def_delegators :@config, :[], :fetch, :dig
31
40
 
32
41
  def initialize(config = {})
33
42
  @config = DEFAULTS.merge(config)
@@ -17,7 +17,11 @@ module Makimono
17
17
  private
18
18
 
19
19
  def options
20
- @config.dig(:CommonMarker, :options)&.map(&:upcase)&.map(&:to_sym) || :DEFAULT
20
+ if (options = @config.dig(:CommonMarker, :options))
21
+ Array(options).map(&:upcase).map(&:to_sym)
22
+ else
23
+ :DEFAULT
24
+ end
21
25
  end
22
26
 
23
27
  def extensions
@@ -19,6 +19,7 @@ module Makimono
19
19
  add_items([@config.style, *resources.reject(&:ordered?)].compact)
20
20
  add_ordered_items(resources.select(&:ordered?).sort_by(&:number))
21
21
 
22
+ FileUtils.mkdir_p(@config[:output]) unless Dir.exist?(@config[:output])
22
23
  @book.generate_epub("#{File.expand_path(@config[:ebook_file_name], @config[:output])}.epub")
23
24
  end
24
25
 
@@ -26,9 +27,9 @@ module Makimono
26
27
 
27
28
  def add_required_metadata
28
29
  @book.identifier = @config.fetch(:identifier)
30
+ @book.lastmodified = @config.fetch(:modified)
29
31
  @book.title = @config.fetch(:title)
30
32
  @book.language = @config.fetch(:language)
31
- @book.lastmodified = parse_config_time(:modified) if @config[:modified]
32
33
  rescue KeyError => e
33
34
  raise InvalidConfigurationError, "Required metadata not found: #{e.key}"
34
35
  end
@@ -41,7 +42,7 @@ module Makimono
41
42
  @book.add_contributor(contributor)
42
43
  end
43
44
 
44
- @book.add_date(parse_config_time(:date).iso8601) if @config[:date]
45
+ @book.add_date(@config[:date].to_time.iso8601) if @config[:date]
45
46
  end
46
47
 
47
48
  def add_items(resources)
@@ -60,12 +61,6 @@ module Makimono
60
61
  end
61
62
  end
62
63
  end
63
-
64
- def parse_config_time(key)
65
- Time.parse(@config[key].to_s)
66
- rescue ArgumentError
67
- raise InvalidConfigurationError, "Invalid time format: #{key}"
68
- end
69
64
  end
70
65
  end
71
66
  end
@@ -4,13 +4,18 @@ module Makimono
4
4
  class Resource
5
5
  ORDERED_BASENAME_REGEXP = /\A(?<number>\d+)-(?<title>.+)\z/.freeze
6
6
 
7
- attr_accessor :path, :content
7
+ attr_reader :path
8
+ attr_accessor :content
8
9
 
9
10
  def initialize(path, content)
10
- @path = path
11
+ self.path = path
11
12
  @content = content
12
13
  end
13
14
 
15
+ def path=(new_path)
16
+ @path = Pathname.new(new_path).cleanpath.to_s
17
+ end
18
+
14
19
  def dirname
15
20
  File.dirname(path)
16
21
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Makimono
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.0'
5
5
  end
@@ -1,3 +1,7 @@
1
- identifier: 'urn:uuid:<%= SecureRandom.uuid %>'
2
- title: '<%= config[:name].capitalize %>'
3
- ebook_file_name: '<%= config[:name] %>'
1
+ identifier: urn:uuid:<%= SecureRandom.uuid %>
2
+ title: <%= config[:name].capitalize %>
3
+ language: ja
4
+ creator:
5
+
6
+ style:
7
+ ebook_file_name: book
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: makimono
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fuji Nakahara
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-10-12 00:00:00.000000000 Z
11
+ date: 2020-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: commonmarker
@@ -74,6 +74,7 @@ executables:
74
74
  extensions: []
75
75
  extra_rdoc_files: []
76
76
  files:
77
+ - ".github/FUNDING.yml"
77
78
  - ".github/workflows/gem-push.yml"
78
79
  - ".github/workflows/ruby.yml"
79
80
  - ".gitignore"
@@ -83,6 +84,7 @@ files:
83
84
  - CODE_OF_CONDUCT.md
84
85
  - Gemfile
85
86
  - LICENSE.txt
87
+ - README-ja.md
86
88
  - README.md
87
89
  - Rakefile
88
90
  - bin/console