docbook_xsl_wrapper 0.0.5 → 0.1.1

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,13 +1,12 @@
1
1
  # DocBook XSL Wrapper
2
2
 
3
- _Initial 'gemification' of the DocBook XSL Ruby script. Please consider
4
- this as an Alpha release._
3
+ _Please consider this as an Alpha release._
5
4
 
6
5
  The DocBook XSL stylesheets are very powerful and provide an easy way to output
7
6
  your DocBook XML documents into a usable format such as EPUB and PDF. This GEM
8
7
  hopes to make using these stylesheets even easier.
9
8
 
10
- At present the wrapper will only convert DocBook to EPUB 2 and is
9
+ At present the wrapper will only convert DocBook to EPUB2 and EPUB3 and is
11
10
  intended to be run from the command-line - future versions will have more
12
11
  functionality (see Future Improvements).
13
12
 
@@ -17,7 +16,7 @@ The original Ruby script can be found at: http://docbook.sourceforge.net/release
17
16
  ## Requirements
18
17
 
19
18
  * DocBook
20
- * DocBook XSL (~> v1.78.0)
19
+ * DocBook XSL (~> v1.78.1)
21
20
  * xsltproc
22
21
 
23
22
  ### NOTE
@@ -31,10 +30,10 @@ needed fixing before everything worked correctly.
31
30
 
32
31
  The catalog file ($XML_CATALOG_FILES) needed updating;
33
32
 
34
- 1. Add an entry to your 1.78.0 path.
33
+ 1. Add an entry to your 1.78.1 path.
35
34
  2. Remove older XSL entries (e.g. 1.76.0 & 1.77.0).
36
35
 
37
- _Please make sure that xsltproc uses the *1.78.0* stylesheets as default_
36
+ _Please make sure that xsltproc uses the *1.78.1* stylesheets as default_
38
37
 
39
38
 
40
39
  ## Installation
@@ -49,7 +48,6 @@ _Please make sure that xsltproc uses the *1.78.0* stylesheets as default_
49
48
 
50
49
  * Better design so it can be used from within other GEMs, as part of a larger tool-chain.
51
50
  * Test that the GEM also works on Linux.
52
- * EPUB3 output
53
51
  * Other output formats (e.g. PDF)
54
52
 
55
53
  ## Contributing
@@ -19,7 +19,7 @@ begin
19
19
  puts "Rendering DocBook file #{options.docbook} to #{options.output}\n\n" if options.verbose
20
20
 
21
21
  epub = DocbookXslWrapper::Epub.new(options)
22
- epub.render_to_file
22
+ epub.create
23
23
  ensure
24
24
  FileUtils.remove_entry_secure tmp_dir
25
25
  end
@@ -8,64 +8,58 @@ module DocbookXslWrapper
8
8
 
9
9
  def initialize(options)
10
10
  @options = options
11
- @options.custom_xsl = File.join(options.docbook_xsl_root, 'epub', 'docbook.xsl') unless options.custom_xsl
11
+
12
+ case options.format
13
+ when 'epub3'
14
+ xsl = File.join('epub3', 'chunk.xsl')
15
+ else
16
+ xsl = File.join('epub', 'docbook.xsl')
17
+ end
18
+ official_docbook_xsl = File.join('http://docbook.sourceforge.net/release/xsl/current', xsl)
19
+
20
+ @options.stylesheet = official_docbook_xsl unless options.stylesheet
12
21
  end
13
22
 
14
- def render_to_file
15
- render_to_epub
16
- bundle_epub
23
+ def create
24
+ begin
25
+ render_to_epub
26
+ bundle_epub
27
+ ensure
28
+ FileUtils.remove_entry_secure @collapsed_docbook_file
29
+ end
17
30
  end
18
31
 
19
32
  private
20
33
 
21
34
  def render_to_epub
22
- @collapsed_docbook_file = collapse_docbook()
35
+ @collapsed_docbook_file = collapse_docbook
23
36
 
24
37
  # Double-quote stylesheet & file to help Windows cmd.exe
25
- db2epub_cmd = %Q(cd "#{options.destination}" && xsltproc #{xsl_parser_options} "#{options.custom_xsl}" "#{@collapsed_docbook_file}")
38
+ db2epub_cmd = %Q(cd "#{options.destination}" && xsltproc #{xsl_parser_options} "#{options.stylesheet}" "#{@collapsed_docbook_file}")
26
39
  STDERR.puts db2epub_cmd if options.debug
27
40
  success = system(db2epub_cmd)
28
41
  raise "Could not render as .epub to #{options.output} (#{db2epub_cmd})" unless success
29
42
  end
30
43
 
31
44
  def xsl_parser_options
32
- chunk_quietly = "--stringparam chunk.quietly " + (options.verbose ? '0' : '1')
33
- co_path = "--stringparam callout.graphics.path #{options.callout_path}/"
34
- co_limit = "--stringparam callout.graphics.number.limit #{options.callout_limit}"
35
- co_ext = "--stringparam callout.graphics.extension #{options.callout_ext}"
36
- html_stylesheet = "--stringparam html.stylesheet #{File.basename(options.css)}" if options.css
37
- base = "--stringparam base.dir #{oebps_path}/"
45
+ chunk_quietly = "--stringparam chunk.quietly 1" if options.verbose == false
46
+ css = "--stringparam html.stylesheet #{File.basename(options.css)}/" if options.css
47
+ base = "--stringparam base.dir #{oebps_path}/"
38
48
  unless options.fonts.empty?
39
49
  fonts = options.fonts.map {|f| File.basename(f)}.join(',')
40
50
  font = "--stringparam epub.embedded.fonts \"#{fonts}\""
41
51
  end
42
- meta = "--stringparam epub.metainf.dir #{meta_inf_path}/"
52
+ meta = "--stringparam epub.metainf.dir #{meta_inf_directory}/"
43
53
  oebps = "--stringparam epub.oebps.dir #{oebps_directory}/"
44
- [chunk_quietly,
45
- co_path,
46
- co_limit,
47
- co_ext,
48
- base,
49
- font,
50
- meta,
51
- oebps,
52
- html_stylesheet,
53
- ].join(" ")
54
- end
55
54
 
56
- def bundle_epub
57
- quiet = options.verbose ? "" : "-q"
58
- mimetype_filename = write_mimetype()
59
- images = copy_images()
60
- csses = copy_csses()
61
- fonts = copy_fonts()
62
- callouts = copy_callouts()
63
- # zip -X -r ../book.epub mimetype META-INF OEBPS
64
- # Double-quote stylesheet & file to help Windows cmd.exe
65
- zip_cmd = %Q(cd "#{options.destination}" && zip #{quiet} -X -r "#{File.expand_path(options.output)}" "#{mimetype_filename}" "#{meta_inf_directory}" "#{oebps_directory}")
66
- puts zip_cmd if options.debug
67
- success = system(zip_cmd)
68
- raise "Could not bundle into .epub file to #{options.output}" unless success
55
+ [
56
+ chunk_quietly,
57
+ base,
58
+ font,
59
+ meta,
60
+ oebps,
61
+ css,
62
+ ].join(" ")
69
63
  end
70
64
 
71
65
  def collapse_docbook
@@ -84,91 +78,108 @@ module DocbookXslWrapper
84
78
  xinclude_success = system(xinclude_collapse_command)
85
79
  raise "Could not collapse XIncludes in #{options.docbook}" unless xinclude_success
86
80
 
87
- return collapsed_file
81
+ collapsed_file
82
+ end
83
+
84
+ def bundle_epub
85
+ quiet = options.verbose ? "" : "-q"
86
+ mimetype_filename = write_mimetype
87
+ images = copy_images
88
+ csses = copy_css
89
+ fonts = copy_fonts
90
+ callouts = copy_callouts
91
+ # zip -X -r ../book.epub mimetype META-INF OEBPS
92
+ # Double-quote stylesheet & file to help Windows cmd.exe
93
+ zip_cmd = %Q(cd "#{options.destination}" && zip #{quiet} -X -r "#{File.expand_path(options.output)}" "#{mimetype_filename}" "#{meta_inf_directory}" "#{oebps_directory}")
94
+ puts zip_cmd if options.debug
95
+ success = system(zip_cmd)
96
+ raise "Could not bundle into .epub file to #{options.output}" unless success
97
+ end
98
+
99
+ def write_mimetype
100
+ filename = File.join(options.destination, "mimetype")
101
+ File.open(filename, "w") {|f| f.print "application/epub+zip"}
102
+ File.basename(filename)
88
103
  end
89
104
 
90
105
  def copy_callouts
91
- new_callout_images = []
92
- if has_callouts?
93
- calloutglob = "#{options.callout_full_path}/*#{options.callout_ext}"
94
- Dir.glob(calloutglob).each {|img|
95
- img_new_filename = File.join(oebps_path, options.callout_path, File.basename(img))
96
-
97
- # TODO: What to rescue for these two?
98
- FileUtils.mkdir_p(File.dirname(img_new_filename))
99
- FileUtils.cp(img, img_new_filename)
100
- new_callout_images << img
101
- }
106
+ return unless has_callouts?
107
+
108
+ images = Array.new
109
+ calloutglob = "#{options.callout_full_path}/*#{options.callout_ext}"
110
+ Dir.glob(calloutglob).each do |image|
111
+ new_filename = File.join(oebps_path, options.callout_path, File.basename(image))
112
+
113
+ # TODO: What to rescue for these two?
114
+ FileUtils.mkdir_p(File.dirname(new_filename))
115
+ FileUtils.cp(image, new_filename)
116
+ images << image
102
117
  end
103
- return new_callout_images
118
+ images
119
+ end
120
+
121
+ # Returns true if the document has code callouts
122
+ def has_callouts?
123
+ parser = REXML::Parsers::PullParser.new(File.new(@collapsed_docbook_file))
124
+ while parser.has_next?
125
+ element = parser.pull
126
+ return true if element.start_element? and (element[0] == "calloutlist" or element[0] == "co")
127
+ end
128
+ false
104
129
  end
105
130
 
106
131
  def copy_fonts
107
- new_fonts = []
108
- options.fonts.each {|font_file|
109
- font_new_filename = File.join(oebps_path, File.basename(font_file))
110
- FileUtils.cp(font_file, font_new_filename)
111
- new_fonts << font_file
132
+ fonts = Array.new
133
+ options.fonts.each {|font|
134
+ new_filename = File.join(oebps_path, File.basename(font))
135
+ FileUtils.cp(font, new_filename)
136
+ fonts << font
112
137
  }
113
- return new_fonts
138
+ fonts
114
139
  end
115
140
 
116
- def copy_csses
117
- if options.css
118
- css_new_filename = File.join(oebps_path, File.basename(options.css))
119
- FileUtils.cp(options.css, css_new_filename)
120
- end
141
+ def copy_css
142
+ return unless options.css
143
+
144
+ filename = File.join(oebps_path, File.basename(options.css))
145
+ FileUtils.cp(options.css, filename)
121
146
  end
122
147
 
123
148
  def copy_images
124
- image_references = get_image_refs()
125
- new_images = []
126
- image_references.each {|img|
127
- # TODO: It'd be cooler if we had a filetype lookup rather than just
128
- # extension
129
- if img =~ /\.(svg|png|gif|jpe?g|xml)/i
130
- img_new_filename = File.join(oebps_path, img)
131
- img_full = File.join(File.expand_path(File.dirname(options.docbook)), img)
132
-
133
- # TODO: What to rescue for these two?
134
- FileUtils.mkdir_p(File.dirname(img_new_filename))
135
- puts(img_full + ": " + img_new_filename) if options.debug
136
- FileUtils.cp(img_full, img_new_filename)
137
- new_images << img_full
138
- end
139
- }
140
- return new_images
149
+ images = Array.new
150
+ xml_image_references.each do |image|
151
+ images << copy_image(image)
152
+ end
153
+ images
141
154
  end
142
155
 
143
- def write_mimetype
144
- mimetype_filename = File.join(options.destination, "mimetype")
145
- File.open(mimetype_filename, "w") {|f| f.print "application/epub+zip"}
146
- return File.basename(mimetype_filename)
156
+ def copy_image(image)
157
+ source_file = File.join(File.expand_path(File.dirname(options.docbook)), image)
158
+ destination_file = File.join(oebps_path, image)
159
+
160
+ FileUtils.mkdir_p(File.dirname(destination_file))
161
+
162
+ puts "Copying image: #{source_file} to #{destination_file}" if options.debug
163
+ FileUtils.cp(source_file, destination_file)
164
+
165
+ destination_file
147
166
  end
148
167
 
149
- # Returns an Array of all of the (image) @filerefs in a document
150
- def get_image_refs
168
+ def xml_image_references
151
169
  parser = REXML::Parsers::PullParser.new(File.new(@collapsed_docbook_file))
152
- image_refs = []
170
+ references = Array.new
153
171
  while parser.has_next?
154
- el = parser.pull
155
- if el.start_element? and (el[0] == "imagedata" or el[0] == "graphic")
156
- image_refs << el[1]['fileref']
157
- end
172
+ element = parser.pull
173
+ references << element[1]['fileref'] if is_valid_image_reference?(element)
158
174
  end
159
- return image_refs.uniq
175
+ references.uniq
160
176
  end
161
177
 
162
- # Returns true if the document has code callouts
163
- def has_callouts?
164
- parser = REXML::Parsers::PullParser.new(File.new(@collapsed_docbook_file))
165
- while parser.has_next?
166
- el = parser.pull
167
- if el.start_element? and (el[0] == "calloutlist" or el[0] == "co")
168
- return true
169
- end
170
- end
171
- return false
178
+ def is_valid_image_reference?(element)
179
+ return false unless element.start_element?
180
+ return false unless element[0] == 'graphic' or element[0] == 'imagedata'
181
+ return true if element[1]['fileref'].match(/\.(jpe?g|png|gif|svg|xml)\Z/i)
182
+ false
172
183
  end
173
184
 
174
185
  def oebps_directory
@@ -183,9 +194,5 @@ module DocbookXslWrapper
183
194
  'META-INF'
184
195
  end
185
196
 
186
- def meta_inf_path
187
- @meta_inf_path ||= File.join(options.destination, meta_inf_directory)
188
- end
189
-
190
197
  end
191
198
  end
@@ -6,16 +6,11 @@ module DocbookXslWrapper
6
6
 
7
7
  def self.parse(args)
8
8
  options = OpenStruct.new
9
- options.docbook_xsl_root = 'http://docbook.sourceforge.net/release/xsl/current'
10
- options.callout_path = File.join('images', 'callouts')
11
- options.callout_full_path = File.join(options.docbook_xsl_root, options.callout_path)
12
- options.callout_limit = 15
13
- options.callout_ext = '.png'
14
9
 
15
10
  options.css = nil
16
- options.custom_xsl = nil
11
+ options.stylesheet = nil
17
12
  options.fonts = []
18
- options.output = nil
13
+ options.format = 'epub'
19
14
  options.debug = false
20
15
  options.verbose = false
21
16
  options.docbook = nil
@@ -33,20 +28,25 @@ module DocbookXslWrapper
33
28
  opts.separator "Specific options:"
34
29
 
35
30
 
36
- opts.on("-c", "--css [FILE]", "Use FILE for CSS on generated XHTML.") do |css|
37
- options.css = css
31
+ opts.on("-c", "--css [FILE]", "Custom CSS for generated HTML") do |css|
32
+ options.css = File.expand_path(css)
38
33
  end
39
34
 
40
- opts.on("-s", "--stylesheet [XSL FILE]", "Use XSL FILE as a custom_xsl layer (imports epub/docbook.xsl).") do |xsl|
41
- options.custom_xsl = xsl
35
+ opts.on("-s", "--stylesheet [XSL FILE]", "Custom XSL layer (imports epub/docbook.xsl, overrides --type)") do |xsl|
36
+ options.stylesheet = File.expand_path(xsl)
42
37
  end
43
38
 
44
- opts.on("-f", "--font [OTF FILE]", "Embed OTF FILE in .epub.") do |otf|
45
- options.fonts << otf
39
+ opts.on("-f", "--font [OTF FILE]", "OpenType Font file for inclusion in the EPUB") do |otf|
40
+ options.fonts << File.expand_path(otf)
46
41
  end
47
42
 
48
- opts.on("-o", "--output [OUTPUT FILE]", "Output EPUB file as OUTPUT FILE.") do |output|
49
- options.output = output
43
+ opts.on("-o", "--output [OUTPUT FILE]", "Filename for the generated document") do |output|
44
+ options.output = File.expand_path(output)
45
+ end
46
+
47
+ opts.on("-t", "--type [BOOK TYPE]", "eBook type (format) that you wish to output: epub, epub3", /\Aepub[23]?\z/i) do |format|
48
+ format = format.downcase if format
49
+ options.format = "#{format}"
50
50
  end
51
51
 
52
52
  opts.separator ""
@@ -79,7 +79,7 @@ module DocbookXslWrapper
79
79
  args = ['-h'] if args.empty?
80
80
  opts.parse!(args)
81
81
 
82
- options.docbook = args.first
82
+ options.docbook = File.expand_path(args.first)
83
83
  unless options.docbook
84
84
  puts "No DocBook XML file(s) specified"
85
85
  exit
@@ -1,3 +1,3 @@
1
1
  module DocbookXslWrapper
2
- VERSION = "0.0.5"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -9,12 +9,14 @@ module DocbookXslWrapper
9
9
  options.css.should be nil
10
10
  options.customization.should be nil
11
11
  options.fonts.should eql []
12
+ options.format.should eq 'epub'
13
+ options.output.should match /etext\.epub\z/
12
14
  options.debug.should be false
13
15
  options.verbose.should be false
14
16
  end
15
17
  it "should assign docbook with the XML file path" do
16
18
  options = Options.parse(['etext.xml'])
17
- options.docbook.should eql 'etext.xml'
19
+ options.docbook.should match /etext\.xml\z/
18
20
  end
19
21
  it "should set the EPUB output filename from the XML filename" do
20
22
  options = Options.parse(['/path/to/etext.xml'])
@@ -40,19 +42,20 @@ module DocbookXslWrapper
40
42
  context "when css option used" do
41
43
  it "should assign value to .css" do
42
44
  options = Options.parse(['--css', 'stylesheet.css', 'etext.xml'])
43
- options.css.should eq 'stylesheet.css'
45
+ options.css.should match /stylesheet\.css\z/
44
46
  end
45
47
  end
46
48
  context "when customization stylsheet given option" do
47
- it "should set .custom_xsl with the value" do
49
+ it "should set .stylesheet with the value" do
48
50
  options = Options.parse(['--stylesheet', 'some.xsl', 'etext.xml'])
49
- options.custom_xsl.should eq 'some.xsl'
51
+ options.stylesheet.should match /some\.xsl\z/
50
52
  end
51
53
  end
52
54
  context "when fonts option" do
53
55
  it "should sets fonts with the OTF files" do
54
56
  options = Options.parse(['--font', 'one.otf', '--font', 'two.otf', 'etext.xml'])
55
- options.fonts.should eq ['one.otf', 'two.otf']
57
+ options.fonts[0].should match /one\.otf\z/
58
+ options.fonts[1].should match /two\.otf\z/
56
59
  end
57
60
  end
58
61
  context "when output file given" do
@@ -61,6 +64,12 @@ module DocbookXslWrapper
61
64
  options.output.should eq '/path/to/new.epub'
62
65
  end
63
66
  end
67
+ context "when output ebook format is given" do
68
+ it "should assign format with the given book format" do
69
+ options = Options.parse(['--type', 'ePub3', 'etext.xml'])
70
+ options.format.should eq 'epub3'
71
+ end
72
+ end
64
73
  end
65
74
 
66
75
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: docbook_xsl_wrapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-05 00:00:00.000000000 Z
12
+ date: 2013-03-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec