owl-cms 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/Gemfile +23 -0
- data/Gemfile.lock +87 -0
- data/README.md +3 -0
- data/Rakefile +8 -0
- data/bin/owl +88 -0
- data/config.ru +3 -0
- data/core/app.rb +21 -0
- data/core/assets/stylesheets/style.css +1 -0
- data/core/classes/cached.rb +36 -0
- data/core/classes/checker.rb +37 -0
- data/core/classes/error.rb +9 -0
- data/core/classes/other.rb +13 -0
- data/core/classes/page.rb +128 -0
- data/core/classes/partial.rb +13 -0
- data/core/classes/path.rb +35 -0
- data/core/classes/settings.rb +19 -0
- data/core/classes/theme.rb +48 -0
- data/core/helpers/base.rb +37 -0
- data/core/helpers/render.rb +26 -0
- data/core/helpers/truncate.rb +17 -0
- data/core/routes/admin.rb +13 -0
- data/core/routes/base.rb +18 -0
- data/core/routes/bootstrap.rb +30 -0
- data/core/routes/cache.rb +36 -0
- data/owl-cms.gemspec +25 -0
- data/sample/.cabi-data +0 -0
- data/sample/data/home/index.haml +21 -0
- data/sample/data/other/nav/links.yml +4 -0
- data/sample/data/page/about/index.haml +14 -0
- data/sample/data/page/contact-us/index.haml +11 -0
- data/sample/data/page/dynamic-page/index.haml +14 -0
- data/sample/data/page/no-front-matter/index.haml +7 -0
- data/sample/data/page/not-found/index.haml +7 -0
- data/sample/data/page/static-page/index.haml +14 -0
- data/sample/data/post/about-life/index.haml +8 -0
- data/sample/data/post/sample-post/index.haml +12 -0
- data/sample/data/post/technology/index.haml +9 -0
- data/sample/data/post/the-40-hour-workweek/index.haml +9 -0
- data/sample/data/post/things-are-changing/index.haml +9 -0
- data/sample/data/post/yet-another-post/index.haml +11 -0
- data/sample/plugins/my-plugin/plugin.rb +15 -0
- data/sample/settings.yml +7 -0
- data/sample/themes/base/assets/config.rb +26 -0
- data/sample/themes/base/assets/images/owl.svg +20 -0
- data/sample/themes/base/assets/javascripts/app/views/main.js +13 -0
- data/sample/themes/base/assets/javascripts/main.js +31 -0
- data/sample/themes/base/assets/javascripts/vendor/backbone.js +4 -0
- data/sample/themes/base/assets/javascripts/vendor/jquery.js +6 -0
- data/sample/themes/base/assets/javascripts/vendor/lodash.underscore.js +38 -0
- data/sample/themes/base/assets/javascripts/vendor/require.js +36 -0
- data/sample/themes/base/assets/scss/main.scss +19 -0
- data/sample/themes/base/assets/scss/modules/_all.scss +7 -0
- data/sample/themes/base/assets/scss/modules/_colors.scss +5 -0
- data/sample/themes/base/assets/scss/modules/_extensions.scss +11 -0
- data/sample/themes/base/assets/scss/modules/_mixins.scss +2 -0
- data/sample/themes/base/assets/scss/modules/_susy.scss +6 -0
- data/sample/themes/base/assets/scss/partials/_base.scss +26 -0
- data/sample/themes/base/assets/scss/partials/_buttons.scss +0 -0
- data/sample/themes/base/assets/scss/partials/_links.scss +15 -0
- data/sample/themes/base/assets/scss/partials/_main.scss +37 -0
- data/sample/themes/base/assets/scss/partials/_typography.scss +16 -0
- data/sample/themes/base/assets/scss/sections/_footer.scss +24 -0
- data/sample/themes/base/assets/scss/sections/_header.scss +18 -0
- data/sample/themes/base/assets/scss/sections/_home.scss +13 -0
- data/sample/themes/base/assets/scss/vendor/_normalize.scss +406 -0
- data/sample/themes/base/assets/stylesheets/main.css +587 -0
- data/sample/themes/base/layouts/default.haml +11 -0
- data/sample/themes/base/layouts/post.haml +17 -0
- data/sample/themes/base/partials/_footer.haml +11 -0
- data/sample/themes/base/partials/_ga.haml +10 -0
- data/sample/themes/base/partials/_head.haml +20 -0
- data/sample/themes/base/partials/_header.haml +7 -0
- data/sample/themes/base/settings.yml +4 -0
- data/test/test_basics.rb +50 -0
- data/test/test_data.rb +14 -0
- data/test/test_includes.rb +43 -0
- data/test/test_page.rb +47 -0
- metadata +612 -0
checksums.yaml
ADDED
@@ -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
|
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'
|
data/Gemfile.lock
ADDED
@@ -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)
|
data/README.md
ADDED
data/Rakefile
ADDED
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
|
data/config.ru
ADDED
data/core/app.rb
ADDED
@@ -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,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
|