bookshelf 1.2.1 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +0,0 @@
1
- module Bookshelf
2
- class DirectoryAlreadyCreatedError < StandardError; end
3
- end
@@ -1,69 +0,0 @@
1
- module RedCloth
2
- INLINE_FORMATTERS = [:textile, :footnote, :link]
3
-
4
- def self.convert(text)
5
- new(text).to_html(*INLINE_FORMATTERS)
6
- end
7
-
8
- module Inline
9
- FN_RE = /
10
- (\s+)? # getting spaces
11
- (\\)?%\{ # opening
12
- (.*?) # footnote
13
- \}# # closing
14
- /xm
15
-
16
- def footnote(text)
17
- text.gsub!(FN_RE) do |m|
18
- if $2
19
- %[#{$1}%{#{$3}}]
20
- else
21
- %(<span class="footnote">#{$3}</span>)
22
- end
23
- end
24
- end
25
-
26
- LINK_RE = /
27
- <
28
- ((?:https?|ftp):\/\/.*?)
29
- >
30
- /xm
31
-
32
- def link(text)
33
- text.gsub!(LINK_RE) do |m|
34
- %(<a href="#{$1}">#{$1}</a>)
35
- end
36
- end
37
- end
38
-
39
- module Formatters
40
- module HTML
41
- def figure(options = {})
42
- %[<p class="figure"><img src="../images/#{options[:text]}" alt="#{options[:class]}" /><br/><span class="caption">#{options[:class]}</span></p>]
43
- end
44
-
45
- def note(options = {})
46
- %[<p class="note">#{options[:text]}</p>]
47
- end
48
-
49
- def attention(options = {})
50
- %[<p class="attention">#{options[:text]}</p>]
51
- end
52
-
53
- def file(options = {})
54
- base_url = Bookshelf.config[:base_url]
55
-
56
- if base_url
57
- url = File.join(base_url, options[:text])
58
- else
59
- url = content
60
- $stderr << "\nYou're using `file. #{content}` but didn't set base_url in your configuration file.\n"
61
- end
62
-
63
- %[<p class="file"><span><strong>Download</strong> <a href="#{url}">#{options[:text]}</a></span></p>]
64
- end
65
- end
66
- end
67
- end
68
-
69
- RedCloth.send(:include, RedCloth::Inline)
@@ -1,11 +0,0 @@
1
- class String
2
- def to_permalink
3
- str = ActiveSupport::Multibyte::Chars.new(self.dup)
4
- str = str.normalize(:kd).gsub(/[^\x00-\x7F]/,'').to_s
5
- str.gsub!(/[^-\w\d]+/xim, "-")
6
- str.gsub!(/-+/xm, "-")
7
- str.gsub!(/^-?(.*?)-?$/, '\1')
8
- str.downcase!
9
- str
10
- end
11
- end
@@ -1,14 +0,0 @@
1
- module Bookshelf
2
- module Parser
3
- class Mobi < Base
4
- def parse
5
- spawn_command ["kindlegen", epub_file.to_s,]
6
- true
7
- end
8
-
9
- def epub_file
10
- root_dir.join("output/#{name}.epub")
11
- end
12
- end
13
- end
14
- end
@@ -1,18 +0,0 @@
1
- module Bookshelf
2
- module Parser
3
- class Txt < Base
4
- def parse
5
- spawn_command ["html2text", "-style", "pretty", "-nobs", "-o", txt_file.to_s, html_file.to_s]
6
- end
7
-
8
- def html_file
9
- root_dir.join("output/#{name}.html")
10
- end
11
-
12
- def txt_file
13
- root_dir.join("output/#{name}.txt")
14
- end
15
- end
16
- end
17
- end
18
-
@@ -1,27 +0,0 @@
1
- module Bookshelf
2
- class Stream
3
- attr_accessor :listener, :content
4
- attr_reader :html
5
-
6
- def initialize(content, listener)
7
- @content = content
8
- @listener = listener
9
- @html = Nokogiri::HTML.parse(content)
10
- end
11
-
12
- def parse
13
- traverse(html)
14
- end
15
-
16
- def traverse(node)
17
- node.children.each do |child|
18
- emit(child)
19
- traverse(child)
20
- end
21
- end
22
-
23
- def emit(node)
24
- listener.send(:tag, node) if node.name =~ /h[1-6]/
25
- end
26
- end
27
- end
@@ -1,124 +0,0 @@
1
- module Bookshelf
2
- class Syntax
3
- autoload :Highlight, "bookshelf/syntax/highlight"
4
-
5
- attr_reader :io
6
- attr_reader :lines
7
- attr_reader :book_dir
8
- attr_reader :format
9
-
10
- # Render syntax blocks from specified source code.
11
- #
12
- # dir = Pathname.new(File.dirname(__FILE__))
13
- # text = File.read(dir.join("text/some_file.textile"))
14
- # Bookshelf::Syntax.render(dir, :textile, text)
15
- #
16
- def self.render(book_dir, format, source_code, raw = false)
17
- source_code.gsub(/@@@(.*?)@@@/m) do |match|
18
- new(book_dir, format, $1, raw).process
19
- end
20
- end
21
-
22
- # Process each syntax block individually.
23
- #
24
- def initialize(book_dir, format, code, raw = false)
25
- @format = format
26
- @book_dir = book_dir
27
- @io = StringIO.new(code)
28
- @lines = io.readlines.collect(&:chomp)
29
- @language = 'text' if raw
30
- end
31
-
32
- # Return unprocessed line codes.
33
- #
34
- def raw
35
- lines[1..-1].join("\n")
36
- end
37
-
38
- # Return meta data from syntax annotation.
39
- #
40
- def meta
41
- @meta ||= begin
42
- line = lines.first.squish
43
- _, language, file, modifier, reference = *line.match(/^([^ ]+)(?: ([^:#]+)(?:(:|#)(.*?))?)?$/)
44
-
45
- if modifier == "#"
46
- type = :block
47
- elsif modifier == ":"
48
- type = :range
49
- elsif file
50
- type = :file
51
- else
52
- type = :inline
53
- end
54
-
55
- {
56
- :language => language,
57
- :file => file,
58
- :type => type,
59
- :reference => reference
60
- }
61
- end
62
- end
63
-
64
- # Process syntax block, returning a +pre+ HTML tag.
65
- #
66
- def process
67
- code = raw.to_s.strip_heredoc
68
- code = process_file.gsub(/\n^.*?@(begin|end):.*?$/, "") if meta[:file]
69
-
70
- code = Highlight.apply(code, language)
71
-
72
- # escape for textile
73
- code = %[<notextile>#{code}</notextile>] if format == :textile
74
- code
75
- end
76
-
77
- private
78
- # Process line range as in <tt>@@@ ruby some_file.rb:15,20 @@@</tt>.
79
- #
80
- def process_range(code)
81
- starts, ends = meta[:reference].split(",").collect(&:to_i)
82
- code = StringIO.new(code).readlines[starts-1..ends-1].join("\n").strip_heredoc.chomp
83
- end
84
-
85
- # Process block name as in <tt>@@@ ruby some_file.rb#some_block @@@</tt>.
86
- #
87
- def process_block(code)
88
- code.gsub!(/\r\n/, "\n")
89
- re = %r[@begin: *\b(#{meta[:reference]})\b *[^\n]*\n(.*?)\n[^\n]*@end: \1]im
90
-
91
- if code.match(re)
92
- $2.strip_heredoc
93
- else
94
- "[missing '#{meta[:reference]}' block name]"
95
- end
96
- end
97
-
98
- # Process file and its relatives.
99
- #
100
- def process_file
101
- file_path = book_dir.join("code/#{meta[:file]}")
102
-
103
- if File.exist?(file_path)
104
- code = File.read(file_path)
105
-
106
- if meta[:type] == :range
107
- process_range(code)
108
- elsif meta[:type] == :block
109
- process_block(code)
110
- else
111
- code
112
- end
113
- else
114
- "[missing 'code/#{meta[:file]}' file]"
115
- end
116
- end
117
-
118
- # Return the language used for this syntax block. Overrideable
119
- # for epub generation.
120
- def language
121
- @language || meta[:language]
122
- end
123
- end
124
- end
@@ -1,6 +0,0 @@
1
- module Bookshelf
2
- module TOC
3
- autoload :HTML, "bookshelf/toc/html"
4
- autoload :Epub, "bookshelf/toc/epub"
5
- end
6
- end
@@ -1,41 +0,0 @@
1
- module Bookshelf
2
- module TOC
3
- class Epub
4
- attr_accessor :navigation
5
-
6
- def initialize(navigation)
7
- @navigation = navigation
8
- end
9
-
10
- def to_html
11
- ERB.new(template).result OpenStruct.new(:navigation => navigation).instance_eval{ binding }
12
- end
13
-
14
- def template
15
- <<-HTML.strip_heredoc.force_encoding("utf-8")
16
- <?xml version="1.0" encoding="utf-8" ?>
17
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
18
- <html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
19
- <head>
20
- <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
21
- <link rel="stylesheet" type="text/css" href="epub.css"/>
22
- <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />
23
- <title>Table of Contents</title>
24
- </head>
25
- <body>
26
- <div id="toc">
27
- <ul>
28
- <% navigation.each do |nav| %>
29
- <li>
30
- <a href="<%= nav[:content] %>"><%= nav[:label] %></a>
31
- </li>
32
- <% end %>
33
- </ul>
34
- </div>
35
- </body>
36
- </html>
37
- HTML
38
- end
39
- end
40
- end
41
- end
@@ -1,78 +0,0 @@
1
- module Bookshelf
2
- module TOC
3
- class HTML
4
- # Return the table of contents in hash format.
5
- #
6
- attr_reader :toc
7
-
8
- private_class_method :new
9
- attr_reader :buffer # :nodoc:
10
- attr_reader :attrs # :nodoc:
11
- attr_accessor :content # :nodoc:
12
-
13
- # Traverse every title and add a +id+ attribute.
14
- # Return the modified content.
15
- #
16
- def self.normalize(content)
17
- counter = {}
18
- html = Nokogiri::HTML.parse(content)
19
- html.search("h1, h2, h3, h4, h5, h6").each do |tag|
20
- title = tag.inner_text
21
- permalink = title.to_permalink
22
-
23
- counter[permalink] ||= 0
24
- counter[permalink] += 1
25
-
26
- permalink = "#{permalink}-#{counter[permalink]}" if counter[permalink] > 1
27
-
28
- tag.set_attribute("id", permalink)
29
- end
30
-
31
- html.css("body").to_xhtml.gsub(/<body>(.*?)<\/body>/m, "\\1")
32
- end
33
-
34
- # Traverse every title normalizing its content as a permalink.
35
- #
36
- def self.generate(content)
37
- content = normalize(content)
38
- listener = new
39
- listener.content = content
40
- Stream.new(content, listener).parse
41
- listener
42
- end
43
-
44
- def initialize # :nodoc:
45
- @toc = []
46
- @counters = {}
47
- end
48
-
49
- def tag(node) # :nodoc:
50
- toc << {
51
- :level => node.name.gsub(/[^\d]/, "").to_i,
52
- :text => node.text,
53
- :permalink => node["id"]
54
- }
55
- end
56
-
57
- # Return a hash with all normalized attributes.
58
- #
59
- def to_hash
60
- {
61
- :content => content,
62
- :html => to_html,
63
- :toc => toc
64
- }
65
- end
66
-
67
- # Return the table of contents in HTML format.
68
- #
69
- def to_html
70
- String.new.tap do |html|
71
- toc.each do |options|
72
- html << %[<div class="level#{options[:level]} #{options[:permalink]}"><a href="##{options[:permalink]}"><span>#{CGI.escape_html(options[:text])}</span></a></div>]
73
- end
74
- end
75
- end
76
- end
77
- end
78
- end