asciibook 0.0.0 → 0.0.1

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.
Files changed (72) hide show
  1. checksums.yaml +5 -5
  2. data/README.adoc +122 -0
  3. data/book_template/asciibook.yml +5 -0
  4. data/book_template/book.adoc +3 -0
  5. data/exe/asciibook +7 -0
  6. data/lib/asciibook.rb +19 -1
  7. data/lib/asciibook/asciidoctor_ext/abstract_node.rb +5 -0
  8. data/lib/asciibook/book.rb +153 -0
  9. data/lib/asciibook/builders/base_builder.rb +24 -0
  10. data/lib/asciibook/builders/epub_builder.rb +84 -0
  11. data/lib/asciibook/builders/html_builder.rb +45 -0
  12. data/lib/asciibook/builders/mobi_builder.rb +21 -0
  13. data/lib/asciibook/builders/pdf_builder.rb +154 -0
  14. data/lib/asciibook/command.rb +85 -0
  15. data/lib/asciibook/converter.rb +303 -0
  16. data/lib/asciibook/page.rb +30 -0
  17. data/lib/asciibook/version.rb +1 -1
  18. data/templates/admonition.html +4 -0
  19. data/templates/audio.html +7 -0
  20. data/templates/colist.html +7 -0
  21. data/templates/dlist.html +12 -0
  22. data/templates/document.html +29 -0
  23. data/templates/embedded.html +20 -0
  24. data/templates/example.html +4 -0
  25. data/templates/footnotes.html +7 -0
  26. data/templates/image.html +11 -0
  27. data/templates/index.html +40 -0
  28. data/templates/inline_anchor.html +12 -0
  29. data/templates/inline_callout.html +1 -0
  30. data/templates/inline_footnote.html +1 -0
  31. data/templates/inline_image.html +3 -0
  32. data/templates/inline_indexterm.html +5 -0
  33. data/templates/inline_quoted.html +24 -0
  34. data/templates/listing.html +4 -0
  35. data/templates/literal.html +1 -0
  36. data/templates/olist.html +8 -0
  37. data/templates/page_break.html +1 -0
  38. data/templates/paragraph.html +1 -0
  39. data/templates/pass.html +1 -0
  40. data/templates/preamble.html +3 -0
  41. data/templates/quote.html +9 -0
  42. data/templates/section.html +4 -0
  43. data/templates/sidebar.html +6 -0
  44. data/templates/stem.html +9 -0
  45. data/templates/table.html +41 -0
  46. data/templates/thematic_break.html +1 -0
  47. data/templates/ulist.html +8 -0
  48. data/templates/verse.html +9 -0
  49. data/templates/video.html +10 -0
  50. data/theme/epub/epub.css +6 -0
  51. data/theme/epub/layout.html +14 -0
  52. data/theme/html/html.css +190 -0
  53. data/theme/html/html.js +29 -0
  54. data/theme/html/layout.html +91 -0
  55. data/theme/mobi/layout.html +13 -0
  56. data/theme/mobi/mobi.css +2 -0
  57. data/theme/pdf/config.yml +6 -0
  58. data/theme/pdf/footer.html +11 -0
  59. data/theme/pdf/header.html +3 -0
  60. data/theme/pdf/layout.html +14 -0
  61. data/theme/pdf/pdf.css +3 -0
  62. data/theme/pdf/toc.xsl +81 -0
  63. data/theme/share/default.css +174 -0
  64. data/theme/share/highlight.css +216 -0
  65. data/theme/share/normalize.css +349 -0
  66. metadata +119 -21
  67. data/.gitignore +0 -9
  68. data/.travis.yml +0 -4
  69. data/Gemfile +0 -4
  70. data/README.md +0 -41
  71. data/Rakefile +0 -10
  72. data/asciibook.gemspec +0 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f64973fae33051b769fb21e19142a7ef45498256
4
- data.tar.gz: d6be9d277506c26178ccfe10a49cfc906c0da131
2
+ SHA256:
3
+ metadata.gz: f5860141a3903d0f2939ec985c5b81bbdd5b3cf14771e65daa16136c1c02bb9f
4
+ data.tar.gz: a89d6248fd14e1088037e5a15e7174f5a43ba8508b6168e4a3b2addf63e4b3e9
5
5
  SHA512:
6
- metadata.gz: ed2d02fa7b9f315fc24dd928dcd41b0e81a0dde9f719601504af83c141490beaec7701438b857c74b50e46f24cab9edb24555f509dc3bed10b1f238e269ec5b6
7
- data.tar.gz: 3a08b54b7815227719252f7d4b5eead8fdfd4c3024f53892dd2eff0f4b32d4f04a205e38050ea63fbaa1ad2ebbccb08cfcf8c55ee07a2344ac7d196336b80fab
6
+ metadata.gz: 2ff6a611b748a2cf9e1ee49ea99ed385fd75d10a3db42615a9ee0804d92b642b996ffdc808c497c596723f56bd1965181fabb6d71e8597714c4c093f08c56fe0
7
+ data.tar.gz: b7f63c4c369a50afbc01c0b6981f13a82f87b15003353f459cc38c79bc1c5d4a47b5216a1cf68f4b9362767a5780eea9b4c25c923fa6b3aadbf6e0f2d859b668
@@ -0,0 +1,122 @@
1
+ = Asciibook
2
+ :toc:
3
+
4
+ Asciibook is an Ebook generator for converting AsciiDoc to HTML, PDF, EPUB and MOBI.
5
+
6
+ == Installation
7
+
8
+ If you are familiar with Ruby, you can use <<manual-installation>>.
9
+
10
+ If your are familiar with Docker, you can use <<docker-installation>>.
11
+
12
+ [[manual-installation]]
13
+ === Manual installation
14
+
15
+ Install by rubygems:
16
+
17
+ [source, console]
18
+ ----
19
+ $ gem install asciibook
20
+ ----
21
+
22
+ For PDF generate, download and install wkhtmltopdf in https://wkhtmltopdf.org/downloads.html .
23
+
24
+ For Mobi generate, download and install kindlegen in https://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211 .
25
+
26
+
27
+ [[docker-installation]]
28
+ === Docker Installation
29
+
30
+ Pull docker image:
31
+
32
+ [source, consle]
33
+ ----
34
+ $ docker pull asciibook/asciibook
35
+ ----
36
+
37
+ Then use asciibook CLI in this way:
38
+
39
+ [source, console]
40
+ ----
41
+ $ docker run -v $(pwd):/asciibook asciibook/asciibook asciibook build mybook.adoc
42
+ ----
43
+
44
+ Or enter the container environment to avoid repeating lengthy commands:
45
+
46
+ [source, console]
47
+ ----
48
+ $ docker run -v $(pwd):/asciibook asciibook/asciibook bash
49
+ /asciibook $ asciibook build mybook.adoc
50
+ ----
51
+
52
+ == Usage
53
+
54
+ For a existing AsciiDoc file, run this command to build all format books:
55
+
56
+ [source, console]
57
+ ----
58
+ $ ascibook build mybook.adoc
59
+ ----
60
+
61
+ Generated books will put in `build` directory.
62
+
63
+ Or generate only partial format:
64
+
65
+ [source, console]
66
+ ----
67
+ $ asciibook build mybook.adoc --format html
68
+ $ asciibook build mybook.adoc --format pdf,mobi
69
+ ----
70
+
71
+ If you don't want to enter the parameters repeatedly, you can create a configuration file for the document:
72
+
73
+ [source, console]
74
+ ----
75
+ $ asciibook init mybook.adoc
76
+ ----
77
+
78
+ It will create a config file `asciibook.yml` in the same directory, edit config for your need, then use this command to build next time:
79
+
80
+ [source, console]
81
+ ----
82
+ $ asciibook build
83
+ ----
84
+
85
+ Use this command to create a empty AsciiDoc and config file:
86
+
87
+ [source, console]
88
+ ----
89
+ $ asciibook new mybook
90
+ ----
91
+
92
+ == Development
93
+
94
+ Clone this repo:
95
+
96
+ [source, console]
97
+ ----
98
+ $ git clone https://github.com/asciibook/asciibook.git
99
+ $ cd asciibook
100
+ ----
101
+
102
+ Star dev environment with docker:
103
+
104
+ [source, console]
105
+ ----
106
+ $ docker-compose run console
107
+ ----
108
+
109
+ Run test:
110
+
111
+ [source, console]
112
+ ----
113
+ /asciibook # rake test
114
+ ----
115
+
116
+ == Contributing
117
+
118
+ Bug reports and pull requests are welcome on GitHub at https://github.com/asciibook/asciibook.
119
+
120
+ == License
121
+
122
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,5 @@
1
+ source: book.adoc
2
+ #formats: ['html', 'pdf', 'epub', 'mobi']
3
+ #theme_dir:
4
+ #template_dir:
5
+ #page_level: 1
@@ -0,0 +1,3 @@
1
+ = My Book
2
+
3
+ Write from here...
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path '../../lib', __FILE__
4
+
5
+ require "asciibook/command"
6
+
7
+ Asciibook::Command.execute(ARGV)
@@ -1,5 +1,23 @@
1
+ require "asciidoctor"
2
+ require "rexml/document"
3
+ require "nokogiri"
4
+ require "fileutils"
5
+ require "liquid"
6
+ require "logger"
7
+ require 'yaml'
8
+ require "gepub"
9
+ require "rouge"
10
+
1
11
  require "asciibook/version"
12
+ require "asciibook/asciidoctor_ext/abstract_node"
13
+ require "asciibook/converter"
14
+ require "asciibook/book"
15
+ require "asciibook/page"
16
+ require "asciibook/builders/base_builder"
17
+ require "asciibook/builders/html_builder"
18
+ require "asciibook/builders/pdf_builder"
19
+ require "asciibook/builders/epub_builder"
20
+ require "asciibook/builders/mobi_builder"
2
21
 
3
22
  module Asciibook
4
- # Your code goes here...
5
23
  end
@@ -0,0 +1,5 @@
1
+ module Asciidoctor
2
+ class AbstractNode
3
+ attr_accessor :page
4
+ end
5
+ end
@@ -0,0 +1,153 @@
1
+ module Asciibook
2
+ class Book
3
+ attr_reader :data, :options, :doc, :pages, :basename, :base_dir, :dest_dir, :theme_dir, :template_dir
4
+
5
+ def initialize(data, options = {})
6
+ @data = data
7
+ @options = options
8
+ @basename = options[:basename] || 'output'
9
+ @base_dir = options[:base_dir] || '.'
10
+ @dest_dir = options[:dest_dir] || File.join(@base_dir, 'build')
11
+ @theme_dir = options[:theme_dir] || File.expand_path('../../../theme', __FILE__)
12
+ @formats = options[:formats] || %w(html pdf epub mobi)
13
+ @template_dir = options[:template_dir]
14
+
15
+ @page_level = @options[:page_level] || 1
16
+
17
+ @logger = @options[:logger] || Logger.new(STDERR, level: :warn)
18
+
19
+ @exclude_patterns = ["build/**/*"]
20
+ end
21
+
22
+ def self.load_file(path, options = {})
23
+ options.merge!(
24
+ basename: File.basename(path, '.*'),
25
+ base_dir: File.dirname(path)
26
+ )
27
+
28
+ if File.exist?(path)
29
+ new(File.open(path, 'r:utf-8').read, options)
30
+ else
31
+ raise "File not exists #{path}"
32
+ end
33
+ end
34
+
35
+ def process
36
+ @doc = Asciidoctor.load(@data, base_dir: @base_dir, backend: 'asciibook', logger: @logger, safe: :unsafe, template_dirs: [@template_dir].compact)
37
+ @toc = nil
38
+ process_pages
39
+ end
40
+
41
+ def title
42
+ doc.attributes['doctitle']
43
+ end
44
+
45
+ def cover_image_path
46
+ doc.attributes['cover-image']
47
+ end
48
+
49
+ def toc
50
+ @toc ||= outline(doc)
51
+ end
52
+
53
+ def outline(node)
54
+ data = []
55
+ node.sections.each do |section|
56
+ section_data = {
57
+ 'title' => section.xreftext,
58
+ 'path' => section.page ? section.page.path : "#{find_page_node(section).page.path}##{section.id}"
59
+ }
60
+ if section.sections.count > 0 and section.level < (doc.attributes['toclevels'] || 2).to_i
61
+ section_data['items'] = outline(section)
62
+ end
63
+ data << section_data
64
+ end
65
+ data
66
+ end
67
+
68
+ def find_page_node(node)
69
+ page_node = node
70
+
71
+ until page_node.page or page_node.parent.nil?
72
+ page_node = page_node.parent
73
+ end
74
+
75
+ page_node
76
+ end
77
+
78
+ def to_hash
79
+ {
80
+ 'title' => doc.attributes['doctitle'],
81
+ 'attributes' => doc.attributes,
82
+ 'toc' => toc
83
+ }
84
+ end
85
+
86
+ def build
87
+ if @formats.include?('html')
88
+ Builders::HtmlBuilder.new(self).build
89
+ end
90
+
91
+ if @formats.include?('pdf')
92
+ Builders::PdfBuilder.new(self).build
93
+ end
94
+
95
+ if @formats.include?('epub')
96
+ Builders::EpubBuilder.new(self).build
97
+ end
98
+
99
+ if @formats.include?('mobi')
100
+ Builders::MobiBuilder.new(self).build
101
+ end
102
+ end
103
+
104
+ def process_pages
105
+ @pages = []
106
+
107
+ append_page('index.html', doc)
108
+
109
+ if @page_level > 0
110
+ doc.sections.each do |section|
111
+ process_page(section)
112
+ end
113
+ end
114
+ end
115
+
116
+ def process_page(node)
117
+ append_page("#{node.id}.html", node)
118
+
119
+ if node.level < @page_level
120
+ node.sections.each do |section|
121
+ process_page(section)
122
+ end
123
+ end
124
+ end
125
+
126
+ def append_page(path, node)
127
+ if @pages.map(&:path).include?(path)
128
+ @logger.warn("Page path already in use: #{path}")
129
+ end
130
+
131
+ page = Page.new(
132
+ path: path,
133
+ node: node
134
+ )
135
+
136
+ if last_page = @pages.last
137
+ page.prev_page = last_page
138
+ last_page.next_page = page
139
+ end
140
+
141
+ node.page = page
142
+ @pages << page
143
+ end
144
+
145
+ def assets
146
+ Dir.glob('**/*.{jpg,png,gif,mp3,mp4,ogg,wav}', File::FNM_CASEFOLD, base: @base_dir).reject do |path|
147
+ @exclude_patterns.any? do |pattern|
148
+ File.fnmatch?(pattern, path)
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,24 @@
1
+ module Asciibook
2
+ module Builders
3
+ class BaseBuilder
4
+ def initialize(book)
5
+ @book = book
6
+ @theme_share_dir = File.join(@book.theme_dir, 'share')
7
+
8
+ # reset book doc
9
+ @book.process
10
+ end
11
+
12
+ def build
13
+ raise NotImplementedError
14
+ end
15
+
16
+ def copy_file(path, src_dir, dest_dir)
17
+ src_path = File.join(src_dir, path)
18
+ dest_path = File.join(dest_dir, path)
19
+ FileUtils.mkdir_p File.dirname(dest_path)
20
+ FileUtils.cp src_path, dest_path
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,84 @@
1
+ module Asciibook
2
+ module Builders
3
+ class EpubBuilder < BaseBuilder
4
+ def initialize(book)
5
+ super
6
+ @dest_dir = File.join(@book.dest_dir, 'epub')
7
+ @theme_dir = File.join(@book.theme_dir, 'epub')
8
+ end
9
+
10
+ def build
11
+ FileUtils.mkdir_p @dest_dir
12
+
13
+ layout = Liquid::Template.parse(File.read(File.join(@theme_dir, 'layout.html')))
14
+
15
+ # Satisfy epub specifications
16
+ @book.pages.each do |page|
17
+ page.path = page.path.gsub(/.html$/, '.xhtml')
18
+ end
19
+
20
+ epub = GEPUB::Book.new do |book|
21
+ book.title = @book.title
22
+ book.identifier = @book.doc.attributes['identifier'] || 'undefined'
23
+ book.language = @book.doc.attributes['language'] || 'en'
24
+
25
+ id_pool = GEPUB::Package::IDPool.new
26
+
27
+ @book.assets.each do |path|
28
+ book.add_item path, content: File.open(File.join(@book.base_dir, path)), id: id_pool.generate_key(prefix: 'asset_')
29
+ end
30
+
31
+ if @book.cover_image_path
32
+ book.add_item(@book.cover_image_path, content: File.open(File.join(@book.base_dir, @book.cover_image_path)), id: 'cover_image').cover_image
33
+ end
34
+
35
+ Dir.glob('**/*.{jpb,png,gif,svg,css,js}', File::FNM_CASEFOLD, base: @theme_share_dir).each do |path|
36
+ book.add_item path, content: File.open(File.join(@theme_share_dir, path)), id: id_pool.generate_key(prefix: 'theme_asset_')
37
+ end
38
+
39
+ Dir.glob('**/*.{jpb,png,gif,svg,css,js}', File::FNM_CASEFOLD, base: @theme_dir).each do |path|
40
+ book.add_item path, content: File.open(File.join(@theme_dir, path)), id: id_pool.generate_key(prefix: 'theme_asset_')
41
+ end
42
+
43
+ book.ordered do
44
+ @book.pages.each do |page|
45
+ html = layout.render(
46
+ 'book' => @book.to_hash,
47
+ 'page' => page.to_hash
48
+ )
49
+ book.add_item page.path, content: StringIO.new(html), id: id_pool.generate_key(prefix: 'page_')
50
+ end
51
+ end
52
+
53
+ book.add_tocdata tocdata
54
+ end
55
+
56
+ epub.generate_epub(File.join(@dest_dir, "#{@book.basename}.epub"))
57
+
58
+ # restore page path
59
+ @book.pages.each do |page|
60
+ page.path = page.path.gsub(/.xhtml$/, '.html')
61
+ end
62
+ end
63
+
64
+ def tocdata
65
+ outline(@book.doc, 1)
66
+ end
67
+
68
+ def outline(node, level)
69
+ data = []
70
+ node.sections.each do |section|
71
+ data << {
72
+ text: section.xreftext,
73
+ link: section.page ? section.page.path : "#{@book.find_page_node(section).page.path}##{section.id}",
74
+ level: level
75
+ }
76
+ if section.sections.count > 0 and section.level < (@book.doc.attributes['toclevels'] || 2).to_i
77
+ data.concat outline(section, level + 1)
78
+ end
79
+ end
80
+ data
81
+ end
82
+ end
83
+ end
84
+ end