strelka-cms 0.0.1.pre.15
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.
- data.tar.gz.sig +0 -0
- data/.gemtest +0 -0
- data/ChangeLog +33 -0
- data/History.rdoc +4 -0
- data/Manifest.txt +52 -0
- data/Procfile +4 -0
- data/README.rdoc +74 -0
- data/Rakefile +68 -0
- data/data/strelka-cms/apps/content-feeds +194 -0
- data/data/strelka-cms/apps/content-manager +159 -0
- data/data/strelka-cms/templates/autoindex/default.tmpl +11 -0
- data/data/strelka-cms/templates/layout.tmpl +58 -0
- data/data/strelka-cms/templates/page.tmpl +21 -0
- data/etc/mongrel.rb +34 -0
- data/lib/strelka/cms.rb +42 -0
- data/lib/strelka/cms/page.rb +322 -0
- data/lib/strelka/cms/pagecatalog.rb +121 -0
- data/lib/strelka/cms/pagefilter.rb +76 -0
- data/lib/strelka/cms/pagefilter/autoindex.rb +140 -0
- data/lib/strelka/cms/pagefilter/cleanup.rb +40 -0
- data/lib/strelka/cms/pagefilter/editorial.rb +55 -0
- data/lib/strelka/cms/pagefilter/example.rb +232 -0
- data/lib/strelka/cms/pagefilter/strip.rb +30 -0
- data/lib/strelka/cms/pagefilter/textile.rb +20 -0
- data/public/humans.txt +8 -0
- data/public/images/misc/button-gloss.png +0 -0
- data/public/images/misc/button-overlay.png +0 -0
- data/public/images/misc/custom-form-sprites.png +0 -0
- data/public/images/misc/input-bg-outset.png +0 -0
- data/public/images/misc/input-bg.png +0 -0
- data/public/images/misc/modal-gloss.png +0 -0
- data/public/images/misc/table-sorter.png +0 -0
- data/public/images/orbit/bullets.jpg +0 -0
- data/public/images/orbit/left-arrow.png +0 -0
- data/public/images/orbit/loading.gif +0 -0
- data/public/images/orbit/mask-black.png +0 -0
- data/public/images/orbit/pause-black.png +0 -0
- data/public/images/orbit/right-arrow.png +0 -0
- data/public/images/orbit/rotator-black.png +0 -0
- data/public/images/orbit/timer-black.png +0 -0
- data/public/index.page +46 -0
- data/public/javascripts/app.js +98 -0
- data/public/javascripts/foundation.js +12 -0
- data/public/javascripts/jquery.min.js +4 -0
- data/public/javascripts/modernizr.foundation.js +4 -0
- data/public/robots.txt +4 -0
- data/public/stylesheets/app.css +30 -0
- data/public/stylesheets/foundation.css +1424 -0
- data/public/stylesheets/ie.css +13 -0
- data/spec/data/test.page +22 -0
- data/spec/lib/helpers.rb +58 -0
- data/spec/strelka/cms/page_spec.rb +139 -0
- data/spec/strelka/cms/pagecatalog_spec.rb +94 -0
- data/spec/strelka/cms_spec.rb +27 -0
- metadata +346 -0
- metadata.gz.sig +0 -0
data.tar.gz.sig
ADDED
Binary file
|
data/.gemtest
ADDED
File without changes
|
data/ChangeLog
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
2012-06-29 Michael Granger <ged@FaerieMUD.org>
|
2
|
+
|
3
|
+
* .hgignore, .pryrc, .rvm.gems, .rvmrc, History.rdoc, Manifest.txt,
|
4
|
+
Procfile, README.rdoc, Rakefile, data/strelka-cms/apps/content-
|
5
|
+
feeds, data/strelka-cms/apps/content-manager, data/strelka-
|
6
|
+
cms/templates/autoindex/default.tmpl, data/strelka-
|
7
|
+
cms/templates/layout.tmpl, data/strelka-cms/templates/page.tmpl,
|
8
|
+
etc/config.yml, etc/mongrel.rb, lib/strelka/cms.rb,
|
9
|
+
lib/strelka/cms/page.rb, lib/strelka/cms/pagecatalog.rb,
|
10
|
+
lib/strelka/cms/pagefilter.rb,
|
11
|
+
lib/strelka/cms/pagefilter/autoindex.rb,
|
12
|
+
lib/strelka/cms/pagefilter/cleanup.rb,
|
13
|
+
lib/strelka/cms/pagefilter/editorial.rb,
|
14
|
+
lib/strelka/cms/pagefilter/example.rb,
|
15
|
+
lib/strelka/cms/pagefilter/strip.rb,
|
16
|
+
lib/strelka/cms/pagefilter/textile.rb, public/humans.txt,
|
17
|
+
public/images/misc/button-gloss.png, public/images/misc/button-
|
18
|
+
overlay.png, public/images/misc/custom-form-sprites.png,
|
19
|
+
public/images/misc/input-bg-outset.png, public/images/misc/input-
|
20
|
+
bg.png, public/images/misc/modal-gloss.png, public/images/misc
|
21
|
+
/table-sorter.png, public/images/orbit/bullets.jpg,
|
22
|
+
public/images/orbit/left-arrow.png, public/images/orbit/loading.gif,
|
23
|
+
public/images/orbit/mask-black.png, public/images/orbit/pause-
|
24
|
+
black.png, public/images/orbit/right-arrow.png, public/images/orbit
|
25
|
+
/rotator-black.png, public/images/orbit/timer-black.png,
|
26
|
+
public/index.page, public/javascripts/app.js,
|
27
|
+
public/javascripts/foundation.js, public/javascripts/jquery.min.js,
|
28
|
+
public/javascripts/modernizr.foundation.js, public/robots.txt,
|
29
|
+
public/stylesheets/app.css, public/stylesheets/foundation.css,
|
30
|
+
public/stylesheets/ie.css, spec/data/test.page, spec/lib/helpers.rb,
|
31
|
+
spec/strelka/cms/page_spec.rb, spec/strelka/cms_spec.rb:
|
32
|
+
Initial commit
|
33
|
+
[5f4c4eb6ef5b] [tip]
|
data/History.rdoc
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
ChangeLog
|
2
|
+
History.rdoc
|
3
|
+
Manifest.txt
|
4
|
+
Procfile
|
5
|
+
README.rdoc
|
6
|
+
Rakefile
|
7
|
+
data/strelka-cms/apps/content-feeds
|
8
|
+
data/strelka-cms/apps/content-manager
|
9
|
+
data/strelka-cms/templates/autoindex/default.tmpl
|
10
|
+
data/strelka-cms/templates/layout.tmpl
|
11
|
+
data/strelka-cms/templates/page.tmpl
|
12
|
+
etc/mongrel.rb
|
13
|
+
lib/strelka/cms.rb
|
14
|
+
lib/strelka/cms/page.rb
|
15
|
+
lib/strelka/cms/pagecatalog.rb
|
16
|
+
lib/strelka/cms/pagefilter.rb
|
17
|
+
lib/strelka/cms/pagefilter/autoindex.rb
|
18
|
+
lib/strelka/cms/pagefilter/cleanup.rb
|
19
|
+
lib/strelka/cms/pagefilter/editorial.rb
|
20
|
+
lib/strelka/cms/pagefilter/example.rb
|
21
|
+
lib/strelka/cms/pagefilter/strip.rb
|
22
|
+
lib/strelka/cms/pagefilter/textile.rb
|
23
|
+
public/humans.txt
|
24
|
+
public/images/misc/button-gloss.png
|
25
|
+
public/images/misc/button-overlay.png
|
26
|
+
public/images/misc/custom-form-sprites.png
|
27
|
+
public/images/misc/input-bg-outset.png
|
28
|
+
public/images/misc/input-bg.png
|
29
|
+
public/images/misc/modal-gloss.png
|
30
|
+
public/images/misc/table-sorter.png
|
31
|
+
public/images/orbit/bullets.jpg
|
32
|
+
public/images/orbit/left-arrow.png
|
33
|
+
public/images/orbit/loading.gif
|
34
|
+
public/images/orbit/mask-black.png
|
35
|
+
public/images/orbit/pause-black.png
|
36
|
+
public/images/orbit/right-arrow.png
|
37
|
+
public/images/orbit/rotator-black.png
|
38
|
+
public/images/orbit/timer-black.png
|
39
|
+
public/index.page
|
40
|
+
public/javascripts/app.js
|
41
|
+
public/javascripts/foundation.js
|
42
|
+
public/javascripts/jquery.min.js
|
43
|
+
public/javascripts/modernizr.foundation.js
|
44
|
+
public/robots.txt
|
45
|
+
public/stylesheets/app.css
|
46
|
+
public/stylesheets/foundation.css
|
47
|
+
public/stylesheets/ie.css
|
48
|
+
spec/data/test.page
|
49
|
+
spec/lib/helpers.rb
|
50
|
+
spec/strelka/cms/page_spec.rb
|
51
|
+
spec/strelka/cms/pagecatalog_spec.rb
|
52
|
+
spec/strelka/cms_spec.rb
|
data/Procfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
= Strelka CMS
|
2
|
+
|
3
|
+
home :: https://bitbucket.org/ged/strelka-cms
|
4
|
+
github :: https://github.com/ged/strelka-cms
|
5
|
+
docs :: http://deveiate.org/code/strelka-cms
|
6
|
+
|
7
|
+
|
8
|
+
== Description
|
9
|
+
|
10
|
+
This is a content-management application for Mongrel2 servers
|
11
|
+
written as a Strelka plugin.
|
12
|
+
|
13
|
+
|
14
|
+
== Prerequisites
|
15
|
+
|
16
|
+
* Strelka
|
17
|
+
* Ruby 1.9.3 or better
|
18
|
+
|
19
|
+
|
20
|
+
== Installation
|
21
|
+
|
22
|
+
$ gem install strelka-cms
|
23
|
+
$ strelka setup --config mongrel2.sqlite \
|
24
|
+
--server main \
|
25
|
+
--url /docs \
|
26
|
+
--append
|
27
|
+
strelka-cms content-manager
|
28
|
+
|
29
|
+
|
30
|
+
== Contributing
|
31
|
+
|
32
|
+
You can check out the current development source with Mercurial via its
|
33
|
+
{project page}[https://bitbucket.org/ged/strelka-cms]. Or if you prefer Git, via
|
34
|
+
{its Github mirror}[https://github.com/ged/strelka-cms].
|
35
|
+
|
36
|
+
After checking out the source, run:
|
37
|
+
|
38
|
+
$ rake newb
|
39
|
+
|
40
|
+
This task will install any missing dependencies, run the tests/specs,
|
41
|
+
and generate the API documentation.
|
42
|
+
|
43
|
+
|
44
|
+
== License
|
45
|
+
|
46
|
+
Copyright (c) 2012, Michael Granger
|
47
|
+
All rights reserved.
|
48
|
+
|
49
|
+
Redistribution and use in source and binary forms, with or without
|
50
|
+
modification, are permitted provided that the following conditions are met:
|
51
|
+
|
52
|
+
* Redistributions of source code must retain the above copyright notice,
|
53
|
+
this list of conditions and the following disclaimer.
|
54
|
+
|
55
|
+
* Redistributions in binary form must reproduce the above copyright notice,
|
56
|
+
this list of conditions and the following disclaimer in the documentation
|
57
|
+
and/or other materials provided with the distribution.
|
58
|
+
|
59
|
+
* Neither the name of the author/s, nor the names of the project's
|
60
|
+
contributors may be used to endorse or promote products derived from this
|
61
|
+
software without specific prior written permission.
|
62
|
+
|
63
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
64
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
65
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
66
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
67
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
68
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
69
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
70
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
71
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
72
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
73
|
+
|
74
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
|
3
|
+
require 'rake/clean'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'hoe'
|
7
|
+
rescue LoadError
|
8
|
+
abort "This Rakefile requires 'hoe' (gem install hoe)"
|
9
|
+
end
|
10
|
+
|
11
|
+
Hoe.plugin :mercurial
|
12
|
+
Hoe.plugin :signing
|
13
|
+
Hoe.plugin :manualgen
|
14
|
+
Hoe.plugin :deveiate
|
15
|
+
|
16
|
+
Hoe.plugins.delete :rubyforge
|
17
|
+
|
18
|
+
hoespec = Hoe.spec 'strelka-cms' do
|
19
|
+
self.readme_file = 'README.rdoc'
|
20
|
+
self.history_file = 'History.rdoc'
|
21
|
+
self.extra_rdoc_files = FileList[ '*.rdoc' ]
|
22
|
+
|
23
|
+
self.developer 'Michael Granger', 'ged@FaerieMUD.org'
|
24
|
+
|
25
|
+
self.dependency 'strelka', '~> 0.0'
|
26
|
+
self.dependency 'ratom', '~> 0.6'
|
27
|
+
self.dependency 'RedCloth', '~> 4.2'
|
28
|
+
self.dependency 'summarize', '~> 1.0'
|
29
|
+
self.dependency 'nokogiri', '~> 1.4'
|
30
|
+
self.dependency 'pluginfactory', '~> 1.0'
|
31
|
+
self.dependency 'tidy-ext', '~> 0.1'
|
32
|
+
self.dependency 'rcodetools', '~> 0.8'
|
33
|
+
|
34
|
+
self.dependency 'hoe-deveiate', '~> 0.1', :developer
|
35
|
+
|
36
|
+
self.spec_extras[:licenses] = ["BSD"]
|
37
|
+
self.spec_extras[:rdoc_options] = ['-f', 'fivefish', '-t', 'Strelka CMS']
|
38
|
+
self.require_ruby_version( '>=1.9.2' )
|
39
|
+
self.hg_sign_tags = true if self.respond_to?( :hg_sign_tags= )
|
40
|
+
self.check_history_on_release = true if self.respond_to?( :check_history_on_release= )
|
41
|
+
|
42
|
+
self.rdoc_locations << "deveiate:/usr/local/www/public/code/#{remote_rdoc_dir}"
|
43
|
+
end
|
44
|
+
|
45
|
+
ENV['VERSION'] ||= hoespec.spec.version.to_s
|
46
|
+
|
47
|
+
# Ensure the specs pass before checking in
|
48
|
+
task 'hg:precheckin' => [ :check_history, :check_manifest, :spec ]
|
49
|
+
|
50
|
+
|
51
|
+
desc "Build a coverage report"
|
52
|
+
task :coverage do
|
53
|
+
ENV["COVERAGE"] = 'yes'
|
54
|
+
Rake::Task[:spec].invoke
|
55
|
+
end
|
56
|
+
|
57
|
+
if Rake::Task.task_defined?( '.gemtest' )
|
58
|
+
Rake::Task['.gemtest'].clear
|
59
|
+
task '.gemtest' do
|
60
|
+
$stderr.puts "Not including a .gemtest until I'm confident the test suite is idempotent."
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Add admin app testing directories to the clobber list
|
66
|
+
CLOBBER.include( 'static', 'run', 'logs', 'strelka.sqlite' )
|
67
|
+
|
68
|
+
|
@@ -0,0 +1,194 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'rss/maker'
|
5
|
+
require 'atom'
|
6
|
+
require 'uuidtools'
|
7
|
+
require 'time'
|
8
|
+
require 'socket'
|
9
|
+
require 'configurability'
|
10
|
+
|
11
|
+
require 'strelka'
|
12
|
+
require 'strelka/mixins'
|
13
|
+
|
14
|
+
require 'strelka/cms'
|
15
|
+
require 'strelka/cms/pagecatalog'
|
16
|
+
require 'strelka/cms/page'
|
17
|
+
|
18
|
+
|
19
|
+
# The Feed applet -- generate RSS and Atom feeds for various things.
|
20
|
+
class Strelka::CMS::ContentFeeds < Strelka::App
|
21
|
+
extend Configurability,
|
22
|
+
Strelka::MethodUtilities
|
23
|
+
include UUIDTools
|
24
|
+
|
25
|
+
|
26
|
+
# Configurability API -- configure this app with the 'feeds' section of the
|
27
|
+
# config.
|
28
|
+
config_key :content_feeds
|
29
|
+
|
30
|
+
|
31
|
+
# Strelka app ID
|
32
|
+
ID = 'content-feeds'
|
33
|
+
|
34
|
+
# Configuration defaults
|
35
|
+
DEFAULT_CONFIG = {
|
36
|
+
uuid: UUID.sha1_create( UUID_DNS_NAMESPACE, Socket.gethostname ).to_s,
|
37
|
+
entry_count: 10,
|
38
|
+
pageroot: Pathname( __FILE__ ).dirname.parent.parent.parent + 'public',
|
39
|
+
paths: [''],
|
40
|
+
}
|
41
|
+
|
42
|
+
|
43
|
+
# The feed's site UUID (for Atom feeds)
|
44
|
+
singleton_attr_accessor :uuid
|
45
|
+
|
46
|
+
# The number of entries to include in a feed
|
47
|
+
singleton_attr_accessor :entry_count
|
48
|
+
|
49
|
+
# The page root
|
50
|
+
singleton_attr_accessor :pageroot
|
51
|
+
|
52
|
+
# The paths, relative to the pageroot, that can be served as a feed
|
53
|
+
singleton_attr_accessor :paths
|
54
|
+
|
55
|
+
|
56
|
+
### Configurability API -- configure the app.
|
57
|
+
def self::configure( config=nil )
|
58
|
+
if config
|
59
|
+
self.uuid = config[:uuid]
|
60
|
+
self.entry_count = config[:entry_count]
|
61
|
+
self.pageroot = config[:pageroot]
|
62
|
+
self.paths = config[:paths]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
### Set up the feeds app.
|
68
|
+
def initialize( * )
|
69
|
+
super
|
70
|
+
@catalog = Strelka::CMS::PageCatalog.new( self.class.pageroot )
|
71
|
+
@site_uuid = UUID.parse( self.class.uuid )
|
72
|
+
end
|
73
|
+
|
74
|
+
######
|
75
|
+
public
|
76
|
+
######
|
77
|
+
|
78
|
+
# The PageCatalog to use for building feeds
|
79
|
+
attr_reader :catalog
|
80
|
+
|
81
|
+
|
82
|
+
#
|
83
|
+
# Routing
|
84
|
+
#
|
85
|
+
plugin :routing
|
86
|
+
|
87
|
+
get 'rss' do |req|
|
88
|
+
feedpath = req.app_path[ %r{/rss/(.*)}, 1 ]
|
89
|
+
newest_pages = self.find_newest_pages( feedpath, req )
|
90
|
+
|
91
|
+
baseuri = req.uri
|
92
|
+
baseuri.path = ''
|
93
|
+
|
94
|
+
# Generate the feed out of the newest 10 pages
|
95
|
+
feed = RSS::Maker.make( '2.0' ) do |feed|
|
96
|
+
feed.channel.title = "DevEiate: %s" % [ feedpath.capitalize ]
|
97
|
+
feed.channel.link = "http://deveiate.org/#{feedpath}/"
|
98
|
+
feed.channel.description = "Making stuff up since 1994"
|
99
|
+
feed.items.do_sort = true # sort items by date
|
100
|
+
|
101
|
+
newest_pages.each do |page|
|
102
|
+
entry_url = baseuri.dup
|
103
|
+
entry_url.path = '/' + File.join( feedpath, page.relative_html_path )
|
104
|
+
|
105
|
+
item = feed.items.new_item
|
106
|
+
item.title = page.title
|
107
|
+
item.link = entry_url
|
108
|
+
item.date = page.date
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
res = req.response
|
113
|
+
|
114
|
+
# Set the cache header and set the mimetype
|
115
|
+
res.headers.last_modified = newest_pages.first.date.httpdate
|
116
|
+
res.content_type = 'application/rss+xml'
|
117
|
+
res.body = feed.to_s
|
118
|
+
|
119
|
+
return res
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
### Action: Return an ATOM feed for the pages under the path made up of +pathparts+.
|
124
|
+
get 'atom' do |req|
|
125
|
+
feedpath = req.app_path[ %r{/atom/(.*)}, 1 ]
|
126
|
+
newest_pages = self.find_newest_pages( feedpath, req )
|
127
|
+
newest_page = newest_pages.first
|
128
|
+
|
129
|
+
baseuri = req.uri
|
130
|
+
baseuri.path = ''
|
131
|
+
|
132
|
+
feed = Atom::Feed.new do |feed|
|
133
|
+
feed.title = "DevEiate: %s" % [ feedpath.capitalize ]
|
134
|
+
feed.links << Atom::Link.new( :href => baseuri )
|
135
|
+
feed.updated = newest_page.date
|
136
|
+
feed.authors << Atom::Person.new( :name => 'Michael Granger' )
|
137
|
+
feed.id = @site_uuid.to_uri
|
138
|
+
|
139
|
+
newest_pages.each do |page|
|
140
|
+
entry_url = baseuri.dup
|
141
|
+
entry_url.path = '/' + File.join( feedpath, page.relative_html_path )
|
142
|
+
|
143
|
+
feed.entries << Atom::Entry.new do |entry|
|
144
|
+
entry.title = page.title
|
145
|
+
entry.id = UUID.sha1_create( UUID_URL_NAMESPACE, entry_url.to_s ).to_uri
|
146
|
+
entry.updated = page.date
|
147
|
+
entry.summary = page.summary
|
148
|
+
|
149
|
+
entry.links << Atom::Link.new( :href => entry_url )
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
res = req.response
|
155
|
+
|
156
|
+
# Set the cache header and set the mimetype
|
157
|
+
res.headers.last_modified = newest_page.date.httpdate
|
158
|
+
res.content_type = 'application/atom+xml'
|
159
|
+
res.body = feed.to_xml
|
160
|
+
|
161
|
+
return res
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
#########
|
166
|
+
protected
|
167
|
+
#########
|
168
|
+
|
169
|
+
### Find the newest pages for the path of the +request+ and return them.
|
170
|
+
def find_newest_pages( feedpath, req )
|
171
|
+
self.log.debug "Looking for newest pages in feed path: %p" % [ feedpath ]
|
172
|
+
finish_with HTTP::NOT_FOUND unless self.class.paths.include?( feedpath )
|
173
|
+
feedpath.untaint
|
174
|
+
|
175
|
+
count = self.class.entry_count
|
176
|
+
newest_pages = self.catalog.relative_to( feedpath ).sort_by( &:date ).first( count )
|
177
|
+
newest_page = newest_pages.first
|
178
|
+
|
179
|
+
# Just 304 if the feed doesn't need to be updated
|
180
|
+
if req.headers.if_modified_since &&
|
181
|
+
Time.parse(req.headers.if_modified_since) > newest_page.date
|
182
|
+
|
183
|
+
self.log.info "Not modified since %s" % [ req.headers.if_modified_since ]
|
184
|
+
finish_with HTTP::NOT_MODIFIED, "No changes since %s" % [ req.headers.if_modified_since ]
|
185
|
+
end
|
186
|
+
|
187
|
+
return newest_pages
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
end # class Strelka::CMS::Feeds
|
192
|
+
|
193
|
+
Encoding.default_internal = Encoding::UTF_8
|
194
|
+
Strelka::CMS::Feeds.run if __FILE__ == $0
|
@@ -0,0 +1,159 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'loggability'
|
4
|
+
require 'pathname'
|
5
|
+
require 'redcloth'
|
6
|
+
require 'mail'
|
7
|
+
|
8
|
+
require 'strelka/app'
|
9
|
+
require 'strelka/mixins'
|
10
|
+
|
11
|
+
require 'strelka/cms'
|
12
|
+
|
13
|
+
|
14
|
+
class Strelka::CMS::ContentManager < Strelka::App
|
15
|
+
extend Loggability,
|
16
|
+
Configurability,
|
17
|
+
Strelka::MethodUtilities
|
18
|
+
|
19
|
+
# Loggability API -- log to Strelka::CMS's logger
|
20
|
+
log_to :strelka_cms
|
21
|
+
|
22
|
+
# Configurability API -- use values from the 'cms' section of the config
|
23
|
+
config_key :content_manager
|
24
|
+
|
25
|
+
|
26
|
+
# Strelka App ID
|
27
|
+
ID = 'content-manager'
|
28
|
+
|
29
|
+
# The default directory to scan for pages
|
30
|
+
DEFAULT_CONFIG = {
|
31
|
+
pageroot: Pathname( __FILE__ ).dirname.parent.parent.parent + 'public'
|
32
|
+
}
|
33
|
+
|
34
|
+
# Pattern for untainting the page path
|
35
|
+
PAGE_PATH_PATTERN = %r{
|
36
|
+
\A
|
37
|
+
(?<path>(?:
|
38
|
+
[\w\-/] # Allow word characters, slashes, and hyphens
|
39
|
+
)*)
|
40
|
+
(?:\.(?<suffix>html|page))? # optional suffix
|
41
|
+
\z
|
42
|
+
}x
|
43
|
+
|
44
|
+
|
45
|
+
##
|
46
|
+
# The configured catalog root
|
47
|
+
singleton_attr_accessor :pageroot
|
48
|
+
|
49
|
+
##
|
50
|
+
# The default content-type
|
51
|
+
default_type 'text/html'
|
52
|
+
|
53
|
+
|
54
|
+
# Strelka App setup
|
55
|
+
plugin :templating
|
56
|
+
layout 'layout.tmpl'
|
57
|
+
templates \
|
58
|
+
page: 'page.tmpl'
|
59
|
+
|
60
|
+
# Error-handler
|
61
|
+
plugin :fancyerrors
|
62
|
+
|
63
|
+
|
64
|
+
### Configurability API -- configure the CMS class once the config is loaded.
|
65
|
+
def self::configure( config=nil )
|
66
|
+
if config && config.member?( :pageroot )
|
67
|
+
self.log.debug "Config is: %p" % [ config ]
|
68
|
+
self.pageroot = Pathname( config.pageroot )
|
69
|
+
else
|
70
|
+
self.pageroot = DEFAULT_CONFIG[:pageroot]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
### Create a new instance of the CMS handler application.
|
76
|
+
def initialize( * )
|
77
|
+
super
|
78
|
+
@catalog = Strelka::CMS::PageCatalog.new( self.class.pageroot )
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
#
|
83
|
+
# Handler Routes
|
84
|
+
#
|
85
|
+
plugin :routing
|
86
|
+
|
87
|
+
# /
|
88
|
+
# -> /.page
|
89
|
+
# -> /index.page
|
90
|
+
|
91
|
+
# /foo/
|
92
|
+
# -> /foo.page
|
93
|
+
# -> /foo/index.page
|
94
|
+
|
95
|
+
# /foo/project
|
96
|
+
# -> /foo/project.page
|
97
|
+
# -> /foo/project/index.page
|
98
|
+
# -> /foo/project.html (literal)
|
99
|
+
# -> /foo/project/index.html (literal)
|
100
|
+
|
101
|
+
get do |request|
|
102
|
+
unless path = request.app_path[ PAGE_PATH_PATTERN, :path ]
|
103
|
+
self.log.error "Invalid app_path: %p" % [ request.app_path ]
|
104
|
+
finish_with HTTP::NOT_FOUND
|
105
|
+
end
|
106
|
+
|
107
|
+
# Force the path to be relative and clean it up
|
108
|
+
path = Pathname( path.gsub(%r{\A\.?/+|/(?=/)|/+\z}, '') )
|
109
|
+
page = nil
|
110
|
+
|
111
|
+
# Try to find a matching .page file
|
112
|
+
self.log.debug "Page path is: %p" % [ path ]
|
113
|
+
if path.to_s.empty?
|
114
|
+
subcat = @catalog.matching_pattern( 'index.page' )
|
115
|
+
page = subcat.first
|
116
|
+
else
|
117
|
+
subcat = @catalog.relative_to( path.dirname ).
|
118
|
+
matching_pattern( "#{path.basename(path.extname)}{.page,/index.page}" )
|
119
|
+
page = subcat.first
|
120
|
+
end
|
121
|
+
|
122
|
+
# If there was a matching .page file, use that
|
123
|
+
if page
|
124
|
+
self.log.debug " found page: %p" % [ page ]
|
125
|
+
return self.page_response( page )
|
126
|
+
end
|
127
|
+
|
128
|
+
# Try a literal HTML page
|
129
|
+
htmlpage = self.class.pageroot + path.sub_ext( '.html' )
|
130
|
+
if htmlpage.exist?
|
131
|
+
return self.raw_response( request, htmlpage )
|
132
|
+
end
|
133
|
+
|
134
|
+
# Give up
|
135
|
+
self.log.error "No pages matching %p" % [ path ]
|
136
|
+
finish_with HTTP::NOT_FOUND
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
### Package up the specified +page+ in the page template and return it.
|
141
|
+
def page_response( page )
|
142
|
+
tmpl = self.template( :page )
|
143
|
+
tmpl.page = page
|
144
|
+
return tmpl
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
### Package up the page at the specified +path+ in the response and return it.
|
149
|
+
def raw_response( request, pagepath )
|
150
|
+
response = request.response
|
151
|
+
response.body = pagepath.open( 'r', encoding: 'utf-8' )
|
152
|
+
return response
|
153
|
+
end
|
154
|
+
|
155
|
+
end # class Strelka::CMS::ContentManager
|
156
|
+
|
157
|
+
Encoding.default_internal = Encoding::UTF_8
|
158
|
+
Strelka::CMS::ContentManager.run if __FILE__ == $0
|
159
|
+
|