pubgen 0.1.2 → 0.1.3

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.
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Pubgen
2
2
 
3
- Pubgen is a simple command-line based epub generator. With the simple YAML
4
- file, Pubgen generate the epub file for you.
3
+ Pubgen is a command-line based epub generator. With a simple YAML, Pubgen make
4
+ a epub for you.
5
5
 
6
6
  ## Installation
7
7
 
@@ -14,7 +14,7 @@ $ gem install pubgen
14
14
 
15
15
  ```bash
16
16
  $ pubgen -h
17
- pubgen 0.1.0, a epub generator.
17
+ pubgen, a epub generator. (http://github.com/9beach/pubgen)
18
18
 
19
19
  Usage:
20
20
  pubgen <yaml file> [-o <epub file>] [-v]
@@ -28,15 +28,13 @@ Usage:
28
28
  ## Quick Start
29
29
 
30
30
  Prepare files (documents, images, style sheets, etc.) that make up the
31
- publication. iBooks requires strict xhtml format,
32
- [`tidy -asxhtml`] (http://tidy.sourceforge.net/) will be helpful.
31
+ publication. iBooks requires strict xhtml. [`tidy -asxhtml`]
32
+ (http://tidy.sourceforge.net/) will be helpful.
33
33
 
34
34
  ```bash
35
35
  $ find .
36
36
  .
37
37
  ./contents
38
- ./contents/a-1.html
39
- ./contents/a-2.html
40
38
  ./contents/a.html
41
39
  ./contents/b.html
42
40
  ./images
@@ -46,14 +44,14 @@ $ find .
46
44
  ./images/cover.jpg
47
45
  ./style.css
48
46
  ```
49
- Create the YAML file describing your publication. As a example,
47
+
48
+ Create the utf-8 encoded YAML file describing the publication. As a example,
50
49
  `will_oldham.yml`.
51
50
 
52
51
  ```yaml
53
52
  # METADATA: Publication metadata (title, author, publisher, etc.).
54
53
  #
55
54
  # See http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.2
56
- # -*- encoding: utf-8 -*-
57
55
  metadata:
58
56
  title: "Will Oldham: Wikipedia, the free encyclopedia"
59
57
  creator: Wikipedia
@@ -61,7 +59,7 @@ metadata:
61
59
  language: en
62
60
  subject: American alternative country singers
63
61
  publisher:
64
- contrubuter:
62
+ contributor:
65
63
  description:
66
64
  source: "http://en.wikipedia.org/wiki/Will_Oldham"
67
65
  rights:
@@ -71,19 +69,22 @@ metadata:
71
69
  # publication, such as table of contents, foreword, bibliography, etc.
72
70
  #
73
71
  # See http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.6
72
+ #
73
+ # If you provide cover-image without cover-page, pubgen automatically
74
+ # generate cover-page xhtml, and add it to manifest and spine
74
75
  guide:
75
76
  toc-page:
76
77
  title-page:
77
- # If you provide cover-image without cover-page, pubgen automatically
78
- # generate cover-page xhtml, and add it to manifest and spine
79
- cover-image: images/cover.jpg
80
78
  cover-page:
79
+ cover-image: images/cover.jpg
81
80
 
82
81
  # MANIFEST: A list of files (documents, images, style sheets, etc.) that make
83
82
  # up the publication.
84
83
  #
85
- # All the files in manifest ought to be in the same or sub-directory of yaml.
86
- # Say yaml's path is /book/a.yaml.
84
+ # See http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.3
85
+ #
86
+ # All the file paths in manifest ought to be relative to yaml's path and in the
87
+ # same or sub-directory of yaml. Say yaml's path is /book/a.yaml.
87
88
  # - a/b/c.html # good. in the sub-directory
88
89
  # - d.jpg # good. in the same directory
89
90
  # - ./e.jpg # good. in the same directory
@@ -93,8 +94,6 @@ guide:
93
94
  # - ../book/f.png # bad. although in the same directory
94
95
  manifest:
95
96
  - contents/a.html
96
- - contents/a-1.html
97
- - contents/a-2.html
98
97
  - contents/b.html
99
98
  - images/cover.jpg
100
99
  - images/1.jpg
@@ -103,18 +102,26 @@ manifest:
103
102
  - style.css
104
103
 
105
104
  # SPINE: An arrangement of documents providing a linear reading order.
105
+ #
106
+ # See http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.4
106
107
  spine:
107
108
  - contents/a.html
108
- - contents/a-1.html
109
- - contents/a-2.html
110
109
  - contents/b.html
111
110
 
112
111
  # TOC: Table of contents
112
+ #
113
+ # See http://idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.4.1
113
114
  toc:
114
- - Music -- contents/a.html: # don't forget colon to indent
115
- - Discography -- contents/a-1.html
116
- - Response -- contents/a-2.html
117
- - Film -- contents/b.html
115
+ # Add a colon suffix to indent
116
+ - 1 Music -- contents/a.html:
117
+ - 1.1 Discography -- contents/a.html#discography:
118
+ - 1.1.1 Studio albums -- contents/a.html#studio_albums
119
+ - 1.2 Response -- contents/a.html#response
120
+ - 2 Film -- contents/b.html:
121
+ - 2.1 Filmography -- contents/b.html#filmography
122
+ - 3 Photography -- contents/b.html#photography
123
+ - 4 References -- contents/b.html#references
124
+ - 5 External links -- contents/b.html#external_links
118
125
  ```
119
126
 
120
127
  Run pubgen.
@@ -123,8 +130,6 @@ Run pubgen.
123
130
  $ pubgen /path/to/will_oldham.yml -v
124
131
  mkdir .pubgen-4f4a210e
125
132
  cp ./contents/a.html .pubgen-4f4a210e/contents
126
- cp ./contents/a-1.html .pubgen-4f4a210e/contents
127
- cp ./contents/a-2.html .pubgen-4f4a210e/contents
128
133
  cp ./contents/b.html .pubgen-4f4a210e/contents
129
134
  cp ./images/cover.jpg .pubgen-4f4a210e/images
130
135
  cp ./images/1.jpg .pubgen-4f4a210e/images
@@ -138,8 +143,10 @@ cat > cover-pubgen.xhtml
138
143
  cat > content.opf
139
144
  cat > toc.ncx
140
145
  zip > pubgen.epub
141
- cd /path/to/pwd
142
- mv .pubgen-4f4a210e /pubgen.epub 'Will Oldham_ Wikipedia, the free encyclopedia.epub'
146
+ cd /path/to/prev_dir
147
+ mv .pubgen-4f4a210e/pubgen.epub 'Will Oldham_ Wikipedia, the free encyclopedia.epub'
143
148
  rm -rf .pubgen-4f4a210e
144
149
  # Successfully generated 'Will Oldham_ Wikipedia, the free encyclopedia.epub'
145
150
  ```
151
+
152
+ Done!
@@ -0,0 +1,10 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ task :default => [:test_units]
5
+ Rake::TestTask.new('test_units') do |t|
6
+ t.libs << %w[lib test]
7
+ t.pattern = 'test/test*.rb'
8
+ t.warning = true
9
+ end
10
+
data/bin/pubgen CHANGED
@@ -1,8 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- PACKAGE = 'pubgen'
4
- VERSION = '0.1.2'
5
-
6
3
  require 'yaml'
7
4
  require 'fileutils'
8
5
  require 'optparse'
@@ -13,11 +10,11 @@ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
13
10
  require 'pubgen'
14
11
 
15
12
  HELP = <<EOF
16
- #{PACKAGE} #{VERSION}, a epub generator. (http://github.com/9beach/pubgen)
13
+ pubgen #{Pubgen::VERSION}, a epub generator. (http://github.com/9beach/pubgen)
17
14
 
18
15
  Usage:
19
- #{PACKAGE} <yaml file> [-o <epub file>] [-v]
20
- #{PACKAGE} <yaml file> -m
16
+ pubgen <yaml file> [-o <epub file>] [-v]
17
+ pubgen <yaml file> -m
21
18
 
22
19
  EOF
23
20
 
@@ -42,18 +39,18 @@ opts.parse!(ARGV)
42
39
  # check options validity
43
40
  if (options[:meta_file_only] == true && options[:epub_path] != nil)
44
41
  $stderr << <<EOF
45
- #{PACKAGE}: `--meta-file-only' with `--output EPUB_PATH', not allowed
42
+ pubgen: `--meta-file-only' with `--output EPUB_PATH', not allowed
46
43
 
47
- Try `#{PACKAGE} -h' for more informations
44
+ Try `pubgen -h' for more informations
48
45
  EOF
49
46
  exit 1
50
47
  end
51
48
 
52
49
  if ARGV.size != 1
53
50
  $stderr << <<EOF
54
- #{PACKAGE}: specify a yaml file
51
+ pubgen: specify a yaml file
55
52
 
56
- Try `#{PACKAGE} -h' for more informations
53
+ Try `pubgen -h' for more informations
57
54
  EOF
58
55
  exit 1
59
56
  else
@@ -68,7 +65,8 @@ rescue Exception=>e
68
65
  end
69
66
 
70
67
  if yaml['metadata']['title'] == nil
71
- pubgen_err("Failed to find the value of 'title' attribute in: " + options[:yaml_path])
68
+ pubgen_err("Failed to find the value of 'title' attribute in: " +
69
+ options[:yaml_path])
72
70
  exit 1
73
71
  end
74
72
 
@@ -77,20 +75,23 @@ if !options[:meta_file_only] && !options[:epub_path]
77
75
  options[:epub_path] = yaml['metadata']['title'] + ".epub"
78
76
  options[:epub_path].gsub!(/[\/:?]/, "_") # file-system friendly
79
77
  end
80
- # now, options done
78
+ # options done
81
79
 
82
- # just for one line
80
+ # just for one line log
83
81
  def pubgen_log(log, verbose = true)
84
82
  $stdout << log + "\n" if verbose
85
83
  end
86
84
 
87
- # just for one line
88
85
  def pubgen_err(err)
89
86
  $stderr << '# ' + err + "\n"
90
87
  end
91
88
 
92
- yaml['metadata']['creator'] = "#{PACKAGE}-#{VERSION}" if yaml['metadata']['creator'] == nil
93
- yaml['metadata']['contributor'] = "#{PACKAGE}-#{VERSION}" if yaml['metadata']['contributor'] == nil
89
+ if yaml['metadata']['creator'] == nil
90
+ yaml['metadata']['creator'] = "pubgen-#{Pubgen::VERSION}"
91
+ end
92
+ if yaml['metadata']['contributor'] == nil
93
+ yaml['metadata']['contributor'] = "pubgen-#{Pubgen::VERSION}"
94
+ end
94
95
 
95
96
  $tmpdir = ""
96
97
  $pwd_old = Dir.pwd
@@ -98,19 +99,20 @@ $exit_code = 0
98
99
 
99
100
  begin
100
101
  if !options[:meta_file_only]
101
- # we need temporal working directory
102
+ # temporal working directory
102
103
  $tmpdir = ".pubgen-%08x" % Time.now.to_i
103
104
  Dir.mkdir($tmpdir)
104
105
  pubgen_log("mkdir " + $tmpdir, options[:verbose])
105
106
 
106
- # copy all files of manifest to $tmpdir
107
+ # copy all the files of manifest to $tmpdir
107
108
  yaml['manifest'].each do |file|
108
109
  if Pubgen::OPF.valid_manifest_element?(file) == false
109
110
  raise "Invalid manifest (not in sub-directory of yaml file): " + file
110
111
  end
111
112
  target_dir = "#{$tmpdir}/#{File.dirname(file)}"
112
113
  FileUtils.mkdir_p(target_dir)
113
- FileUtils.cp("#{File.dirname(options[:yaml_path])}/#{file}", target_dir, :verbose=>options[:verbose])
114
+ FileUtils.cp("#{File.dirname(options[:yaml_path])}/#{file}",
115
+ target_dir, :verbose=>options[:verbose])
114
116
  end
115
117
 
116
118
  # change pwd
@@ -119,15 +121,16 @@ begin
119
121
  end
120
122
 
121
123
  # generate container.xml
122
- # it's name and path are fixed (META-INF/container.xml)
124
+ # it's path is fixed (META-INF/container.xml)
123
125
  Dir.mkdir('META-INF') if !File::directory?('META-INF')
124
126
  container = File.new('META-INF/container.xml', 'w')
125
127
  container.write(Pubgen::Container.generate)
126
128
  container.close
127
- pubgen_log('cat > META-INF/container.xml', options[:meta_file_only] || options[:verbose])
129
+ pubgen_log('cat > META-INF/container.xml',
130
+ options[:meta_file_only] || options[:verbose])
128
131
 
129
132
  # generate mimetype
130
- # it's name and path are also fixed (./mimetype)
133
+ # it's path is also fixed (./mimetype)
131
134
  mimetype = File.new('mimetype', 'w')
132
135
  mimetype.write('application/epub+zip')
133
136
  mimetype.close
@@ -135,12 +138,13 @@ begin
135
138
 
136
139
  # pubgen automatically generates cover page if cover-image is given without
137
140
  # cover-page
138
- if Pubgen::CoverPage.need_to_generate?(yaml['guide'])
141
+ if yaml['guide']['cover-image'] != nil && yaml['guide']['cover-page'] == nil
139
142
  COVER_PAGE_PATH = 'cover-pubgen.xhtml'
140
143
  cover_page = File.new(COVER_PAGE_PATH, 'w')
141
144
  cover_page.write(Pubgen::CoverPage.generate(yaml['guide']['cover-image']))
142
145
  cover_page.close
143
- pubgen_log("cat > " + COVER_PAGE_PATH, options[:meta_file_only] || options[:verbose])
146
+ pubgen_log("cat > " + COVER_PAGE_PATH,
147
+ options[:meta_file_only] || options[:verbose])
144
148
 
145
149
  # add/set it to manifest, spine, and cover-page
146
150
  yaml['manifest'] << COVER_PAGE_PATH
@@ -149,24 +153,26 @@ begin
149
153
  end
150
154
 
151
155
  # generate uuid
152
- uuid = "%08x" % Time.now.to_i + "-" + [4,4,4,12].map {|l| "%0#{l}x" % rand(1 << l*4) }.join('-')
153
- # require 'uuid'
156
+ uuid = "%08x-" % Time.now.to_i +
157
+ [4,4,4,12].map {|l| "%0#{l}x" % rand(1 << l*4) }.join('-')
154
158
  # uuid = UUID.new.generate
155
159
 
156
- # generate opf file
160
+ # generate .opf file
157
161
  opf = File.new(Pubgen::Container.opf_path, 'w')
158
162
  opf.write(Pubgen::OPF.generate(yaml, uuid))
159
163
  opf.close
160
- pubgen_log("cat > " + Pubgen::Container.opf_path, options[:meta_file_only] || options[:verbose])
161
- # pubgen automatically added ncx file to opf's manifest (but not to yaml[]'s)
164
+ pubgen_log("cat > " + Pubgen::Container.opf_path,
165
+ options[:meta_file_only] || options[:verbose])
166
+ # pubgen automatically added .ncx file to opf's manifest
162
167
 
163
- # generate ncx file
168
+ # generate .ncx file
164
169
  ncx = File.new(Pubgen::OPF.ncx_path, 'w')
165
170
  ncx.write(Pubgen::NCX.generate(yaml['metadata']['title'], yaml['toc'], uuid))
166
171
  ncx.close
167
- pubgen_log("cat > " + Pubgen::OPF.ncx_path, options[:meta_file_only] || options[:verbose])
172
+ pubgen_log("cat > " + Pubgen::OPF.ncx_path,
173
+ options[:meta_file_only] || options[:verbose])
168
174
 
169
- # generate epub
175
+ # make an epub
170
176
  if !options[:meta_file_only]
171
177
  Zip::Archive.open("pubgen.epub", Zip::CREATE | Zip::TRUNC) do |ar|
172
178
  Dir.glob('**/*').each do |path|
@@ -183,7 +189,8 @@ begin
183
189
  Dir.chdir($pwd_old)
184
190
  pubgen_log("cd " + $pwd_old, options[:verbose])
185
191
  FileUtils.mv($tmpdir + "/pubgen.epub", options[:epub_path])
186
- pubgen_log("mv #{$tmpdir} /pubgen.epub '#{options[:epub_path]}'", options[:verbose])
192
+ pubgen_log("mv #{$tmpdir}/pubgen.epub '#{options[:epub_path]}'",
193
+ options[:verbose])
187
194
  end
188
195
  rescue Exception=>e
189
196
  $exit_code = 1
@@ -2,3 +2,4 @@ require 'pubgen/cover_page'
2
2
  require 'pubgen/ncx'
3
3
  require 'pubgen/opf'
4
4
  require 'pubgen/container'
5
+ require 'pubgen/version'
@@ -7,11 +7,11 @@ module Pubgen
7
7
  def self.generate
8
8
  <<EOF
9
9
  <?xml version="1.0"?>
10
- <container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container"
11
- >
10
+ <container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:\
11
+ container">
12
12
  <rootfiles>
13
- <rootfile full-path="#{opf_path}" media-type="application/oebps-package+xml"
14
- />
13
+ <rootfile full-path="#{opf_path}" media-type="application/\
14
+ oebps-package+xml"/>
15
15
  </rootfiles>
16
16
  </container>
17
17
  EOF
@@ -1,9 +1,5 @@
1
1
  module Pubgen
2
2
  module CoverPage
3
- def self.need_to_generate?(guide)
4
- guide['cover-image'] != nil && guide['cover-page'] == nil
5
- end
6
-
7
3
  def self.generate(cover_image)
8
4
  <<EOF
9
5
  <?xml version='1.0' encoding='utf-8'?>
@@ -19,7 +15,9 @@ module Pubgen
19
15
  </head>
20
16
  <body>
21
17
  <div>
22
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100%" height="100%" viewBox="0 0 469 616" preserveAspectRatio="xMinYMin">
18
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/\
19
+ 1999/xlink" version="1.1" width="100%" height="100%" viewBox="0 0 469 616" \
20
+ preserveAspectRatio="xMinYMin">
23
21
  <image width="469" height="616" xlink:href="#{cover_image}"/>
24
22
  </svg>
25
23
  </div>
@@ -2,72 +2,68 @@ module Pubgen
2
2
  module NCX
3
3
  def self.generate(title, toc, uuid)
4
4
  # header
5
- toc_xml = TOC_XML_HEADER_FORMAT % [uuid, CGI.escapeHTML(title || '')]
6
- # NavPoint traces indentation, so we need class and instantiation of it
7
- nav_point = NavPointImpl.new
8
- toc.each do |name_and_path|
9
- toc_xml += nav_point.generate(name_and_path)
10
- end
11
- # footer
12
- toc_xml += TOC_XML_FOOTER
13
- end
14
-
15
- # define NavPointImpl class and some constants
16
- # they are all private, only Pubgen.NCX.generate use them
17
- NAVPOINT_XML_HEADER_FORMAT = <<EOF
18
- <navPoint id="d%03d" playOrder="%d">
19
- <navLabel>
20
- <text>%s</text>
21
- </navLabel>
22
- <content src="%s"/>
23
- EOF
24
- NAVPOINT_XML_FOOTER = " </navPoint>\n"
25
- TOC_XML_HEADER_FORMAT = <<EOF
5
+ toc_xml = <<EOF
26
6
  <?xml version='1.0' encoding='utf-8'?>
27
- <ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" xml:lang="en">
7
+ <ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" \
8
+ xml:lang="en">
28
9
  <head>
29
- <meta content="%s" name="dtb:uid"/>
10
+ <meta content="#{uuid}" name="dtb:uid"/>
30
11
  <meta content="2" name="dtb:depth"/>
31
12
  <meta content="pubgen" name="dtb:generator"/>
32
13
  <meta content="0" name="dtb:totalPageCount"/>
33
14
  <meta content="0" name="dtb:maxPageNumber"/>
34
15
  </head>
35
16
  <docTitle>
36
- <text>%s</text>
17
+ <text>#{CGI.escapeHTML(title || '')}</text>
37
18
  </docTitle>
38
19
  <navMap>
39
20
  EOF
40
- TOC_XML_FOOTER = " </navMap>\n</ncx>"
21
+ # NavPoint traces indentation, so we need class and instantiation of it
22
+ nav_point = NavPointImpl.new
23
+ toc.each do |name_and_path|
24
+ toc_xml += nav_point.generate(name_and_path)
25
+ end
26
+ # footer
27
+ toc_xml += " </navMap>\n</ncx>"
28
+ end
41
29
 
30
+ # define NavPointImpl class
31
+ # it's private. only Pubgen.NCX.generate use it
42
32
  class NavPointImpl
43
33
  private
44
34
  def generate_impl(name_and_path, depth)
45
- header = NAVPOINT_XML_HEADER_FORMAT
46
- footer = NAVPOINT_XML_FOOTER
47
- @toc_indent_order += 1
35
+ header = <<EOF
36
+ <navPoint id="d%03d" playOrder="%d">
37
+ <navLabel>
38
+ <text>%s</text>
39
+ </navLabel>
40
+ <content src="%s"/>
41
+ EOF
42
+ footer = " </navPoint>\n"
48
43
  if depth
49
44
  depth.times do
50
- header = header.gsub(/^/, ' ')
51
- footer = footer.gsub(/^/, ' ')
45
+ header.gsub!(/^/, ' ')
46
+ footer.gsub!(/^/, ' ')
52
47
  end
53
48
  end
54
49
 
50
+ @play_order += 1
55
51
  navpoint_xml = ''
56
52
  if name_and_path.is_a?(String)
57
53
  if name_and_path.split(" -- ").size != 2
58
54
  raise "Bad toc contents format: " + name_and_path
59
55
  end
60
- navpoint_xml = header % [@toc_indent_order, @toc_indent_order,
61
- CGI.escapeHTML(name_and_path.split(" -- ")[0]),
62
- name_and_path.split(" -- ")[1]]
56
+ navpoint_xml = header % [@play_order, @play_order,
57
+ CGI.escapeHTML(name_and_path.split(" -- ")[0]),
58
+ name_and_path.split(" -- ")[1]]
63
59
  else
64
60
  # if not string, it's hash map with just one element
65
61
  name_and_path.each do |key, value|
66
62
  if key.split(" -- ").size != 2
67
63
  raise "Bad toc contents format: " + key
68
64
  end
69
- navpoint_xml = header % [@toc_indent_order, @toc_indent_order,
70
- CGI.escapeHTML(key.split(" -- ")[0]), key.split(" -- ")[1]]
65
+ navpoint_xml = header % [@play_order, @play_order,
66
+ CGI.escapeHTML(key.split(" -- ")[0]), key.split(" -- ")[1]]
71
67
  value.each do |v|
72
68
  navpoint_xml += generate_impl(v, depth + 1)
73
69
  end
@@ -79,7 +75,7 @@ EOF
79
75
 
80
76
  public
81
77
  def initialize
82
- @toc_indent_order = 0
78
+ @play_order = 0
83
79
  end
84
80
 
85
81
  def generate(name_and_path)
@@ -3,49 +3,32 @@ require 'cgi'
3
3
  module Pubgen
4
4
  module OPF
5
5
  def self.ncx_path
6
- NCX_PATH
6
+ 'toc.ncx'
7
7
  end
8
8
 
9
9
  def self.generate(yaml, uuid)
10
10
  cover_id, manifest_xml, file2id =
11
- OPFImpl.get_cover_id_and_manifest_xml(yaml['guide']['cover-image'],
12
- yaml['manifest'])
11
+ OPFImpl.get_cover_id_and_manifest_xml(yaml['guide']['cover-image'],
12
+ yaml['manifest'])
13
13
  metadata_xml = OPFImpl.get_metadata_xml(yaml['metadata'], uuid, cover_id)
14
14
  spine_xml = OPFImpl.get_spine_xml(yaml['spine'], file2id)
15
15
  guide_xml = OPFImpl.get_guide_xml(yaml['guide'], file2id)
16
- return OPF_XML_HEADER + metadata_xml + manifest_xml + spine_xml +
17
- guide_xml + OPF_XML_FOOTER
16
+
17
+ <<EOF
18
+ <?xml version='1.0' encoding='utf-8'?>
19
+ <package xmlns="http://www.idpf.org/2007/opf" version="2.0" \
20
+ unique-identifier="uuid_id">
21
+ #{metadata_xml}#{manifest_xml}#{spine_xml}#{guide_xml}</package>
22
+ EOF
18
23
  end
19
24
 
25
+ # sub directories and relative paths
20
26
  def self.valid_manifest_element?(e)
21
27
  e[0..2] != "../" && e[0] != "/"
22
28
  end
23
29
 
24
- # define OPFImpl class and some constants
25
- # they are all private, only Pubgen.OPF.generate use them
26
- NCX_PATH = "toc.ncx"
27
- METADATA_FORMAT = <<EOF
28
- <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
29
- <dc:title>%s</dc:title>
30
- <dc:creator opf:role="aut">%s</dc:creator>
31
- <dc:date>%s</dc:date>
32
- <dc:language>%s</dc:language>
33
- <dc:subject>%s</dc:subject>
34
- <dc:publisher>%s</dc:publisher>
35
- <dc:description>%s</dc:description>
36
- <dc:contributor opf:role="bkp">%s</dc:contributor>
37
- <dc:source>%s</dc:source>
38
- <dc:rights>%s</dc:rights>
39
- <dc:relation>%s</dc:relation>
40
- <dc:identifier id="BookID" opf:scheme="UUID">%s</dc:identifier>%s
41
- </metadata>
42
- EOF
43
- OPF_XML_HEADER = <<EOF
44
- <?xml version='1.0' encoding='utf-8'?>
45
- <package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="uuid_id">
46
- EOF
47
- OPF_XML_FOOTER = '</package>'
48
-
30
+ # define OPFImpl class
31
+ # it's private. only Pubgen.OPF.generate use it
49
32
  module OPFImpl
50
33
  def self.guess_media_type(filename)
51
34
  case filename.downcase
@@ -78,10 +61,12 @@ EOF
78
61
 
79
62
  manifest.each do |path|
80
63
  if OPF.valid_manifest_element?(path) == false
81
- raise "One of manifest element (" + path + ") is not in sub-directory of yaml file"
64
+ raise "A manifest file, #{path} is not in sub-directory of " +
65
+ "yaml file"
82
66
  end
83
67
  id = "i%03d" % no
84
- manifest_xml += " <item id=\"#{id}\" href=\"#{path}\" media-type=\"#{guess_media_type(path)}\"/>\n"
68
+ manifest_xml += " <item id=\"#{id}\" href=\"#{path}\" " +
69
+ "media-type=\"#{guess_media_type(path)}\"/>\n"
85
70
  if path == cover_path
86
71
  cover_id = id
87
72
  end
@@ -91,34 +76,45 @@ EOF
91
76
  end
92
77
 
93
78
  if cover_path && cover_id == nil
94
- raise "Can't find cover-image from manifest"
79
+ raise "Failed to find cover-image from manifest"
95
80
  end
96
81
 
97
- manifest_xml += " <item id=\"ncx\" href=\"#{NCX_PATH}\" media-type=\"application/x-dtbncx+xml\"/>\n </manifest>\n"
82
+ manifest_xml += " <item id=\"ncx\" href=\"#{OPF.ncx_path}\" " +
83
+ "media-type=\"application/x-dtbncx+xml\"/>\n </manifest>\n"
98
84
 
99
85
  return cover_id, manifest_xml, file2id
100
86
  end
101
87
 
88
+ def self.cgi_escape(text)
89
+ CGI.escapeHTML(text || '')
90
+ end
91
+
102
92
  def self.get_metadata_xml(metadata, uuid, cover_id)
103
93
  cover_id_xml = ''
104
94
  if cover_id != nil
105
- cover_id_xml = "\n <meta name=\"cover\" content=\"%s\"/>" % cover_id
95
+ cover_id_xml = "\n <meta name=\"cover\" content=\"#{cover_id}\"/>"
106
96
  end
107
- METADATA_FORMAT % [
108
- CGI.escapeHTML(metadata['title'] || ''),
109
- CGI.escapeHTML(metadata['creator'] || ''),
110
- CGI.escapeHTML((metadata['date'].is_a?(Fixnum) ?
111
- metadata['date'].to_s : metadata['date']) || ''),
112
- CGI.escapeHTML(metadata['language'] || ''),
113
- CGI.escapeHTML(metadata['subject'] || ''),
114
- CGI.escapeHTML(metadata['publisher'] || ''),
115
- CGI.escapeHTML(metadata['description'] || ''),
116
- CGI.escapeHTML(metadata['contributor'] || ''),
117
- CGI.escapeHTML(metadata['source'] || ''),
118
- CGI.escapeHTML(metadata['rights'] || ''),
119
- CGI.escapeHTML(metadata['relation'] || ''),
120
- uuid, cover_id_xml
121
- ]
97
+ <<EOF
98
+ <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" \
99
+ xmlns:opf="http://www.idpf.org/2007/opf">
100
+ <dc:title>#{cgi_escape(metadata['title'])}</dc:title>
101
+ <dc:creator opf:role="aut">#{cgi_escape(metadata['creator'])}\
102
+ </dc:creator>
103
+ <dc:date>#{cgi_escape((metadata['date'].is_a?(Fixnum) ? \
104
+ metadata['date'].to_s : metadata['date']))}</dc:date>
105
+ <dc:language>#{cgi_escape(metadata['language'])}</dc:language>
106
+ <dc:subject>#{cgi_escape(metadata['subject'])}</dc:subject>
107
+ <dc:publisher>#{cgi_escape(metadata['publisher'])}</dc:publisher>
108
+ <dc:description>#{cgi_escape(metadata['description'])}</dc:description>
109
+ <dc:contributor opf:role="bkp">#{cgi_escape(metadata['contributor'])}\
110
+ </dc:contributor>
111
+ <dc:source>#{cgi_escape(metadata['source'])}</dc:source>
112
+ <dc:rights>#{cgi_escape(metadata['rights'])}</dc:rights>
113
+ <dc:relation>#{cgi_escape(metadata['relation'])}</dc:relation>
114
+ <dc:identifier id="BookID" opf:scheme="UUID">#{uuid}</dc:identifier>\
115
+ #{cover_id_xml}
116
+ </metadata>
117
+ EOF
122
118
  end
123
119
 
124
120
  def self.get_guide_xml(guide, file2id)
@@ -126,25 +122,28 @@ EOF
126
122
  cover_page = guide['cover-page']
127
123
  if cover_page != nil
128
124
  if file2id[cover_page] == nil
129
- raise "Can't find cover-page from manifest"
125
+ raise "Failed to find cover-page from manifest"
130
126
  else
131
- guide_xml += " <reference href=\"%s\" type=\"cover\" title=\"Cover\"/>\n" % cover_page
127
+ guide_xml += " <reference href=\"#{cover_page}\" " +
128
+ "type=\"cover\" title=\"Cover\"/>\n"
132
129
  end
133
130
  end
134
131
  toc_page = guide['toc-page']
135
132
  if toc_page != nil
136
133
  if file2id[toc_page] == nil
137
- raise "Can't find toc-page from manifest"
134
+ raise "Failed to find toc-page from manifest"
138
135
  else
139
- guide_xml += " <reference href=\"%s\" type=\"toc\" title=\"Table of Contents\"/>\n" % toc_page
136
+ guide_xml += " <reference href=\"#{toc_page}\" type=\"toc\" " +
137
+ "title=\"Table of Contents\"/>\n"
140
138
  end
141
139
  end
142
140
  title_page = guide['title-page']
143
141
  if title_page != nil
144
142
  if file2id[title_page] == nil
145
- raise "Can't find title-page from manifest"
143
+ raise "Failed to find title-page from manifest"
146
144
  else
147
- guide_xml += " <reference href=\"%s\" type=\"title-page\" title=\"Title Page\"/>\n" % toc_page
145
+ guide_xml += " <reference href=\"#{title_page}\" " +
146
+ "type=\"title-page\" title=\"Title Page\"/>\n"
148
147
  end
149
148
  end
150
149
  guide_xml += " </guide>\n"
@@ -156,7 +155,7 @@ EOF
156
155
  if file2id[path] != nil
157
156
  spine_xml += " <itemref idref=\"#{file2id[path]}\"/>\n"
158
157
  else
159
- raise "Can't find spine element `#{path}' from manifest"
158
+ raise "Failed to find spine element `#{path}' from manifest"
160
159
  end
161
160
  end
162
161
  spine_xml += " </spine>\n"
@@ -0,0 +1,3 @@
1
+ module Pubgen
2
+ VERSION = "0.1.3"
3
+ end
@@ -1,8 +1,11 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
+ $:.push File.expand_path("../lib", __FILE__)
4
+ require "pubgen/version"
5
+
3
6
  Gem::Specification.new do |s|
4
7
  s.name = "pubgen"
5
- s.version = "0.1.2"
8
+ s.version = Pubgen::VERSION
6
9
  s.platform = Gem::Platform::RUBY
7
10
  s.author = "9beach"
8
11
  s.email = ["9beach@gmail.com"]
@@ -12,6 +15,6 @@ Gem::Specification.new do |s|
12
15
  s.bindir = 'bin'
13
16
  s.require_paths = ["lib"]
14
17
  s.summary = "command-line based epub generator"
15
- s.description = "Pubgen is a simple command-line based epub generator. With the simple YAML file, Pubgen generate the epub file for you."
18
+ s.description = "Pubgen is a simple command-line based epub generator. With a plain YAML, Pubgen generate the epub for you."
16
19
  s.add_dependency "zipruby"
17
20
  end
@@ -0,0 +1 @@
1
+ require 'pubgen'
@@ -0,0 +1,11 @@
1
+ require 'test/unit'
2
+ require 'yaml'
3
+
4
+ require 'helper'
5
+
6
+ class TestCoverPage < Test::Unit::TestCase
7
+ def test_generate
8
+ xml = Pubgen::CoverPage.generate("test.jpg")
9
+ assert_match(/<image.*"test.jpg"\/>/, xml)
10
+ end
11
+ end
@@ -0,0 +1,90 @@
1
+ require 'test/unit'
2
+ require 'yaml'
3
+
4
+ require 'helper'
5
+
6
+ $test_yaml = <<EOF
7
+ metadata:
8
+ title: "Will Oldham"
9
+ creator: Wikipedia
10
+ date: 2012
11
+ language: en
12
+ subject: American alternative country singers
13
+ publisher: 9beach
14
+ contributor: 9valley
15
+ description: describe here
16
+ source: "http://en.wikipedia.org/wiki/Will_Oldham"
17
+ rights: I've got no right
18
+ relation: bad relation
19
+
20
+ guide:
21
+ toc-page: contents/a.html
22
+ title-page: contents/b.html
23
+ cover-page: contents/c.html
24
+ cover-image: images/cover.jpg
25
+
26
+ manifest:
27
+ - contents/a.html
28
+ - contents/b.html
29
+ - contents/c.html
30
+ - images/cover.jpg
31
+ - images/1.jpg
32
+ - images/2.jpg
33
+ - images/3.jpg
34
+ - style.css
35
+
36
+ spine:
37
+ - contents/a.html
38
+ - contents/b.html
39
+ - contents/c.html
40
+
41
+ toc:
42
+ - 1 Music -- contents/a.html:
43
+ - 1.1 Discography -- contents/a.html#discography:
44
+ - 1.1.1 Studio albums -- contents/a.html#studio_albums
45
+ - 1.2 Response -- contents/a.html#response
46
+ - 2 Film -- contents/b.html:
47
+ - 2.1 Filmography -- contents/b.html#filmography
48
+ - 3 Photography -- contents/b.html#photography
49
+ - 4 References -- contents/b.html#references
50
+ - 5 External links -- contents/c.html
51
+ EOF
52
+
53
+ class TestNCX < Test::Unit::TestCase
54
+ def setup
55
+ $yaml = YAML::load $test_yaml
56
+ end
57
+
58
+ def test_generate
59
+ xml = Pubgen::NCX.generate('English Patient', $yaml['toc'], '1111')
60
+
61
+ assert_match(/<meta content="1111" name="dtb:uid"\/>/, xml)
62
+ assert_match(/^ <navPoint id="d001" playOrder="1">/, xml)
63
+ assert_match(/^ <content src="contents\/a.html"/, xml)
64
+ assert_match(/^ <text>1 Music</, xml)
65
+ assert_match(/^ <navPoint id="d002" playOrder="2">/, xml)
66
+ assert_match(/^ <content src="contents\/a.html#discography"/, xml)
67
+ assert_match(/^ <text>1.1 Discography</, xml)
68
+ assert_match(/^ <navPoint id="d003" playOrder="3">/, xml)
69
+ assert_match(/^ <content src="contents\/a.html#studio_albums"/, xml)
70
+ assert_match(/^ <text>1.1.1 Studio albums</, xml)
71
+ assert_match(/^ <navPoint id="d004" playOrder="4">/, xml)
72
+ assert_match(/^ <content src="contents\/a.html#response"/, xml)
73
+ assert_match(/^ <text>1.2 Response</, xml)
74
+ assert_match(/^ <navPoint id="d005" playOrder="5">/, xml)
75
+ assert_match(/^ <content src="contents\/b.html"/, xml)
76
+ assert_match(/^ <text>2 Film</, xml)
77
+ assert_match(/^ <navPoint id="d006" playOrder="6">/, xml)
78
+ assert_match(/^ <content src="contents\/b.html#filmography"/, xml)
79
+ assert_match(/^ <text>2.1 Filmography</, xml)
80
+ assert_match(/^ <navPoint id="d007" playOrder="7">/, xml)
81
+ assert_match(/^ <content src="contents\/b.html#photography"/, xml)
82
+ assert_match(/^ <text>3 Photography</, xml)
83
+ assert_match(/^ <navPoint id="d008" playOrder="8">/, xml)
84
+ assert_match(/^ <content src="contents\/b.html#references"/, xml)
85
+ assert_match(/^ <text>4 References</, xml)
86
+ assert_match(/^ <navPoint id="d009" playOrder="9">/, xml)
87
+ assert_match(/^ <content src="contents\/c.html"/, xml)
88
+ assert_match(/^ <text>5 External links</, xml)
89
+ end
90
+ end
@@ -0,0 +1,112 @@
1
+ require 'test/unit'
2
+ require 'yaml'
3
+
4
+ require 'helper'
5
+
6
+ $test_yaml = <<EOF
7
+ metadata:
8
+ title: "Will Oldham"
9
+ creator: Wikipedia
10
+ date: 2012
11
+ language: en
12
+ subject: American alternative country singers
13
+ publisher: 9beach
14
+ contributor: 9valley
15
+ description: describe here
16
+ source: "http://en.wikipedia.org/wiki/Will_Oldham"
17
+ rights: I've got no right
18
+ relation: bad relation
19
+
20
+ guide:
21
+ toc-page: contents/a.html
22
+ title-page: contents/b.html
23
+ cover-page: contents/c.html
24
+ cover-image: images/cover.jpg
25
+
26
+ manifest:
27
+ - contents/a.html
28
+ - contents/b.html
29
+ - contents/c.html
30
+ - images/cover.jpg
31
+ - images/1.jpg
32
+ - images/2.jpg
33
+ - images/3.jpg
34
+ - style.css
35
+
36
+ spine:
37
+ - contents/a.html
38
+ - contents/b.html
39
+ - contents/c.html
40
+
41
+ toc:
42
+ - 1 Music -- contents/a.html:
43
+ - 1.1 Discography -- contents/a.html#discography:
44
+ - 1.1.1 Studio albums -- contents/a.html#studio_albums
45
+ - 1.2 Response -- contents/a.html#response
46
+ - 2 Film -- contents/b.html:
47
+ - 2.1 Filmography -- contents/b.html#filmography
48
+ - 3 Photography -- contents/b.html#photography
49
+ - 4 References -- contents/b.html#references
50
+ - 5 External links -- contents/c.html
51
+ EOF
52
+
53
+ class TestOPF < Test::Unit::TestCase
54
+ def setup
55
+ $yaml = YAML::load $test_yaml
56
+ end
57
+
58
+ def test_metadata
59
+ xml = Pubgen::OPF.generate($yaml, 'aaaaaaaa-1111')
60
+ assert_match(/<dc:title>Will Oldham<\/dc:[^>].*>/, xml)
61
+ assert_match(/<dc:creator opf:role="aut">Wikipedia<\/dc:[^>].*>/, xml)
62
+ assert_match(/<dc:date>2012<\/dc:[^>].*>/, xml)
63
+ assert_match(/<dc:language>en<\/dc:[^>].*>/, xml)
64
+ assert_match(/<dc:subject>American alternative country singers<\/dc:[^>].*>/, xml)
65
+ assert_match(/<dc:publisher>9beach<\/dc:[^>].*>/, xml)
66
+ assert_match(/<dc:description>describe here<\/dc:[^>].*>/, xml)
67
+ assert_match(/<dc:source>http:\/\/en.wikipedia.org\/wiki\/Will_Oldham<\/dc:[^>].*>/, xml)
68
+ assert_match(/<dc:rights>I've got no right<\/dc:[^>].*>/, xml)
69
+ assert_match(/<dc:relation>bad relation<\/dc:[^>].*>/, xml)
70
+ assert_match(/<dc:contributor opf:role="bkp">9valley<\/dc:[^>].*>/, xml)
71
+ assert_match(/<dc:identifier id="BookID" opf:scheme="UUID">aaaaaaaa-1111<\/dc:[^>].*>/, xml)
72
+ end
73
+
74
+ def test_guide
75
+ xml = Pubgen::OPF.generate($yaml, 'aaaaaaaa')
76
+
77
+ assert_match(/reference href="contents\/a.html" type="toc"/, xml)
78
+ assert_match(/reference href="contents\/b.html" type="title-page"/, xml)
79
+ assert_match(/reference href="contents\/c.html" type="cover"/, xml)
80
+ assert_match(/<meta name="cover" content/, xml)
81
+
82
+ $yaml['guide']['cover-image'] = nil
83
+ xml = Pubgen::OPF.generate($yaml, 'aaaaaaa')
84
+ assert_no_match(/<meta name="cover" content/, xml)
85
+ end
86
+
87
+ def test_manifest
88
+ xml = Pubgen::OPF.generate($yaml, 'a')
89
+ assert_match(/item id="i001" href="contents\/a.html" media-type="application\/xhtml\+xml"\/>/, xml)
90
+ assert_match(/item id="i002" href="contents\/b.html" media-type="application\/xhtml\+xml"\/>/, xml)
91
+ assert_match(/item id="i003" href="contents\/c.html" media-type="application\/xhtml\+xml"\/>/, xml)
92
+ assert_match(/item id="i004" href="images\/cover.jpg" media-type="image\/jpeg"\/>/, xml)
93
+ assert_match(/item id="i005" href="images\/1.jpg" media-type="image\/jpeg"\/>/, xml)
94
+ assert_match(/item id="i006" href="images\/2.jpg" media-type="image\/jpeg"\/>/, xml)
95
+ assert_match(/item id="i007" href="images\/3.jpg" media-type="image\/jpeg"\/>/, xml)
96
+ assert_match(/item id="i008" href="style.css" media-type="text\/css"\/>/, xml)
97
+ assert_match(/item id="ncx" href="#{Pubgen::OPF.ncx_path}" media-type="application\/x-dtbncx\+xml"\/>/, xml)
98
+ end
99
+
100
+ def test_spine
101
+ xml = Pubgen::OPF.generate($yaml, 'aaaaaaaa-1111')
102
+ assert_match(/<itemref idref="i001"\/>/, xml)
103
+ assert_match(/<itemref idref="i002"\/>/, xml)
104
+ assert_match(/<itemref idref="i003"\/>/, xml)
105
+ assert_no_match(/<itemref idref="i004"\/>/, xml)
106
+ assert_no_match(/<itemref idref="i005"\/>/, xml)
107
+ assert_no_match(/<itemref idref="i006"\/>/, xml)
108
+ assert_no_match(/<itemref idref="i007"\/>/, xml)
109
+ assert_no_match(/<itemref idref="i008"\/>/, xml)
110
+ assert_no_match(/<itemref idref="ncx"\/>/, xml)
111
+ end
112
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pubgen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-26 00:00:00.000000000Z
12
+ date: 2012-02-27 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: zipruby
16
- requirement: &2157391000 !ruby/object:Gem::Requirement
16
+ requirement: &15276980 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,9 +21,9 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2157391000
25
- description: Pubgen is a simple command-line based epub generator. With the simple
26
- YAML file, Pubgen generate the epub file for you.
24
+ version_requirements: *15276980
25
+ description: Pubgen is a simple command-line based epub generator. With a plain YAML,
26
+ Pubgen generate the epub for you.
27
27
  email:
28
28
  - 9beach@gmail.com
29
29
  executables:
@@ -34,13 +34,19 @@ files:
34
34
  - .gitignore
35
35
  - LICENSE
36
36
  - README.md
37
+ - Rakefile
37
38
  - bin/pubgen
38
39
  - lib/pubgen.rb
39
40
  - lib/pubgen/container.rb
40
41
  - lib/pubgen/cover_page.rb
41
42
  - lib/pubgen/ncx.rb
42
43
  - lib/pubgen/opf.rb
44
+ - lib/pubgen/version.rb
43
45
  - pubgen.gemspec
46
+ - test/helper.rb
47
+ - test/test_cover_page.rb
48
+ - test/test_ncx.rb
49
+ - test/test_opf.rb
44
50
  homepage: https://github.com/9beach/pubgen
45
51
  licenses: []
46
52
  post_install_message: