stormy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.travis.yml +7 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +65 -0
  6. data/README.md +64 -0
  7. data/Rakefile +4 -0
  8. data/lib/stormy.rb +34 -0
  9. data/lib/stormy/caches/base.rb +46 -0
  10. data/lib/stormy/caches/dummy_cache.rb +12 -0
  11. data/lib/stormy/caches/file_cache.rb +47 -0
  12. data/lib/stormy/caches/memory_cache.rb +24 -0
  13. data/lib/stormy/chunk.rb +63 -0
  14. data/lib/stormy/content.rb +21 -0
  15. data/lib/stormy/content_list.rb +18 -0
  16. data/lib/stormy/engines/base.rb +7 -0
  17. data/lib/stormy/engines/erb.rb +8 -0
  18. data/lib/stormy/engines/haml.rb +9 -0
  19. data/lib/stormy/engines/html.rb +6 -0
  20. data/lib/stormy/engines/markdown.rb +8 -0
  21. data/lib/stormy/engines/sass.rb +12 -0
  22. data/lib/stormy/layout.rb +21 -0
  23. data/lib/stormy/page.rb +32 -0
  24. data/lib/stormy/static.rb +20 -0
  25. data/lib/stormy/stores/base.rb +52 -0
  26. data/lib/stormy/stores/file_store.rb +70 -0
  27. data/lib/stormy/template.rb +67 -0
  28. data/lib/stormy/version.rb +3 -0
  29. data/lib/stormy_app.rb +40 -0
  30. data/lib/stormy_server.rb +41 -0
  31. data/spec/fixtures/dummy_site/config.yml +1 -0
  32. data/spec/fixtures/dummy_site/content/blog/blog-post-1.md +5 -0
  33. data/spec/fixtures/dummy_site/content/blog/blog-post-2.md +5 -0
  34. data/spec/fixtures/dummy_site/layouts/main.haml +2 -0
  35. data/spec/fixtures/dummy_site/public/assets/storm.jpg +0 -0
  36. data/spec/fixtures/dummy_site/public/blog.haml +12 -0
  37. data/spec/fixtures/dummy_site/public/blog_desc.haml +13 -0
  38. data/spec/fixtures/dummy_site/public/hardcoded_blog_post.haml +12 -0
  39. data/spec/fixtures/dummy_site/public/missing.haml +1 -0
  40. data/spec/fixtures/dummy_site/public/pathtest/:permalink.haml +16 -0
  41. data/spec/fixtures/dummy_site/public/redirecto.haml +1 -0
  42. data/spec/fixtures/dummy_site/public/redirects/:permalink.haml +1 -0
  43. data/spec/fixtures/dummy_site/public/subdir/index.haml +1 -0
  44. data/spec/fixtures/dummy_site/public/tester.haml +4 -0
  45. data/spec/fixtures/dummy_site/public/tester_invalid_layout.haml +4 -0
  46. data/spec/fixtures/dummy_site/tester.haml +1 -0
  47. data/spec/spec_helper.rb +14 -0
  48. data/spec/stormy/caches/caches_spec.rb +50 -0
  49. data/spec/stormy/engines/erb_spec.rb +24 -0
  50. data/spec/stormy/engines/sass_spec.rb +24 -0
  51. data/spec/stormy/page_spec.rb +73 -0
  52. data/spec/stormy/stores/file_store_spec.rb +66 -0
  53. data/spec/stormy_app_spec.rb +37 -0
  54. data/spec/stormy_server_spec.rb +41 -0
  55. data/stormy.gemspec +33 -0
  56. data/tasks/rspec.rake +4 -0
  57. metadata +263 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b4c45f5229be3b57d3b909f6f69391f038580c41
4
+ data.tar.gz: e8e2e5a4212e298d0f18a17ea90b2f9b2a908cc6
5
+ SHA512:
6
+ metadata.gz: 077e81823d634590c1ab71995bf2e61a54449d13f99739c5d88af1dbf393f525a731e988b1b2e568643d1b5a91d1f8605b19193c696b1070b9493dec0a42a9cd
7
+ data.tar.gz: c11e797044f8635e5cbdfcfb2bb8c1beb09ecf653afad4b783729e9b9a0a7ad5eab00f6c86ee2457ef56985cb3ed0d0bf43da4c353dc43f654042a343b5829e1
@@ -0,0 +1,3 @@
1
+ coverage/
2
+ tmp/
3
+ spec/fixtures/dummy_site/tmp
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 2.1.1
5
+ addons:
6
+ code_climate:
7
+ repo_token: f2044ac7f053b31968fd99e29c28487a7c015eeab865dbeb9df68ddf7c9f3979
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,65 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ stormy (0.0.1)
5
+ activesupport
6
+ haml
7
+ kramdown
8
+ rack
9
+ sass
10
+ tilt
11
+
12
+ GEM
13
+ remote: http://rubygems.org/
14
+ specs:
15
+ activesupport (4.1.6)
16
+ i18n (~> 0.6, >= 0.6.9)
17
+ json (~> 1.7, >= 1.7.7)
18
+ minitest (~> 5.1)
19
+ thread_safe (~> 0.1)
20
+ tzinfo (~> 1.1)
21
+ codeclimate-test-reporter (0.4.0)
22
+ simplecov (>= 0.7.1, < 1.0.0)
23
+ diff-lcs (1.2.5)
24
+ docile (1.1.5)
25
+ haml (4.0.5)
26
+ tilt
27
+ i18n (0.6.11)
28
+ json (1.8.1)
29
+ kramdown (1.4.2)
30
+ minitest (5.4.1)
31
+ multi_json (1.10.1)
32
+ rack (1.5.2)
33
+ rake (10.3.2)
34
+ rspec (3.0.0)
35
+ rspec-core (~> 3.0.0)
36
+ rspec-expectations (~> 3.0.0)
37
+ rspec-mocks (~> 3.0.0)
38
+ rspec-core (3.0.4)
39
+ rspec-support (~> 3.0.0)
40
+ rspec-expectations (3.0.4)
41
+ diff-lcs (>= 1.2.0, < 2.0)
42
+ rspec-support (~> 3.0.0)
43
+ rspec-mocks (3.0.4)
44
+ rspec-support (~> 3.0.0)
45
+ rspec-support (3.0.4)
46
+ sass (3.4.5)
47
+ simplecov (0.9.0)
48
+ docile (~> 1.1.0)
49
+ multi_json
50
+ simplecov-html (~> 0.8.0)
51
+ simplecov-html (0.8.0)
52
+ thread_safe (0.3.4)
53
+ tilt (2.0.1)
54
+ tzinfo (1.2.2)
55
+ thread_safe (~> 0.1)
56
+
57
+ PLATFORMS
58
+ ruby
59
+
60
+ DEPENDENCIES
61
+ bundler (~> 1.6)
62
+ codeclimate-test-reporter
63
+ rake
64
+ rspec
65
+ stormy!
@@ -0,0 +1,64 @@
1
+ # Stormy
2
+
3
+ [![Code Climate](https://codeclimate.com/github/cykod/Stormy/badges/gpa.svg)](https://codeclimate.com/github/cykod/Stormy)
4
+ [![Test Coverage](https://codeclimate.com/github/cykod/Stormy/badges/coverage.svg)](https://codeclimate.com/github/cykod/Stormy)
5
+
6
+ A not-ready-for-primetime Opinionated semi-static CMS/Site Builder designed for simplicity and flexibility.
7
+
8
+ > While Frank Sinatra sings "Stormy Weather" the flies and spiders get along together.
9
+ > Cobwebs fall on an old skipping record. - Cake
10
+
11
+ ## Why Stormy?
12
+
13
+ Frameworks like Rails and Django are great, but they are a lot of code to drag around for small projects. Stop paying attention to a half-dozen side projects for a few months and suddenly the API has changed underneath you and you've got to spend all your time just to keep your projects up to date instead of having fun building stuff.
14
+
15
+ On the other hand, static site generators like Jekyll are great, but sometimes you still want to run some code on each request - just not enough to justify a full MVC.
16
+
17
+ Imagine writing some Ruby like it was a simple PHP site - a little markup here, some code there, all stuck together without gobs of config or setup.
18
+
19
+ ## PHP is your model, Really?
20
+
21
+ Again, Frameworks are great, but if you've ever tried teaching someone new to web development a Framework, it's a lot to take in. Just getting everything set up and configued (what do you mean you can't connect to the database, is Postgres even running? What do you mean you don't know?) is a multi-step affair.
22
+
23
+ Imagine you could just start writing code in your favorite languages (provided your favorite languages are Ruby, HAML, and Sass) and not worry about the other stuff. Wouldn't that be great? Imagine you could deploy your running app to Heroku without configuring jack squat.
24
+
25
+ That's the goal of Stormy - a simple, minimal-dependency semi-static rack-based app server that throws away all the best practices we've been using for the past decade to get you writing your mini-project's code asap.
26
+
27
+ ## Why didn't you just use [Sinatra|Flask|Express|INSERT MICRO-FRAMEWORK HERE]?
28
+
29
+ Dammit, I should have - you're right. Oh well.
30
+
31
+ No really, I just wanted to write some code in a file and have a server serve that code up. routes or setup.
32
+
33
+ ## How to use
34
+
35
+ ### Basics
36
+
37
+ Shell scripts coming soon - for now, put Stormy in your Gemfile, bundle and then create a config.ru
38
+
39
+ require "stormy"
40
+ run StormyServer.new( root: File.dirname(__FILE__) )
41
+
42
+ Create a `/public` directory and put directories and files ending in .md, .haml, .scss or .html in it along with any of your static assets.
43
+
44
+ Run:
45
+
46
+ rackup
47
+
48
+ Your site should now be live.
49
+
50
+ ### Front Matter
51
+
52
+ ... Documentation Forthcoming ...
53
+
54
+ ### Content, Pagination and Blogs
55
+
56
+ ... Documentation Forthcoming ...
57
+
58
+ ### Redirects
59
+
60
+ ... Documentation Forthcoming ...
61
+
62
+ ### Permalinks
63
+
64
+
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ Dir.glob('tasks/**/*.rake').each(&method(:import))
4
+ task :default => :spec
@@ -0,0 +1,34 @@
1
+ require 'active_support/all'
2
+
3
+ module Stormy
4
+
5
+ end
6
+
7
+ require_relative 'stormy/static'
8
+
9
+ require_relative 'stormy/caches/base'
10
+ require_relative 'stormy/caches/file_cache'
11
+ require_relative 'stormy/caches/dummy_cache'
12
+ require_relative 'stormy/caches/memory_cache'
13
+
14
+ require_relative 'stormy/chunk'
15
+ require_relative 'stormy/content'
16
+ require_relative 'stormy/content_list'
17
+ require_relative 'stormy/page'
18
+ require_relative 'stormy/layout'
19
+
20
+ require_relative 'stormy/stores/base'
21
+ require_relative 'stormy/stores/file_store'
22
+
23
+ require_relative 'stormy/engines/base'
24
+ require_relative 'stormy/engines/markdown'
25
+ require_relative 'stormy/engines/erb'
26
+ require_relative 'stormy/engines/haml'
27
+ require_relative 'stormy/engines/sass'
28
+ require_relative 'stormy/engines/html'
29
+
30
+ require_relative 'stormy/template'
31
+
32
+ require_relative "stormy_app"
33
+ require_relative "stormy_server"
34
+
@@ -0,0 +1,46 @@
1
+ require 'digest/md5'
2
+
3
+ module Stormy::Caches
4
+
5
+ class Base
6
+
7
+ def initialize(app)
8
+ @app = app
9
+ end
10
+
11
+ def content(category,key,options={},&block)
12
+ data = self.get(category,key)
13
+ if !data.nil?
14
+ log "Cache Hit: #{category} #{key}"
15
+ data
16
+ else
17
+ log "Cache Miss: #{category} #{key}"
18
+ self.put(category,key,yield(options))
19
+ end
20
+ end
21
+
22
+ def page(key,&block)
23
+ content("_pages",key,&block)
24
+ end
25
+
26
+ def layout(key,&block)
27
+ content("_layouts",key,&block)
28
+ end
29
+
30
+ def content_list(category,options = {}, &block)
31
+ content("list-#{category}",hash_options(options),&block)
32
+ end
33
+
34
+ def log(str)
35
+ #puts str
36
+ end
37
+
38
+ protected
39
+
40
+ def hash_options(options)
41
+ Digest::MD5.hexdigest(options.to_a.sort_by { |key,val| key }.to_json)
42
+ end
43
+
44
+ end
45
+ end
46
+
@@ -0,0 +1,12 @@
1
+ class Stormy::Caches::DummyCache < Stormy::Caches::Base
2
+
3
+ def get(category,key)
4
+ nil
5
+ end
6
+
7
+
8
+ def put(category,key,value)
9
+ value
10
+ end
11
+
12
+ end
@@ -0,0 +1,47 @@
1
+ require "fileutils"
2
+
3
+ class Stormy::Caches::FileCache < Stormy::Caches::Base
4
+
5
+ def initialize(app)
6
+ super
7
+ @base_path = app.join("tmp","cache")
8
+ clean_path
9
+ end
10
+
11
+ protected
12
+
13
+ def build_cache_key(category,key)
14
+ path("#{category}--#{key.gsub("/","--")}.cache")
15
+ end
16
+
17
+
18
+ def get(category,key)
19
+ filename = build_cache_key(category,key)
20
+ if File.exists?(filename)
21
+ File.read(filename)
22
+ end
23
+ end
24
+
25
+
26
+ def put(category,key,value)
27
+ filename = build_cache_key(category,key)
28
+ File.open(filename,"wt") do |fp|
29
+ fp.write(value)
30
+ end
31
+ value
32
+ end
33
+
34
+ def clean_path
35
+ path_exists = File.directory?(@base_path)
36
+ if path_exists
37
+ FileUtils.rm Dir.glob(path("*.cache"))
38
+ else
39
+ FileUtils.mkpath(@base_path)
40
+ end
41
+ end
42
+
43
+ def path(file)
44
+ File.join(@base_path,file)
45
+ end
46
+
47
+ end
@@ -0,0 +1,24 @@
1
+ class Stormy::Caches::MemoryCache < Stormy::Caches::Base
2
+
3
+ def initialize(app)
4
+ super
5
+ @data = {}
6
+ end
7
+
8
+ protected
9
+
10
+ def build_cache_key(category,key)
11
+ "#{category}--#{key.gsub("/","--")}"
12
+ end
13
+
14
+
15
+ def get(category,key)
16
+ @data[build_cache_key(category,key)]
17
+ end
18
+
19
+
20
+ def put(category,key,value)
21
+ @data[build_cache_key(category,key)] = value
22
+ end
23
+
24
+ end
@@ -0,0 +1,63 @@
1
+ require "rack/mime"
2
+
3
+ class Stormy::Chunk
4
+ attr_reader :details, :content, :body
5
+
6
+ def initialize(app,details,params={})
7
+ @app = app
8
+
9
+ @params = params
10
+ @details = ActiveSupport::HashWithIndifferentAccess.new(app.defaults)
11
+ @details.merge!(details)
12
+
13
+ @body = details[:body]
14
+ @content = {}
15
+
16
+ @template = app.template(details[:path],@details) if @body
17
+ end
18
+
19
+ def valid?
20
+ @template.present? && !@invalid_content
21
+ end
22
+
23
+
24
+ def resolve_content
25
+ pieces = details[:content]
26
+ pieces = [ pieces ] unless pieces.is_a?(Array)
27
+ pieces.each do |piece|
28
+ if !resolve_piece(piece)
29
+ @invalid_content = true
30
+ end
31
+ end
32
+ self.content
33
+ end
34
+
35
+ def resolve_piece(piece)
36
+ name = (piece[:name] || piece[:type]).to_sym
37
+ type = piece[:type]
38
+ if piece[:key].present?
39
+ resolve_content_piece(name,type,piece)
40
+ else
41
+ resolve_content_list(name,type,piece)
42
+ end
43
+ end
44
+
45
+ def resolve_content_piece(name,type,piece)
46
+ key = if piece[:key].is_a?(Symbol)
47
+ details[piece[:key]]
48
+ else
49
+ piece[:key]
50
+ end
51
+ content_chunk = @app.content(type,key)
52
+
53
+ if content_chunk && content_chunk.valid?
54
+ content[name] = content_chunk.render
55
+ end
56
+ end
57
+
58
+ def resolve_content_list(name,type,piece)
59
+ content_list = @app.content_list(type,piece)
60
+ content[name] = content_list.items
61
+ end
62
+
63
+ end
@@ -0,0 +1,21 @@
1
+ class Stormy::Content < Stormy::Chunk
2
+
3
+ def initialize(app,details)
4
+ super(app,details)
5
+ resolve_content if details[:content] && @template
6
+ end
7
+
8
+ def render
9
+ @details.merge({
10
+ body: @template.render
11
+ })
12
+ end
13
+
14
+ def self.fetch(app, category, key)
15
+ details = app.cache.content(category,key) do
16
+ app.store.content(category,key)
17
+ end
18
+
19
+ self.new(app,details)
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ class Stormy::ContentList
2
+
3
+ attr_reader :items
4
+
5
+ def initialize(app,items)
6
+ @items = items.map do |item|
7
+ Stormy::Content.new(app,item).render
8
+ end
9
+ end
10
+
11
+ def self.fetch(app,category,options = {})
12
+ items = app.cache.content_list(category,options) do
13
+ app.store.content_list(category,options)
14
+ end
15
+
16
+ self.new(app,items)
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ module Stormy::Engines
2
+ class Base
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+ end
7
+ end