burr 0.0.2
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 +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,58 @@
|
|
|
1
|
+
# steal from https://github.com/silas/liquid-blocks
|
|
2
|
+
|
|
3
|
+
module Burr
|
|
4
|
+
class BlockDrop < ::Liquid::Drop
|
|
5
|
+
def initialize(block)
|
|
6
|
+
@block = block
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def super
|
|
10
|
+
@block.call_super(@context)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class BlockTag < ::Liquid::Block
|
|
15
|
+
Syntax = /(\w)+/
|
|
16
|
+
|
|
17
|
+
attr_accessor :parent
|
|
18
|
+
attr_reader :name
|
|
19
|
+
|
|
20
|
+
def initialize(tag_name, markup, tokens)
|
|
21
|
+
if markup =~ Syntax
|
|
22
|
+
@name = $1
|
|
23
|
+
else
|
|
24
|
+
raise Liquid::SyntaxError.new("Syntax Error in 'block' - Valid syntax: block [name]")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
super if tokens
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def render(context)
|
|
31
|
+
context.stack do
|
|
32
|
+
context['block'] = BlockDrop.new(self)
|
|
33
|
+
|
|
34
|
+
render_all(@nodelist, context)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def add_parent(nodelist)
|
|
39
|
+
if parent
|
|
40
|
+
parent.add_parent(nodelist)
|
|
41
|
+
else
|
|
42
|
+
self.parent = BlockTag.new(@tag_name, @name, nil)
|
|
43
|
+
parent.nodelist = nodelist
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def call_super(context)
|
|
48
|
+
if parent
|
|
49
|
+
parent.render(context)
|
|
50
|
+
else
|
|
51
|
+
''
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
Liquid::Template.register_tag(:block, Burr::BlockTag)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# steal from https://github.com/silas/liquid-blocks
|
|
2
|
+
|
|
3
|
+
module Burr
|
|
4
|
+
class ExtendsTag < ::Liquid::Block
|
|
5
|
+
Syntax = /(#{Liquid::QuotedFragment}+)/
|
|
6
|
+
|
|
7
|
+
def initialize(tag_name, markup, tokens)
|
|
8
|
+
if markup =~ Syntax
|
|
9
|
+
@template_name = $1
|
|
10
|
+
else
|
|
11
|
+
raise Liquid::SyntaxError.new("Syntax Error in 'extends' - Valid syntax: extends [template]")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
super
|
|
15
|
+
|
|
16
|
+
@blocks = @nodelist.inject({}) do |m, node|
|
|
17
|
+
m[node.name] = node if node.is_a?(Burr::BlockTag); m
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def parse(tokens)
|
|
22
|
+
parse_all(tokens)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def render(context)
|
|
26
|
+
template = load_template(context)
|
|
27
|
+
parent_blocks = find_blocks(template.root)
|
|
28
|
+
|
|
29
|
+
@blocks.each do |name, block|
|
|
30
|
+
if pb = parent_blocks[name]
|
|
31
|
+
pb.parent = block.parent
|
|
32
|
+
pb.add_parent(pb.nodelist)
|
|
33
|
+
pb.nodelist = block.nodelist
|
|
34
|
+
else
|
|
35
|
+
if is_extending?(template)
|
|
36
|
+
template.root.nodelist << block
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
template.render(context)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def parse_all(tokens)
|
|
47
|
+
@nodelist ||= []
|
|
48
|
+
@nodelist.clear
|
|
49
|
+
|
|
50
|
+
while token = tokens.shift
|
|
51
|
+
case token
|
|
52
|
+
when /^#{Liquid::TagStart}/
|
|
53
|
+
if token =~ /^#{Liquid::TagStart}\s*(\w+)\s*(.*)?#{Liquid::TagEnd}$/
|
|
54
|
+
# fetch the tag from registered blocks
|
|
55
|
+
if tag = Liquid::Template.tags[$1]
|
|
56
|
+
@nodelist << tag.new($1, $2, tokens)
|
|
57
|
+
else
|
|
58
|
+
# this tag is not registered with the system
|
|
59
|
+
# pass it to the current block for special handling or error reporting
|
|
60
|
+
unknown_tag($1, $2, tokens)
|
|
61
|
+
end
|
|
62
|
+
else
|
|
63
|
+
raise Liquid::SyntaxError, "Tag '#{token}' was not properly terminated with regexp: #{Liquid::TagEnd.inspect}"
|
|
64
|
+
end
|
|
65
|
+
when /^#{Liquid::VariableStart}/
|
|
66
|
+
@nodelist << create_variable(token)
|
|
67
|
+
when ''
|
|
68
|
+
# pass
|
|
69
|
+
else
|
|
70
|
+
@nodelist << token
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def load_template(context)
|
|
76
|
+
base = File.join('templates', context.registers[:book].format, "_#{ @template_name[1..-2] }.liquid")
|
|
77
|
+
default = File.join(context.registers[:book].gem_dir, 'resources', base)
|
|
78
|
+
custom = File.join(context.registers[:book].root_dir, base)
|
|
79
|
+
|
|
80
|
+
if File.exist?(custom)
|
|
81
|
+
path = custom
|
|
82
|
+
elsif !File.exist?(custom) && File.exist?(default)
|
|
83
|
+
path = default
|
|
84
|
+
else
|
|
85
|
+
raise "#{ @template_name[1..-2] } missing!"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
Liquid::Template.parse(File.read(path))
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def find_blocks(node, blocks={})
|
|
92
|
+
if node.respond_to?(:nodelist) && !node.nodelist.nil?
|
|
93
|
+
node.nodelist.inject(blocks) do |b, node|
|
|
94
|
+
if node.is_a?(Burr::BlockTag)
|
|
95
|
+
b[node.name] = node
|
|
96
|
+
else
|
|
97
|
+
find_blocks(node, b)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
b
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
blocks
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def is_extending?(template)
|
|
108
|
+
template.root.nodelist.any? { |node| node.is_a?(ExtendsTag) }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
Liquid::Template.register_tag(:extends, Burr::ExtendsTag)
|
data/lib/burr/plugin.rb
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module Burr
|
|
2
|
+
|
|
3
|
+
# steal from jekyll: https://github.com/mojombo/jekyll/blob/master/lib/jekyll/plugin.rb
|
|
4
|
+
class Plugin
|
|
5
|
+
|
|
6
|
+
PRIORITIES = {
|
|
7
|
+
:lowest => -100,
|
|
8
|
+
:low => -10,
|
|
9
|
+
:normal => 0,
|
|
10
|
+
:high => 10,
|
|
11
|
+
:highest => 100
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
VALIDS = [:before_parse, :after_parse, :before_decorate, :after_decorate]
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
|
|
18
|
+
# Install a hook so that subclasses are recorded. This method is only
|
|
19
|
+
# ever called by Ruby itself.
|
|
20
|
+
def inherited(base)
|
|
21
|
+
subclasses << base
|
|
22
|
+
subclasses.sort!
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# The list of Classes that have been subclassed.
|
|
26
|
+
#
|
|
27
|
+
# @return An array of Class objects.
|
|
28
|
+
def subclasses
|
|
29
|
+
@subclasses ||= []
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Get or set the priority of this plugin. When called without an
|
|
33
|
+
# argument it returns the priority. When an argument is given, it will
|
|
34
|
+
# set the priority.
|
|
35
|
+
#
|
|
36
|
+
# @param [Symbol] priority The priority (default: nil). Valid options are:
|
|
37
|
+
# :lowest, :low, :normal, :high, :highest
|
|
38
|
+
# @return The Symbol priority.
|
|
39
|
+
def priority(priority=nil)
|
|
40
|
+
@priority ||= nil
|
|
41
|
+
if priority && PRIORITIES.has_key?(priority)
|
|
42
|
+
@priority = priority
|
|
43
|
+
end
|
|
44
|
+
@priority || :normal
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Spaceship is priority [higher -> lower]
|
|
48
|
+
#
|
|
49
|
+
# other - The class to be compared.
|
|
50
|
+
#
|
|
51
|
+
# Returns -1, 0, 1.
|
|
52
|
+
def <=>(other)
|
|
53
|
+
PRIORITIES[other.priority] <=> PRIORITIES[self.priority]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
attr_accessor :book
|
|
59
|
+
|
|
60
|
+
# Initialize a new plugin. This should be overridden by the subclass.
|
|
61
|
+
#
|
|
62
|
+
# book - The book object.
|
|
63
|
+
#
|
|
64
|
+
# Returns a new instance.
|
|
65
|
+
def initialize(book)
|
|
66
|
+
@book = book
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Burr
|
|
2
|
+
class AsidePlugin < Plugin
|
|
3
|
+
|
|
4
|
+
# Do something after parsed the item content.
|
|
5
|
+
def after_parse
|
|
6
|
+
add_label
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# Adds label and id to Aside block.
|
|
12
|
+
#
|
|
13
|
+
def add_label
|
|
14
|
+
item = self.book.current_item
|
|
15
|
+
return unless self.book.config['formats']["#{self.book.format}"]['label']['elements'].include?('aside')
|
|
16
|
+
|
|
17
|
+
counter = 1
|
|
18
|
+
number = if item['number']
|
|
19
|
+
item['number']
|
|
20
|
+
else
|
|
21
|
+
item['element']
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
dom = ::Nokogiri::HTML::DocumentFragment.parse(item['content'])
|
|
25
|
+
dom.css('div.aside').each do |aside|
|
|
26
|
+
# add id
|
|
27
|
+
aside['id'] = "aside-#{number}-#{counter}"
|
|
28
|
+
|
|
29
|
+
# add label
|
|
30
|
+
caption = aside.css('h4').first
|
|
31
|
+
unless caption.blank?
|
|
32
|
+
label = self.book.render_label('aside', { 'item' => { 'number' => number, 'counter' => counter } })
|
|
33
|
+
caption_html = "<span>#{label}</span>#{caption.inner_html}"
|
|
34
|
+
caption.children = ::Nokogiri::HTML.fragment(caption_html, 'utf-8')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
counter += 1
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
item['content'] = dom.to_xhtml
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Burr
|
|
2
|
+
class CodeblockPlugin < Plugin
|
|
3
|
+
|
|
4
|
+
# Do something after parsed the item content.
|
|
5
|
+
def after_parse
|
|
6
|
+
add_label
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# Adds label and id to code block.
|
|
12
|
+
#
|
|
13
|
+
def add_label
|
|
14
|
+
item = self.book.current_item
|
|
15
|
+
return unless self.book.config['formats']["#{self.book.format}"]['label']['elements'].include?('codeblock')
|
|
16
|
+
|
|
17
|
+
counter = 1
|
|
18
|
+
number = if item['number']
|
|
19
|
+
item['number']
|
|
20
|
+
else
|
|
21
|
+
item['element']
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
dom = ::Nokogiri::HTML::DocumentFragment.parse(item['content'])
|
|
25
|
+
dom.css('.codeblock.has-caption').each do |codeblock|
|
|
26
|
+
# add id
|
|
27
|
+
codeblock.set_attribute('id', "codeblock-#{number}-#{counter}")
|
|
28
|
+
|
|
29
|
+
# add label
|
|
30
|
+
caption = codeblock.css('.caption').first
|
|
31
|
+
label = self.book.render_label('codeblock', { 'item' => { 'number' => number, 'counter' => counter } })
|
|
32
|
+
caption_html = "<span>#{label}</span>#{caption.inner_html}"
|
|
33
|
+
caption.children = ::Nokogiri::HTML.fragment(caption_html, 'utf-8')
|
|
34
|
+
|
|
35
|
+
counter += 1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
item['content'] = dom.to_xhtml
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Burr
|
|
2
|
+
class FigurePlugin < Plugin
|
|
3
|
+
|
|
4
|
+
# Do something after parsed the item content.
|
|
5
|
+
def after_parse
|
|
6
|
+
fix_src_for_pdf if self.book.format == 'pdf'
|
|
7
|
+
|
|
8
|
+
add_label
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
# Replaces figure src for pdf.
|
|
14
|
+
#
|
|
15
|
+
# 'figures/sample.png' => '<root_dir>/figures/sample.png'
|
|
16
|
+
#
|
|
17
|
+
def fix_src_for_pdf
|
|
18
|
+
item = self.book.current_item
|
|
19
|
+
prefix = File.join(self.book.outputs_dir, 'site')
|
|
20
|
+
dom = ::Nokogiri::HTML::DocumentFragment.parse(item['content'])
|
|
21
|
+
dom.search('img').each do |img|
|
|
22
|
+
ori_src = img.get_attribute('src')
|
|
23
|
+
new_src = File.join(prefix, ori_src)
|
|
24
|
+
img.set_attribute('src', new_src)
|
|
25
|
+
end
|
|
26
|
+
item['content'] = dom.to_xhtml
|
|
27
|
+
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Adds label and id to figure block.
|
|
32
|
+
#
|
|
33
|
+
def add_label
|
|
34
|
+
item = self.book.current_item
|
|
35
|
+
return unless self.book.config['formats']["#{self.book.format}"]['label']['elements'].include?('figure')
|
|
36
|
+
|
|
37
|
+
counter = 1
|
|
38
|
+
number = if item['number']
|
|
39
|
+
item['number']
|
|
40
|
+
else
|
|
41
|
+
item['element']
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
dom = ::Nokogiri::HTML::DocumentFragment.parse(item['content'])
|
|
45
|
+
dom.css('div.figure').each do |figure|
|
|
46
|
+
# add id
|
|
47
|
+
figure.set_attribute('id', "figure-#{number}-#{counter}")
|
|
48
|
+
|
|
49
|
+
# add label
|
|
50
|
+
caption = figure.css('.caption').first
|
|
51
|
+
label = self.book.render_label('figure', { 'item' => { 'number' => number, 'counter' => counter } })
|
|
52
|
+
caption_html = "<span>#{label}</span>#{caption.inner_html}"
|
|
53
|
+
caption.children = ::Nokogiri::HTML.fragment(caption_html, 'utf-8')
|
|
54
|
+
|
|
55
|
+
counter += 1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
item['content'] = dom.to_xhtml
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Burr
|
|
2
|
+
class LinkPlugin < Plugin
|
|
3
|
+
|
|
4
|
+
# Do something after parsed the item content.
|
|
5
|
+
def after_parse
|
|
6
|
+
extend_url if %w(site epub).include?(self.book.format)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# Extends cross link url.
|
|
12
|
+
#
|
|
13
|
+
def extend_url
|
|
14
|
+
item = self.book.current_item
|
|
15
|
+
dom = ::Nokogiri::HTML::DocumentFragment.parse(item['content'])
|
|
16
|
+
dom.css('a[href]').each do |link|
|
|
17
|
+
href = link['href']
|
|
18
|
+
next unless cross_link?(href)
|
|
19
|
+
|
|
20
|
+
parts = href.split('-')
|
|
21
|
+
|
|
22
|
+
next if parts[0].start_with?('#fn')
|
|
23
|
+
|
|
24
|
+
if href.start_with?('#chapter')
|
|
25
|
+
new_href = "chapter#{parts[1]}.html"
|
|
26
|
+
elsif href.start_with?('#section', '#figure', '#codeblock', '#table', '#aside')
|
|
27
|
+
new_href = "chapter#{parts[1]}.html#{parts.join('-')}"
|
|
28
|
+
else
|
|
29
|
+
new_href = "#{href[1..-1]}.html"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
link['href'] = new_href
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
item['content'] = dom.to_xhtml
|
|
36
|
+
|
|
37
|
+
nil
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def cross_link?(url)
|
|
41
|
+
return true if url.start_with?('#')
|
|
42
|
+
|
|
43
|
+
false
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Burr
|
|
2
|
+
class ParserPlugin < Plugin
|
|
3
|
+
|
|
4
|
+
# Do something after parsed the item content.
|
|
5
|
+
def after_parse
|
|
6
|
+
#replace_br
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# Replace <br> by <br/> (it causes problems for epub books)
|
|
12
|
+
def replace_br
|
|
13
|
+
item = self.book.current_item
|
|
14
|
+
item['content'].gsub!('<br>', '<br />')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|