owl-cms 0.1.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.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/Gemfile +23 -0
  4. data/Gemfile.lock +87 -0
  5. data/README.md +3 -0
  6. data/Rakefile +8 -0
  7. data/bin/owl +88 -0
  8. data/config.ru +3 -0
  9. data/core/app.rb +21 -0
  10. data/core/assets/stylesheets/style.css +1 -0
  11. data/core/classes/cached.rb +36 -0
  12. data/core/classes/checker.rb +37 -0
  13. data/core/classes/error.rb +9 -0
  14. data/core/classes/other.rb +13 -0
  15. data/core/classes/page.rb +128 -0
  16. data/core/classes/partial.rb +13 -0
  17. data/core/classes/path.rb +35 -0
  18. data/core/classes/settings.rb +19 -0
  19. data/core/classes/theme.rb +48 -0
  20. data/core/helpers/base.rb +37 -0
  21. data/core/helpers/render.rb +26 -0
  22. data/core/helpers/truncate.rb +17 -0
  23. data/core/routes/admin.rb +13 -0
  24. data/core/routes/base.rb +18 -0
  25. data/core/routes/bootstrap.rb +30 -0
  26. data/core/routes/cache.rb +36 -0
  27. data/owl-cms.gemspec +25 -0
  28. data/sample/.cabi-data +0 -0
  29. data/sample/data/home/index.haml +21 -0
  30. data/sample/data/other/nav/links.yml +4 -0
  31. data/sample/data/page/about/index.haml +14 -0
  32. data/sample/data/page/contact-us/index.haml +11 -0
  33. data/sample/data/page/dynamic-page/index.haml +14 -0
  34. data/sample/data/page/no-front-matter/index.haml +7 -0
  35. data/sample/data/page/not-found/index.haml +7 -0
  36. data/sample/data/page/static-page/index.haml +14 -0
  37. data/sample/data/post/about-life/index.haml +8 -0
  38. data/sample/data/post/sample-post/index.haml +12 -0
  39. data/sample/data/post/technology/index.haml +9 -0
  40. data/sample/data/post/the-40-hour-workweek/index.haml +9 -0
  41. data/sample/data/post/things-are-changing/index.haml +9 -0
  42. data/sample/data/post/yet-another-post/index.haml +11 -0
  43. data/sample/plugins/my-plugin/plugin.rb +15 -0
  44. data/sample/settings.yml +7 -0
  45. data/sample/themes/base/assets/config.rb +26 -0
  46. data/sample/themes/base/assets/images/owl.svg +20 -0
  47. data/sample/themes/base/assets/javascripts/app/views/main.js +13 -0
  48. data/sample/themes/base/assets/javascripts/main.js +31 -0
  49. data/sample/themes/base/assets/javascripts/vendor/backbone.js +4 -0
  50. data/sample/themes/base/assets/javascripts/vendor/jquery.js +6 -0
  51. data/sample/themes/base/assets/javascripts/vendor/lodash.underscore.js +38 -0
  52. data/sample/themes/base/assets/javascripts/vendor/require.js +36 -0
  53. data/sample/themes/base/assets/scss/main.scss +19 -0
  54. data/sample/themes/base/assets/scss/modules/_all.scss +7 -0
  55. data/sample/themes/base/assets/scss/modules/_colors.scss +5 -0
  56. data/sample/themes/base/assets/scss/modules/_extensions.scss +11 -0
  57. data/sample/themes/base/assets/scss/modules/_mixins.scss +2 -0
  58. data/sample/themes/base/assets/scss/modules/_susy.scss +6 -0
  59. data/sample/themes/base/assets/scss/partials/_base.scss +26 -0
  60. data/sample/themes/base/assets/scss/partials/_buttons.scss +0 -0
  61. data/sample/themes/base/assets/scss/partials/_links.scss +15 -0
  62. data/sample/themes/base/assets/scss/partials/_main.scss +37 -0
  63. data/sample/themes/base/assets/scss/partials/_typography.scss +16 -0
  64. data/sample/themes/base/assets/scss/sections/_footer.scss +24 -0
  65. data/sample/themes/base/assets/scss/sections/_header.scss +18 -0
  66. data/sample/themes/base/assets/scss/sections/_home.scss +13 -0
  67. data/sample/themes/base/assets/scss/vendor/_normalize.scss +406 -0
  68. data/sample/themes/base/assets/stylesheets/main.css +587 -0
  69. data/sample/themes/base/layouts/default.haml +11 -0
  70. data/sample/themes/base/layouts/post.haml +17 -0
  71. data/sample/themes/base/partials/_footer.haml +11 -0
  72. data/sample/themes/base/partials/_ga.haml +10 -0
  73. data/sample/themes/base/partials/_head.haml +20 -0
  74. data/sample/themes/base/partials/_header.haml +7 -0
  75. data/sample/themes/base/settings.yml +4 -0
  76. data/test/test_basics.rb +50 -0
  77. data/test/test_data.rb +14 -0
  78. data/test/test_includes.rb +43 -0
  79. data/test/test_page.rb +47 -0
  80. metadata +612 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5e252eecd1ef4b780e2e8b6fc4c86473f132bedb
4
+ data.tar.gz: cdc046025f41f5a95ad11e70542115863eb35e36
5
+ SHA512:
6
+ metadata.gz: 7ef2300235c154f7f05d11c86e8cf157faeeae3ffe3a95c442a4e8dafa4fdc5b9071f34a1ca75982643b5318292f9a5c4f01bd4144ba22b031b0a57e3203a1a7
7
+ data.tar.gz: 3e8b017ff3bbe7c842efb1dc652fcfe1205bc0470e0dca0773a5ec14e33f5a1c236d142ff380d553a01d02426ae82d10eb4a2a999264d620c4a82148f80762ea
@@ -0,0 +1,6 @@
1
+
2
+ .cache
3
+ .DS_Store
4
+ .sass-cache
5
+
6
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,23 @@
1
+
2
+ source 'http://rubygems.org'
3
+
4
+ # Sinatra & Rack
5
+ gem 'sinatra', '1.4.3', :require => 'sinatra/base'
6
+ gem 'sinatra-contrib', '1.4.1', :require => 'sinatra/contrib/all'
7
+ gem 'rack-cache', '1.2', :require => 'rack/cache'
8
+ gem 'rack-funky-cache', '0.0.6', :require => 'rack/funky-cache'
9
+ gem 'rack-session-file', '0.5.0', :require => 'rack-session-file'
10
+ gem 'thin', '1.5.1', :require => 'thin'
11
+ gem 'rerun', '0.8.1', :require => 'rerun'
12
+
13
+ # Frontend
14
+ gem 'haml', '4.0.3', :require => 'haml'
15
+ gem 'sass', '3.2.10', :require => 'sass'
16
+ gem 'compass', '0.12.2', :require => 'compass'
17
+ gem 'susy', '1.0.9', :require => 'susy'
18
+ gem 'maruku', '0.6.1', :require => 'maruku'
19
+ gem 'html_truncator', '0.3.1', :require => 'html_truncator'
20
+
21
+
22
+ # Datastore
23
+ gem 'cabi', '0.1.5', :require => 'cabi'
@@ -0,0 +1,87 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ backports (3.3.4)
5
+ cabi (0.1.5)
6
+ thor (~> 0.18, >= 0.18.1)
7
+ chunky_png (1.2.8)
8
+ compass (0.12.2)
9
+ chunky_png (~> 1.2)
10
+ fssm (>= 0.2.7)
11
+ sass (~> 3.1)
12
+ daemons (1.1.9)
13
+ eventmachine (1.0.3)
14
+ ffi (1.9.0)
15
+ fssm (0.2.10)
16
+ haml (4.0.3)
17
+ tilt
18
+ html_truncator (0.3.1)
19
+ nokogiri (~> 1.5)
20
+ listen (1.3.1)
21
+ rb-fsevent (>= 0.9.3)
22
+ rb-inotify (>= 0.9)
23
+ rb-kqueue (>= 0.2)
24
+ maruku (0.6.1)
25
+ syntax (>= 1.0.0)
26
+ mini_portile (0.5.1)
27
+ multi_json (1.8.0)
28
+ nokogiri (1.6.0)
29
+ mini_portile (~> 0.5.0)
30
+ rack (1.5.2)
31
+ rack-cache (1.2)
32
+ rack (>= 0.4)
33
+ rack-funky-cache (0.0.6)
34
+ rack-protection (1.5.0)
35
+ rack
36
+ rack-session-file (0.5.0)
37
+ rack (>= 1.1.0)
38
+ rack-test (0.6.2)
39
+ rack (>= 1.0)
40
+ rb-fsevent (0.9.3)
41
+ rb-inotify (0.9.2)
42
+ ffi (>= 0.5.0)
43
+ rb-kqueue (0.2.0)
44
+ ffi (>= 0.5.0)
45
+ rerun (0.8.1)
46
+ listen (>= 1.0.3)
47
+ sass (3.2.10)
48
+ sinatra (1.4.3)
49
+ rack (~> 1.4)
50
+ rack-protection (~> 1.4)
51
+ tilt (~> 1.3, >= 1.3.4)
52
+ sinatra-contrib (1.4.1)
53
+ backports (>= 2.0)
54
+ multi_json
55
+ rack-protection
56
+ rack-test
57
+ sinatra (~> 1.4.0)
58
+ tilt (~> 1.3)
59
+ susy (1.0.9)
60
+ compass (>= 0.12.2)
61
+ sass (>= 3.2.0)
62
+ syntax (1.0.0)
63
+ thin (1.5.1)
64
+ daemons (>= 1.0.9)
65
+ eventmachine (>= 0.12.6)
66
+ rack (>= 1.0.0)
67
+ thor (0.18.1)
68
+ tilt (1.4.1)
69
+
70
+ PLATFORMS
71
+ ruby
72
+
73
+ DEPENDENCIES
74
+ cabi (= 0.1.5)
75
+ compass (= 0.12.2)
76
+ haml (= 4.0.3)
77
+ html_truncator (= 0.3.1)
78
+ maruku (= 0.6.1)
79
+ rack-cache (= 1.2)
80
+ rack-funky-cache (= 0.0.6)
81
+ rack-session-file (= 0.5.0)
82
+ rerun (= 0.8.1)
83
+ sass (= 3.2.10)
84
+ sinatra (= 1.4.3)
85
+ sinatra-contrib (= 1.4.1)
86
+ susy (= 1.0.9)
87
+ thin (= 1.5.1)
@@ -0,0 +1,3 @@
1
+ # <img src="http://s.cdpn.io/4629/owl.svg" width=30 style="margin-right: 10px"> OwlCMS
2
+
3
+ A work in progress -- bear with me.
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
data/bin/owl ADDED
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+ require "thor"
3
+ require "fileutils"
4
+
5
+ ROOT = File.expand_path("../..", __FILE__)
6
+ CONFIG_RU = File.join( ROOT, "config.ru")
7
+ SAMPLE_DIR = File.join( ROOT, "sample")
8
+ GEMFILE = File.join( ROOT, "Gemfile")
9
+
10
+ class OwlCLI < Thor
11
+
12
+ # -----------------------------------------------------------------------------------------------------------
13
+ # Serve Task
14
+ # -----------------------------------------------------------------------------------------------------------
15
+ desc "start", "Startup Owl server for local viewing. (use --port to specify your own port)"
16
+ method_options port: :integer, rerun: true
17
+ def start
18
+ port = options[:port] || 3000
19
+ no_reload = options[:rerun]
20
+ thin_string = "BUNDLE_GEMFILE='#{GEMFILE}' thin start -R #{CONFIG_RU} --port #{port}"
21
+
22
+ puts "\n** Starting OwlCMS\n"
23
+
24
+ if options[:rerun]
25
+ puts "** (rerun enabled)"
26
+ system "rerun '#{thin_string}' --no-growl"
27
+ else
28
+ puts "** (rerun disabled)"
29
+ system "#{thin_string}"
30
+ end
31
+ end
32
+
33
+ # -----------------------------------------------------------------------------------------------------------
34
+ # Init Task
35
+ # -----------------------------------------------------------------------------------------------------------
36
+ desc "init", "Initialize new Owl project"
37
+ method_options :port => :integer
38
+ def init
39
+ puts "\n** Creating new OwlCMS instance"
40
+
41
+ found = []
42
+ Dir.foreach( SAMPLE_DIR ).each do |file|
43
+ next if ['.', '..', '.DS_Store'].include? file
44
+ found << file if File.exists? file
45
+ end
46
+
47
+ raise "** Cannot continue! The following files would be deleted: #{found.join(',')}\n\n" if !found.empty?
48
+
49
+ # Copy all of the files.
50
+ puts "** Copying files"
51
+ system "cp -r #{SAMPLE_DIR}/.cabi-data ."
52
+ system "cp -r #{SAMPLE_DIR}/* ."
53
+
54
+ puts "** Success!"
55
+ end
56
+
57
+ # -----------------------------------------------------------------------------------------------------------
58
+ # Clean Task
59
+ # -----------------------------------------------------------------------------------------------------------
60
+ desc "clean", "Clean current directory of Owl-related files & directories"
61
+ method_options :force => :false
62
+ def clean
63
+ puts "\n** Cleaning: #{Dir.pwd}."
64
+
65
+ if options[:force]
66
+ puts "** About to destroy..."
67
+ Dir.foreach( SAMPLE_DIR ).each do |file|
68
+ next if ['.', '..', '.DS_Store'].include? file
69
+ FileUtils.rm_rf(File.basename(file)) if File.exists?(file)
70
+ end
71
+ else
72
+ puts "** Ooops! Not cleaning without --force. Files & dirs **will** be harmed."
73
+ end
74
+
75
+ end
76
+
77
+ # -----------------------------------------------------------------------------------------------------------
78
+ # Theme Task
79
+ # -----------------------------------------------------------------------------------------------------------
80
+ desc "theme", "Install base theme or theme from git"
81
+ def theme
82
+ # install base theme or install
83
+ # theme from
84
+ end
85
+
86
+ end
87
+
88
+ OwlCLI.start
@@ -0,0 +1,3 @@
1
+
2
+ require File.expand_path('../core/app', __FILE__)
3
+ run Owl::CMS::App
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+
5
+ # Base requires.
6
+ Bundler.require(:default)
7
+
8
+ module Owl
9
+
10
+ ROOT = File.expand_path '../..', __FILE__
11
+ CORE = File.join(Owl::ROOT, 'core')
12
+ require Owl::CORE + '/routes/bootstrap'
13
+
14
+ module CMS
15
+
16
+ class App < Sinatra::Base
17
+ register Owl::CMS::Bootstrap
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1 @@
1
+ body{ color: blue; }
@@ -0,0 +1,36 @@
1
+
2
+ require 'fileutils'
3
+
4
+ module Owl
5
+ module Lib
6
+ class CachedFile
7
+
8
+
9
+ def self.find(request)
10
+ path = Rack::Utils.unescape(request.path_info)
11
+
12
+ file_to_return = false
13
+ self.possible_paths(path).each do |file|
14
+ break if file_to_return
15
+ file_to_return = file if File.exists?(file)
16
+ end
17
+
18
+ file_to_return
19
+ end
20
+
21
+ def self.possible_paths(path)
22
+ [
23
+ File.expand_path("#{Owl::CMS::Cache::CACHE_STORE}#{path}.html" ),
24
+ File.expand_path("#{Owl::CMS::Cache::CACHE_STORE}#{path}/index.html" ),
25
+ File.expand_path("#{Owl::CMS::Cache::CACHE_STORE}#{path}index.html" )
26
+ ]
27
+ end
28
+
29
+ def self.clear
30
+ puts "** Removing OwlCMS cache **"
31
+ FileUtils.rm_rf Owl::CMS::Cache::CACHE_STORE
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+
2
+ require Owl::CORE + '/classes/error'
3
+
4
+ module Owl
5
+
6
+ DEFAULT_THEME_DIR = 'themes'
7
+ DEFAULT_DATA_DIR = 'data'
8
+ REQUIRED_DATA_SUB_DIRS = ['post', 'page', 'home']
9
+
10
+ module Lib
11
+ class Checker
12
+
13
+ def self.check!
14
+ unless self.base_dirs? and self.sub_dirs?
15
+ raise Owl::Error.new('Directory structure is not correct! Have you run the `owl new` command?')
16
+ end
17
+ end
18
+
19
+ def self.base_dirs?
20
+ Cabi.file(DEFAULT_DATA_DIR) and
21
+ Cabi.file(DEFAULT_THEME_DIR)
22
+ end
23
+
24
+ def self.sub_dirs?
25
+ ok = nil
26
+ REQUIRED_DATA_SUB_DIRS.each do |dir|
27
+ ok = Cabi.file( [DEFAULT_DATA_DIR, dir].join(':') )
28
+ break if not ok
29
+ end
30
+ ok
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+
37
+ Owl::Lib::Checker.check!
@@ -0,0 +1,9 @@
1
+
2
+ module Owl
3
+ class Error < StandardError
4
+ def initialize(msg = "An error has occurred.")
5
+ super( [" ** OwlCMS", msg].join(' - ') )
6
+ end
7
+ end
8
+ end
9
+
@@ -0,0 +1,13 @@
1
+ module Owl
2
+ module Lib
3
+ class OtherData
4
+
5
+ OTHER_PATH = 'other'
6
+
7
+ def self.read(key)
8
+ Cabi.read [ Owl::Lib::Path::DATA_PATH, OTHER_PATH, key].join(':')
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,128 @@
1
+
2
+ require 'digest/sha1'
3
+ require 'date'
4
+
5
+ module Owl
6
+ module Lib
7
+ class Page
8
+
9
+ DEFAULT_PAGE_LAYOUT = "default.haml"
10
+ FRONT_MATTER_RE = /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
11
+
12
+ attr_accessor :raw
13
+ attr_accessor :haml
14
+ attr_accessor :html
15
+ attr_accessor :front_matter
16
+ attr_accessor :path
17
+
18
+ def initialize(path, current_scope=self, quiet=false)
19
+
20
+ read(path)
21
+ @path = path
22
+
23
+ raise Sinatra::NotFound if (@raw.nil? and !quiet)
24
+
25
+ @scope = current_scope
26
+ @scope.instance_variable_set :@page, self
27
+ parse_haml
28
+ parse_front_matter
29
+ render
30
+ end
31
+
32
+ def read(path)
33
+ @raw ||= Cabi.read( Owl::Lib::Path.path(path) ) || Cabi.read( Owl::Lib::Path.page_path(path) )
34
+ end
35
+
36
+ def parse_haml
37
+ @haml ||= raw.gsub FRONT_MATTER_RE, ''
38
+ end
39
+
40
+ def parse_front_matter
41
+ @front_matter ||= begin
42
+ raise unless raw.index(FRONT_MATTER_RE)
43
+ YAML.load(@raw) || Hash.new
44
+ rescue Exception => e
45
+ Hash.new
46
+ end
47
+ end
48
+
49
+ def render
50
+ @html = Haml::Engine.new( layout ).render( @scope, front_matter ) do
51
+ Haml::Engine.new( @haml ).render( @scope, front_matter )
52
+ end
53
+ end
54
+
55
+ def content
56
+ # This is the page without the content.
57
+ @content ||= Haml::Engine.new( @haml ).render( @scope, front_matter )
58
+ end
59
+
60
+ def setting(key)
61
+ @front_matter[key]
62
+ end
63
+
64
+ def haml_opts
65
+ opts = front_matter
66
+ opts[:layout] = layout
67
+ opts
68
+ end
69
+
70
+ def layout
71
+ user_layout = setting('layout')
72
+ Owl::Lib::Theme.instance.layout( user_layout )
73
+ end
74
+
75
+ def type
76
+ post? ? 'post' : 'page'
77
+ end
78
+
79
+ def page?
80
+ !post?
81
+ end
82
+
83
+ def post?
84
+ path.index("/post") == 0
85
+ end
86
+
87
+ def cache?
88
+ if @front_matter.has_key?('cache')
89
+ setting('cache')
90
+ else
91
+ true
92
+ end
93
+ end
94
+
95
+ def publish?
96
+ setting('publish')
97
+ end
98
+
99
+ def age
100
+ begin
101
+ Date.parse(date).to_time.to_i
102
+ rescue Exception => e
103
+ 0
104
+ end
105
+ end
106
+
107
+ def sha1
108
+ Digest::SHA1.hexdigest @raw
109
+ end
110
+
111
+ def self.all_posts(current_scope=self, opts)
112
+ files = Cabi.file( Owl::Lib::Path.all_posts_path )
113
+
114
+ posts = []
115
+ files.each do |path|
116
+ path = '/' + path.gsub(Cabi::data_dir, '')[1..-1].split('/')[1..-2].join('/')
117
+ post = Owl::Lib::Page.new( path, current_scope, true)
118
+ posts << post if post.publish? or opts[:include_unpublished]
119
+ end
120
+
121
+ posts.sort! {|a,b| a.age <=> b.age }
122
+ posts.reverse!
123
+ posts
124
+ end
125
+
126
+ end
127
+ end
128
+ end