kitabu 1.0.0.rc1 → 1.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/Gemfile.lock +14 -20
  2. data/README.rdoc +54 -23
  3. data/kitabu.gemspec +1 -1
  4. data/lib/kitabu.rb +11 -4
  5. data/lib/kitabu/cli.rb +49 -6
  6. data/lib/kitabu/dependency.rb +19 -0
  7. data/lib/kitabu/exporter.rb +4 -5
  8. data/lib/kitabu/generator.rb +12 -15
  9. data/lib/kitabu/parser.rb +27 -2
  10. data/lib/kitabu/parser/epub.rb +96 -83
  11. data/lib/kitabu/parser/html.rb +51 -16
  12. data/lib/kitabu/parser/mobi.rb +1 -4
  13. data/lib/kitabu/parser/pdf.rb +23 -20
  14. data/lib/kitabu/parser/txt.rb +1 -5
  15. data/lib/kitabu/syntax.rb +5 -3
  16. data/lib/kitabu/syntax/highlight.rb +22 -0
  17. data/lib/kitabu/toc.rb +4 -78
  18. data/lib/kitabu/toc/epub.rb +41 -0
  19. data/lib/kitabu/toc/html.rb +78 -0
  20. data/lib/kitabu/version.rb +1 -1
  21. data/spec/kitabu/cli/export_spec.rb +2 -2
  22. data/spec/kitabu/cli/new_spec.rb +1 -1
  23. data/spec/kitabu/cli/permalinks_spec.rb +1 -1
  24. data/spec/kitabu/cli/version_spec.rb +1 -1
  25. data/spec/kitabu/extensions/redcloth_spec.rb +6 -6
  26. data/spec/kitabu/extensions/string_spec.rb +1 -1
  27. data/spec/kitabu/parser/epub_spec.rb +5 -1
  28. data/spec/kitabu/parser/html_spec.rb +15 -15
  29. data/spec/kitabu/parser/pdf_spec.rb +4 -4
  30. data/spec/kitabu/syntax_spec.rb +78 -74
  31. data/spec/kitabu/{toc_spec.rb → toc/html_spec.rb} +5 -5
  32. data/spec/spec_helper.rb +3 -1
  33. data/spec/support/mybook/output/mybook.pdf.html +83 -0
  34. data/spec/support/mybook/templates/{cover.erb → epub/cover.erb} +1 -1
  35. data/spec/support/mybook/templates/{epub.erb → epub/page.erb} +1 -1
  36. data/spec/support/mybook/templates/epub/style.css +0 -0
  37. data/spec/support/mybook/templates/html/layout.css +353 -0
  38. data/spec/support/mybook/templates/html/layout.erb +50 -0
  39. data/spec/support/mybook/templates/html/syntax.css +58 -0
  40. data/spec/support/mybook/templates/html/user.css +1 -0
  41. data/spec/support/shared.rb +48 -15
  42. data/templates/cover.erb +1 -1
  43. data/templates/cover.png +0 -0
  44. data/templates/epub.css +1 -0
  45. data/templates/epub.erb +1 -1
  46. data/templates/sample.md +6 -0
  47. data/templates/syntax.css +58 -0
  48. metadata +32 -44
  49. data/spec/support/mybook/templates/epub.css +0 -1
  50. data/spec/support/mybook/templates/layout.css +0 -137
  51. data/spec/support/mybook/templates/layout.erb +0 -46
  52. data/spec/support/mybook/templates/syntax.css +0 -186
  53. data/spec/support/mybook/templates/user.css +0 -1
  54. data/templates/styles/active4d.css +0 -114
  55. data/templates/styles/all_hallows_eve.css +0 -72
  56. data/templates/styles/amy.css +0 -147
  57. data/templates/styles/blackboard.css +0 -88
  58. data/templates/styles/brilliance_black.css +0 -605
  59. data/templates/styles/brilliance_dull.css +0 -599
  60. data/templates/styles/cobalt.css +0 -149
  61. data/templates/styles/dawn.css +0 -121
  62. data/templates/styles/eiffel.css +0 -121
  63. data/templates/styles/espresso_libre.css +0 -109
  64. data/templates/styles/idle.css +0 -62
  65. data/templates/styles/iplastic.css +0 -80
  66. data/templates/styles/lazy.css +0 -73
  67. data/templates/styles/mac_classic.css +0 -123
  68. data/templates/styles/magicwb_amiga.css +0 -104
  69. data/templates/styles/pastels_on_dark.css +0 -188
  70. data/templates/styles/slush_poppies.css +0 -85
  71. data/templates/styles/spacecadet.css +0 -51
  72. data/templates/styles/sunburst.css +0 -180
  73. data/templates/styles/twilight.css +0 -137
  74. data/templates/styles/zenburnesque.css +0 -91
@@ -0,0 +1,22 @@
1
+ module Kitabu
2
+ class Syntax
3
+ class Highlight
4
+ def self.apply(code, language)
5
+ if Dependency.pygments_rb?
6
+ pygments(code, language)
7
+ else
8
+ coderay(code, language)
9
+ end
10
+ end
11
+
12
+ private
13
+ def self.pygments(code, language)
14
+ Pygments.highlight(code, :lexer => language, :options => {:encoding => "utf-8"})
15
+ end
16
+
17
+ def self.coderay(code, language)
18
+ CodeRay.scan(code, language).div(:css => :class)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,80 +1,6 @@
1
1
  module Kitabu
2
- class Toc
3
- # Return the table of contents in hash format.
4
- #
5
- attr_reader :toc
6
-
7
- private_class_method :new
8
- attr_reader :buffer # :nodoc:
9
- attr_reader :attrs # :nodoc:
10
- attr_accessor :content # :nodoc:
11
-
12
- # Traverse every title and add a +id+ attribute.
13
- # Return the modified content.
14
- #
15
- def self.normalize(content)
16
- counter = {}
17
- html = Nokogiri::HTML.parse(content)
18
- html.search("h2, h3, h4, h5, h6").each do |tag|
19
- title = tag.inner_text
20
- permalink = title.to_permalink
21
-
22
- counter[permalink] ||= 0
23
- counter[permalink] += 1
24
-
25
- permalink = "#{permalink}-#{counter[permalink]}" if counter[permalink] > 1
26
-
27
- tag.set_attribute("id", permalink)
28
- end
29
-
30
- html = html.to_xhtml
31
- html.force_encoding("UTF-8") if html.encoding_aware?
32
-
33
- _, content = *html.match(/<body>(.*?)<\/body>/m)
34
- content
35
- end
36
-
37
- # Traverse every title normalizing its content as a permalink.
38
- #
39
- def self.generate(content)
40
- content = normalize(content)
41
- listener = new
42
- listener.content = content
43
- Stream.new(content, listener).parse
44
- listener
45
- end
46
-
47
- def initialize # :nodoc:
48
- @toc = []
49
- @counters = {}
50
- end
51
-
52
- def tag(node) # :nodoc:
53
- toc << {
54
- :level => node.name.gsub(/[^\d]/, "").to_i,
55
- :text => node.text,
56
- :permalink => node["id"]
57
- }
58
- end
59
-
60
- # Return a hash with all normalized attributes.
61
- #
62
- def to_hash
63
- {
64
- :content => content,
65
- :html => to_html,
66
- :toc => toc
67
- }
68
- end
69
-
70
- # Return the table of contents in HTML format.
71
- #
72
- def to_html
73
- String.new.tap do |html|
74
- toc.each do |options|
75
- html << %[<div class="level#{options[:level]} #{options[:permalink]}"><a href="##{options[:permalink]}"><span>#{CGI.escape_html(options[:text])}</span></a></div>]
76
- end
77
- end
78
- end
2
+ module TOC
3
+ autoload :HTML, "kitabu/toc/html"
4
+ autoload :Epub, "kitabu/toc/epub"
79
5
  end
80
- end
6
+ end
@@ -0,0 +1,41 @@
1
+ module Kitabu
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
@@ -0,0 +1,78 @@
1
+ module Kitabu
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("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").inner_html
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
@@ -3,6 +3,6 @@ module Kitabu
3
3
  MAJOR = 1
4
4
  MINOR = 0
5
5
  PATCH = 0
6
- STRING = "#{MAJOR}.#{MINOR}.#{PATCH}.rc1"
6
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}.rc2"
7
7
  end
8
8
  end
@@ -2,13 +2,13 @@ require "spec_helper"
2
2
 
3
3
  describe Kitabu::Cli do
4
4
  context "while running export" do
5
- it "should exit with status 1 when an invalid --only option is provided" do
5
+ it "exits with status 1 when an invalid --only option is provided" do
6
6
  expect {
7
7
  capture(:stderr){ Kitabu::Cli.start(["export", "--only=invalid"]) }
8
8
  }.to exit_with_code(1)
9
9
  end
10
10
 
11
- it "should exit with status 1 when no config file is found" do
11
+ it "exits with status 1 when no config file is found" do
12
12
  expect {
13
13
  capture(:stderr){ Kitabu::Cli.start(["export"]) }
14
14
  }.to exit_with_code(1)
@@ -10,7 +10,7 @@ describe Kitabu::Cli do
10
10
  it_behaves_like "e-book"
11
11
  end
12
12
 
13
- it "should exit with status 1 when no path is provided" do
13
+ it "exits with status 1 when no path is provided" do
14
14
  expect {
15
15
  capture(:stderr){ Kitabu::Cli.start(["new"]) }
16
16
  }.to exit_with_code(1)
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe Kitabu::Cli do
4
4
  context "while running permalinks" do
5
- it "should recognize command" do
5
+ it "recognizes command" do
6
6
  Dir.chdir SPECDIR.join("support/mybook")
7
7
  expect {
8
8
  capture(:stdout) { Kitabu::Cli.start(["permalinks"]) }
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe Kitabu::Cli do
4
4
  context "while running version" do
5
- it "should output version" do
5
+ it "outputs version" do
6
6
  %w[version -v --version].each do |arg|
7
7
  output = capture(:stdout){ Kitabu::Cli.start([arg]) }.chomp
8
8
  output.should == "Kitabu version #{Kitabu::Version::STRING}"
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe RedCloth do
4
4
  describe "#figure" do
5
- it "should render html" do
5
+ it "renders html" do
6
6
  html = RedCloth.convert("figure(The Rails logo). rails.png")
7
7
  html.should have_tag("p.figure") do |p|
8
8
  p.should have_tag("img[@src='../images/rails.png'][@alt='The Rails logo']")
@@ -12,21 +12,21 @@ describe RedCloth do
12
12
  end
13
13
 
14
14
  describe "#note" do
15
- it "should render html" do
15
+ it "renders html" do
16
16
  html = RedCloth.convert("note. Some important note!")
17
17
  html.should have_tag("p.note", "Some important note!")
18
18
  end
19
19
  end
20
20
 
21
21
  describe "#attention" do
22
- it "should render html" do
22
+ it "renders html" do
23
23
  html = RedCloth.convert("attention. Some warning note!")
24
24
  html.should have_tag("p.attention", "Some warning note!")
25
25
  end
26
26
  end
27
27
 
28
28
  describe "#file" do
29
- it "should render html" do
29
+ it "renders html" do
30
30
  Kitabu.stub :config => { :base_url => "http://example.com" }
31
31
  html = RedCloth.convert("file. app/models/users.rb")
32
32
 
@@ -37,14 +37,14 @@ describe RedCloth do
37
37
  end
38
38
 
39
39
  context "custom footnote helper" do
40
- it "should render html" do
40
+ it "renders html" do
41
41
  html = RedCloth.convert("Writing some text with a footnote %{this is a footnote}")
42
42
  html.should == %[<p>Writing some text with a footnote<span class="footnote">this is a footnote</span></p>]
43
43
  end
44
44
  end
45
45
 
46
46
  context "custom url helper" do
47
- it "should render html" do
47
+ it "renders html" do
48
48
  html = RedCloth.convert("<http://example.com>")
49
49
  html.should == %[<p><a href="http://example.com">http://example.com</a></p>]
50
50
  end
@@ -3,7 +3,7 @@ require "spec_helper"
3
3
 
4
4
  describe String do
5
5
  describe "#to_permalink" do
6
- it "should normalize strings" do
6
+ it "normalizes strings" do
7
7
  {
8
8
  'This IS a Tripped out title!!.!1 (well/ not really)' => 'this-is-a-tripped-out-title-1-well-not-really',
9
9
  '////// meph1sto r0x ! \\\\\\' => 'meph1sto-r0x',
@@ -3,8 +3,12 @@ require "spec_helper"
3
3
  describe Kitabu::Parser::Epub do
4
4
  let(:root) { SPECDIR.join("support/mybook") }
5
5
 
6
- it "should generate e-pub" do
6
+ before do
7
+ Kitabu::Parser::HTML.parse(root)
7
8
  Kitabu::Parser::Epub.parse(root)
9
+ end
10
+
11
+ it "generates e-pub" do
8
12
  root.join("output/mybook.epub").should be_file
9
13
  end
10
14
  end
@@ -1,36 +1,36 @@
1
1
  require "spec_helper"
2
2
 
3
- describe Kitabu::Parser::Html do
3
+ describe Kitabu::Parser::HTML do
4
4
  let(:root) { SPECDIR.join("support/mybook") }
5
5
  let(:source) { root.join("text") }
6
- let(:parser) { Kitabu::Parser::Html.new(root) }
6
+ let(:parser) { described_class.new(root) }
7
7
  let(:entries) { parser.entries }
8
8
  let(:relative) { entries.collect {|e| e.to_s.gsub(/^#{Regexp.escape(source.to_s)}\//, "")} }
9
9
 
10
10
  context "when filtering entries" do
11
- it "should skip dot directories" do
11
+ it "skips dot directories" do
12
12
  relative.should_not include(".")
13
13
  relative.should_not include("..")
14
14
  end
15
15
 
16
- it "should skip dot files" do
16
+ it "skips dot files" do
17
17
  relative.should_not include(".gitkeep")
18
18
  end
19
19
 
20
- it "should skip files that start with underscore" do
20
+ it "skips files that start with underscore" do
21
21
  relative.should_not include("_00_Introduction.markdown")
22
22
  end
23
23
 
24
- it "should skip other files" do
24
+ it "skips other files" do
25
25
  relative.should_not include("CHANGELOG.textile")
26
26
  relative.should_not include("TOC.textile")
27
27
  end
28
28
 
29
- it "should return only first-level entries" do
29
+ it "returns only first-level entries" do
30
30
  relative.should_not include("04_With_Directory/Some_Chapter.mkdn")
31
31
  end
32
32
 
33
- it "should return entries" do
33
+ it "returns entries" do
34
34
  relative.first.should == "01_Markdown_Chapter.markdown"
35
35
  relative.second.should == "02_Textile_Chapter.textile"
36
36
  relative.third.should == "03_HTML_Chapter.html"
@@ -44,31 +44,31 @@ describe Kitabu::Parser::Html do
44
44
  let(:html) { File.read(file) }
45
45
  before { parser.parse }
46
46
 
47
- it "should have several chapters" do
47
+ it "has several chapters" do
48
48
  html.should have_tag("div.chapter", 4)
49
49
  end
50
50
 
51
- it "should render .markdown" do
51
+ it "renders .markdown" do
52
52
  html.should have_tag("div.chapter > h2#markdown", "Markdown")
53
53
  end
54
54
 
55
- it "should render .mkdn" do
55
+ it "renders .mkdn" do
56
56
  html.should have_tag("div.chapter > h2#some-chapter", "Some Chapter")
57
57
  end
58
58
 
59
- it "should render .textile" do
59
+ it "renders .textile" do
60
60
  html.should have_tag("div.chapter > h2#textile", "Textile")
61
61
  end
62
62
 
63
- it "should render .html" do
63
+ it "renders .html" do
64
64
  html.should have_tag("div.chapter > h2#html", "HTML")
65
65
  end
66
66
 
67
- it "should have use config file" do
67
+ it "uses config file" do
68
68
  html.should have_tag("div.imprint p", "Copyright (C) 2010 John Doe.")
69
69
  end
70
70
 
71
- it "should render changelog" do
71
+ it "renders changelog" do
72
72
  html.should have_tag("div.changelog h2", "Revisions")
73
73
  end
74
74
  end
@@ -1,14 +1,14 @@
1
1
  require "spec_helper"
2
2
 
3
- describe Kitabu::Parser::Pdf do
3
+ describe Kitabu::Parser::PDF do
4
4
  let(:root) { SPECDIR.join("support/mybook") }
5
5
 
6
6
  before do
7
- Kitabu::Parser::Html.new(root).parse
8
- Kitabu::Parser::Pdf.new(root).parse
7
+ Kitabu::Parser::HTML.new(root).parse
8
+ Kitabu::Parser::PDF.new(root).parse
9
9
  end
10
10
 
11
- it "should generate pdf file" do
11
+ it "generates pdf file" do
12
12
  root.join("output/mybook.pdf").should be_file
13
13
  end
14
14
  end