monograph 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/Gemfile +3 -0
  2. data/Gemfile.lock +28 -0
  3. data/Rakefile +7 -0
  4. data/bin/monograph +19 -0
  5. data/lib/monograph.rb +23 -0
  6. data/lib/monograph/book.rb +52 -0
  7. data/lib/monograph/book_template_context.rb +53 -0
  8. data/lib/monograph/chapter.rb +48 -0
  9. data/lib/monograph/chapter_template_context.rb +40 -0
  10. data/lib/monograph/cli.rb +32 -0
  11. data/lib/monograph/export.rb +78 -0
  12. data/lib/monograph/markdown_renderer.rb +37 -0
  13. data/lib/monograph/template_context.rb +26 -0
  14. data/lib/monograph/version.rb +3 -0
  15. data/monograph.gemspec +21 -0
  16. data/templates/default/assets/images/icon-info.svg +15 -0
  17. data/templates/default/assets/images/icon-warning.svg +18 -0
  18. data/templates/default/assets/images/icon.svg +1 -0
  19. data/templates/default/assets/reset.css +118 -0
  20. data/templates/default/assets/stylesheet.scss +160 -0
  21. data/templates/default/contents.html +17 -0
  22. data/templates/default/index.html +11 -0
  23. data/templates/default/template.html +33 -0
  24. data/test/book_test.rb +30 -0
  25. data/test/chapter_test.rb +34 -0
  26. data/test/cli_test.rb +24 -0
  27. data/test/export_test.rb +34 -0
  28. data/test/fixtures/book1/01-introduction.md +7 -0
  29. data/test/fixtures/book1/02-dogs.md +53 -0
  30. data/test/fixtures/book1/03-cats.md +12 -0
  31. data/test/fixtures/book1/assets/images/dog.jpg +0 -0
  32. data/test/fixtures/book1/assets/images/flowchart.png +0 -0
  33. data/test/fixtures/book1/assets/images/penguin.jpg +0 -0
  34. data/test/fixtures/book1/config.yml +13 -0
  35. data/test/fixtures/book2/01-bananas.md +3 -0
  36. data/test/fixtures/book2/02-apples.md +5 -0
  37. data/test/fixtures/book2/config.yml +10 -0
  38. data/test/fixtures/book2/template.html +4 -0
  39. data/test/test_helper.rb +4 -0
  40. metadata +148 -0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+ gem 'test-unit'
@@ -0,0 +1,28 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ monograph (1.0.0)
5
+ pygments.rb (~> 0.5.0)
6
+ rake (~> 10.0.4)
7
+ redcarpet (~> 2.2.2)
8
+ sass (~> 3.2.9)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ posix-spawn (0.3.6)
14
+ pygments.rb (0.5.0)
15
+ posix-spawn (~> 0.3.6)
16
+ yajl-ruby (~> 1.1.0)
17
+ rake (10.0.4)
18
+ redcarpet (2.2.2)
19
+ sass (3.2.9)
20
+ test-unit (2.5.5)
21
+ yajl-ruby (1.1.0)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ monograph!
28
+ test-unit
@@ -0,0 +1,7 @@
1
+ desc 'Run the test suite'
2
+ task :test do
3
+ $:.unshift File.expand_path('../lib', __FILE__)
4
+ $:.unshift File.expand_path('../test', __FILE__)
5
+ require 'test_helper'
6
+ Dir[File.expand_path('../test/*.rb', __FILE__)].each { |file| require file }
7
+ end
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.expand_path('../../lib', __FILE__))
3
+ require 'monograph'
4
+
5
+ if ARGV.first.nil?
6
+ puts "usage: monograph [command]"
7
+ exit 1
8
+ end
9
+
10
+ cli = Monograph::CLI.new
11
+ begin
12
+ cli.send(*ARGV)
13
+ rescue NoMethodError => e
14
+ puts "Invalid command '#{ARGV.first}'"
15
+ exit 1
16
+ rescue Monograph::CLI::Error => e
17
+ puts "\e[31m#{e.message}\e[0m"
18
+ exit 1
19
+ end
@@ -0,0 +1,23 @@
1
+ require 'redcarpet'
2
+ require 'pygments'
3
+ require 'yaml'
4
+ require 'erb'
5
+ require 'sass'
6
+
7
+ require 'monograph/version'
8
+ require 'monograph/book'
9
+ require 'monograph/chapter'
10
+ require 'monograph/export'
11
+ require 'monograph/template_context'
12
+ require 'monograph/chapter_template_context'
13
+ require 'monograph/book_template_context'
14
+ require 'monograph/markdown_renderer'
15
+ require 'monograph/cli'
16
+
17
+ module Monograph
18
+
19
+ def self.root
20
+ File.expand_path('../../', __FILE__)
21
+ end
22
+
23
+ end
@@ -0,0 +1,52 @@
1
+ module Monograph
2
+ class Book
3
+
4
+ attr_reader :path
5
+
6
+ def initialize(path)
7
+ @path = path
8
+ end
9
+
10
+ def config_path
11
+ File.join(@path, 'config.yml')
12
+ end
13
+
14
+ def title
15
+ config['title']
16
+ end
17
+
18
+ def config
19
+ @config ||= YAML.load(File.read(config_path))
20
+ end
21
+
22
+ def chapters
23
+ @chapters ||= Dir[File.join(@path, '*.md')].map { |path| Monograph::Chapter.new(self, path) }
24
+ end
25
+
26
+ def builtin_template
27
+ config['template'] || 'default'
28
+ end
29
+
30
+ def builtin_template_path
31
+ File.join(Monograph.root, 'templates', builtin_template)
32
+ end
33
+
34
+ def template_file(name)
35
+ template_path = File.join(@path, name)
36
+ if File.exist?(template_path)
37
+ File.read(template_path)
38
+ else
39
+ File.read(File.join(builtin_template_path, name))
40
+ end
41
+ end
42
+
43
+ def template
44
+ @template ||= template_file('template.html')
45
+ end
46
+
47
+ def export
48
+ @export ||= Export.new(self)
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,53 @@
1
+ module Monograph
2
+ # The BookTemplateContext is used whenever a non-chapter page (cover, contents) is to be
3
+ # rendered within the template.
4
+ class BookTemplateContext < TemplateContext
5
+
6
+ attr_reader :book
7
+
8
+ def initialize(book, template)
9
+ @book = book
10
+ @template = template
11
+ end
12
+
13
+ def content
14
+ @content ||= @book.template_file(@template)
15
+ end
16
+
17
+ def page_title
18
+ title
19
+ end
20
+
21
+ def title
22
+ case @template
23
+ when 'index.html' then @book.title
24
+ when 'contents.html' then 'Contents'
25
+ end
26
+ end
27
+
28
+ def author
29
+ @book.config['author']
30
+ end
31
+
32
+ def permalink
33
+ @template.gsub(/\.html\z/, '')
34
+ end
35
+
36
+ def next_page
37
+ case @template
38
+ when 'index.html'
39
+ self.class.new(@book, 'contents.html')
40
+ when 'contents.html'
41
+ @book.chapters.first
42
+ end
43
+ end
44
+
45
+ def previous_page
46
+ case @template
47
+ when 'contents.html'
48
+ self.class.new(@book, 'index.html')
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,48 @@
1
+ module Monograph
2
+ class Chapter
3
+
4
+ attr_reader :book
5
+ attr_reader :path
6
+
7
+ def initialize(book, path)
8
+ @book = book
9
+ @path = path
10
+ end
11
+
12
+ def number
13
+ @number ||= permalink.split('-').first.to_i
14
+ end
15
+
16
+ def permalink
17
+ @permalink ||= @path.split('/').last.gsub(/\.md\z/, '')
18
+ end
19
+
20
+ def raw
21
+ @raw ||= File.open(File.join(@path), 'rb', &:read)
22
+ end
23
+
24
+ def html
25
+ @html ||= begin
26
+ rc = Redcarpet::Markdown.new(MarkdownRenderer.new(:with_toc_data => true), :fenced_code_blocks => true)
27
+ rc.render(self.raw)
28
+ end
29
+ end
30
+
31
+ def title
32
+ @title ||= raw =~ /\A\# ([a-z0-9 ]+)$/i ? $1 : 'Unknown'
33
+ end
34
+
35
+ def template_context
36
+ @template_context ||= ChapterTemplateContext.new(self)
37
+ end
38
+
39
+ def sections(level = 2)
40
+ items = self.html.scan(/<h#{level} id=\"([a-z0-9\-\_]+)\">(.*?)<\/h#{level}>/m)
41
+ items.inject({}) do |hash, match|
42
+ hash[match[0]] = match[1]
43
+ hash
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,40 @@
1
+ module Monograph
2
+ # The ChapterTemplateContext is used whenever a chapter is to be rendered within the template.
3
+ class ChapterTemplateContext < TemplateContext
4
+
5
+ attr_reader :chapter
6
+
7
+ def initialize(chapter)
8
+ @chapter = chapter
9
+ end
10
+
11
+ def book
12
+ @chapter.book
13
+ end
14
+
15
+ def page_title
16
+ "#{chapter.title} - #{book.title}"
17
+ end
18
+
19
+ def content
20
+ @chapter.html
21
+ end
22
+
23
+ def permalink
24
+ @chapter.permalink + ".html"
25
+ end
26
+
27
+ def next_page
28
+ @chapter.book.chapters.select { |c| c.number == @chapter.number + 1}.first
29
+ end
30
+
31
+ def previous_page
32
+ if @chapter.number == 1
33
+ BookTemplateContext.new(@chapter.book, 'contents.html')
34
+ else
35
+ @chapter.book.chapters.select { |c| c.number == @chapter.number - 1}.first
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,32 @@
1
+ module Monograph
2
+ class CLI
3
+
4
+ class Error < StandardError; end
5
+
6
+ # Initialize a new book in the given path
7
+ def init(path = nil)
8
+ raise Error, "You must specify a path to create your new book in" if path.nil?
9
+ raise Error, "File already exists at #{path}" if File.exist?(path)
10
+ FileUtils.mkdir_p(path)
11
+ FileUtils.cp_r(File.join(Monograph.root, 'test', 'fixtures', 'book1', '.'), path)
12
+ puts "Initialized new monograph book at #{path}"
13
+ Book.new(path)
14
+ end
15
+
16
+ # Export a book, assuming we're in the root of it
17
+ def build(destination = nil, source = nil)
18
+ source = Dir.pwd if source.nil?
19
+ destination = File.join(source, 'build') if destination.nil?
20
+ raise Error, "You are not currently within a Monograph root" unless File.exist?(File.join(source, 'config.yml'))
21
+ FileUtils.rm_rf(destination)
22
+ book = Book.new(source)
23
+ book.export.save(destination)
24
+ puts
25
+ puts " Saved build to #{destination}."
26
+ puts " Open your cover page at file://#{File.expand_path(destination)}/index.html"
27
+ puts
28
+ book
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,78 @@
1
+ module Monograph
2
+ class Export
3
+
4
+ class AlreadyExists < StandardError; end
5
+
6
+ def initialize(book)
7
+ @book = book
8
+ end
9
+
10
+ # Return a hash of all HTML files needed for the book. The hash key is
11
+ # the filename and the value is the full HTML document.
12
+ def html_files
13
+ @html ||= begin
14
+ erb = ERB.new(@book.template)
15
+ hash = {}
16
+
17
+ # export the chapters
18
+ @book.chapters.inject(hash) do |hash, chapter|
19
+ hash["#{chapter.permalink}.html"] = erb.result(chapter.template_context.get_binding)
20
+ hash
21
+ end
22
+
23
+ # export other ancillary pages
24
+ ['index.html', 'contents.html'].each do |page|
25
+ context = BookTemplateContext.new(@book, page)
26
+ page_erb = ERB.new(erb.result(context.get_binding))
27
+ hash[page] = page_erb.result(context.get_binding)
28
+ end
29
+
30
+ hash
31
+ end
32
+ end
33
+
34
+ # Return a hash of all required assets for the book. This combines all
35
+ # the files from the built-in template with those provided within the
36
+ # book itself.
37
+ #
38
+ # The copy within the book will always win if there's a filename conflict.
39
+ def assets
40
+ @assets ||= begin
41
+ hash = Hash.new
42
+ search_paths = []
43
+ search_paths << File.join(@book.builtin_template_path, 'assets', '**', '*')
44
+ search_paths << File.join(@book.path, 'assets', '**', '*')
45
+ search_paths.each do |search_path|
46
+ Dir[search_path].inject(hash) do |hash, path|
47
+ if File.file?(path)
48
+ content = File.open(path, 'rb', &:read)
49
+ case path.split('.').last
50
+ when 'scss'
51
+ path.gsub!(/.scss\z/, '.css')
52
+ content = Sass::Engine.new(content, :syntax => :scss).render
53
+ end
54
+ hash[path.gsub(/\A.*\/assets\//, '')] = content
55
+ end
56
+ hash
57
+ end
58
+ end
59
+ hash
60
+ end
61
+ end
62
+
63
+ # Actually run the export to the local file system. This method accepts a path and
64
+ # an optional boolean for forcing the creation.
65
+ def save(path, force = false)
66
+ raise AlreadyExists, "Export path already exists at #{path}" if File.exist?(path) && !force
67
+ FileUtils.rm_rf(path) if File.exist?(path) && force
68
+ FileUtils.mkdir_p(path)
69
+ html_files.each { |filename, content| File.open(File.join(path, filename), 'wb') { |f| f.write(content) }}
70
+ assets.each do |filename, content|
71
+ full_path = File.join(path, filename)
72
+ dir = File.dirname(full_path)
73
+ FileUtils.mkdir_p(dir)
74
+ File.open(full_path, 'w') { |f| f.write(content) }
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,37 @@
1
+ module Monograph
2
+ class MarkdownRenderer < Redcarpet::Render::HTML
3
+
4
+ def block_code(code, language)
5
+ Pygments.highlight(code, :lexer => language)
6
+ end
7
+
8
+ def paragraph(text)
9
+ klass = ''
10
+ text.gsub!(/\A\[([A-Z]+)\]/) do
11
+ klass = " class='#{$1.downcase}'"
12
+ ''
13
+ end
14
+ "<p#{klass}>#{text}</p>"
15
+ end
16
+
17
+ # Images need positioning ability
18
+ def image(src, title, alt)
19
+ if alt.gsub!(/\*([\w\-\s]+)\z/, '')
20
+ klass = "imgcontainer #{$1}"
21
+ else
22
+ klass = nil
23
+ end
24
+ String.new.tap do |s|
25
+ s << "<span class='#{klass}'>"
26
+ if klass == "imgcontainer captioned"
27
+ s << "<span class='image'><img src='#{src}' title='#{title}' alt='#{alt}'></span>"
28
+ s << "<span class='caption'>#{alt}</span>"
29
+ else
30
+ s << "<img src='#{src}' title='#{title}' alt='#{alt}'>"
31
+ end
32
+ s << "</span>"
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,26 @@
1
+ module Monograph
2
+ # Template contexts are used to provide ERB templates with access to various methods.
3
+ # Each type of context must inherit from TemplateContext.
4
+ class TemplateContext
5
+
6
+ def book
7
+ end
8
+
9
+ # This title will be displayed in the <title> attribute on the page.
10
+ def page_title
11
+ end
12
+
13
+ # This must return either nil or an object which responds to 'permalink' and 'title'.
14
+ def previous_page
15
+ end
16
+
17
+ # This must return either nil or an object which responds to 'permalink' and 'title'.
18
+ def next_page
19
+ end
20
+
21
+ def get_binding
22
+ binding
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module Monograph
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,21 @@
1
+ $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
2
+ require 'monograph/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'monograph'
6
+ s.version = Monograph::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.summary = "A beautiful HTML book builder for Markdown"
9
+ s.description = "A command line tool for generating beautiful HTML eBooks from Markdown documents"
10
+ s.files = Dir["**/*"]
11
+ s.add_dependency('redcarpet', '~> 2.2.2')
12
+ s.add_dependency('pygments.rb', '~> 0.5.0')
13
+ s.add_dependency('rake', '~> 10.0.4')
14
+ s.add_dependency('sass', '~> 3.2.9')
15
+ s.bindir = "bin"
16
+ s.require_path = 'lib'
17
+ s.has_rdoc = false
18
+ s.author = "Adam Cooke"
19
+ s.email = "adam@atechmedia.com"
20
+ s.homepage = "http://atechmedia.com"
21
+ end
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
5
+ width="96.731px" height="97.396px" viewBox="0 0 96.731 97.396" enable-background="new 0 0 96.731 97.396" xml:space="preserve">
6
+ <g>
7
+ <path fill="#03779E" d="M47.385,2.399C21.983,2.739,1.667,23.61,2.004,49.015c0.34,25.393,21.209,45.715,46.611,45.377
8
+ c25.398-0.342,45.719-21.213,45.381-46.615C93.656,22.382,72.785,2.061,47.385,2.399z M52.484,17.729
9
+ c4.676,0,6.057,2.714,6.057,5.815c0,3.877-3.104,7.461-8.396,7.461c-4.43,0-6.537-2.229-6.414-5.91
10
+ C43.731,21.992,46.33,17.729,52.484,17.729z M40.497,77.146c-3.195,0-5.537-1.938-3.301-10.467l3.666-15.125
11
+ c0.637-2.424,0.744-3.393,0-3.393c-0.959,0-5.107,1.674-7.557,3.322l-1.598-2.617c7.773-6.491,16.712-10.299,20.544-10.299
12
+ c3.195,0,3.727,3.779,2.131,9.594l-4.199,15.9c-0.744,2.811-0.424,3.779,0.318,3.779c0.961,0,4.102-1.166,7.188-3.59l1.811,2.424
13
+ C51.939,74.233,43.69,77.146,40.497,77.146z"/>
14
+ </g>
15
+ </svg>
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
5
+ width="96.731px" height="97.396px" viewBox="0 0 96.731 97.396" enable-background="new 0 0 96.731 97.396" xml:space="preserve">
6
+ <path fill="#EF7D08" d="M88.946,59.506l-8.254-7.356c-2.391-2.131-2.39-5.616,0.001-7.746l8.253-7.355
7
+ c2.391-2.131,1.753-4.118-1.417-4.42l-10.948-1.036c-3.169-0.301-4.874-3.026-3.784-6.055l5.809-16.173
8
+ c1.088-3.031-0.244-4.136-2.961-2.452l-12.913,7.986c-2.718,1.681-6.227,0.762-7.799-2.043l-4.677-8.347
9
+ c-1.573-2.805-4.17-2.82-5.772-0.034l-4.347,7.557c-1.602,2.787-5.287,3.977-8.186,2.645l-7.647-3.513
10
+ c-2.9-1.332-5.131,0.213-4.958,3.433l0.415,7.723c0.173,3.22-2.204,6.535-5.28,7.363l-7.385,1.986
11
+ c-3.076,0.83-3.638,3.25-1.248,5.381l8.255,7.355c2.391,2.129,2.391,5.614,0,7.744l-8.255,7.357
12
+ c-2.391,2.131-1.759,4.187,1.402,4.572l10.016,1.218c3.161,0.387,4.922,3.205,3.915,6.264l-5.138,15.579
13
+ c-1.008,3.059,0.429,4.251,3.194,2.652l11.777-6.815c2.765-1.599,6.483-0.719,8.262,1.954l4.89,7.353
14
+ c1.778,2.676,4.447,2.529,5.928-0.325l4.3-8.287c1.482-2.856,5.031-4.023,7.885-2.596l8.292,4.146
15
+ c2.856,1.425,5.05-0.039,4.877-3.259l-0.415-7.727c-0.172-3.22,2.205-6.533,5.282-7.361l7.382-1.987
16
+ C90.775,64.056,91.337,61.636,88.946,59.506z M52.178,68.357h-9.563V58.317h9.563V68.357z M52.178,53.058h-9.563V28.195h9.563
17
+ V53.058z"/>
18
+ </svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="utf-8"?> <!-- Generator: IcoMoon.io --> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="48px" height="48px" viewBox="0 0 48 48" enable-background="new 0 0 16 16" xml:space="preserve" fill="#ffffff"> <path d="M 45.00,42.00c-4.59,0.201-13.341,0.987-18.09,3.453 C 26.685,46.887, 25.497,48.00, 24.00,48.00c-1.497,0.00-2.682-1.113-2.91-2.547C 16.344,42.987, 7.59,42.201, 3.00,42.00c-1.656,0.00-3.00-1.341-3.00-3.00L0.00,3.00 c0.00-1.656, 1.344-3.00, 3.00-3.00c 0.105,0.00, 0.192,0.051, 0.297,0.06C 23.928,0.591, 24.00,6.00, 24.00,6.00s 0.072-5.409, 20.703-5.94C 44.808,0.051, 44.895,0.00, 45.00,0.00 c 1.659,0.00, 3.00,1.344, 3.00,3.00l0.00,36.00 C 48.00,40.659, 46.659,42.00, 45.00,42.00z M 21.00,9.402C 17.13,7.434, 10.728,6.615, 6.00,6.267l0.00,29.898 C 14.052,36.573, 18.558,37.779, 21.00,39.00 L21.00,9.402 z M 42.00,6.267c-4.728,0.348-11.13,1.167-15.00,3.135L27.00,39.00 c 2.442-1.221, 6.948-2.427, 15.00-2.835L42.00,6.267 z M 39.00,12.00l0.00,6.00 c0.00,0.00-9.00,0.00-9.00,3.00L30.00,15.00 C 30.00,15.00, 30.00,12.00, 39.00,12.00z M 39.00,24.00l0.00,6.00 c0.00,0.00-9.00,0.00-9.00,3.00L30.00,27.00 C 30.00,27.00, 30.00,24.00, 39.00,24.00z M 18.00,15.00l0.00,6.00 c0.00-3.00-9.00-3.00-9.00-3.00L9.00,12.00 C 18.00,12.00, 18.00,15.00, 18.00,15.00z M 18.00,27.00l0.00,6.00 c0.00-3.00-9.00-3.00-9.00-3.00L9.00,24.00 C 18.00,24.00, 18.00,27.00, 18.00,27.00z" ></path></svg>
@@ -0,0 +1,118 @@
1
+ /*
2
+ HTML5 Reset :: style.css
3
+ ----------------------------------------------------------
4
+ We have learned much from/been inspired by/taken code where offered from:
5
+
6
+ Eric Meyer :: http://meyerweb.com
7
+ HTML5 Doctor :: http://html5doctor.com
8
+ and the HTML5 Boilerplate :: http://html5boilerplate.com
9
+
10
+ -------------------------------------------------------------------------------*/
11
+
12
+ /* Let's default this puppy out
13
+ -------------------------------------------------------------------------------*/
14
+
15
+ html, body, body div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, figure, footer, header, hgroup, menu, nav, section, time, mark, audio, video, details, summary {
16
+ margin: 0;
17
+ padding: 0;
18
+ border: 0;
19
+ font-size: 100%;
20
+ vertical-align: baseline;
21
+ background: transparent;
22
+ }
23
+
24
+ /* consider resetting the default cursor: https://gist.github.com/murtaugh/5247154 */
25
+
26
+ article, aside, figure, footer, header, hgroup, nav, section, details, summary {display: block;}
27
+
28
+ /* Responsive images and other embedded objects
29
+ Note: keeping IMG here will cause problems if you're using foreground images as sprites.
30
+ If this default setting for images is causing issues, you might want to replace it with a .responsive class instead. */
31
+ img,
32
+ object,
33
+ embed {max-width: 100%;}
34
+
35
+ /* force a vertical scrollbar to prevent a jumpy page */
36
+ html {overflow-y: scroll;}
37
+
38
+ /* we use a lot of ULs that aren't bulleted.
39
+ don't forget to restore the bullets within content. */
40
+ ul {list-style: none;}
41
+
42
+ blockquote, q {quotes: none;}
43
+
44
+ blockquote:before,
45
+ blockquote:after,
46
+ q:before,
47
+ q:after {content: ''; content: none;}
48
+
49
+ a {margin: 0; padding: 0; font-size: 100%; vertical-align: baseline; background: transparent;}
50
+
51
+ del {text-decoration: line-through;}
52
+
53
+ abbr[title], dfn[title] {border-bottom: 1px dotted #000; cursor: help;}
54
+
55
+ /* tables still need cellspacing="0" in the markup */
56
+ table {border-collapse: collapse; border-spacing: 0;}
57
+ th {font-weight: bold; vertical-align: bottom;}
58
+ td {font-weight: normal; vertical-align: top;}
59
+
60
+ hr {display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0;}
61
+
62
+ input, select {vertical-align: middle;}
63
+
64
+ pre {
65
+ white-space: pre; /* CSS2 */
66
+ white-space: pre-wrap; /* CSS 2.1 */
67
+ white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */
68
+ word-wrap: break-word; /* IE */
69
+ }
70
+
71
+ input[type="radio"] {vertical-align: text-bottom;}
72
+ input[type="checkbox"] {vertical-align: bottom;}
73
+ .ie7 input[type="checkbox"] {vertical-align: baseline;}
74
+ .ie6 input {vertical-align: text-bottom;}
75
+
76
+ select, input, textarea {font: 99% sans-serif;}
77
+
78
+ table {font-size: inherit; font: 100%;}
79
+
80
+ small {font-size: 85%;}
81
+
82
+ strong {font-weight: bold;}
83
+
84
+ td, td img {vertical-align: top;}
85
+
86
+ /* Make sure sup and sub don't screw with your line-heights
87
+ gist.github.com/413930 */
88
+ sub, sup {font-size: 75%; line-height: 0; position: relative;}
89
+ sup {top: -0.5em;}
90
+ sub {bottom: -0.25em;}
91
+
92
+ /* standardize any monospaced elements */
93
+ pre, code, kbd, samp {font-family: monospace, sans-serif;}
94
+
95
+ /* hand cursor on clickable elements */
96
+ .clickable,
97
+ label,
98
+ input[type=button],
99
+ input[type=submit],
100
+ input[type=file],
101
+ button {cursor: pointer;}
102
+
103
+ /* Webkit browsers add a 2px margin outside the chrome of form elements */
104
+ button, input, select, textarea {margin: 0;}
105
+
106
+ /* make buttons play nice in IE */
107
+ button {width: auto; overflow: visible;}
108
+
109
+ /* scale images in IE7 more attractively */
110
+ .ie7 img {-ms-interpolation-mode: bicubic;}
111
+
112
+ /* prevent BG image flicker upon hover */
113
+ .ie6 html {filter: expression(document.execCommand("BackgroundImageCache", false, true));}
114
+
115
+ /* let's clear some floats */
116
+ .clearfix:before, .clearfix:after { content: "\0020"; display: block; height: 0; overflow: hidden; }
117
+ .clearfix:after { clear: both; }
118
+ .clearfix { zoom: 1; }
@@ -0,0 +1,160 @@
1
+ html {
2
+ font-family:'Proxima Nova', 'Helvetica Neue', 'Arial', sans-serif;
3
+ font-size:15px;
4
+ color:#000;
5
+ margin:0;
6
+ background:#efefef;
7
+
8
+ a { color:#298EBE; font-weight:600; text-decoration:none; border-bottom:1px solid #298EBE}
9
+
10
+ body {
11
+ margin:0;
12
+ }
13
+
14
+ div.inner {
15
+ width:800px;
16
+ margin:auto;
17
+ }
18
+
19
+ header {
20
+ position:fixed;
21
+ top:0;
22
+ background:#efefef;
23
+ border-bottom:1px solid #ccc;
24
+ width:100%;
25
+ padding-bottom:15px;
26
+ height:65px;
27
+ div.inner {
28
+ padding-top:40px;
29
+ p.left { float:left; font-weight:100;}
30
+ p.right { float:right; font-weight:100;}
31
+ p { color:#999; }
32
+ p a { font-weight:100; color:inherit; border:0;}
33
+ }
34
+ }
35
+
36
+ section.content {
37
+ section.cover {
38
+ background:url(images/icon.svg) #000 no-repeat center 130px;;
39
+ background-size:103px;
40
+ color:#fff;
41
+ padding:300px 0 100px 0;
42
+ text-align:center;
43
+ h1 { font-size:400%;font-weight:100; margin-bottom:0; padding:0;}
44
+ h3 { margin-top:5px; font-size:120%; color:#888; font-weight:100;}
45
+ h3 a { border:0; color:#888; text-decoration:none;}
46
+ p.intro {
47
+ padding:0 20%;
48
+ margin-top:60px;
49
+ line-height:1.5;
50
+ font-style:italic;
51
+ font-size:120%;
52
+ }
53
+ p.start {
54
+ margin-top:120px;
55
+ a {
56
+ border-radius:5px;
57
+ background:#76c21b;
58
+
59
+ padding:7px 20px 5px 20px;
60
+ border-bottom:3px solid #588d19;
61
+ font-size:120%;
62
+ font-weight:600;
63
+ text-decoration:none;
64
+ color:#fff;
65
+ }
66
+ }
67
+ }
68
+
69
+ overflow:hidden;
70
+ padding-top:95px;
71
+ background:#fff;
72
+ padding-bottom:45px;
73
+ h1, h2, h3, h4, h5, p, ul, ol, pre, blockquote { margin:20px 0; line-height:1.7;}
74
+ h1 { font-size:260%; font-weight:100; background:#000; margin-top:0;color:#fff; padding:25px; text-align:center; margin-bottom:30px;}
75
+ h2 { font-size:180%; border-bottom:1px solid #000; padding-bottom:2px;}
76
+ h3 { font-size:150%;}
77
+ h4 { font-size:120%;}
78
+ h5 { font-size:100%;}
79
+ ul, ol { margin-left:35px;}
80
+ ul li { list-style:disc;}
81
+
82
+ pre {
83
+ background:#efefef;
84
+ white-space:pre;
85
+ font-family:'Consolas', Monaco, 'Courier New', fixed;
86
+ font-size:90%;
87
+ line-height:1.4;
88
+ padding:15px;
89
+ border:1px solid #ccc;
90
+ }
91
+
92
+ p code, li code {
93
+ background:#efefef;
94
+ white-space:pre;
95
+ font-family:'Consolas', Monaco, 'Courier New', fixed;
96
+ font-size:90%;
97
+ line-height:1.4;
98
+ padding:2px;
99
+ border:1px solid #ccc;
100
+ }
101
+
102
+ p span.imgcontainer {
103
+ display:block;
104
+ &.left { float:left; margin-right:20px; margin-bottom:20px;}
105
+ &.right { float:right; margin-left:20px; margin-bottom:20px;}
106
+ &.captioned {
107
+ border:1px solid #ccc;
108
+ text-align:center;
109
+ span.image {
110
+ background:#fff;
111
+ text-align:center;
112
+ padding:15px 0;
113
+ display:block;
114
+ }
115
+ span.caption { display:block;background:#efefef; color:#999; padding:6px;}
116
+ }
117
+ }
118
+
119
+ blockquote {
120
+ border-left:3px solid #000;
121
+ padding-left:15px;
122
+ margin-left:30px;
123
+ font-style:italic;
124
+ }
125
+
126
+ p.note {
127
+ border:1px solid #aed2e1;
128
+ padding:15px;
129
+ color:#00769d;
130
+ background:url(images/icon-info.svg) #e7f8ff no-repeat 15px 15px;
131
+ background-size:20px;
132
+ font-size:90%;
133
+ padding-left:46px;
134
+ }
135
+
136
+ p.warning {
137
+ border:1px solid #dedfb2;
138
+ padding:15px;
139
+ color:#f17d00;
140
+ background:url(images/icon-warning.svg) #ffffeb no-repeat 15px 15px;
141
+ background-size:20px;
142
+ font-size:90%;
143
+ padding-left:46px;
144
+ }
145
+
146
+ }
147
+
148
+ footer {
149
+ border-top:1px solid #ccc;
150
+ padding:15px 0;
151
+ div.inner {
152
+ padding-top:15px;
153
+ font-size:90%;
154
+ padding-bottom:15px;
155
+ overflow:hidden;
156
+ p.left { float:left; }
157
+ p.right { float:right; }
158
+ }
159
+ }
160
+ }
@@ -0,0 +1,17 @@
1
+ <section class='contents'>
2
+ <h1>Contents</h1>
3
+ <ul class='chapters'>
4
+ <% for chapter in book.chapters %>
5
+ <li>
6
+ <a href="<%= chapter.permalink %>.html"><%= chapter.title %></a>
7
+ <% unless chapter.sections.empty? %>
8
+ <ul>
9
+ <% for key, title in chapter.sections %>
10
+ <li><a href="<%=chapter.permalink%>.html#<%=key%>"><%=title%></a></li>
11
+ <% end %>
12
+ </ul>
13
+ <% end %>
14
+ </li>
15
+ <% end%>
16
+ </ul>
17
+ </section>
@@ -0,0 +1,11 @@
1
+ <section class='cover'>
2
+ <h1><%= book.title %></h1>
3
+ <h3 class='author'>by <a href='mailto:<%=book.config['author']['email']%>'><%= book.config['author']['name'] %></a></h3>
4
+ <% if book.config['description'] %>
5
+ <p class='intro'><%= book.config['description']%></p>
6
+ <% end %>
7
+
8
+ <p class='start'>
9
+ <a href='contents.html'>Start reading</a>
10
+ </p>
11
+ </section>
@@ -0,0 +1,33 @@
1
+ <!DOCTYPE>
2
+ <html>
3
+ <head>
4
+ <title><%= page_title %></title>
5
+ <link rel="stylesheet" href="reset.css" type="text/css" />
6
+ <link rel="stylesheet" href="stylesheet.css" type="text/css" />
7
+ </head>
8
+ <body>
9
+ <header>
10
+ <div class='inner'>
11
+ <p class='left'><a href='contents.html'><%= book.title %></a></p>
12
+ <%if respond_to?(:chapter)%><p class='right'><%= chapter.title %></p><%end%>
13
+ </div>
14
+ </header>
15
+ <section class='content <%=respond_to?(:chapter) ? 'chapter' + chapter.number.to_s : ''%>'>
16
+ <div class='inner'>
17
+ <%= content %>
18
+ </div>
19
+ </section>
20
+ <footer>
21
+ <div class='inner'>
22
+ <nav class='chapters'>
23
+ <% if previous_page %>
24
+ <p class='left'><a href='<%=previous_page.permalink%>.html'>&larr; <%=previous_page.title%></a></p>
25
+ <% end %>
26
+ <% if next_page %>
27
+ <p class='right'><a href='<%=next_page.permalink%>.html'><%=next_page.title%> &rarr;</a></p>
28
+ <% end %>
29
+ </nav>
30
+ </div>
31
+ </footer>
32
+ </body>
33
+ </html>
@@ -0,0 +1,30 @@
1
+ class BookTest < Test::Unit::TestCase
2
+
3
+ def setup
4
+ @book1 = Monograph::Book.new(File.join(FIXTURES_PATH, 'book1'))
5
+ @book2 = Monograph::Book.new(File.join(FIXTURES_PATH, 'book2'))
6
+ end
7
+
8
+ def test_that_books_can_be_initialized
9
+ assert_equal Monograph::Book, @book1.class
10
+ end
11
+
12
+ def test_that_books_have_config
13
+ assert @book1.config.is_a?(Hash)
14
+ assert_equal 'Example Book', @book1.config['title']
15
+ assert_equal 'Adam Cooke', @book1.config['author']['name']
16
+ assert_equal 2013, @book1.config['copyright']['year']
17
+ end
18
+
19
+ def test_that_books_have_chapers
20
+ assert_equal 3, @book1.chapters.length
21
+ assert @book1.chapters.all? { |c| c.is_a?(Monograph::Chapter) }
22
+ end
23
+
24
+ def test_that_books_have_a_template
25
+ assert_equal File.read(File.join(Monograph.root, 'templates', 'default', 'template.html')), @book1.template
26
+ assert_equal File.read(File.join(@book2.path, 'template.html')), @book2.template
27
+ assert @book2.template =~ /<div class='demo-template'>/
28
+ end
29
+
30
+ end
@@ -0,0 +1,34 @@
1
+ class ChapterTest < Test::Unit::TestCase
2
+
3
+ def setup
4
+ @book = Monograph::Book.new(File.join(FIXTURES_PATH, 'book1'))
5
+ @chapter = @book.chapters[0]
6
+ end
7
+
8
+ def test_that_chapters_have_access_to_its_book
9
+ assert_equal @book, @chapter.book
10
+ end
11
+
12
+ def test_that_chapters_have_a_titles
13
+ assert_equal 'Introduction', @chapter.title
14
+ assert_equal ['Introduction', 'Dogs', 'Cats'], @book.chapters.map(&:title)
15
+ end
16
+
17
+ def test_that_chapters_have_numbers
18
+ assert_equal 1, @chapter.number
19
+ assert_equal [1,2,3], @book.chapters.map(&:number)
20
+ end
21
+
22
+ def test_that_chapters_have_html_content
23
+ assert @chapter.html =~ /<h1.*>Introduction<\/h1>$/
24
+ assert @chapter.html =~ /<p>Lorem\s/
25
+ end
26
+
27
+ def test_that_chapters_have_sections
28
+ assert @book.chapters[1].sections.is_a?(Hash)
29
+ assert @book.chapters[1].sections['a-secondary-heading-for-this-page'] = 'A secondary heading for this page'
30
+ assert @book.chapters[1].sections['another-secondary-heading'] = 'Another secondary heading'
31
+ assert @book.chapters[1].sections['a-final-secondary-heading'] = 'A final secondary heading'
32
+ end
33
+
34
+ end
@@ -0,0 +1,24 @@
1
+ class CLITest < Test::Unit::TestCase
2
+
3
+ def setup
4
+ @book = Monograph::Book.new(File.join(FIXTURES_PATH, 'book1'))
5
+ @cli = Monograph::CLI.new
6
+ @test_path = "/tmp/monograph-new-book"
7
+ FileUtils.rm_rf(@test_path)
8
+ end
9
+
10
+ def test_init
11
+ new_book = @cli.init(@test_path)
12
+ assert_equal Monograph::Book, new_book.class
13
+ assert File.directory?(@test_path)
14
+ assert File.file?(File.join(@test_path, 'config.yml'))
15
+ end
16
+
17
+ def test_saving
18
+ @cli.init(@test_path)
19
+ assert_equal Monograph::Book, @cli.build(nil, @test_path).class
20
+ assert File.directory?(File.join(@test_path, 'build'))
21
+ assert File.file?(File.join(@test_path, 'build', 'index.html'))
22
+ end
23
+
24
+ end
@@ -0,0 +1,34 @@
1
+ class ExportTest < Test::Unit::TestCase
2
+ def setup
3
+ @book = Monograph::Book.new(File.join(FIXTURES_PATH, 'book1'))
4
+ @export = @book.export
5
+ end
6
+
7
+ def test_html_files_hash_is_present
8
+ assert_equal Hash, @export.html_files.class
9
+ assert_equal ['01-introduction.html','02-dogs.html','03-cats.html', 'index.html', 'contents.html'], @export.html_files.keys
10
+ end
11
+
12
+ def test_html_files_contains_html
13
+ assert @export.html_files['01-introduction.html'].include?("<title>Introduction - Example Book</title>")
14
+ assert @export.html_files['01-introduction.html'].include?("Introduction</h1>")
15
+ assert @export.html_files['01-introduction.html'].include?("<p>Lorem")
16
+ assert @export.html_files['02-dogs.html'].include?("<title>Dogs - Example Book</title>")
17
+ assert @export.html_files['03-cats.html'].include?("<title>Cats - Example Book</title>")
18
+ end
19
+
20
+ def test_assets_hash
21
+ assert_equal Hash, @export.assets.class
22
+ end
23
+
24
+ def test_export_saving
25
+ tmp_path = "/tmp/monograph-book-export"
26
+ FileUtils.rm_rf(tmp_path)
27
+ assert @book.export.save(tmp_path)
28
+ assert File.file?(File.join(tmp_path, '01-introduction.html'))
29
+ assert File.file?(File.join(tmp_path, 'images/penguin.jpg'))
30
+ assert File.file?(File.join(tmp_path, 'stylesheet.css'))
31
+ assert File.file?(File.join(tmp_path, 'index.html'))
32
+ end
33
+
34
+ end
@@ -0,0 +1,7 @@
1
+ # Introduction
2
+
3
+ ![Penguin*left](images/penguin.jpg)
4
+
5
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
6
+
7
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
@@ -0,0 +1,53 @@
1
+ # Dogs
2
+
3
+ ![Dog*right](images/dog.jpg)
4
+
5
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
6
+
7
+ * This is an example
8
+ * list of item which
9
+ * will be displayed within the page.
10
+
11
+ ## A secondary heading for this page
12
+
13
+ Lorem ipsum dolor sit amet, consectetur **adipisicing elit, sed do eiusmod tempor** incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
14
+
15
+ 1. Another list of things
16
+ 2. this time they are numbered
17
+ 3. which will sometimes be helpful.
18
+
19
+ ## Another secondary heading
20
+
21
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor _incididunt ut labore et dolore magna aliqua_. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
22
+
23
+ ### A teritary heading
24
+
25
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
26
+
27
+ > This is a quote from something which may or may not be helpful.
28
+ > It spans multiple lines in the markdown but won't elsewhere.
29
+
30
+
31
+ ### Another teritary heading
32
+
33
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
34
+
35
+ ~~~ ruby
36
+ module Monograph
37
+ class Chapter
38
+
39
+ attr_reader :book
40
+ attr_reader :path
41
+
42
+ def initialize(book, path)
43
+ @book = book
44
+ @path = path
45
+ end
46
+
47
+ end
48
+ end
49
+ ~~~
50
+
51
+ ## A final secondary heading
52
+
53
+ Lorem ipsum dolor sit amet, consectetur adipisicing `elit, sed do eiusmod tempor incididunt ut labore` et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
@@ -0,0 +1,12 @@
1
+ # Cats
2
+
3
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
4
+
5
+ ![An example flowchart which can be displayed nicely*captioned](images/flowchart.png)
6
+
7
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
8
+
9
+ [NOTE] This item of information will be displayed as a piece of information. To add these to your own documents, just prefix any paragraph with [NOTE] and we'll take care of the rest. There are also others:
10
+
11
+ [WARNING] This is a warning item. The information here should be read and therefore we will display this in a suitable style to suggest urgent attention is nessessary.
12
+
@@ -0,0 +1,13 @@
1
+ title: Example Book
2
+ description:
3
+ An interesting look at the behaviours of household pets within the United Kingdom.
4
+ Fully illustrated with a single picture of a penguin.
5
+
6
+ author:
7
+ name: Adam Cooke
8
+ email: adam@atechmedia.com
9
+
10
+ copyright:
11
+ owner: Adam Cooke
12
+ year: 2013
13
+
@@ -0,0 +1,3 @@
1
+ # Bananas
2
+
3
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
@@ -0,0 +1,5 @@
1
+ # Apples
2
+
3
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
4
+
5
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
@@ -0,0 +1,10 @@
1
+ title: Fruits of the world
2
+
3
+ author:
4
+ name: Adam Cooke
5
+ email: adam@atechmedia.com
6
+
7
+ copyright:
8
+ owner: Adam Cooke
9
+ year: 2013
10
+
@@ -0,0 +1,4 @@
1
+ <h1><%= title %></h1>
2
+ <div class='demo-template'>
3
+ <%= content %>
4
+ </div>
@@ -0,0 +1,4 @@
1
+ require 'test/unit'
2
+ require 'monograph'
3
+
4
+ FIXTURES_PATH = File.expand_path('../fixtures', __FILE__)
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: monograph
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Adam Cooke
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: redcarpet
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.2.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 2.2.2
30
+ - !ruby/object:Gem::Dependency
31
+ name: pygments.rb
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.5.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.5.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 10.0.4
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 10.0.4
62
+ - !ruby/object:Gem::Dependency
63
+ name: sass
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 3.2.9
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 3.2.9
78
+ description: A command line tool for generating beautiful HTML eBooks from Markdown
79
+ documents
80
+ email: adam@atechmedia.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - bin/monograph
86
+ - Gemfile
87
+ - Gemfile.lock
88
+ - lib/monograph/book.rb
89
+ - lib/monograph/book_template_context.rb
90
+ - lib/monograph/chapter.rb
91
+ - lib/monograph/chapter_template_context.rb
92
+ - lib/monograph/cli.rb
93
+ - lib/monograph/export.rb
94
+ - lib/monograph/markdown_renderer.rb
95
+ - lib/monograph/template_context.rb
96
+ - lib/monograph/version.rb
97
+ - lib/monograph.rb
98
+ - monograph.gemspec
99
+ - Rakefile
100
+ - templates/default/assets/images/icon-info.svg
101
+ - templates/default/assets/images/icon-warning.svg
102
+ - templates/default/assets/images/icon.svg
103
+ - templates/default/assets/reset.css
104
+ - templates/default/assets/stylesheet.scss
105
+ - templates/default/contents.html
106
+ - templates/default/index.html
107
+ - templates/default/template.html
108
+ - test/book_test.rb
109
+ - test/chapter_test.rb
110
+ - test/cli_test.rb
111
+ - test/export_test.rb
112
+ - test/fixtures/book1/01-introduction.md
113
+ - test/fixtures/book1/02-dogs.md
114
+ - test/fixtures/book1/03-cats.md
115
+ - test/fixtures/book1/assets/images/dog.jpg
116
+ - test/fixtures/book1/assets/images/flowchart.png
117
+ - test/fixtures/book1/assets/images/penguin.jpg
118
+ - test/fixtures/book1/config.yml
119
+ - test/fixtures/book2/01-bananas.md
120
+ - test/fixtures/book2/02-apples.md
121
+ - test/fixtures/book2/config.yml
122
+ - test/fixtures/book2/template.html
123
+ - test/test_helper.rb
124
+ homepage: http://atechmedia.com
125
+ licenses: []
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ! '>='
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubyforge_project:
144
+ rubygems_version: 1.8.23
145
+ signing_key:
146
+ specification_version: 3
147
+ summary: A beautiful HTML book builder for Markdown
148
+ test_files: []