burr 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -0
- data/LICENSE.md +30 -0
- data/README.md +180 -0
- data/Rakefile +118 -0
- data/bin/burr +9 -0
- data/burr.gemspec +36 -0
- data/generators/Gemfile.txt +3 -0
- data/generators/config.yml +55 -0
- data/generators/contents/chapter1.md +7 -0
- data/generators/contents/chapter2.md +7 -0
- data/generators/stylesheets/pdf.css +569 -0
- data/generators/stylesheets/site.css +1 -0
- data/lib/burr.rb +56 -0
- data/lib/burr/book.rb +289 -0
- data/lib/burr/cli.rb +64 -0
- data/lib/burr/converter.rb +19 -0
- data/lib/burr/core_ext/blank.rb +107 -0
- data/lib/burr/dependency.rb +28 -0
- data/lib/burr/eeepub_ext/maker.rb +131 -0
- data/lib/burr/exporter.rb +137 -0
- data/lib/burr/exporters/epub.rb +163 -0
- data/lib/burr/exporters/pdf.rb +95 -0
- data/lib/burr/exporters/site.rb +101 -0
- data/lib/burr/generator.rb +41 -0
- data/lib/burr/kramdown_ext/converter.rb +145 -0
- data/lib/burr/kramdown_ext/options.rb +38 -0
- data/lib/burr/kramdown_ext/parser.rb +65 -0
- data/lib/burr/liquid_ext/block.rb +58 -0
- data/lib/burr/liquid_ext/extends.rb +114 -0
- data/lib/burr/plugin.rb +70 -0
- data/lib/burr/plugins/aside.rb +44 -0
- data/lib/burr/plugins/codeblock.rb +42 -0
- data/lib/burr/plugins/figure.rb +62 -0
- data/lib/burr/plugins/link.rb +47 -0
- data/lib/burr/plugins/parser_plugin.rb +18 -0
- data/lib/burr/plugins/table.rb +42 -0
- data/lib/burr/plugins/toc.rb +105 -0
- data/lib/burr/ruby_version_check.rb +4 -0
- data/lib/burr/server.rb +27 -0
- data/lib/burr/ui.rb +46 -0
- data/lib/burr/version.rb +8 -0
- data/resources/locales/labels/en.yml +45 -0
- data/resources/locales/labels/zh_CN.yml +46 -0
- data/resources/locales/titles/en.yml +21 -0
- data/resources/locales/titles/zh_CN.yml +21 -0
- data/resources/templates/epub/_layout.liquid +17 -0
- data/resources/templates/epub/acknowledgement.liquid +10 -0
- data/resources/templates/epub/afterword.liquid +10 -0
- data/resources/templates/epub/appendix.liquid +10 -0
- data/resources/templates/epub/author.liquid +10 -0
- data/resources/templates/epub/chapter.liquid +10 -0
- data/resources/templates/epub/conclusion.liquid +10 -0
- data/resources/templates/epub/cover.liquid +9 -0
- data/resources/templates/epub/dedication.liquid +10 -0
- data/resources/templates/epub/edition.liquid +1 -0
- data/resources/templates/epub/epilogue.liquid +1 -0
- data/resources/templates/epub/foreword.liquid +10 -0
- data/resources/templates/epub/glossary.liquid +1 -0
- data/resources/templates/epub/introduction.liquid +1 -0
- data/resources/templates/epub/license.liquid +1 -0
- data/resources/templates/epub/lof.liquid +24 -0
- data/resources/templates/epub/lot.liquid +24 -0
- data/resources/templates/epub/part.liquid +4 -0
- data/resources/templates/epub/preface.liquid +10 -0
- data/resources/templates/epub/prologue.liquid +1 -0
- data/resources/templates/epub/table.liquid +7 -0
- data/resources/templates/epub/title.liquid +3 -0
- data/resources/templates/epub/toc.liquid +10 -0
- data/resources/templates/pdf/_item.liquid +6 -0
- data/resources/templates/pdf/acknowledgement.liquid +1 -0
- data/resources/templates/pdf/afterword.liquid +1 -0
- data/resources/templates/pdf/appendix.liquid +4 -0
- data/resources/templates/pdf/author.liquid +1 -0
- data/resources/templates/pdf/blank.liquid +3 -0
- data/resources/templates/pdf/book.liquid +42 -0
- data/resources/templates/pdf/chapter.liquid +4 -0
- data/resources/templates/pdf/code.liquid +3 -0
- data/resources/templates/pdf/conclusion.liquid +1 -0
- data/resources/templates/pdf/cover.liquid +6 -0
- data/resources/templates/pdf/dedication.liquid +3 -0
- data/resources/templates/pdf/edition.liquid +1 -0
- data/resources/templates/pdf/epilogue.liquid +1 -0
- data/resources/templates/pdf/foreword.liquid +1 -0
- data/resources/templates/pdf/glossary.liquid +1 -0
- data/resources/templates/pdf/introduction.liquid +1 -0
- data/resources/templates/pdf/license.liquid +1 -0
- data/resources/templates/pdf/lof.liquid +24 -0
- data/resources/templates/pdf/lot.liquid +24 -0
- data/resources/templates/pdf/part.liquid +4 -0
- data/resources/templates/pdf/preface.liquid +1 -0
- data/resources/templates/pdf/prologue.liquid +1 -0
- data/resources/templates/pdf/table.liquid +7 -0
- data/resources/templates/pdf/title.liquid +3 -0
- data/resources/templates/pdf/toc.liquid +4 -0
- data/resources/templates/site/_layout.liquid +27 -0
- data/resources/templates/site/author.liquid +13 -0
- data/resources/templates/site/chapter.liquid +13 -0
- data/resources/templates/site/foreword.liquid +13 -0
- data/resources/templates/site/preface.liquid +13 -0
- metadata +232 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
module Burr
|
2
|
+
module Dependency
|
3
|
+
|
4
|
+
# Checks if PrinceXML installed.
|
5
|
+
#
|
6
|
+
# Returns true if installed, otherwise false.
|
7
|
+
def self.prince_installed?
|
8
|
+
installed? 'prince'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.kindlegen_installed?
|
12
|
+
installed? 'kindlegen'
|
13
|
+
end
|
14
|
+
|
15
|
+
# Checks if Dependent libx installed.
|
16
|
+
#
|
17
|
+
# Returns true if installed, otherwise false.
|
18
|
+
def self.installed?(cmd)
|
19
|
+
return true if which(cmd)
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
# Finds the executable.
|
24
|
+
def self.which(cmd)
|
25
|
+
system "which #{cmd} > /dev/null 2>&1"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# Custom the eeepub maker.
|
2
|
+
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module Burr
|
7
|
+
class EpubMaker
|
8
|
+
[
|
9
|
+
:title,
|
10
|
+
:creator,
|
11
|
+
:publisher,
|
12
|
+
:date,
|
13
|
+
:language,
|
14
|
+
:subject,
|
15
|
+
:description,
|
16
|
+
:rights,
|
17
|
+
:relation
|
18
|
+
].each do |name|
|
19
|
+
class_eval <<-DELIM
|
20
|
+
def #{name}(value)
|
21
|
+
@#{name}s ||= []
|
22
|
+
@#{name}s << value
|
23
|
+
end
|
24
|
+
DELIM
|
25
|
+
end
|
26
|
+
|
27
|
+
[
|
28
|
+
:uid,
|
29
|
+
:files,
|
30
|
+
:nav,
|
31
|
+
:cover,
|
32
|
+
:ncx_file,
|
33
|
+
:opf_file,
|
34
|
+
:guide
|
35
|
+
].each do |name|
|
36
|
+
define_method(name) do |arg|
|
37
|
+
instance_variable_set("@#{name}", arg)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def identifier(id, options)
|
42
|
+
@identifiers ||= []
|
43
|
+
@identifiers << {:value => id, :scheme => options[:scheme], :id => options[:id]}
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param [Proc] block the block for initialize
|
47
|
+
def initialize(&block)
|
48
|
+
@files ||= []
|
49
|
+
@nav ||= []
|
50
|
+
@ncx_file ||= 'toc.ncx'
|
51
|
+
@opf_file ||= 'content.opf'
|
52
|
+
|
53
|
+
instance_eval(&block) if block_given?
|
54
|
+
end
|
55
|
+
|
56
|
+
# Save as ePub file
|
57
|
+
#
|
58
|
+
# @param [String] filename the ePub file name to save
|
59
|
+
def save(filename)
|
60
|
+
create_epub.save(filename)
|
61
|
+
end
|
62
|
+
|
63
|
+
# instead of saving to file, output the file contents.
|
64
|
+
# important for serving on-the-fly doc creation from
|
65
|
+
# web interface where we don't want to allow file system
|
66
|
+
# writes (Heroku, et al.)
|
67
|
+
def render
|
68
|
+
create_epub.render
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def create_epub
|
74
|
+
@uid ||= 'BookId'
|
75
|
+
unique_identifier = @identifiers.select{ |i| i[:id] == @uid }.first
|
76
|
+
unless unique_identifier
|
77
|
+
unique_identifier = @identifiers.first
|
78
|
+
unique_identifier[:id] = @uid
|
79
|
+
end
|
80
|
+
dir = Dir.mktmpdir
|
81
|
+
@files.each do |file|
|
82
|
+
case file
|
83
|
+
when String
|
84
|
+
FileUtils.cp(file, dir)
|
85
|
+
when Hash
|
86
|
+
file_path, dir_path = *file.first
|
87
|
+
dest_dir = File.join(dir, dir_path)
|
88
|
+
FileUtils.mkdir_p(dest_dir)
|
89
|
+
FileUtils.cp(file_path, dest_dir)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
::EeePub::NCX.new(
|
94
|
+
:uid => @identifiers.select{ |i| i[:id] == @uid }.first,
|
95
|
+
:title => @titles[0],
|
96
|
+
:nav => @nav
|
97
|
+
).save(File.join(dir, @ncx_file))
|
98
|
+
|
99
|
+
::EeePub::OPF.new(
|
100
|
+
:title => @titles,
|
101
|
+
:unique_identifier => @uid,
|
102
|
+
:identifier => @identifiers,
|
103
|
+
:creator => @creators,
|
104
|
+
:publisher => @publishers,
|
105
|
+
:date => @dates,
|
106
|
+
:language => @languages,
|
107
|
+
:subject => @subjects,
|
108
|
+
:description => @descriptions,
|
109
|
+
:rights => @rightss,
|
110
|
+
:cover => @cover,
|
111
|
+
:relation => @relations,
|
112
|
+
:manifest => @files.map{|file|
|
113
|
+
case file
|
114
|
+
when String
|
115
|
+
File.basename(file)
|
116
|
+
when Hash
|
117
|
+
file_path, dir_path = *file.first
|
118
|
+
File.join(dir_path, File.basename(file_path))
|
119
|
+
end
|
120
|
+
},
|
121
|
+
:ncx => @ncx_file,
|
122
|
+
:guide => @guide
|
123
|
+
).save(File.join(dir, @opf_file))
|
124
|
+
|
125
|
+
::EeePub::OCF.new(
|
126
|
+
:dir => dir,
|
127
|
+
:container => @opf_file
|
128
|
+
)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module Burr
|
2
|
+
class Exporter
|
3
|
+
|
4
|
+
FRONTMATTER = %w(acknowledgement author cover dedication edition foreword
|
5
|
+
introduction license preface prologue title toc)
|
6
|
+
BODYMATTER = %w(appendix blank chapter conclusion part)
|
7
|
+
BACKMATTER = %w(afterword epilogue glossary lof lot)
|
8
|
+
|
9
|
+
attr_accessor :book, :config
|
10
|
+
attr_accessor :frontmatter, :bodymatter, :backmatter
|
11
|
+
|
12
|
+
def initialize(book)
|
13
|
+
@book = book
|
14
|
+
@config = book.config
|
15
|
+
|
16
|
+
@frontmatter = []
|
17
|
+
@bodymatter = []
|
18
|
+
@backmatter = []
|
19
|
+
|
20
|
+
prepare_output_dir
|
21
|
+
end
|
22
|
+
|
23
|
+
# Run all hooks of a type.
|
24
|
+
#
|
25
|
+
# type - The plugin name in Symbol, valid options are: :before_parse, :after_parse
|
26
|
+
# :before_decorate, :after_decorate.
|
27
|
+
#
|
28
|
+
# Returns nothing.
|
29
|
+
def run_plugins_of_type(type)
|
30
|
+
type = type.to_sym
|
31
|
+
|
32
|
+
Burr::Plugin.subclasses.each do |k|
|
33
|
+
k_obj = k.new(self.book)
|
34
|
+
Burr::Plugin::VALIDS.each do |h|
|
35
|
+
k_obj.send(type) if k_obj.respond_to?(h) && h == type
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# Run exporter.
|
43
|
+
#
|
44
|
+
# The details should implement in subclass.
|
45
|
+
def run
|
46
|
+
self.load_contents
|
47
|
+
self.parse_contents
|
48
|
+
self.decorate_contents
|
49
|
+
self.assemble_book
|
50
|
+
end
|
51
|
+
|
52
|
+
# Load book contents
|
53
|
+
def load_contents
|
54
|
+
special_elements = %w(cover toc blank)
|
55
|
+
|
56
|
+
self.config['contents'].each do |content_config|
|
57
|
+
item = initialize_item(content_config)
|
58
|
+
|
59
|
+
# if the element defines its own content file (usually: `chapter`, `appendix`)
|
60
|
+
if !item['file'].blank?
|
61
|
+
content_file = File.join(self.book.contents_dir, item['file'])
|
62
|
+
|
63
|
+
# check that content file exists and is readable
|
64
|
+
if !File.readable? content_file
|
65
|
+
raise <<-MESSAGE % content_config['file'], item['element'], "outputs/#{content_config['file']}"
|
66
|
+
The '%s' content associated with '%s' element doesn't exist\n
|
67
|
+
or is not readable.\n\n
|
68
|
+
Check that '%s'\n
|
69
|
+
file exists and check its permissions.
|
70
|
+
MESSAGE
|
71
|
+
end
|
72
|
+
|
73
|
+
item['original'] = File.read(content_file)
|
74
|
+
elsif item['file'].blank? && special_elements.include?(item['element'])
|
75
|
+
item['skip'] = true
|
76
|
+
else
|
77
|
+
# look for a default content defined by burr for this element
|
78
|
+
# e.g. `cover.md`, `license.md`, `title.md`
|
79
|
+
default_content_file = File.join(self.book.contents_dir, "#{item['element']}.md")
|
80
|
+
if File.exist?(default_content_file)
|
81
|
+
item['original'] = File.read(default_content_file)
|
82
|
+
else
|
83
|
+
self.book.ui.error("Missing file for #{item['element']}")
|
84
|
+
exit 1
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
self.frontmatter << item if item['matter'] == 'frontmatter'
|
89
|
+
self.bodymatter << item if item['matter'] == 'bodymatter'
|
90
|
+
self.backmatter << item if item['matter'] == 'backmatter'
|
91
|
+
self.book.items << item
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def initialize_item(configs)
|
98
|
+
item = {
|
99
|
+
'element' => '', # the type of this content (`chapter', `appendix', `toc', `license', ...)
|
100
|
+
'number' => '', # the number/letter of the content (useful for `chapter', `part' and `appendix')
|
101
|
+
'c_title' => '', # the title of the content defined in `config.yml' (usually only `part' defines it)
|
102
|
+
'title' => '', # the `title' of this file, the first h1 in `content'
|
103
|
+
'original' => '', # original content as written by book author
|
104
|
+
'content' => '', # transformed content of the element (HTML usually)
|
105
|
+
'file' => '', # the name of this item contents file (it's a relative path from book's `contents/')
|
106
|
+
'toc' => [], # the table of contents of this element
|
107
|
+
'skip' => false, # some elements, like `toc', do not need to covert, so just skip
|
108
|
+
}
|
109
|
+
|
110
|
+
item.merge!(configs)
|
111
|
+
|
112
|
+
# set the matter
|
113
|
+
if FRONTMATTER.include?(item['element'])
|
114
|
+
item['matter'] = 'frontmatter'
|
115
|
+
elsif BODYMATTER.include?(item['element'])
|
116
|
+
item['matter'] = 'bodymatter'
|
117
|
+
elsif BACKMATTER.include?(item['element'])
|
118
|
+
item['matter'] = 'backmatter'
|
119
|
+
else
|
120
|
+
self.book.ui.error("Element #{ item['element'] } not defined!")
|
121
|
+
exit 1
|
122
|
+
end
|
123
|
+
|
124
|
+
item
|
125
|
+
end
|
126
|
+
|
127
|
+
# If the outpus directory for current format not exists, create it!
|
128
|
+
#
|
129
|
+
def prepare_output_dir
|
130
|
+
dir = File.join(self.book.outputs_dir, self.book.format)
|
131
|
+
if !File.exist?(dir)
|
132
|
+
FileUtils.mkdir_p dir
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Burr
|
2
|
+
class Epub < Exporter
|
3
|
+
|
4
|
+
# Convert original contents into HTML
|
5
|
+
#
|
6
|
+
def parse_contents
|
7
|
+
parsed_items = []
|
8
|
+
self.book.items.each do |item|
|
9
|
+
self.book.current_item = item
|
10
|
+
|
11
|
+
# 'blank' element not include in epub
|
12
|
+
next if item['element'] == 'blank'
|
13
|
+
|
14
|
+
self.run_plugins_of_type(:before_parse)
|
15
|
+
|
16
|
+
unless item['skip']
|
17
|
+
item['content'] = Burr::Converter.new(self.book).convert(item['original'])
|
18
|
+
end
|
19
|
+
|
20
|
+
self.run_plugins_of_type(:after_parse)
|
21
|
+
|
22
|
+
parsed_items << self.book.current_item
|
23
|
+
end
|
24
|
+
self.book.items = parsed_items
|
25
|
+
end
|
26
|
+
|
27
|
+
# Decorate the contents with template
|
28
|
+
#
|
29
|
+
def decorate_contents
|
30
|
+
decorated_items = []
|
31
|
+
self.book.items.each do |item|
|
32
|
+
self.book.current_item = item
|
33
|
+
self.run_plugins_of_type(:before_decorate)
|
34
|
+
self.run_plugins_of_type(:after_decorate)
|
35
|
+
decorated_items << self.book.current_item
|
36
|
+
end
|
37
|
+
self.book.items = decorated_items
|
38
|
+
end
|
39
|
+
|
40
|
+
def assemble_book
|
41
|
+
# 1. create html files
|
42
|
+
special_elements = %w(blank)
|
43
|
+
base = File.join(self.book.outputs_dir, 'epub')
|
44
|
+
included_files = []
|
45
|
+
tmp_files = []
|
46
|
+
|
47
|
+
self.book.items.each do |item|
|
48
|
+
next if special_elements.include?(item['element'])
|
49
|
+
|
50
|
+
basename = if item['file'].blank?
|
51
|
+
item['element']
|
52
|
+
else
|
53
|
+
item['file'].split('.')[0..-2].join('.')
|
54
|
+
end
|
55
|
+
html_path = File.join(base, "#{ basename }.html")
|
56
|
+
included_files << html_path
|
57
|
+
tmp_files << html_path
|
58
|
+
|
59
|
+
File.open(html_path, 'w') do |f|
|
60
|
+
f.puts self.book.render(self.book.template_for(item['element']), { 'item' => item, 'toc' => html_toc })
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# 2. add other files
|
65
|
+
included_files << File.join(base, 'style.css')
|
66
|
+
Dir.glob(File.join(self.book.outputs_dir, 'site', 'figures', '*.*')) do |figure|
|
67
|
+
included_files << { figure => 'figures' }
|
68
|
+
end
|
69
|
+
included_files << File.join(base, 'cover.jpg')
|
70
|
+
|
71
|
+
# 3. build epub file
|
72
|
+
config = self.book.config
|
73
|
+
nav = ncx_toc
|
74
|
+
guide = build_guide
|
75
|
+
|
76
|
+
epub = Burr::EpubMaker.new do
|
77
|
+
title config['title']
|
78
|
+
creator config['translator'].blank? ? config['author'] : config['translator']
|
79
|
+
publisher config['publisher']
|
80
|
+
date config['pubdate']
|
81
|
+
identifier config['identifier'], :scheme => config['id_scheme'], :id => config['slug']
|
82
|
+
uid config['slug']
|
83
|
+
language config['language']
|
84
|
+
cover 'cover.jpg'
|
85
|
+
|
86
|
+
files included_files
|
87
|
+
nav nav
|
88
|
+
guide guide
|
89
|
+
end
|
90
|
+
|
91
|
+
epub.save(File.join(base, "#{self.book.config['slug']}-#{Time.new.strftime('%Y%m%d')}.epub"))
|
92
|
+
|
93
|
+
# 4. remove useless files
|
94
|
+
tmp_files.each do |file|
|
95
|
+
FileUtils.remove_entry(file)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def ncx_toc
|
102
|
+
nav = []
|
103
|
+
self.book.items.each do |item|
|
104
|
+
special_elements = %w(cover toc blank)
|
105
|
+
next if special_elements.include?(item['element'])
|
106
|
+
level_1 = item['toc'].first
|
107
|
+
next unless level_1['level'] == 1
|
108
|
+
basename = if item['file'].blank?
|
109
|
+
item['element']
|
110
|
+
else
|
111
|
+
item['file'].split('.')[0..-2].join('.')
|
112
|
+
end
|
113
|
+
html_path = "#{ basename }.html"
|
114
|
+
nav_label = if level_1['label'].blank?
|
115
|
+
"#{level_1['title']}"
|
116
|
+
else
|
117
|
+
"#{level_1['label']} #{level_1['title']}"
|
118
|
+
end
|
119
|
+
nav << { :label => nav_label, :content => html_path }
|
120
|
+
end
|
121
|
+
|
122
|
+
nav
|
123
|
+
end
|
124
|
+
|
125
|
+
def html_toc
|
126
|
+
html = '<ol class="toc-list">'
|
127
|
+
self.book.items.each do |item|
|
128
|
+
# editions define the *tocable* items
|
129
|
+
if self.book.config['formats']['epub']['toc']['elements'].include?(item['element'])
|
130
|
+
# item has several elements in its toc
|
131
|
+
if item['toc'].size > 0
|
132
|
+
item['toc'].each do |entry|
|
133
|
+
if entry['level'] <= self.book.config['formats'][self.book.format]['toc']['deep']
|
134
|
+
anchor = "#{item['element']}#{entry['id'].split('-')[1]}.html"
|
135
|
+
html << <<-LI1
|
136
|
+
<li class="#{ item['matter'] } #{ item['element'] } level-#{ entry['level'] }">
|
137
|
+
<a href="#{ anchor }##{ entry['id']}">#{ entry['label'] } #{ entry['title'] }</a>
|
138
|
+
</li>
|
139
|
+
LI1
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# empty or special item (anything different from 'chapter' and 'appendix')
|
145
|
+
elsif !%w(cover blank toc).include?(item['element'])
|
146
|
+
html << <<-LI2
|
147
|
+
<li class="#{ item['matter'] } #{ item['element'] } level-1">
|
148
|
+
<a href="#{ item['id'] }.html">#{ item['title'] }</a>
|
149
|
+
</li>
|
150
|
+
LI2
|
151
|
+
end
|
152
|
+
end
|
153
|
+
html << '</ol>'
|
154
|
+
end
|
155
|
+
|
156
|
+
def build_guide
|
157
|
+
o = []
|
158
|
+
o << { :type => 'toc', :href => "toc.html", :title => 'Table of Contents' }
|
159
|
+
o << { :type => 'cover', :href => "cover.html", :title => 'Cover' }
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|