bookery 0.0.2 → 0.1.0

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