kitabu 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +5 -5
  2. data/.github/CODEOWNERS +4 -0
  3. data/.github/FUNDING.yml +4 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
  5. data/.github/ISSUE_TEMPLATE/config.yml +5 -0
  6. data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  7. data/.github/PULL_REQUEST_TEMPLATE.md +38 -0
  8. data/.github/dependabot.yml +15 -0
  9. data/.github/workflows/ruby-tests.yml +61 -0
  10. data/.rubocop.yml +17 -0
  11. data/CHANGELOG.md +13 -2
  12. data/CODE_OF_CONDUCT.md +74 -0
  13. data/CONTRIBUTING.md +79 -0
  14. data/Gemfile +2 -0
  15. data/LICENSE.md +20 -0
  16. data/README.md +103 -88
  17. data/Rakefile +7 -0
  18. data/bin/kitabu +4 -0
  19. data/kitabu.gemspec +21 -15
  20. data/lib/kitabu/cli.rb +54 -39
  21. data/lib/kitabu/dependency.rb +11 -5
  22. data/lib/kitabu/errors.rb +2 -0
  23. data/lib/kitabu/exporter/base.rb +11 -11
  24. data/lib/kitabu/exporter/css.rb +6 -15
  25. data/lib/kitabu/exporter/epub.rb +23 -17
  26. data/lib/kitabu/exporter/html.rb +27 -21
  27. data/lib/kitabu/exporter/mobi.rb +7 -1
  28. data/lib/kitabu/exporter/pdf.rb +9 -3
  29. data/lib/kitabu/exporter.rb +15 -16
  30. data/lib/kitabu/extensions/rouge.rb +6 -1
  31. data/lib/kitabu/extensions/string.rb +5 -3
  32. data/lib/kitabu/footnotes/base.rb +2 -0
  33. data/lib/kitabu/footnotes/html.rb +18 -13
  34. data/lib/kitabu/footnotes/pdf.rb +17 -11
  35. data/lib/kitabu/generator.rb +13 -8
  36. data/lib/kitabu/helpers.rb +12 -9
  37. data/lib/kitabu/markdown.rb +12 -10
  38. data/lib/kitabu/source_list.rb +15 -12
  39. data/lib/kitabu/stats.rb +3 -1
  40. data/lib/kitabu/syntax/highlight.rb +4 -11
  41. data/lib/kitabu/toc/epub.rb +5 -2
  42. data/lib/kitabu/toc/html/stream.rb +3 -1
  43. data/lib/kitabu/toc/html.rb +12 -8
  44. data/lib/kitabu/version.rb +4 -2
  45. data/lib/kitabu.rb +8 -10
  46. data/spec/kitabu/cli/export_spec.rb +6 -4
  47. data/spec/kitabu/cli/new_spec.rb +6 -4
  48. data/spec/kitabu/cli/permalinks_spec.rb +4 -2
  49. data/spec/kitabu/cli/stats_spec.rb +19 -15
  50. data/spec/kitabu/cli/version_spec.rb +3 -1
  51. data/spec/kitabu/exporter/css_spec.rb +3 -1
  52. data/spec/kitabu/exporter/epub_spec.rb +2 -0
  53. data/spec/kitabu/exporter/html_spec.rb +11 -9
  54. data/spec/kitabu/exporter/mobi_spec.rb +5 -5
  55. data/spec/kitabu/exporter/pdf_spec.rb +8 -4
  56. data/spec/kitabu/extensions/string_spec.rb +14 -9
  57. data/spec/kitabu/footnotes/html_spec.rb +35 -33
  58. data/spec/kitabu/generator_spec.rb +3 -1
  59. data/spec/kitabu/markdown_spec.rb +8 -6
  60. data/spec/kitabu/source_list_spec.rb +8 -2
  61. data/spec/kitabu/stats_spec.rb +10 -6
  62. data/spec/kitabu/toc/html_spec.rb +37 -21
  63. data/spec/spec_helper.rb +23 -8
  64. data/spec/support/exit_with_code.rb +7 -5
  65. data/spec/support/have_tag.rb +44 -32
  66. data/spec/support/helper.rb +5 -3
  67. data/spec/support/mybook/code/code.rb +2 -0
  68. data/spec/support/mybook/config/helper.rb +2 -0
  69. data/spec/support/shared.rb +8 -6
  70. data/templates/Gemfile +5 -3
  71. data/templates/Guardfile +3 -1
  72. data/templates/helper.rb +8 -6
  73. data/templates/templates/styles/epub.css +1 -0
  74. data/templates/templates/styles/files/normalize.css +351 -0
  75. data/templates/templates/styles/{html.scss → html.css} +28 -26
  76. data/templates/templates/styles/{pdf.scss → pdf.css} +49 -47
  77. data/templates/templates/styles/print.css +2 -0
  78. data/templates/text/01_Getting_Started.md +27 -9
  79. data/templates/text/02_Creating_Chapters.md +9 -3
  80. data/templates/text/{03_Syntax_Highlighting.erb → 03_Syntax_Highlighting.md.erb} +12 -7
  81. data/templates/text/04_Dynamic_Content.md.erb +48 -0
  82. data/templates/text/05_Exporting_Files.md +17 -8
  83. metadata +40 -48
  84. data/.gitmodules +0 -3
  85. data/.travis.yml +0 -18
  86. data/lib/kitabu/exporter/txt.rb +0 -18
  87. data/spec/kitabu/exporter/txt_spec.rb +0 -14
  88. data/templates/ebook.png +0 -0
  89. data/templates/templates/styles/epub.scss +0 -1
  90. data/templates/templates/styles/files/_normalize.scss +0 -427
  91. data/templates/templates/styles/print.scss +0 -2
  92. data/templates/text/04_Dynamic_Content.erb +0 -64
@@ -1,15 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitabu
2
4
  class Exporter
3
5
  class Epub < Base
4
6
  def sections
5
- @sections ||= html.css("div.chapter").each_with_index.map do |chapter, index|
6
- OpenStruct.new({
7
- index: index,
8
- filename: "section_#{index}.html",
9
- filepath: tmp_dir.join("section_#{index}.html").to_s,
10
- html: Nokogiri::HTML(chapter.inner_html)
11
- })
12
- end
7
+ @sections ||=
8
+ html.css("div.chapter").each_with_index.map do |chapter, index|
9
+ OpenStruct.new(
10
+ index: index,
11
+ filename: "section_#{index}.html",
12
+ filepath: tmp_dir.join("section_#{index}.html").to_s,
13
+ html: Nokogiri::HTML(chapter.inner_html)
14
+ )
15
+ end
13
16
  end
14
17
 
15
18
  def epub
@@ -34,7 +37,7 @@ module Kitabu
34
37
  epub.save(epub_path)
35
38
 
36
39
  true
37
- rescue Exception => error
40
+ rescue StandardError => error
38
41
  handle_error(error)
39
42
  false
40
43
  end
@@ -54,7 +57,8 @@ module Kitabu
54
57
  epub.publisher config[:publisher]
55
58
  epub.date config[:published_at]
56
59
  epub.uid config[:uid]
57
- epub.identifier config[:identifier][:id], scheme: config[:identifier][:type]
60
+ epub.identifier config[:identifier][:id],
61
+ scheme: config[:identifier][:type]
58
62
  epub.cover_page cover_image if cover_image && File.exist?(cover_image)
59
63
  end
60
64
 
@@ -70,13 +74,11 @@ module Kitabu
70
74
  # First we need to get all ids, which are used as
71
75
  # the anchor target.
72
76
  #
73
- links = sections.inject({}) do |buffer, section|
77
+ links = sections.each_with_object({}) do |section, buffer|
74
78
  section.html.css("[id]").each do |element|
75
- anchor = "##{element["id"]}"
79
+ anchor = "##{element['id']}"
76
80
  buffer[anchor] = "#{section.filename}#{anchor}"
77
81
  end
78
-
79
- buffer
80
82
  end
81
83
 
82
84
  # Then we can normalize all links and
@@ -102,14 +104,16 @@ module Kitabu
102
104
  # Save file to disk.
103
105
  #
104
106
  File.open(section.filepath, "w") do |file|
105
- body = section.html.css("body").to_xhtml.gsub(%r[<body>(.*?)</body>]m, "\\1")
107
+ body = section.html.css("body").to_xhtml.gsub(
108
+ %r{<body>(.*?)</body>}m, "\\1"
109
+ )
106
110
  file << render_chapter(body)
107
111
  end
108
112
  end
109
113
  end
110
114
 
111
115
  def render_chapter(content)
112
- locals = config.merge(:content => content)
116
+ locals = config.merge(content: content)
113
117
  render_template(template_path, locals)
114
118
  end
115
119
 
@@ -122,7 +126,9 @@ module Kitabu
122
126
  end
123
127
 
124
128
  def cover_image
125
- path = Dir[root_dir.join("templates/epub/cover.{jpg,png,gif}").to_s].first
129
+ path =
130
+ Dir[root_dir.join("templates/epub/cover.{jpg,png,gif}").to_s].first
131
+
126
132
  return path if path && File.exist?(path)
127
133
  end
128
134
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitabu
2
4
  class Exporter
3
5
  class HTML < Base
@@ -21,7 +23,7 @@ module Kitabu
21
23
  end
22
24
 
23
25
  true
24
- rescue Exception => error
26
+ rescue StandardError => error
25
27
  handle_error(error)
26
28
  false
27
29
  end
@@ -33,28 +35,29 @@ module Kitabu
33
35
  # Return all chapters wrapped in a <tt>div.chapter</tt> tag.
34
36
  #
35
37
  def content
36
- String.new.tap do |content|
38
+ buffer = [].tap do |content|
37
39
  source_list.each_chapter do |files|
38
40
  content << %[<div class="chapter">#{render_chapter(files)}</div>]
39
41
  end
40
42
  end
43
+
44
+ buffer.join
41
45
  end
42
46
 
43
- private
44
47
  # Render +file+ considering its extension.
45
48
  #
46
- def render_file(file)
47
- if format(file) == :erb
48
- content = render_template(file, config)
49
- else
50
- content = File.read(file)
51
- end
49
+ private def render_file(file_path)
50
+ content = if file_format(file_path) == :erb
51
+ render_template(file_path, config)
52
+ else
53
+ File.read(file_path)
54
+ end
52
55
 
53
56
  Kitabu::Markdown.render(content)
54
57
  end
55
58
 
56
- def format(file)
57
- if File.extname(file) == '.erb'
59
+ private def file_format(file_path)
60
+ if File.extname(file_path) == ".erb"
58
61
  :erb
59
62
  else
60
63
  :markdown
@@ -63,15 +66,16 @@ module Kitabu
63
66
 
64
67
  # Parse layout file, making available all configuration entries.
65
68
  #
66
- def parse_layout(html)
69
+ private def parse_layout(html)
67
70
  toc = TOC::HTML.generate(html)
68
- content = Footnotes::HTML.process(toc.content).html.css('body').first.inner_html
71
+ content =
72
+ Footnotes::HTML.process(toc.content).html.css("body").first.inner_html
69
73
 
70
- locals = config.merge({
74
+ locals = config.merge(
71
75
  content: content,
72
76
  toc: toc.to_html,
73
77
  changelog: render_changelog
74
- })
78
+ )
75
79
 
76
80
  render_template(root_dir.join("templates/html/layout.erb"), locals)
77
81
  end
@@ -79,36 +83,38 @@ module Kitabu
79
83
  # Render changelog file.
80
84
  # This file can be used to inform any book change.
81
85
  #
82
- def render_changelog
86
+ private def render_changelog
83
87
  changelog = Dir[root_dir.join("text/CHANGELOG.*")].first
84
88
  render_file(changelog) if changelog
85
89
  end
86
90
 
87
91
  # Render all +files+ from a given chapter.
88
92
  #
89
- def render_chapter(files)
90
- String.new.tap do |chapter|
93
+ private def render_chapter(files)
94
+ buffer = [].tap do |chapter|
91
95
  files.each do |file|
92
96
  chapter << render_file(file) << "\n\n"
93
97
  end
94
98
  end
99
+
100
+ buffer.join
95
101
  end
96
102
 
97
103
  # Copy images
98
104
  #
99
- def copy_images!
105
+ private def copy_images!
100
106
  copy_directory("images", "output/images")
101
107
  end
102
108
 
103
109
  # Copy font files
104
110
  #
105
- def copy_fonts!
111
+ private def copy_fonts!
106
112
  copy_directory("fonts", "output/fonts")
107
113
  end
108
114
 
109
115
  # Export all root stylesheets.
110
116
  #
111
- def export_stylesheets!
117
+ private def export_stylesheets!
112
118
  Exporter::CSS.new(root_dir).export
113
119
  end
114
120
  end
@@ -1,11 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitabu
2
4
  class Exporter
3
5
  class Mobi < Base
4
6
  def export
5
- spawn_command ["kindlegen", epub_file.to_s]
7
+ spawn_command ["ebook-convert", epub_file.to_s, mobi_file.to_s]
6
8
  true
7
9
  end
8
10
 
11
+ def mobi_file
12
+ root_dir.join("output/#{name}.mobi")
13
+ end
14
+
9
15
  def epub_file
10
16
  root_dir.join("output/#{name}.epub")
11
17
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitabu
2
4
  class Exporter
3
5
  class PDF < Base
@@ -9,13 +11,17 @@ module Kitabu
9
11
 
10
12
  def apply_footnotes!
11
13
  html = Footnotes::PDF.process(html_file.read).html
12
- create_html_file(html_for_print, html, 'print')
13
- create_html_file(html_for_pdf, html, 'pdf')
14
+ create_html_file(html_for_print, html, "print")
15
+ create_html_file(html_for_pdf, html, "pdf")
14
16
  end
15
17
 
16
18
  def create_html_file(target, html, class_name)
17
19
  html.css("html").first.set_attribute "class", class_name
18
- html.css("link[name=stylesheet]").first.set_attribute "href", "styles/#{class_name}.css"
20
+ html
21
+ .css("link[name=stylesheet]")
22
+ .first
23
+ .set_attribute "href", "styles/#{class_name}.css"
24
+
19
25
  File.open(target, "w") {|f| f << html.to_html }
20
26
  end
21
27
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitabu
2
4
  class Exporter
3
5
  def self.run(root_dir, options)
@@ -5,8 +7,7 @@ module Kitabu
5
7
  exporter.export!
6
8
  end
7
9
 
8
- attr_accessor :root_dir
9
- attr_accessor :options
10
+ attr_accessor :root_dir, :options
10
11
 
11
12
  def initialize(root_dir, options)
12
13
  @root_dir = root_dir
@@ -26,37 +27,35 @@ module Kitabu
26
27
  export_pdf = [nil, "pdf"].include?(options[:only])
27
28
  export_epub = [nil, "mobi", "epub"].include?(options[:only])
28
29
  export_mobi = [nil, "mobi"].include?(options[:only])
29
- export_txt = [nil, "txt"].include?(options[:only])
30
30
 
31
31
  exported = []
32
32
  exported << HTML.export(root_dir)
33
33
  exported << PDF.export(root_dir) if export_pdf && Dependency.prince?
34
34
  exported << Epub.export(root_dir) if export_epub
35
- exported << Mobi.export(root_dir) if export_mobi && Dependency.kindlegen?
36
- exported << Txt.export(root_dir) if export_txt && Dependency.html2text?
35
+ exported << Mobi.export(root_dir) if export_mobi && Dependency.calibre?
37
36
 
38
37
  if exported.all?
39
38
  color = :green
40
- message = options[:auto] ? "exported!" : "** e-book has been exported"
39
+ message = options[:auto] ? "exported!" : "=> e-book has been exported"
41
40
 
42
41
  if options[:open] && export_pdf
43
42
  filepath = root_dir.join("output/#{File.basename(root_dir)}.pdf")
44
43
 
45
- if RUBY_PLATFORM =~ /darwin/
44
+ case RUBY_PLATFORM
45
+ when /darwin/
46
46
  IO.popen("open -a Preview.app '#{filepath}'").close
47
- elsif RUBY_PLATFORM =~ /linux/
48
- Process.detach(Process.spawn("xdg-open '#{filepath}'", :out => "/dev/null"))
47
+ when /linux/
48
+ Process.detach(Process.spawn("xdg-open '#{filepath}'",
49
+ out: "/dev/null"))
49
50
  end
50
51
  end
51
-
52
- Notifier.notify(
53
- :image => Kitabu::ROOT.join("templates/ebook.png").to_s,
54
- :title => "Kitabu",
55
- :message => "Your \"#{config[:title]}\" e-book has been exported!"
56
- )
57
52
  else
58
53
  color = :red
59
- message = options[:auto] ? "could not be exported!" : "** e-book couldn't be exported"
54
+ message = if options[:auto]
55
+ "could not be exported!"
56
+ else
57
+ "=> e-book couldn't be exported"
58
+ end
60
59
  end
61
60
 
62
61
  ui.say message, color
@@ -1,9 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rouge
2
4
  module Plugins
3
5
  module Redcarpet
4
6
  def rouge_formatter(lexer)
5
7
  options = lexer.respond_to?(:options) ? lexer.options : {}
6
- Formatters::HTMLLegacy.new({css_class: "highlight #{lexer.tag}"}.merge(options))
8
+
9
+ Formatters::HTMLLegacy.new(
10
+ {css_class: "highlight #{lexer.tag}"}.merge(options)
11
+ )
7
12
  end
8
13
  end
9
14
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class String
2
4
  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, "-")
5
+ str = dup.unicode_normalize(:nfkd)
6
+ str = str.gsub(/[^\x00-\x7F]/, "").to_s
7
+ str.gsub!(/[^-\w]+/xim, "-")
6
8
  str.gsub!(/-+/xm, "-")
7
9
  str.gsub!(/^-?(.*?)-?$/, '\1')
8
10
  str.downcase!
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitabu
2
4
  module Footnotes
3
5
  class Base
@@ -1,25 +1,28 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitabu
2
4
  module Footnotes
3
5
  class HTML < Base
4
6
  def process
5
- html.css('.chapter').each(&method(:process_chapter))
7
+ html.css(".chapter").each(&method(:process_chapter))
6
8
  end
7
9
 
8
10
  def process_chapter(chapter)
9
- footnotes = chapter.css('.footnotes').first
11
+ footnotes = chapter.css(".footnotes").first
10
12
  return unless footnotes
11
- list = footnotes.css('ol').first
12
- list.set_attribute 'start', footnote_index
13
13
 
14
- chapter.css('.footnotes li').each do |footnote|
14
+ list = footnotes.css("ol").first
15
+ list.set_attribute "start", footnote_index
16
+
17
+ chapter.css(".footnotes li").each do |footnote|
15
18
  process_footnote(chapter, footnote)
16
19
  increment_footnote_index!
17
20
  end
18
21
  end
19
22
 
20
23
  def process_footnote(chapter, footnote)
21
- current_index = footnote.get_attribute('id').gsub(/[^\d]/m, '')
22
- footnote.set_attribute 'id', "fn#{footnote_index}"
24
+ current_index = footnote.get_attribute("id").gsub(/[^\d]/m, "")
25
+ footnote.set_attribute "id", "fn#{footnote_index}"
23
26
 
24
27
  process_links_to_footnote(chapter, current_index)
25
28
  process_rev_links(chapter, current_index)
@@ -28,25 +31,27 @@ module Kitabu
28
31
 
29
32
  def process_links_to_footnote(chapter, current_index)
30
33
  chapter.css("a[href='#fn#{current_index}']").each do |link|
31
- link.set_attribute 'href', "#fn#{footnote_index}"
34
+ link.set_attribute "href", "#fn#{footnote_index}"
32
35
  end
33
36
  end
34
37
 
35
38
  def process_rev_links(chapter, current_index)
36
39
  chapter.css("a[href='#fnref#{current_index}']").each do |link|
37
- link.set_attribute 'href', "#fnref#{footnote_index}"
40
+ link.set_attribute "href", "#fnref#{footnote_index}"
38
41
  end
39
42
  end
40
43
 
41
44
  def process_ref_elements(chapter, current_index)
42
- chapter.css("sup[id=fnref#{current_index}]").each_with_index do |sup, index|
45
+ selector = "sup[id=fnref#{current_index}]"
46
+
47
+ chapter.css(selector).each_with_index do |sup, index|
43
48
  if index.zero?
44
- sup.set_attribute 'id', "fnref#{footnote_index}"
49
+ sup.set_attribute "id", "fnref#{footnote_index}"
45
50
  else
46
- sup.remove_attribute 'id'
51
+ sup.remove_attribute "id"
47
52
  end
48
53
 
49
- sup.css('a').first.content = footnote_index
54
+ sup.css("a").first.content = footnote_index
50
55
  end
51
56
  end
52
57
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitabu
2
4
  module Footnotes
3
5
  class PDF < Base
@@ -8,35 +10,39 @@ module Kitabu
8
10
 
9
11
  def remove_duplicated_attributes
10
12
  # https://github.com/sparklemotion/nokogiri/issues/339
11
- html.css('html').first.tap do |element|
13
+ html.css("html").first.tap do |element|
12
14
  next unless element
13
- element.delete('xmlns')
14
- element.delete('xml:lang')
15
+
16
+ element.delete("xmlns")
17
+ element.delete("xml:lang")
15
18
  end
16
19
  end
17
20
 
18
21
  def process_chapter(chapter)
19
- chapter.css('.footnotes li').each do |footnote|
22
+ chapter.css(".footnotes li").each do |footnote|
20
23
  process_footnote(chapter, footnote)
21
24
  increment_footnote_index!
22
25
  end
23
26
 
24
- chapter.css('.footnotes').each(&:remove)
27
+ chapter.css(".footnotes").each(&:remove)
25
28
  end
26
29
 
27
30
  def process_footnote(chapter, footnote)
28
31
  # Remove rev links
29
- footnote.css('[rev=footnote]').map(&:remove)
32
+ footnote.css("[rev=footnote]").map(&:remove)
30
33
 
31
34
  # Create an element for storing the footnote description
32
- description = Nokogiri::XML::Node.new('span', Nokogiri::HTML::DocumentFragment.parse(''))
33
- description.set_attribute 'class', 'footnote'
34
- description.inner_html = footnote.css('p').map(&:inner_html).join("\n")
35
+ description = Nokogiri::XML::Node.new(
36
+ "span",
37
+ Nokogiri::HTML::DocumentFragment.parse("")
38
+ )
39
+ description.set_attribute "class", "footnote"
40
+ description.inner_html = footnote.css("p").map(&:inner_html).join("\n")
35
41
 
36
42
  # Find ref based on footnote's id
37
- fn_id = footnote.get_attribute('id')
43
+ fn_id = footnote.get_attribute("id")
38
44
 
39
- refs = chapter.css("a[href='##{fn_id}']").each do |ref|
45
+ chapter.css("a[href='##{fn_id}']").each do |ref|
40
46
  sup = ref.parent
41
47
  sup.after(description)
42
48
  sup.remove
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitabu
2
4
  # The Kitabu::Generator class will create a new book structure.
3
5
  #
@@ -11,7 +13,7 @@ module Kitabu
11
13
  desc "Generate a new e-Book structure"
12
14
 
13
15
  def self.source_root
14
- File.dirname(__FILE__) + "/../../templates"
16
+ "#{File.dirname(__FILE__)}/../../templates"
15
17
  end
16
18
 
17
19
  def copy_templates
@@ -64,13 +66,16 @@ module Kitabu
64
66
  end
65
67
  end
66
68
 
67
- private
68
- # Retrieve user's name using finger.
69
- # Defaults to <tt>John Doe</tt>.
70
- #
71
- def full_name
72
- name = `finger $USER 2> /dev/null | grep Login | colrm 1 46 2> /dev/null`.chomp
73
- name.present? ? name.squish : "John Doe"
69
+ no_commands do
70
+ # Retrieve user's name using finger.
71
+ # Defaults to <tt>John Doe</tt>.
72
+ #
73
+ def full_name
74
+ name =
75
+ `finger $USER 2> /dev/null | grep Login | colrm 1 46 2> /dev/null`
76
+ .chomp
77
+ name.present? ? name.squish : "John Doe"
78
+ end
74
79
  end
75
80
  end
76
81
  end
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: false
2
+
1
3
  module Kitabu
2
4
  module Helpers
3
5
  def highlight_theme(name = theme)
4
6
  html = '<style type="text/css">'
5
- html << Rouge::Theme.find(name).render(scope: '.highlight')
6
- html << '</style>'
7
+ html << Rouge::Theme.find(name).render(scope: ".highlight")
8
+ html << "</style>"
7
9
  html
8
10
  end
9
11
 
10
- def image_tag(path, attributes = {})
11
- html = %[<img src="images/#{path}" />]
12
+ def image_tag(path, _attributes = {})
13
+ %[<img src="images/#{path}" />]
12
14
  end
13
15
 
14
16
  def escape_html(content)
@@ -17,19 +19,20 @@ module Kitabu
17
19
 
18
20
  def note(class_name = :info, &block)
19
21
  content = block_content(block)
20
- output << '<div class="note %s">' % escape_html(class_name)
22
+ output << ('<div class="note %s">' % escape_html(class_name)) # rubocop:disable Style/FormatString
21
23
  output << markdown(content)
22
- output << '</div>'
24
+ output << "</div>"
23
25
  end
24
26
 
25
27
  def block_content(block)
26
- output, @_output = @_output.dup, ''
28
+ output = @_output.dup
29
+ @_output = ""
27
30
  content = block.call
28
31
  @_output = output
29
32
  content
30
33
  end
31
34
 
32
- def markdown(content, deindent_content = true)
35
+ def markdown(content, deindent_content: true)
33
36
  content = deindent(content) if deindent_content
34
37
  Markdown.render(content)
35
38
  end
@@ -37,7 +40,7 @@ module Kitabu
37
40
  def deindent(content)
38
41
  content = content.to_s
39
42
  indent = (content.scan(/^[ \t]*(?=\S)/) || []).size
40
- content.gsub(/^[ \t]{#{indent}}/, '')
43
+ content.gsub(/^[ \t]{#{indent}}/, "")
41
44
  end
42
45
 
43
46
  def output
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitabu
2
4
  module Markdown
3
5
  class Renderer < Redcarpet::Render::HTML
@@ -13,16 +15,16 @@ module Kitabu
13
15
  renderer = Renderer.new(hard_wrap: true, safe_links_only: true)
14
16
 
15
17
  self.processor = Redcarpet::Markdown.new(renderer, {
16
- tables: true,
17
- footnotes: true,
18
- space_after_headers: true,
19
- superscript: true,
20
- highlight: true,
21
- strikethrough: true,
22
- autolink: true,
23
- fenced_code_blocks: true,
24
- no_intra_emphasis: true
25
- })
18
+ tables: true,
19
+ footnotes: true,
20
+ space_after_headers: true,
21
+ superscript: true,
22
+ highlight: true,
23
+ strikethrough: true,
24
+ autolink: true,
25
+ fenced_code_blocks: true,
26
+ no_intra_emphasis: true
27
+ })
26
28
 
27
29
  def self.render(text)
28
30
  processor.render(text)