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.
- 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
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Owl
|
|
2
|
+
module Lib
|
|
3
|
+
class Path
|
|
4
|
+
|
|
5
|
+
DATA_PATH = 'data'
|
|
6
|
+
INDEX_PATH = 'index'
|
|
7
|
+
NOT_FOUND_PATH = 'not-found'
|
|
8
|
+
POST_PATH = "post"
|
|
9
|
+
PAGE_PATH = "page"
|
|
10
|
+
|
|
11
|
+
def self.cabi_id(p, opts={})
|
|
12
|
+
p = p[1..-1]
|
|
13
|
+
[DATA_PATH, p.gsub('/', ':'), INDEX_PATH].compact.join(':')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.path(p)
|
|
17
|
+
self.cabi_id(p)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.page_path(p)
|
|
21
|
+
self.cabi_id( ['/', PAGE_PATH, p].join('/') )
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.partial_cabi_id(p)
|
|
25
|
+
p = "_" + p
|
|
26
|
+
[Owl::Lib::Theme.instance.path, Owl::Lib::Theme::PARTIALS_PATH, p].join(':')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.all_posts_path
|
|
30
|
+
[DATA_PATH, POST_PATH, "**/#{INDEX_PATH}.*"].join(':')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
require 'singleton'
|
|
3
|
+
require Owl::CORE + '/classes/theme'
|
|
4
|
+
|
|
5
|
+
module Owl
|
|
6
|
+
module Lib
|
|
7
|
+
class Settings
|
|
8
|
+
include Singleton
|
|
9
|
+
|
|
10
|
+
SETTINGS_PATH = 'settings.yml'
|
|
11
|
+
THEME_SETTINGS_PATH = [Owl::Lib::Theme::THEMES_PATH, SETTINGS_PATH].join(':')
|
|
12
|
+
|
|
13
|
+
def settings
|
|
14
|
+
Cabi.read(SETTINGS_PATH)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
|
|
2
|
+
require 'singleton'
|
|
3
|
+
|
|
4
|
+
module Owl
|
|
5
|
+
|
|
6
|
+
module Lib
|
|
7
|
+
class Theme
|
|
8
|
+
include Singleton
|
|
9
|
+
|
|
10
|
+
THEMES_PATH = 'themes'
|
|
11
|
+
LAYOUTS_PATH = 'layouts'
|
|
12
|
+
PARTIALS_PATH = 'partials'
|
|
13
|
+
ASSETS_PATH = 'assets'
|
|
14
|
+
DEFAULT_THEME = 'base'
|
|
15
|
+
DEFAULT_PAGE_LAYOUT = 'default'
|
|
16
|
+
|
|
17
|
+
def current
|
|
18
|
+
Owl::Lib::Settings.instance.settings['theme'] || DEFAULT_THEME
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def layout(layout)
|
|
22
|
+
layout = DEFAULT_PAGE_LAYOUT if layout.nil?
|
|
23
|
+
|
|
24
|
+
Cabi.read([ path, LAYOUTS_PATH, layout ].join(':')) ||
|
|
25
|
+
Cabi.read([ path, LAYOUTS_PATH, DEFAULT_PAGE_LAYOUT ].join(':')) ||
|
|
26
|
+
"= yield"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def file_path
|
|
30
|
+
Cabi.file( path )
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def path
|
|
34
|
+
[ THEMES_PATH, current ].join(':')
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def theme_path
|
|
38
|
+
Cabi.file( [path, ASSETS_PATH].join(':') )
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def settings
|
|
42
|
+
Cabi.read([ path, Owl::Lib::Settings::SETTINGS_PATH ].join(':'))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
|
|
2
|
+
module Owl
|
|
3
|
+
module CMS
|
|
4
|
+
module Helpers
|
|
5
|
+
include Sinatra
|
|
6
|
+
|
|
7
|
+
module Base
|
|
8
|
+
|
|
9
|
+
def site_setting(key)
|
|
10
|
+
Owl::CMS::App.settings.site_settings[key]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def theme_setting(key)
|
|
14
|
+
Owl::CMS::App.settings.theme_settings[key]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def posts(include_unpublished=false)
|
|
18
|
+
Owl::Lib::Page.all_posts(self, { include_unpublished: include_unpublished })
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def data(key)
|
|
22
|
+
Owl::Lib::OtherData.read key
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def page_path
|
|
26
|
+
@page.path
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def page_type
|
|
30
|
+
@page.type
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
|
|
2
|
+
require 'digest/md5'
|
|
3
|
+
|
|
4
|
+
module Owl
|
|
5
|
+
module CMS
|
|
6
|
+
module Helpers
|
|
7
|
+
include Sinatra
|
|
8
|
+
|
|
9
|
+
module Render
|
|
10
|
+
|
|
11
|
+
def render_page(path)
|
|
12
|
+
# Grab the page & render it.
|
|
13
|
+
page = Owl::Lib::Page.new(path, self)
|
|
14
|
+
page.html
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def partial(path, locals={})
|
|
18
|
+
partial = Owl::Lib::Partial.new(path)
|
|
19
|
+
haml(partial.raw, {}, locals)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/core/routes/base.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
module Owl
|
|
3
|
+
module CMS
|
|
4
|
+
module Base
|
|
5
|
+
extend Sinatra::Extension
|
|
6
|
+
|
|
7
|
+
not_found do
|
|
8
|
+
# => If 404, let's look for the page somewhere else.
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
get '*' do |path|
|
|
12
|
+
path = "/home" if path == '/'
|
|
13
|
+
render_page(path)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
# Require Owl's libs.
|
|
3
|
+
Dir[Owl::CORE + "/**/*.rb"].each {|file| require file }
|
|
4
|
+
|
|
5
|
+
# Require user plugins.
|
|
6
|
+
Cabi.file('plugins:**/*.rb').each{ |file| require file }
|
|
7
|
+
|
|
8
|
+
module Owl
|
|
9
|
+
module CMS
|
|
10
|
+
module Bootstrap
|
|
11
|
+
extend Sinatra::Extension
|
|
12
|
+
|
|
13
|
+
register Owl::CMS::Admin
|
|
14
|
+
register Owl::CMS::Cache
|
|
15
|
+
register Owl::CMS::Base
|
|
16
|
+
|
|
17
|
+
helpers Owl::CMS::Helpers::Base
|
|
18
|
+
helpers Owl::CMS::Helpers::Render
|
|
19
|
+
helpers Owl::CMS::Helpers::Truncate
|
|
20
|
+
|
|
21
|
+
configure do
|
|
22
|
+
set :static, true
|
|
23
|
+
set :public_folder, Owl::Lib::Theme.instance.theme_path
|
|
24
|
+
set :site_settings, Owl::Lib::Settings.instance.settings
|
|
25
|
+
set :theme_settings, Owl::Lib::Theme.instance.settings
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
module Owl
|
|
3
|
+
|
|
4
|
+
module CMS
|
|
5
|
+
module Cache
|
|
6
|
+
extend Sinatra::Extension
|
|
7
|
+
|
|
8
|
+
CACHE_ROOT = "#{Dir.pwd}"
|
|
9
|
+
CACHE_PATH = ".cache"
|
|
10
|
+
CACHE_STORE = File.join(CACHE_ROOT, CACHE_PATH)
|
|
11
|
+
METASTORE_URI = "file:#{CACHE_STORE}"
|
|
12
|
+
ENTITYSTORE_URI = "file:#{CACHE_STORE}"
|
|
13
|
+
|
|
14
|
+
use Rack::Cache do
|
|
15
|
+
set :verbose, true
|
|
16
|
+
set :metastore, METASTORE_URI
|
|
17
|
+
set :entitystore, ENTITYSTORE_URI
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
use Rack::FunkyCache, :root => CACHE_ROOT, :path => CACHE_PATH
|
|
21
|
+
|
|
22
|
+
before do
|
|
23
|
+
|
|
24
|
+
if env['HTTP_PRAGMA'] != 'no-cache'
|
|
25
|
+
file = Owl::Lib::CachedFile.find(request)
|
|
26
|
+
if file
|
|
27
|
+
last_modified File.mtime(file)
|
|
28
|
+
send_file(file)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
data/owl-cms.gemspec
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
require 'bundler'
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |gem|
|
|
5
|
+
gem.name = 'owl-cms'
|
|
6
|
+
gem.version = '0.1.0'
|
|
7
|
+
gem.summary = 'A ruby CMS.'
|
|
8
|
+
|
|
9
|
+
gem.description = 'A ruby CMS...'
|
|
10
|
+
gem.authors = ["Brian Gonzalez"]
|
|
11
|
+
gem.email = 'me@briangonzalez.org'
|
|
12
|
+
gem.homepage = 'http://github.com/briangonzalez/owl-cms-gem'
|
|
13
|
+
gem.license = 'MIT'
|
|
14
|
+
|
|
15
|
+
gem.files = `git ls-files`.split($/)
|
|
16
|
+
gem.executables << 'owl'
|
|
17
|
+
|
|
18
|
+
# CLI
|
|
19
|
+
gem.add_dependency 'thor', '~> 0.18'
|
|
20
|
+
|
|
21
|
+
# From gemfile.
|
|
22
|
+
Bundler.definition.specs.each{ |r| gem.add_dependency r.name, r.version }
|
|
23
|
+
|
|
24
|
+
gem.required_ruby_version = '>= 1.9.3'
|
|
25
|
+
end
|
data/sample/.cabi-data
ADDED
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Home
|
|
3
|
+
publish: true
|
|
4
|
+
date: April 19, 1775
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
.posts
|
|
8
|
+
- posts.each do |p|
|
|
9
|
+
|
|
10
|
+
%article
|
|
11
|
+
/ The title
|
|
12
|
+
%h2= p.setting('title') || "Untitled"
|
|
13
|
+
|
|
14
|
+
/ The content
|
|
15
|
+
= truncate p.content, 100
|
|
16
|
+
|
|
17
|
+
%h4
|
|
18
|
+
%a{ href: p.path }= "Read more"
|
|
19
|
+
|
|
20
|
+
/ The date
|
|
21
|
+
%small= p.setting('date') || "No date given"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: About Us
|
|
3
|
+
layout: foo # this layout is missing (by design), will use default.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
%h1= @page.setting('title')
|
|
7
|
+
|
|
8
|
+
%p
|
|
9
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ullamcorper justo sem. Fusce ac sem est. Aenean dignissim feugiat auctor. Vestibulum in ante sem. Ut sit amet erat arcu, eget fringilla odio. Aenean a nibh est. Cras metus urna, vulputate non feugiat vel, condimentum sit amet purus.
|
|
10
|
+
|
|
11
|
+
%p
|
|
12
|
+
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec dictum egestas lorem. Vestibulum tempus, ante a adipiscing tempus, eros lectus mollis tellus, id viverra arcu purus vitae sapien. Suspendisse sed quam leo. Suspendisse volutpat nunc sit amet nulla venenatis ultrices. Quisque bibendum, purus pulvinar lacinia euismod, dolor tortor cursus enim, tempus porttitor magna neque in nibh. Quisque vel turpis sit amet mi semper venenatis in et arcu. Mauris mattis hendrerit turpis, tristique bibendum felis dictum et. Mauris elit turpis, suscipit eget sollicitudin id, congue sed erat. Mauris fringilla semper magna eget vulputate. Fusce ut ligula a velit ultricies condimentum at hendrerit lectus.
|
|
13
|
+
|
|
14
|
+
- puts "Test"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Contact Us
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
%h1= @page.setting('title')
|
|
6
|
+
|
|
7
|
+
%p
|
|
8
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ullamcorper justo sem. Fusce ac sem est. Aenean dignissim feugiat auctor. Vestibulum in ante sem. Ut sit amet erat arcu, eget fringilla odio. Aenean a nibh est. Cras metus urna, vulputate non feugiat vel, condimentum sit amet purus.
|
|
9
|
+
|
|
10
|
+
%p
|
|
11
|
+
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec dictum egestas lorem. Vestibulum tempus, ante a adipiscing tempus, eros lectus mollis tellus, id viverra arcu purus vitae sapien. Suspendisse sed quam leo. Suspendisse volutpat nunc sit amet nulla venenatis ultrices. Quisque bibendum, purus pulvinar lacinia euismod, dolor tortor cursus enim, tempus porttitor magna neque in nibh. Quisque vel turpis sit amet mi semper venenatis in et arcu. Mauris mattis hendrerit turpis, tristique bibendum felis dictum et. Mauris elit turpis, suscipit eget sollicitudin id, congue sed erat. Mauris fringilla semper magna eget vulputate. Fusce ut ligula a velit ultricies condimentum at hendrerit lectus.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
%h1 Contact Us
|
|
2
|
+
|
|
3
|
+
%p
|
|
4
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ullamcorper justo sem. Fusce ac sem est. Aenean dignissim feugiat auctor. Vestibulum in ante sem. Ut sit amet erat arcu, eget fringilla odio. Aenean a nibh est. Cras metus urna, vulputate non feugiat vel, condimentum sit amet purus.
|
|
5
|
+
|
|
6
|
+
%p
|
|
7
|
+
Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec dictum egestas lorem. Vestibulum tempus, ante a adipiscing tempus, eros lectus mollis tellus, id viverra arcu purus vitae sapien. Suspendisse sed quam leo. Suspendisse volutpat nunc sit amet nulla venenatis ultrices. Quisque bibendum, purus pulvinar lacinia euismod, dolor tortor cursus enim, tempus porttitor magna neque in nibh. Quisque vel turpis sit amet mi semper venenatis in et arcu. Mauris mattis hendrerit turpis, tristique bibendum felis dictum et. Mauris elit turpis, suscipit eget sollicitudin id, congue sed erat. Mauris fringilla semper magna eget vulputate. Fusce ut ligula a velit ultricies condimentum at hendrerit lectus.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Life
|
|
3
|
+
publish: true
|
|
4
|
+
layout: post
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
%p
|
|
8
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ullamcorper justo sem. Fusce ac sem est. Aenean dignissim feugiat auctor. Vestibulum in ante sem. Ut sit amet erat arcu, eget fringilla odio. Aenean a nibh est. Cras metus urna, vulputate non feugiat vel, condimentum sit amet purus.
|