asciibook 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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