rack-bunto 1.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3a0a6260a7e80b2dec58dc78f6a1564190c936b4
4
+ data.tar.gz: 508e696fb10d80687adcabc91992b747dc607003
5
+ SHA512:
6
+ metadata.gz: d3841eb3fae037ac0eeff9c831ff33db3966c88c6d9078ff5d11df5f834dffc873367f893223b8f25e3d56f40c2e466207b9f70f92b7cff71b94fdff31b68ab3
7
+ data.tar.gz: 3bc0ed70bb0d426d1ee4842d29f23581a70d5f415eacc0c43ca1a7e9017fd94a264ba70bfa8a1f6a96347029599f970bdda451039bf19b5f63eadc9dcd1220cc
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org/'
2
+
3
+ group :test do
4
+ gem "cucumber", "2.1.0"
5
+ end
6
+
7
+ gemspec
data/History.markdown ADDED
@@ -0,0 +1,5 @@
1
+ # Rack-Bunto Release History
2
+ > See [commit log](https://github.com/bunto/rack-bunto/commits/master) on GitHub!
3
+
4
+ ## 1.0.0 / 2016-03-25
5
+ * Birthday!
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016-present Bryan Goines & Suriyaa Kudo
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,93 @@
1
+ # Rack-Bunto
2
+
3
+ > **Transform your [Bunto](https://bunto.github.io/) app
4
+ into a [Rack](https://github.com/rack/rack) application.**
5
+
6
+ - You can run it with rackup, [shotgun](https://github.com/rtomayko/shotgun),
7
+ [unicorn](http://unicorn.bogomips.org/), and more.
8
+ - You can run Rack-Bunto with any modified Bunto.
9
+ - You can deploy Rack-Bunto to Heroku, EC2, Rackspace,
10
+ dedicated servers, VPS, etc.
11
+
12
+
13
+ ## How to use it
14
+
15
+ A `config.ru` file is required in order to run with shotgun and rackup.
16
+ You can even deploy your Bunto app to [Heroku](https://www.heroku.com/)!
17
+
18
+ Copy this into `config.ru` in your Bunto site's root directory:
19
+
20
+ ``` ruby
21
+ require "rack/bunto"
22
+
23
+ run Rack::Bunto.new
24
+ ```
25
+
26
+ That's it.
27
+
28
+ Heroku provides a read-only filesystem, so you need to generate pages
29
+ and git-commit them *before* you deploy your Bunto site to Heroku.
30
+
31
+ 1. `cd` to your Bunto directory
32
+ 2. add a `config.ru` file (see example above)
33
+ 3. build pages with `bunto build`
34
+ 4. add `gem "rack-bunto"` to your `Gemfile`
35
+ 5. `git init && git add .`
36
+ 6. `git commit -m "Initial commit"`
37
+ 7. `heroku create`
38
+ 8. `git push heroku master`
39
+
40
+
41
+ ## Configuration
42
+
43
+ Bunto configuration options can be specified in a `_config.yml` file
44
+ or as Rack-Bunto initialization options in `config.ru`.
45
+
46
+ Example:
47
+
48
+ ``` ruby
49
+ run Rack::Bunto.new(:destination => "mysite")
50
+ ```
51
+
52
+ This will set a custom destination path, overriding the default (`_site`)
53
+ and settings from a config file.
54
+
55
+ See [Bunto's configuration docs](https://bunto.github.io/docs/configuration/)
56
+ for more settings.
57
+
58
+ Additional Rack-Bunto initialization options:
59
+
60
+ :config - use given config file (default: "_config.yml")
61
+ :force_build - whether to always generate the site at startup, even
62
+ when the destination path is not empty (default: false)
63
+ :auto - whether to watch for changes and rebuild (default: false)
64
+
65
+ Note that on read-only filesystems a site build will fail,
66
+ so do not set `:force_build => true` in these cases.
67
+
68
+
69
+ ## 404 page
70
+
71
+ In your site's root directory you can provide a custom `404.html` file
72
+ with YAML front matter.
73
+
74
+
75
+ ## Contributing
76
+
77
+ Contributions are more than just welcome.
78
+ Fork this repo and create a new branch, then submit a pull request.
79
+
80
+
81
+ ## Contributors
82
+
83
+ * adaoraul (Adão Raul)
84
+ * SuriyaaKudoIsc (Suriyaa Kudo)
85
+ * Nerian (Gonzalo Rodríguez-Baltanás Díaz)
86
+ * scottwater (Scott Watermasysk)
87
+ * thedjinn (Emil Loer)
88
+ * bry4n (Bryan Goines)
89
+ * thibaudgg (Thibaud Guillaume-Gentil)
90
+ * bemurphy (Brendon Murphy)
91
+ * imajes (James Cox)
92
+ * mattr- (Matt Rogers)
93
+ * stomar (Marcus Stollsteimer)
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ require 'rake/testtask'
2
+
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.pattern = 'test/test_*.rb'
8
+ t.verbose = true
9
+ t.warning = true
10
+ end
11
+
12
+ desc "Build gem"
13
+ task :build do
14
+ sh "gem build rack-bunto.gemspec"
15
+ end
16
+
17
+ desc "Install gem"
18
+ task :install => :build do
19
+ sh "gem install rack-bunto-#{Rack::Bunto.version}.gem"
20
+ end
21
+
22
+ desc "Push gem to rubygems.org"
23
+ task :push do
24
+ sh "gem push rack-bunto-#{Rack::Bunto.version}.gem"
25
+ end
26
+
27
+ desc "Clean up gem"
28
+ task :clean do
29
+ sh "rm *.gem"
30
+ end
31
+
32
+ desc "Run demo"
33
+ task :demo do
34
+ puts " ==> Starting demo: http://localhost:3000/"
35
+ Dir.chdir("example") do
36
+ sh "rackup -p 3000"
37
+ end
38
+ end
data/example/404.md ADDED
@@ -0,0 +1,10 @@
1
+ ---
2
+ layout: default
3
+ title: 404
4
+ ---
5
+
6
+ # 404: Not Found
7
+
8
+ The requested page does not exist.
9
+
10
+ [Go back to home page](/)
@@ -0,0 +1,5 @@
1
+ permalink: /:year/:month/:day/:title/
2
+ markdown: kramdown
3
+
4
+ exclude:
5
+ - config.ru
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <link rel="stylesheet" type="text/css" href="/css/site.css">
6
+ {% if page.title != null %}
7
+ <title>Rack-Bunto Demo - {{ page.title }}</title>
8
+ {% else %}
9
+ <title>Rack-Bunto Demo</title>
10
+ {% endif %}
11
+ </head>
12
+ <body>
13
+ {{ content }}
14
+ </body>
15
+ </html>
@@ -0,0 +1,7 @@
1
+ ---
2
+ layout: default
3
+ ---
4
+
5
+ {{ content }}
6
+
7
+ <p><a href="/">Go back to home page</a></p>
@@ -0,0 +1,8 @@
1
+ ---
2
+ layout: post
3
+ title: Hello World!
4
+ ---
5
+
6
+ # Hello World!
7
+
8
+ A demo blog post for Rack-Bunto.
data/example/config.ru ADDED
@@ -0,0 +1,6 @@
1
+ require_relative "../lib/rack/bunto"
2
+
3
+ # Middleware
4
+ use Rack::ShowExceptions # Nice looking errors
5
+
6
+ run Rack::Bunto.new
@@ -0,0 +1,6 @@
1
+ body {
2
+ background-color: #f0f0f0;
3
+ font-family: sans-serif;
4
+ }
5
+
6
+ .date { color: #808080; }
data/example/index.md ADDED
@@ -0,0 +1,16 @@
1
+ ---
2
+ layout: default
3
+ ---
4
+
5
+ # Rack-Bunto Demo
6
+
7
+ Blog posts:
8
+
9
+ <ul>
10
+ {% for post in site.posts %}
11
+ <li>
12
+ <span class="date">{{ post.date | date_to_string }}:</span>
13
+ <a href="{{ post.url }}">{{ post.title }}</a>
14
+ </li>
15
+ {% endfor %}
16
+ </ul>
@@ -0,0 +1,36 @@
1
+ Feature: Rack-Bunto
2
+ In order to ensure results are correct
3
+ As a Bunto
4
+ I want to become a Rack application
5
+
6
+ Scenario: Request 200 page
7
+ Given I have entered the path /
8
+ When I request a page
9
+ Then the http status should be 200
10
+ Then the content-type should be text/html
11
+ And the content-length should be 24
12
+ And the data should show <p>Rack-Bunto Test</p>
13
+
14
+ Scenario: Request 304 page
15
+ Given I have entered the path /
16
+ When I request a page with a date of Last-Modified
17
+ Then the http status should be 304
18
+ And there should be no 'Content-Length' header
19
+
20
+ Scenario: Request 404 page
21
+ Given I have entered the path /show/me/404/
22
+ When I request a page
23
+ Then the http status should be 404
24
+ And the content-type should be text/html
25
+ And the content-length should be 9
26
+
27
+ Scenario: Request static pages
28
+ Given I have entered the path /css/test.css
29
+ When I request a page
30
+ Then the http status should be 200
31
+ Then the content-type should be text/css
32
+
33
+ Given I have entered the path /js/test.js
34
+ When I request a page
35
+ Then the http status should be 200
36
+ Then the content-type should be application/javascript
@@ -0,0 +1,58 @@
1
+ Before do
2
+ @old_pwd = Dir.pwd
3
+ FileUtils.mkdir_p(TEMP_DIR) unless File.exist?(TEMP_DIR)
4
+ Dir.chdir(TEMP_DIR)
5
+
6
+ FileUtils.mkdir_p(SOURCE_DIR) unless File.exist?(SOURCE_DIR)
7
+ FileUtils.mkdir_p(DEST_DIR) unless File.exist?(DEST_DIR)
8
+
9
+ @bunto = Rack::Bunto.new(:force_build => true,
10
+ :source => SOURCE_DIR,
11
+ :destination => DEST_DIR)
12
+ end
13
+
14
+ After do
15
+ FileUtils.rm_rf(TEMP_DIR) if File.exist?(TEMP_DIR)
16
+ Dir.chdir(@old_pwd)
17
+ end
18
+
19
+
20
+ Given /^I have entered the path (.*)$/ do |path|
21
+ @path = path
22
+ end
23
+
24
+
25
+ When /^I request a page$/ do
26
+ @response = get(@path)
27
+ end
28
+
29
+ When /^I request a page with a date of Last-Modified$/ do
30
+ modify_time = get(@path).headers["Last-Modified"]
31
+ @response = get(@path, {'HTTP_IF_MODIFIED_SINCE' => modify_time})
32
+ end
33
+
34
+
35
+ Then /^the http status should be (.*)$/ do |code|
36
+ assert_equal(code, @response.status.to_s)
37
+ end
38
+
39
+ Then /^the content\-type should be (.*)$/ do |type|
40
+ assert_equal(type, @response.headers["Content-Type"])
41
+ end
42
+
43
+ Then /^the content\-length should be (.*)$/ do |length|
44
+ assert_equal(length, @response.original_headers["Content-Length"])
45
+ end
46
+
47
+ Then /^the data should show (.*)$/ do |body|
48
+ assert_equal(body.chomp, @response.body.chomp)
49
+ end
50
+
51
+ Then /^there should be no '(.*)' header$/ do |header|
52
+ refute @response.headers.has_key?(header)
53
+ end
54
+
55
+ def get(path, headers={})
56
+ req = Rack::MockRequest.new(@bunto)
57
+ req.get(path,headers)
58
+ end
@@ -0,0 +1,9 @@
1
+ require "minitest"
2
+ require "rack/mock"
3
+
4
+ require_relative "../../lib/rack/bunto"
5
+
6
+ TEST_DIR = File.expand_path("../../../test", __FILE__)
7
+ TEMP_DIR = File.join(TEST_DIR, "tmp")
8
+ SOURCE_DIR = File.join(TEST_DIR, "source")
9
+ DEST_DIR = File.join(TEMP_DIR, "_site")
@@ -0,0 +1,56 @@
1
+ module Rack
2
+ class Bunto
3
+ class FileHandler
4
+
5
+ attr_reader :root, :files
6
+
7
+ # Initializes a FileHandler for a given root directory
8
+ # (for testing only: use a given array of filenames, +files+).
9
+ def initialize(root, files = nil)
10
+ @root = ::File.expand_path(root)
11
+ @files = files || get_file_list
12
+ end
13
+
14
+ def empty?
15
+ @files.empty?
16
+ end
17
+
18
+ def update
19
+ @files = get_file_list
20
+ end
21
+
22
+ # Returns the full file system path of the file corresponding to
23
+ # the given URL path, or +nil+ if no corresponding file exists.
24
+ def get_filename(path)
25
+ fullpath = ::File.join(@root, path)
26
+
27
+ if fullpath.end_with?("/")
28
+ normalized = fullpath + "index.html"
29
+ elsif !@files.include?(fullpath)
30
+ normalized = fullpath + "/index.html"
31
+ else
32
+ normalized = fullpath
33
+ end
34
+
35
+ if @files.include?(normalized)
36
+ filename = normalized
37
+ else
38
+ filename = nil
39
+ end
40
+
41
+ filename
42
+ end
43
+
44
+ private
45
+
46
+ # Retrieves and returns a list of all files in the root directory
47
+ # (excluding directory names).
48
+ def get_file_list
49
+ files = ::Dir[@root + "/**/*"]
50
+ files.delete_if {|file| ::FileTest.directory?(file) }
51
+
52
+ files
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,21 @@
1
+ module Rack
2
+ class Bunto
3
+ module Utils
4
+
5
+ def self.media_type(filename)
6
+ extension = ::File.extname(filename)
7
+
8
+ Rack::Mime.mime_type(extension)
9
+ end
10
+
11
+ def self.file_info(path)
12
+ info = {
13
+ :body => ::File.read(path),
14
+ :time => ::File.mtime(path).httpdate
15
+ }
16
+
17
+ info
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ module Rack
2
+ class Bunto
3
+ def self.version
4
+ '1.0.0'
5
+ end
6
+ end
7
+ end
data/lib/rack/bunto.rb ADDED
@@ -0,0 +1,133 @@
1
+ require "rack"
2
+ require "bunto"
3
+
4
+ require_relative "bunto/filehandler"
5
+ require_relative "bunto/utils"
6
+ require_relative "bunto/version"
7
+
8
+ module Rack
9
+ class Bunto
10
+
11
+ attr_reader :config, :destination
12
+
13
+ # Initializes a new Rack::Bunto site.
14
+ #
15
+ # Options:
16
+ #
17
+ # +:config+:: use given config file (default: "_config.yml")
18
+ #
19
+ # +:force_build+:: whether to always generate the site at startup, even
20
+ # when the destination path is not empty (default: +false+)
21
+ #
22
+ # +:auto+:: whether to watch for changes and rebuild (default: +false+)
23
+ #
24
+ # Other options are passed on to Bunto::Site.
25
+ def initialize(options = {})
26
+ overrides = options.dup
27
+ @compiling = false
28
+ @force_build = overrides.fetch(:force_build, false)
29
+ @auto = overrides.fetch(:auto, false)
30
+
31
+ overrides.delete(:force_build)
32
+ overrides.delete(:auto)
33
+ @config = ::Bunto.configuration(overrides)
34
+
35
+ @destination = @config["destination"]
36
+ @source = @config["source"]
37
+
38
+ @files = FileHandler.new(@destination)
39
+ @site = ::Bunto::Site.new(@config)
40
+
41
+ if @files.empty? || @force_build
42
+ process("Generating site: #{@source} -> #{@destination}")
43
+ end
44
+
45
+ if @auto
46
+ require 'listen'
47
+ require 'listen/version'
48
+ require 'pathname'
49
+
50
+ puts "Auto-regeneration enabled: #{@source} -> #{@destination}"
51
+
52
+ source_abs = ::File.expand_path(@source)
53
+ dest_abs = ::File.expand_path(@destination)
54
+ relative_path_to_dest = Pathname.new(dest_abs)
55
+ .relative_path_from(Pathname.new(source_abs))
56
+ .to_path
57
+ ignore_pattern = %r{#{Regexp.escape(relative_path_to_dest)}}
58
+
59
+ listener = Listen.to(@source, :ignore => ignore_pattern) do |modified, added, removed|
60
+ t = Time.now.strftime("%Y-%m-%d %H:%M:%S")
61
+ n = modified.length + added.length + removed.length
62
+ process("[#{t}] Regenerating: #{n} file(s) changed")
63
+ end
64
+ listener.start unless Listen::VERSION =~ /\A[0-1]\./
65
+ end
66
+ end
67
+
68
+ def call(env)
69
+ while @compiling
70
+ sleep 0.1
71
+ end
72
+
73
+ request = Rack::Request.new(env)
74
+
75
+ filename = @files.get_filename(request.path_info)
76
+
77
+ if filename
78
+ media_type = Utils.media_type(filename)
79
+
80
+ file = Utils.file_info(filename)
81
+ body = file[:body]
82
+ time = file[:time]
83
+ hdrs = { "Last-Modified" => time }
84
+
85
+ if time == request.env["HTTP_IF_MODIFIED_SINCE"]
86
+ response = [304, hdrs, []]
87
+ else
88
+ hdrs.update({ "Content-Length" => body.bytesize.to_s,
89
+ "Content-Type" => media_type })
90
+ response = [200, hdrs, [body]]
91
+ end
92
+
93
+ else
94
+ body = not_found_message
95
+ hdrs = { "Content-Length" => body.bytesize.to_s,
96
+ "Content-Type" => "text/html" }
97
+ response = [404, hdrs, [body]]
98
+ end
99
+
100
+ request.head? ? remove_body(response) : response
101
+ end
102
+
103
+ private
104
+
105
+ def process(message = nil)
106
+ @compiling = true
107
+ puts message if message
108
+ @site.process
109
+ @files.update
110
+ @compiling = false
111
+ end
112
+
113
+ def not_found_message
114
+ custom_404 || default_404
115
+ end
116
+
117
+ def default_404
118
+ "Not found"
119
+ end
120
+
121
+ def custom_404
122
+ filename = @files.get_filename("/404.html")
123
+
124
+ filename ? Utils.file_info(filename)[:body] : nil
125
+ end
126
+
127
+ def remove_body(response)
128
+ status, headers, _body = response
129
+
130
+ [status, headers, []]
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,45 @@
1
+ # coding: utf-8
2
+
3
+ require_relative "lib/rack/bunto/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.required_rubygems_version = ">= 1.3.6"
7
+
8
+ s.name = "rack-bunto"
9
+ s.version = Rack::Bunto.version
10
+
11
+ s.summary = "Transform your Bunto app into a Rack application."
12
+ s.description = "Rack-Bunto transforms your Bunto app into a Rack application."
13
+
14
+ s.authors = ["Bryan Goines", "Suriyaa Kudo", "Adão Raul"]
15
+ s.email = ["adao.raul@gmail.com", "SuriyaaKudoIsc@users.noreply.github.com"]
16
+ s.homepage = "https://github.com/bunto/rack-bunto"
17
+
18
+ s.files = %w{
19
+ README.markdown
20
+ rack-bunto.gemspec
21
+ Gemfile
22
+ Rakefile
23
+ History.markdown
24
+ LICENSE
25
+ } +
26
+ Dir.glob("lib/**/*") +
27
+ Dir.glob("example/**/*").reject {|f| f =~ %r(\Aexample/_site/) }
28
+ s.test_files = Dir.glob("{test,features}/**/*")
29
+ s.require_paths = ["lib"]
30
+
31
+ s.extra_rdoc_files = %w[README.markdown History.markdown LICENSE]
32
+ s.rdoc_options = ['--charset=UTF-8', '--main=README.markdown']
33
+
34
+ s.required_ruby_version = '>= 1.9.3'
35
+
36
+ s.add_dependency "bunto", ">= 2.0"
37
+ s.add_dependency "rack", "~> 1.5"
38
+ s.add_dependency "listen", ">= 1.3"
39
+
40
+ s.add_development_dependency "rake"
41
+ s.add_development_dependency "minitest"
42
+
43
+ s.platform = Gem::Platform::RUBY
44
+ s.rubyforge_project = "rack-bunto"
45
+ end