flutterby 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 20cc78c87b60aef744ffbc565db9bee17d25733f
4
- data.tar.gz: '09966bb3f860d28727e6569e73b105679ac39045'
3
+ metadata.gz: 8e74e653d62257035937eb6cec35fafae4ae6272
4
+ data.tar.gz: b0b8918a534bad69247b60e209e5431d31f08731
5
5
  SHA512:
6
- metadata.gz: 94a9745b04134116f517348ebf0dc3569827226d67ee04fcfd59928781b15c12cf47ac58e4eb1d99b1f3eee4df020caf0857b53a8577f26881d755d2c7886fdf
7
- data.tar.gz: d46433b7fd0c1ec835032739bd39afaf320e16f60d8f43248dbfc6b54a35711e76373a13f817cceadc3adc492506b47471ef7de2da974643a212a12b79d28cad
6
+ metadata.gz: d3a8ac8a2eb8e1c53bdbec7b07742cd82461d8255ffe612ef630eaa7b925c6f657e18769854c559463bbc80f08497e5268d31a29d05adaf0ec4c3c910c1a5054
7
+ data.tar.gz: 1189422cf9ed293b66e6295ff3c0eb0a8b7eeba09d7efe1ffda75ab0de592197e5c97f75a86211f3dd5d6d6cf1503ecdb3577190a0f6941184fa2b22cfd9bb9c
data/flutterby.gemspec CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency "rake", "~> 10.0"
26
26
  spec.add_development_dependency "rspec", "~> 3.0"
27
27
  spec.add_development_dependency 'awesome_print'
28
+ spec.add_development_dependency 'gem-release'
28
29
 
29
30
  spec.add_dependency 'commander'
30
31
  spec.add_dependency 'slodown'
@@ -33,4 +34,6 @@ Gem::Specification.new do |spec|
33
34
  spec.add_dependency 'slim'
34
35
  spec.add_dependency 'toml-rb'
35
36
  spec.add_dependency 'rack'
37
+ spec.add_dependency 'listen'
38
+ spec.add_dependency 'mime-types'
36
39
  end
data/lib/flutterby/cli.rb CHANGED
@@ -21,6 +21,22 @@ Commander.configure do
21
21
  end
22
22
  end
23
23
 
24
+ command :serve do |c|
25
+ c.syntax = 'flutterby serve [options]'
26
+ c.description = "Serve your website for development."
27
+
28
+ c.option '--in DIR', String, "Directory containing your source files"
29
+
30
+ c.action do |args, options|
31
+ options.default in: "./site/"
32
+
33
+ root = Flutterby.from(options.in, name: "/")
34
+ server = Flutterby::Server.new(root)
35
+ server.run!
36
+ end
37
+ end
38
+
39
+
24
40
  command :test do |c|
25
41
  c.syntax = 'flutterby test'
26
42
  c.description = 'TEST. Yo.'
@@ -1,15 +1,16 @@
1
1
  module Flutterby
2
2
  class Entity
3
- attr_reader :name, :ext, :filters, :parent, :fs_path, :path
3
+ attr_reader :name, :ext, :filters, :parent, :fs_path, :path, :data
4
4
 
5
5
  def initialize(name, parent: nil, fs_path: nil)
6
6
  @parent = parent
7
+ @data = {}
7
8
 
8
9
  # Extract name, extension, and filters from given name
9
10
  parts = name.split(".")
10
11
  @name = parts.shift
11
12
  @ext = parts.shift
12
- @filters = parts
13
+ @filters = parts.reverse
13
14
 
14
15
  # Calculate full path
15
16
  @path = parent ? ::File.join(parent.path, full_name) : full_name
@@ -21,6 +22,10 @@ module Flutterby
21
22
  end
22
23
  end
23
24
 
25
+ def reload!
26
+ read
27
+ end
28
+
24
29
  def list(indent: 0)
25
30
  puts "#{" " * indent}[#{self.class}] #{path}"
26
31
  end
@@ -33,7 +38,8 @@ module Flutterby
33
38
  end
34
39
  end
35
40
 
36
- def process
41
+ def process_filters(input)
42
+ input
37
43
  end
38
44
 
39
45
  def url
@@ -44,15 +50,27 @@ module Flutterby
44
50
  ::File.expand_path(::File.join(base, full_name))
45
51
  end
46
52
 
47
- def call(env)
48
- ['200', {"Content-Type" => "text/html"}, [name]]
49
- end
50
-
51
53
  def root
52
54
  parent ? parent.root : self
53
55
  end
54
56
 
55
- private
57
+
58
+ #
59
+ # Serving
60
+ #
61
+
62
+ def call(env)
63
+ env['rack.request'] ||= Rack::Request.new(env)
64
+ env['rack.response'] ||= Rack::Response.new([], 200, {})
65
+ parts = env['rack.request'].path.split("/").reject(&:empty?)
66
+
67
+ serve(parts, env['rack.request'], env['rack.response'])
68
+
69
+ env['rack.response']
70
+ end
71
+
72
+ def serve(parts, req, res)
73
+ end
56
74
 
57
75
  def sibling(name)
58
76
  parent && parent.find(name)
@@ -3,14 +3,23 @@ require 'sass'
3
3
  require 'tilt'
4
4
  require 'slim'
5
5
  require 'toml'
6
+ require 'mime-types'
6
7
 
7
8
  module Flutterby
8
9
  class File < Entity
9
- attr_reader :contents, :data
10
+ attr_reader :contents
10
11
 
11
12
  def read
12
13
  @contents = ::File.read(fs_path)
13
- @data = parse_frontmatter
14
+
15
+ # Extract date from name
16
+ if name =~ %r{^(\d\d\d\d\-\d\d?\-\d\d?)\-}
17
+ @data['date'] = Time.parse($1)
18
+ end
19
+
20
+ # Read remaining data from frontmatter. Data in frontmatter
21
+ # will always have precedence!
22
+ @data.merge! parse_frontmatter
14
23
  end
15
24
 
16
25
  def parse_frontmatter
@@ -28,16 +37,18 @@ module Flutterby
28
37
  data
29
38
  end
30
39
 
31
- def process!
32
- # Apply processors
33
- while filter = filters.pop do
40
+ def process_filters(input)
41
+ # Apply all filters
42
+ filters.each do |filter|
34
43
  meth = "process_#{filter}"
35
44
  if respond_to?(meth)
36
- send(meth)
45
+ input = send(meth, input)
37
46
  else
38
47
  puts "Woops, no #{meth} available :("
39
48
  end
40
49
  end
50
+
51
+ input
41
52
  end
42
53
 
43
54
  def page?
@@ -48,27 +59,27 @@ module Flutterby
48
59
  @view ||= View.new(self)
49
60
  end
50
61
 
51
- def process_erb
52
- tilt = Tilt["erb"].new { @contents }
53
- @contents = tilt.render(view)
62
+ def process_erb(input)
63
+ tilt = Tilt["erb"].new { input }
64
+ tilt.render(view)
54
65
  end
55
66
 
56
- def process_slim
57
- tilt = Tilt["slim"].new { @contents }
58
- @contents = tilt.render(view)
67
+ def process_slim(input)
68
+ tilt = Tilt["slim"].new { input }
69
+ tilt.render(view)
59
70
  end
60
71
 
61
- def process_md
62
- @contents = Slodown::Formatter.new(@contents).complete.to_s
72
+ def process_md(input)
73
+ Slodown::Formatter.new(input).complete.to_s
63
74
  end
64
75
 
65
- def process_scss
66
- engine = Sass::Engine.new(@contents, syntax: :scss)
67
- @contents = engine.render
76
+ def process_scss(input)
77
+ engine = Sass::Engine.new(input, syntax: :scss)
78
+ engine.render
68
79
  end
69
80
 
70
- def apply_layout
71
- output = @contents
81
+ def apply_layout(input)
82
+ output = input
72
83
 
73
84
  # collect layouts to apply
74
85
  layouts = []
@@ -93,10 +104,23 @@ module Flutterby
93
104
  end
94
105
 
95
106
  def write_static(path)
96
- process!
97
- output = apply_layout? ? apply_layout : @contents
107
+ rendered = process_filters(@contents)
108
+ output = apply_layout? ? apply_layout(rendered) : rendered
98
109
 
99
110
  ::File.write(path, output)
100
111
  end
112
+
113
+ def serve(parts, req, res)
114
+ # TODO: DRY this up
115
+ rendered = process_filters(@contents)
116
+ output = apply_layout? ? apply_layout(rendered) : rendered
117
+
118
+ # Determine MIME type
119
+ mime_type = MIME::Types.type_for(ext) || "text/plain"
120
+
121
+ # Build response
122
+ res.headers["Content-Type"] = mime_type
123
+ res.body = [output]
124
+ end
101
125
  end
102
126
  end
@@ -22,6 +22,7 @@ module Flutterby
22
22
  end
23
23
 
24
24
  def find(name)
25
+ name = name.split('.').first
25
26
  @children.find { |c| c.name == name }
26
27
  end
27
28
 
@@ -30,5 +31,18 @@ module Flutterby
30
31
  def pages
31
32
  children.select { |c| c.ext == "html" }
32
33
  end
34
+
35
+
36
+
37
+ def serve(parts, req, res)
38
+ # If no further parts are requested, let's look for an index
39
+ # document and serve that instead.
40
+ if child = find(parts.empty? ? "index" : parts.shift)
41
+ child.serve(parts, req, res)
42
+ else
43
+ res.headers["Content-Type"] = "text/html"
44
+ res.body = ["404"]
45
+ end
46
+ end
33
47
  end
34
48
  end
@@ -1,4 +1,5 @@
1
1
  require 'rack'
2
+ require 'listen'
2
3
 
3
4
  module Flutterby
4
5
  class Server
@@ -7,7 +8,28 @@ module Flutterby
7
8
  end
8
9
 
9
10
  def run!
10
- Rack::Handler::WEBrick.run @root
11
+ # Set up listener
12
+ listener = Listen.to(@root.fs_path) do |modified, added, removed|
13
+ # puts "modified absolute path: #{modified}"
14
+ # puts "added absolute path: #{added}"
15
+ # puts "removed absolute path: #{removed}"
16
+
17
+ puts "Change detected, reloading everything!"
18
+ @root.reload!
19
+ end
20
+
21
+ # Set up server
22
+ server = Rack::Handler::WEBrick
23
+
24
+ # Make sure we handle interrupts correctly
25
+ trap('INT') do
26
+ listener.stop
27
+ server.shutdown
28
+ end
29
+
30
+ # Go!
31
+ listener.start
32
+ server.run @root
11
33
  end
12
34
  end
13
35
  end
@@ -1,3 +1,3 @@
1
1
  module Flutterby
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flutterby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hendrik Mans
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: gem-release
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: commander
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +178,34 @@ dependencies:
164
178
  - - ">="
165
179
  - !ruby/object:Gem::Version
166
180
  version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: listen
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: mime-types
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
167
209
  description: There are many static site generators. This is mine.
168
210
  email:
169
211
  - hendrik@mans.de