bookery 0.0.2 → 0.1.0

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -8
  3. data/.travis.yml +5 -0
  4. data/{LICENSE.txt → LICENSE} +0 -0
  5. data/README.md +26 -11
  6. data/Rakefile +2 -1
  7. data/bookery.gemspec +18 -14
  8. data/docs/config.md +61 -0
  9. data/docs/contributing.md +47 -0
  10. data/docs/editing.md +82 -0
  11. data/docs/project.md +77 -0
  12. data/lib/bookery.rb +27 -4
  13. data/lib/bookery/book.rb +13 -15
  14. data/lib/bookery/cli.rb +29 -12
  15. data/lib/bookery/config.rb +42 -0
  16. data/lib/bookery/factories/chapter_factory.rb +35 -0
  17. data/lib/bookery/factories/publisher_factory.rb +13 -0
  18. data/lib/bookery/processors/include_processor.rb +17 -0
  19. data/lib/bookery/project.rb +75 -0
  20. data/lib/bookery/publishers/html_publisher.rb +68 -0
  21. data/lib/bookery/version.rb +1 -1
  22. data/{bin → libexec}/bookery +1 -4
  23. data/templates/basic/Gemfile.tt +2 -0
  24. data/templates/basic/assets/css/base.css +7 -0
  25. data/templates/basic/assets/css/layout.css +23 -0
  26. data/templates/basic/assets/css/modules/code-block.css +132 -0
  27. data/templates/{book/assets → basic/assets/includes}/.empty_directory +0 -0
  28. data/templates/basic/assets/style.css +3 -0
  29. data/templates/basic/assets/templates/template.html.erb +30 -0
  30. data/templates/basic/book/en/001-first-chapter/01-chapter-file.md +9 -0
  31. data/templates/basic/config.yml +14 -0
  32. data/test/bookery/book_test.rb +32 -9
  33. data/test/bookery/cli_test.rb +25 -14
  34. data/test/bookery/config_test.rb +26 -0
  35. data/test/bookery/factories/chapter_factory_test.rb +24 -0
  36. data/test/bookery/factories/publisher_factory_test.rb +16 -0
  37. data/test/bookery/processor/include_processor_test.rb +38 -0
  38. data/test/bookery/project_test.rb +37 -0
  39. data/test/bookery/publishers/html_publisher_test.rb +78 -0
  40. data/test/data/project/Gemfile.tt +2 -0
  41. data/{templates/book/book/.empty_directory → test/data/project/assets/images/cover.png} +0 -0
  42. data/test/data/project/assets/includes/ruby/chapter2.rb +3 -0
  43. data/test/data/project/assets/style.css +1 -0
  44. data/test/data/project/assets/templates/template.html.erb +15 -0
  45. data/test/data/project/book/en/001-first-chapter/01-chapter-file.md +9 -0
  46. data/test/data/project/book/en/002-second-chapter/01-chapter-file.md +7 -0
  47. data/test/data/project/book/en/002-second-chapter/02-second-chapter-file.md +1 -0
  48. data/{templates/book/book/en/.empty_directory → test/data/project/book/es/.git-keep} +0 -0
  49. data/test/data/project/config.yml +19 -0
  50. data/test/test_helper.rb +3 -46
  51. metadata +107 -79
  52. data/Gemfile.lock +0 -64
  53. data/Guardfile +0 -9
  54. data/lib/bookery/chapter.rb +0 -30
  55. data/templates/book/Gemfile +0 -2
  56. data/templates/book/README.md +0 -3
  57. data/templates/book/config.yml +0 -5
  58. data/templates/sample/Gemfile +0 -2
  59. data/templates/sample/README.md +0 -3
  60. data/templates/sample/book/en/01-introduction/01-intro-to-book.md +0 -0
  61. data/templates/sample/book/en/02-second-chapter/01-first-things-first.md +0 -1
  62. data/templates/sample/book/en/02-second-chapter/02-before_intro.md +0 -1
  63. data/templates/sample/config.yml +0 -5
  64. data/test/bookery/chapter_test.rb +0 -21
@@ -0,0 +1,3 @@
1
+ @import 'css/base.css';
2
+ @import 'css/layout.css';
3
+ @import 'css/modules/code-block.css';
@@ -0,0 +1,30 @@
1
+ <!DOCTYPE html>
2
+ <html lang="<%= language %>">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <title><%= title %> by <%= authors %></title>
7
+ <meta name="author" content="<%= authors %>">
8
+ <meta name="description" content="<%= title %>">
9
+ <meta name="generator" content="bookery">
10
+ <meta name="viewport" content="width=device-width, initial-scale=1">
11
+ <link rel="stylesheet" type="text/css" href="assets/style.css">
12
+ </head>
13
+ <body>
14
+ <header>
15
+ <div class="container">
16
+ <h1><%= title %></h1>
17
+ </div>
18
+ </header>
19
+
20
+ <section class="container">
21
+ <%= body %>
22
+ </section>
23
+
24
+ <footer>
25
+ <div class="container">
26
+ Copyright &copy; <%= Time.now.year %> <%= authors %>
27
+ </div>
28
+ </footer>
29
+ </body>
30
+ </html>
@@ -0,0 +1,9 @@
1
+ # The First Chapter
2
+
3
+ Checkout some ruby code...
4
+
5
+ ```ruby
6
+ def some_method_name(with, *args)
7
+ does_something(with, args)
8
+ end
9
+ ```
@@ -0,0 +1,14 @@
1
+ ---
2
+ book:
3
+ title: My Book
4
+ authors:
5
+ - Your name here
6
+ editors:
7
+ - Any editors
8
+ template: assets/templates/template.html.erb
9
+
10
+ generator:
11
+ input: GFM
12
+ enable_coderay: true
13
+ coderay_css: class
14
+ coderay_line_numbers: inline
@@ -1,19 +1,42 @@
1
1
  require 'test_helper'
2
2
 
3
- class BookTest < AppTest
3
+ class BookTest < Minitest::Test
4
4
  def setup
5
- super
6
- @book = Bookery::Book.new('en', cwd: 'sandbox')
5
+ config = Bookery::Config.new('en', {
6
+ title: 'My Title',
7
+ authors: ['David Muto', 'Jesus Christ'],
8
+ editors: ['Kevin Centeno', 'Kevin Ackland'],
9
+ language: 'en'
10
+ })
11
+
12
+ book_dir = 'test/data/project/book/en'
13
+ chapters = Bookery::Factories::ChapterFactory.create_chapters(book_dir)
14
+
15
+ @book = Bookery::Book.new(chapters, config)
16
+ end
17
+
18
+ def test_title_pulled_from_options
19
+ refute_empty @book.title
7
20
  end
8
21
 
9
- def test_loads_chapters
10
- expected_names = ['Introduction', 'Second Chapter']
11
- actual_names = @book.chapters.map { |c| c.name }
22
+ def test_authors_pulled_from_options
23
+ assert_equal 2, @book.authors.size
24
+ end
25
+
26
+ def test_editors_pulled_from_options
27
+ assert_equal 2, @book.editors.size
28
+ end
12
29
 
13
- assert_equal expected_names, actual_names
30
+ def test_language_pulled_from_options
31
+ refute_empty @book.language
14
32
  end
15
33
 
16
- def template_name
17
- 'sample'
34
+ def test_content_combines_all_chapters
35
+ expected = [
36
+ '# The First Chapter',
37
+ '# The Second Chapter'
38
+ ]
39
+
40
+ expected.each { |heading| assert_includes @book.content, heading }
18
41
  end
19
42
  end
@@ -1,28 +1,39 @@
1
1
  require 'test_helper'
2
2
 
3
- class CLITest < AppTest
4
-
5
- def test_new_creates_readme_file
6
- assert_file 'README.md'
3
+ class CLITest < Minitest::Test
4
+ def setup
5
+ @cli = Bookery::CLI.new
7
6
  end
8
7
 
9
- def test_new_creates_gemfile
10
- assert_file 'Gemfile'
8
+ def test_source_root_points_to_templates
9
+ templates_dir = File.expand_path('../../../templates', __FILE__)
10
+ assert_equal templates_dir, Bookery::CLI.source_root
11
11
  end
12
12
 
13
- def test_new_creates_book_folder
14
- assert_dir 'book'
13
+ def test_version_returns_gem_version
14
+ expected = Bookery::VERSION
15
+
16
+ output, _ = capture_io { @cli.version }
17
+ assert_equal expected, output.chomp
15
18
  end
16
19
 
17
- def test_new_creates_en_folder_in_book
18
- assert_dir 'book/en'
20
+ def test_new_creates_project
21
+ @cli.stubs(:directory).with('basic', 'project').once
22
+ @cli.new('project')
19
23
  end
20
24
 
21
- def test_new_creates_assets_folder
22
- assert_dir 'assets'
25
+ def test_new_creates_project_from_template
26
+ @cli.stubs(:directory).with('example', 'project').once
27
+ @cli.stubs(:options).returns({ template: 'example' })
28
+ @cli.new('project')
23
29
  end
24
30
 
25
- def test_new_creates_config_yml
26
- assert_file 'config.yml'
31
+ def test_publish_publishes_book
32
+ FileUtils.stubs(:mkdir_p)
33
+ FileUtils.stubs(:cp)
34
+ File.stubs(:write)
35
+
36
+ @cli.stubs(:options).returns({ project_dir: 'test/data/project' })
37
+ @cli.publish
27
38
  end
28
39
  end
@@ -0,0 +1,26 @@
1
+ require 'test_helper'
2
+
3
+ class ConfigTest < Minitest::Test
4
+ def setup
5
+ options = YAML.load_file('test/data/project/config.yml')
6
+ @config = Bookery::Config.new('es', options['book'])
7
+ end
8
+
9
+ def test_language_specific_keys_override_globals
10
+ assert_equal 'El libro Testing', @config.title
11
+ end
12
+
13
+ def test_global_values_returns_when_languages_specifics_not_found
14
+ assert_equal 2, @config.authors.size
15
+ end
16
+
17
+ def test_can_retrieve_values_like_hashes
18
+ assert_equal @config.title, @config[:title]
19
+ end
20
+
21
+ def test_method_missing_bubbles_to_super
22
+ assert_raises(NoMethodError) do
23
+ @config.invalid_meta_method
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ class ChapterFactoryTest < Minitest::Test
4
+
5
+ def setup
6
+ book_dir = 'test/data/project/book/en'
7
+ @chapters = Bookery::Factories::ChapterFactory.create_chapters(book_dir)
8
+ end
9
+
10
+ def test_create_chapters_loads_each_chapter
11
+ assert_equal 2, @chapters.size
12
+ end
13
+
14
+ def test_each_chapter_loads_chapter_files
15
+ expected = [
16
+ '# The Second Chapter',
17
+ '# Another File in Chapter 2'
18
+ ]
19
+
20
+ expected.each do |string|
21
+ assert_includes @chapters.last.content, string
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ require 'test_helper'
2
+
3
+ class PublisherFactoryTest < Minitest::Test
4
+
5
+ def setup
6
+ @options = {
7
+ enable_coderay: false,
8
+ project_dir: './',
9
+ template: 'test/data/project/assets/template/template.html.erb'
10
+ }
11
+ end
12
+
13
+ def test_create_publishers
14
+ refute_equal 0, Bookery::Factories::PublisherFactory.create_publishers(@options)
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ require 'test_helper'
2
+
3
+ class IncludeProcessorTest < Minitest::Test
4
+
5
+ def setup
6
+ @processor = Bookery::Processors::IncludeProcessor.new('./')
7
+
8
+ File.stubs('read').with('./js/file.js').returns('function someThing() {}')
9
+ File.stubs('read').with('./ruby/chapter2.rb').returns('def some_method; end')
10
+ end
11
+
12
+ def test_replaces_includes_with_file_content
13
+ input = <<-EOF
14
+ ```javascript
15
+ includes::js/file.js
16
+ ```
17
+ EOF
18
+
19
+ output = @processor.process(input)
20
+ assert_includes output, 'function someThing() {}'
21
+ end
22
+
23
+ def test_supports_multiple_includes
24
+ input = <<-EOF
25
+ ```javascript
26
+ includes::js/file.js
27
+ ```
28
+
29
+ ```ruby
30
+ includes::ruby/chapter2.rb
31
+ ```
32
+ EOF
33
+
34
+ output = @processor.process(input)
35
+ assert_includes output, 'function someThing() {}'
36
+ assert_includes output, 'def some_method'
37
+ end
38
+ end
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+
3
+ class ProjectTest < Minitest::Test
4
+ def setup
5
+ config = YAML.load_file('test/data/project/config.yml').symbolize_keys
6
+ @project = Bookery::Project.new('test/data/project', config)
7
+ end
8
+
9
+ def test_book_config
10
+ refute_empty @project.book_config[:title]
11
+ end
12
+
13
+ def test_generator_config
14
+ refute_empty @project.generator_config[:input]
15
+ assert_equal @project.dir, @project.generator_config[:project_dir]
16
+ end
17
+
18
+ def test_books_returns_a_book_for_each_language
19
+ assert_equal 2, @project.books.size
20
+ end
21
+
22
+ def test_publish_sends_each_book_to_each_publisher
23
+ books = @project.books
24
+ publishers = [mock(), mock()]
25
+ publishers.each { |pub| pub.expects(:publish).twice }
26
+
27
+ @project.stubs(:prepare_output_dir)
28
+ @project.publish(publishers)
29
+ end
30
+
31
+ def test_assets_return_without_includes_and_templates
32
+ assert_equal 2, @project.assets.size
33
+ assert_equal 'test/data/project/assets/images/cover.png', @project.assets.first
34
+ assert_equal 'test/data/project/assets/style.css', @project.assets.last
35
+ end
36
+
37
+ end
@@ -0,0 +1,78 @@
1
+ require 'test_helper'
2
+
3
+ class HTMLPublisherTest < Minitest::Test
4
+ def setup
5
+ @publisher = Bookery::Publishers::HTMLPublisher.new({
6
+ project_dir: 'test/data/project'
7
+ })
8
+
9
+ FileUtils.stubs(:mkdir_p)
10
+ File.stubs(:write)
11
+ end
12
+
13
+ def with_stubbed_book(content)
14
+ book = OpenStruct.new({
15
+ content: content,
16
+ title: 'Some Title',
17
+ authors: [],
18
+ editors: [],
19
+ language: 'en',
20
+ template: 'test/data/project/assets/templates/template.html.erb'
21
+ })
22
+
23
+ yield(book)
24
+ end
25
+
26
+ def test_publish_renders_html_from_markdown
27
+ with_stubbed_book('# Introduction') do |book|
28
+ expected = '<h1 id="introduction">Introduction</h1>'
29
+ assert_includes @publisher.publish(book), expected
30
+ end
31
+ end
32
+
33
+ def test_publish_ignores_intra_emphasis
34
+ with_stubbed_book('_some_method_def_') do |book|
35
+ expected = '<p><em>some_method_def</em></p>'
36
+ assert_includes @publisher.publish(book), expected
37
+ end
38
+ end
39
+
40
+ def test_publish_uses_pre_tags_for_standard_code_blocks
41
+ content = <<-EOF
42
+ def some_method(with, *params)
43
+ # Do Something
44
+ end
45
+ EOF
46
+
47
+ with_stubbed_book(content) do |book|
48
+ assert_includes @publisher.publish(book), '<pre><code>'
49
+ end
50
+ end
51
+
52
+ def test_publish_uses_coderay_for_fenced_code_blocks
53
+ content = <<-EOF
54
+ ```ruby
55
+ def some_method(with, *params)
56
+ # Do Something
57
+ end
58
+ ```
59
+ EOF
60
+
61
+ with_stubbed_book(content) do |book|
62
+ assert_includes @publisher.publish(book), '<div class="CodeRay">'
63
+ end
64
+ end
65
+
66
+ def test_publish_supports_includes
67
+ content = <<-EOF
68
+ ```ruby
69
+ includes::ruby/chapter2.rb
70
+ ```
71
+ EOF
72
+
73
+ with_stubbed_book(content) do |book|
74
+ assert_includes @publisher.publish(book), 'some_included_method'
75
+ end
76
+ end
77
+
78
+ end
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gem 'bookery'
@@ -0,0 +1,3 @@
1
+ def some_included_method(with, *args)
2
+ # Will eventually do something here
3
+ end
@@ -0,0 +1 @@
1
+ /*stylesheet for book*/
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html lang="<%= language %>">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <title><%= title %></title>
7
+ <meta name="author" content="<%= authors %>">
8
+ <meta name="description" content="<%= title %>">
9
+ <meta name="generator" content="bookery">
10
+ <meta name="viewport" content="width=device-width, initial-scale=1">
11
+ </head>
12
+ <body>
13
+ <%= body %>
14
+ </body>
15
+ </html>
@@ -0,0 +1,9 @@
1
+ # The First Chapter
2
+
3
+ Checkout some ruby code...
4
+
5
+ ```ruby
6
+ def some_method_name(with, *args)
7
+ does_something(with, args)
8
+ end
9
+ ```