rack-bunto 1.0.0

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