strelka-cms 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +95 -1
- data/History.rdoc +5 -0
- data/Manifest.txt +5 -3
- data/Rakefile +43 -9
- data/lib/strelka/apps.rb +12 -0
- data/lib/strelka/cms.rb +2 -2
- data/{data/strelka-cms/apps/content-feeds → lib/strelka/cms/feeds.rb} +1 -4
- data/lib/strelka/cms/page.rb +1 -0
- data/lib/strelka/cms/pagecatalog.rb +22 -4
- data/lib/strelka/cms/pagefilter.rb +0 -28
- data/lib/strelka/cms/pagefilter/autoindex.rb +37 -29
- data/{data/strelka-cms/apps/content-manager → lib/strelka/cms/publisher.rb} +50 -28
- data/spec/{lib/helpers.rb → helpers.rb} +5 -15
- data/spec/strelka/cms/page_spec.rb +18 -26
- data/spec/strelka/cms/pagecatalog_spec.rb +42 -26
- data/spec/strelka/cms/pagefilter/autoindex_spec.rb +83 -0
- data/spec/strelka/cms_spec.rb +5 -10
- metadata +122 -90
- metadata.gz.sig +1 -3
- data/.gemtest +0 -0
@@ -11,7 +11,7 @@ require 'strelka/mixins'
|
|
11
11
|
require 'strelka/cms'
|
12
12
|
|
13
13
|
|
14
|
-
class Strelka::CMS::
|
14
|
+
class Strelka::CMS::Publisher < Strelka::App
|
15
15
|
extend Loggability,
|
16
16
|
Configurability,
|
17
17
|
Strelka::MethodUtilities
|
@@ -81,11 +81,17 @@ class Strelka::CMS::ContentManager < Strelka::App
|
|
81
81
|
end
|
82
82
|
|
83
83
|
|
84
|
+
##
|
85
|
+
# The Strelka::CMS::PageCatalog for the page root.
|
86
|
+
attr_reader :catalog
|
87
|
+
|
88
|
+
|
84
89
|
#
|
85
90
|
# Handler Routes
|
86
91
|
#
|
87
92
|
plugin :routing
|
88
93
|
|
94
|
+
|
89
95
|
# /
|
90
96
|
# -> /.page
|
91
97
|
# -> /index.page
|
@@ -100,47 +106,66 @@ class Strelka::CMS::ContentManager < Strelka::App
|
|
100
106
|
# -> /foo/project.html (literal)
|
101
107
|
# -> /foo/project/index.html (literal)
|
102
108
|
|
109
|
+
### GET /.*
|
103
110
|
get do |request|
|
111
|
+
path = self.get_page_path( request )
|
112
|
+
|
113
|
+
# If there was a matching .page file, use that
|
114
|
+
if page = self.get_page_for( path )
|
115
|
+
self.log.debug " found page: %p" % [ page ]
|
116
|
+
return self.make_page_response( page )
|
117
|
+
|
118
|
+
# Try a literal HTML page
|
119
|
+
elsif htmlpage = self.get_html_path( path )
|
120
|
+
return self.make_raw_response( request, htmlpage )
|
121
|
+
|
122
|
+
else
|
123
|
+
# Give up
|
124
|
+
self.log.error "No pages matching %p" % [ path ]
|
125
|
+
finish_with HTTP::NOT_FOUND
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
### Return the page requested by the specified +request+ as a Pathname relative to the
|
131
|
+
### application path.
|
132
|
+
def get_page_path( request )
|
104
133
|
unless path = request.app_path[ PAGE_PATH_PATTERN, :path ]
|
105
134
|
self.log.error "Invalid app_path: %p" % [ request.app_path ]
|
106
135
|
finish_with HTTP::NOT_FOUND
|
107
136
|
end
|
108
137
|
|
109
138
|
# Force the path to be relative and clean it up
|
110
|
-
|
111
|
-
|
139
|
+
return Pathname( path.gsub(%r{\A\.?/+|/(?=/)|/+\z}, '') )
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
### Look for a static .html file in the catalog and return a Pathname for it if
|
144
|
+
### one exists.
|
145
|
+
def get_html_path( path )
|
146
|
+
path = self.class.pageroot + path.sub_ext( '.html' )
|
147
|
+
return path if path.exist?
|
148
|
+
return nil
|
149
|
+
end
|
150
|
+
|
112
151
|
|
113
|
-
|
152
|
+
### Find a page that corresponds to the specified +path+ (a Pathname). Returns +nil+ if
|
153
|
+
### no matching page was found.
|
154
|
+
def get_page_for( path )
|
114
155
|
self.log.debug "Page path is: %p" % [ path ]
|
115
156
|
if path.to_s.empty?
|
116
157
|
subcat = @catalog.matching_pattern( 'index.page' )
|
117
|
-
|
158
|
+
return subcat.first
|
118
159
|
else
|
119
160
|
subcat = @catalog.relative_to( path.dirname ).
|
120
161
|
matching_pattern( "#{path.basename(path.extname)}{.page,/index.page}" )
|
121
|
-
|
162
|
+
return subcat.first
|
122
163
|
end
|
123
|
-
|
124
|
-
# If there was a matching .page file, use that
|
125
|
-
if page
|
126
|
-
self.log.debug " found page: %p" % [ page ]
|
127
|
-
return self.page_response( page )
|
128
|
-
end
|
129
|
-
|
130
|
-
# Try a literal HTML page
|
131
|
-
htmlpage = self.class.pageroot + path.sub_ext( '.html' )
|
132
|
-
if htmlpage.exist?
|
133
|
-
return self.raw_response( request, htmlpage )
|
134
|
-
end
|
135
|
-
|
136
|
-
# Give up
|
137
|
-
self.log.error "No pages matching %p" % [ path ]
|
138
|
-
finish_with HTTP::NOT_FOUND
|
139
164
|
end
|
140
165
|
|
141
166
|
|
142
167
|
### Package up the specified +page+ in the page template and return it.
|
143
|
-
def
|
168
|
+
def make_page_response( page )
|
144
169
|
tmpl = self.template( :page )
|
145
170
|
tmpl.page = page
|
146
171
|
return tmpl
|
@@ -148,14 +173,11 @@ class Strelka::CMS::ContentManager < Strelka::App
|
|
148
173
|
|
149
174
|
|
150
175
|
### Package up the page at the specified +path+ in the response and return it.
|
151
|
-
def
|
176
|
+
def make_raw_response( request, pagepath )
|
152
177
|
response = request.response
|
153
178
|
response.body = pagepath.open( 'r', encoding: 'utf-8' )
|
154
179
|
return response
|
155
180
|
end
|
156
181
|
|
157
|
-
end # class Strelka::CMS::
|
158
|
-
|
159
|
-
Encoding.default_internal = Encoding::UTF_8
|
160
|
-
Strelka::CMS::ContentManager.run if __FILE__ == $0
|
182
|
+
end # class Strelka::CMS::Publisher
|
161
183
|
|
@@ -1,20 +1,6 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
# coding: utf-8
|
3
3
|
|
4
|
-
BEGIN {
|
5
|
-
require 'pathname'
|
6
|
-
basedir = Pathname.new( __FILE__ ).dirname.parent.parent
|
7
|
-
|
8
|
-
srcdir = basedir.parent
|
9
|
-
strelkadir = srcdir + 'Strelka/lib'
|
10
|
-
|
11
|
-
libdir = basedir + "lib"
|
12
|
-
|
13
|
-
$LOAD_PATH.unshift( strelkadir.to_s ) unless $LOAD_PATH.include?( strelkadir.to_s )
|
14
|
-
$LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
|
15
|
-
$LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
|
16
|
-
}
|
17
|
-
|
18
4
|
# SimpleCov test coverage reporting; enable this using the :coverage rake task
|
19
5
|
if ENV['COVERAGE']
|
20
6
|
$stderr.puts "\n\n>>> Enabling coverage report.\n\n"
|
@@ -38,6 +24,8 @@ require 'mongrel2/testing'
|
|
38
24
|
require 'strelka'
|
39
25
|
require 'strelka/cms'
|
40
26
|
|
27
|
+
require 'fakefs/spec_helpers'
|
28
|
+
|
41
29
|
|
42
30
|
### RSpec helper functions.
|
43
31
|
module Strelka::CMS::SpecHelpers
|
@@ -47,7 +35,9 @@ end
|
|
47
35
|
|
48
36
|
### Mock with RSpec
|
49
37
|
RSpec.configure do |c|
|
50
|
-
c.mock_with( :rspec )
|
38
|
+
c.mock_with( :rspec ) do |config|
|
39
|
+
config.syntax = :expect
|
40
|
+
end
|
51
41
|
|
52
42
|
c.include( Loggability::SpecHelpers )
|
53
43
|
c.include( Mongrel2::SpecHelpers )
|
@@ -2,21 +2,13 @@
|
|
2
2
|
# vim: set nosta noet ts=4 sw=4:
|
3
3
|
# encoding: utf-8
|
4
4
|
|
5
|
-
|
6
|
-
require 'pathname'
|
7
|
-
basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
|
8
|
-
$LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
|
9
|
-
}
|
5
|
+
require_relative '../../helpers'
|
10
6
|
|
11
7
|
require 'pathname'
|
12
8
|
require 'tmpdir'
|
13
9
|
require 'tempfile'
|
14
10
|
require 'stringio'
|
15
11
|
|
16
|
-
require 'rspec'
|
17
|
-
|
18
|
-
require 'spec/lib/helpers'
|
19
|
-
require 'strelka/cms'
|
20
12
|
require 'strelka/cms/page'
|
21
13
|
|
22
14
|
|
@@ -88,10 +80,10 @@ describe Strelka::CMS::Page do
|
|
88
80
|
|
89
81
|
page = described_class.load( tmp.path )
|
90
82
|
|
91
|
-
page.title.
|
92
|
-
page.tags.
|
93
|
-
page.content.
|
94
|
-
page.path.to_s.
|
83
|
+
expect( page.title ).to eq( 'Fun With TextMate 2' )
|
84
|
+
expect( page.tags ).to include( 'editors', 'software', 'tools', 'textmate2' )
|
85
|
+
expect( page.content ).to include( 'One of the things that kept me from switching' )
|
86
|
+
expect( page.path.to_s ).to eq( tmp.path )
|
95
87
|
end
|
96
88
|
|
97
89
|
it "can read a page from an IO stream" do
|
@@ -99,17 +91,17 @@ describe Strelka::CMS::Page do
|
|
99
91
|
|
100
92
|
page = described_class.read( io )
|
101
93
|
|
102
|
-
page.title.
|
103
|
-
page.tags.
|
104
|
-
page.content.
|
94
|
+
expect( page.title ).to eq( 'Fun With TextMate 2' )
|
95
|
+
expect( page.tags ).to include( 'editors', 'software', 'tools', 'textmate2' )
|
96
|
+
expect( page.content ).to include( 'One of the things that kept me from switching' )
|
105
97
|
end
|
106
98
|
|
107
99
|
it "can parse a page from source" do
|
108
100
|
page = described_class.parse( TEST_DOCUMENT )
|
109
101
|
|
110
|
-
page.title.
|
111
|
-
page.tags.
|
112
|
-
page.content.
|
102
|
+
expect( page.title ).to eq( 'Fun With TextMate 2' )
|
103
|
+
expect( page.tags ).to include( 'editors', 'software', 'tools', 'textmate2' )
|
104
|
+
expect( page.content ).to include( 'One of the things that kept me from switching' )
|
113
105
|
end
|
114
106
|
|
115
107
|
|
@@ -118,16 +110,16 @@ describe Strelka::CMS::Page do
|
|
118
110
|
let( :page ) { described_class.parse(TEST_DOCUMENT) }
|
119
111
|
|
120
112
|
it "can generate a summary of its contents" do
|
121
|
-
page.summary.
|
113
|
+
expect( page.summary ).to match( /^If you're using the WebKit formatter,/ )
|
122
114
|
end
|
123
115
|
|
124
116
|
it "can generate a list of topics from its content" do
|
125
|
-
page.summary_topics.
|
117
|
+
expect( page.summary_topics ).to include( "formatter", "rspec" )
|
126
118
|
end
|
127
119
|
|
128
120
|
it "can generate keywords if none are set by the header" do
|
129
121
|
page.instance_variable_set( :@tags, nil )
|
130
|
-
page.keywords.
|
122
|
+
expect( page.keywords ).to include( 'formatter', 'rspec', 'editor', 'textmate' )
|
131
123
|
end
|
132
124
|
|
133
125
|
end
|
@@ -140,15 +132,15 @@ describe Strelka::CMS::Page do
|
|
140
132
|
|
141
133
|
|
142
134
|
it "has a default set of filters" do
|
143
|
-
page.filters.
|
135
|
+
expect( page.filters ).to eq( %w[strip textile] )
|
144
136
|
end
|
145
137
|
|
146
138
|
it "returns its contents after applying filters when stringified" do
|
147
|
-
page.to_s.
|
139
|
+
expect( page.to_s ).to eq( %{<h1>Title</h1>\n<p>Some content.</p>} )
|
148
140
|
end
|
149
141
|
|
150
142
|
it "can return its first heading" do
|
151
|
-
page.first_heading.
|
143
|
+
expect( page.first_heading ).to eq( 'Title' )
|
152
144
|
end
|
153
145
|
|
154
146
|
end
|
@@ -177,7 +169,7 @@ describe Strelka::CMS::Page do
|
|
177
169
|
|
178
170
|
|
179
171
|
it "knows what its path relative to its catalog's base is" do
|
180
|
-
page.relative_path.
|
172
|
+
expect( page.relative_path ).to eq( relative_pagefile_pathname )
|
181
173
|
end
|
182
174
|
|
183
175
|
end
|
@@ -2,22 +2,8 @@
|
|
2
2
|
# vim: set nosta noet ts=4 sw=4:
|
3
3
|
# encoding: utf-8
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
basedir = Pathname.new( __FILE__ ).dirname.parent.parent.parent
|
8
|
-
$LOAD_PATH.unshift( basedir ) unless $LOAD_PATH.include?( basedir )
|
9
|
-
}
|
10
|
-
|
11
|
-
require 'pathname'
|
12
|
-
require 'tmpdir'
|
13
|
-
require 'tempfile'
|
14
|
-
require 'stringio'
|
15
|
-
|
16
|
-
require 'rspec'
|
17
|
-
|
18
|
-
require 'spec/lib/helpers'
|
19
|
-
require 'strelka/cms'
|
20
|
-
require 'strelka/cms/page'
|
5
|
+
require_relative '../../helpers'
|
6
|
+
|
21
7
|
require 'strelka/cms/pagecatalog'
|
22
8
|
|
23
9
|
|
@@ -26,10 +12,16 @@ require 'strelka/cms/pagecatalog'
|
|
26
12
|
#####################################################################
|
27
13
|
|
28
14
|
describe Strelka::CMS::PageCatalog do
|
15
|
+
include FakeFS::SpecHelpers
|
29
16
|
|
30
17
|
before( :all ) do
|
31
18
|
setup_logging()
|
32
|
-
|
19
|
+
end
|
20
|
+
|
21
|
+
before( :each ) do
|
22
|
+
FileUtils.mkdir_p( '/var/www/local/test' )
|
23
|
+
FileUtils.mkdir_p( '/var/www/local/lib' )
|
24
|
+
Dir.chdir( '/var/www/local' )
|
33
25
|
end
|
34
26
|
|
35
27
|
after( :all ) do
|
@@ -42,7 +34,27 @@ describe Strelka::CMS::PageCatalog do
|
|
42
34
|
subject { described_class.new }
|
43
35
|
|
44
36
|
it "has a glob pattern that matches .page files under the current directory" do
|
45
|
-
subject.glob.
|
37
|
+
expect( subject.glob ).to eq( "/var/www/local/**/*.page" )
|
38
|
+
end
|
39
|
+
|
40
|
+
it "can load page files by name" do
|
41
|
+
FileUtils.touch( '/var/www/local/test/index.page' )
|
42
|
+
|
43
|
+
page = subject['test/index']
|
44
|
+
|
45
|
+
expect( page ).to be_a( Strelka::CMS::Page )
|
46
|
+
expect( page.path.to_s ).to eq( '/var/www/local/test/index.page' )
|
47
|
+
expect( page.catalog ).to be( subject )
|
48
|
+
end
|
49
|
+
|
50
|
+
it "doesn't require the .page extension when loading page files by name" do
|
51
|
+
FileUtils.touch( '/var/www/local/test/index.page' )
|
52
|
+
|
53
|
+
page = subject['test/index']
|
54
|
+
|
55
|
+
expect( page ).to be_a( Strelka::CMS::Page )
|
56
|
+
expect( page.path.to_s ).to eq( '/var/www/local/test/index.page' )
|
57
|
+
expect( page.catalog ).to be( subject )
|
46
58
|
end
|
47
59
|
|
48
60
|
end
|
@@ -50,11 +62,11 @@ describe Strelka::CMS::PageCatalog do
|
|
50
62
|
|
51
63
|
context "created with a base directory" do
|
52
64
|
|
53
|
-
subject { described_class.new(
|
65
|
+
subject { described_class.new('/var/www') }
|
54
66
|
|
55
67
|
|
56
68
|
it "has a glob pattern that matches .page files under the directory it was created with" do
|
57
|
-
subject.glob.
|
69
|
+
expect( subject.glob ).to eq( "/var/www/**/*.page" )
|
58
70
|
end
|
59
71
|
|
60
72
|
end
|
@@ -62,28 +74,32 @@ describe Strelka::CMS::PageCatalog do
|
|
62
74
|
|
63
75
|
context "created with a base directory and a glob pattern" do
|
64
76
|
|
65
|
-
subject { described_class.new(
|
77
|
+
subject { described_class.new('/var/www/local', '**/*.rb') }
|
66
78
|
|
67
79
|
|
68
80
|
it "has a glob pattern that matches files that match the pattern under the directory it was " +
|
69
81
|
"created with" do
|
70
|
-
subject.glob.
|
82
|
+
expect( subject.glob ).to eq( "/var/www/local/**/*.rb" )
|
71
83
|
end
|
72
84
|
|
73
85
|
it "has a mutator that clones it for a subdirectory" do
|
74
|
-
subject.relative_to(
|
86
|
+
expect( subject.relative_to('lib').glob ).to eq( "/var/www/local/lib/**/*.rb" )
|
75
87
|
end
|
76
88
|
|
77
89
|
it "has a mutator that clones it for a different glob pattern" do
|
78
|
-
subject.matching_pattern(
|
90
|
+
expect( subject.matching_pattern('*.txt').glob ).to eq( "/var/www/local/*.txt" )
|
79
91
|
end
|
80
92
|
|
81
93
|
it "has an iterator that yields files that match its glob pattern" do
|
82
|
-
|
94
|
+
pending "Database rewrite"
|
95
|
+
FileUtils.touch( '/var/www/local/lib/payment.rb' )
|
96
|
+
|
97
|
+
expect( subject.relative_to('lib').map(&:path) ).
|
98
|
+
to include( Pathname('/var/www/local/lib/payment.rb') )
|
83
99
|
end
|
84
100
|
|
85
101
|
it "strips leading directory separators from relative paths" do
|
86
|
-
subject.relative_to( '/lib' ).glob.
|
102
|
+
expect( subject.relative_to( '/lib' ).glob ).to eq( "/var/www/local/lib/**/*.rb" )
|
87
103
|
end
|
88
104
|
|
89
105
|
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# encoding: utf-8
|
3
|
+
# vim: set nosta noet ts=4 sw=4:
|
4
|
+
|
5
|
+
require_relative '../../../helpers'
|
6
|
+
|
7
|
+
require 'tmpdir'
|
8
|
+
require 'strelka/cms'
|
9
|
+
require 'strelka/cms/pagefilter'
|
10
|
+
|
11
|
+
|
12
|
+
#####################################################################
|
13
|
+
### C O N T E X T S
|
14
|
+
#####################################################################
|
15
|
+
|
16
|
+
describe Strelka::CMS::PageFilter, 'AutoIndex' do
|
17
|
+
|
18
|
+
SIMPLE_TEST_SOURCE = (<<-END_PAGE_SOURCE).gsub( /^\t{2}/, '' ).freeze
|
19
|
+
<?autoindex /blog/*.page ?>
|
20
|
+
END_PAGE_SOURCE
|
21
|
+
|
22
|
+
before( :all ) do
|
23
|
+
# Need to load this before fakefs hides the filesystem
|
24
|
+
Inversion::Template::Tag.load_all
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
around( :each ) do |example|
|
29
|
+
Dir.mktmpdir( "autoindex_spec" ) do |dirname|
|
30
|
+
@tmpdir = dirname
|
31
|
+
example.call
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
it "is ignored when used from a page that isn't part of a catalog" do
|
38
|
+
filter = described_class.create( 'autoindex' )
|
39
|
+
|
40
|
+
page = Strelka::CMS::Page.parse( SIMPLE_TEST_SOURCE )
|
41
|
+
output = filter.process( SIMPLE_TEST_SOURCE, page )
|
42
|
+
|
43
|
+
expect( output ).to match( /<!-- autoindex skipped/i )
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
it "renders an index of the matched files in the page's catalog" do
|
48
|
+
pending "Database rewrite"
|
49
|
+
FileUtils.mkdir_p( "#@tmpdir/content/blog" )
|
50
|
+
FileUtils.mkdir_p( "#@tmpdir/templates/autoindex" )
|
51
|
+
|
52
|
+
FileUtils.touch( "#@tmpdir/content/blog/post1.page" )
|
53
|
+
FileUtils.touch( "#@tmpdir/content/blog/post2.page" )
|
54
|
+
FileUtils.touch( "#@tmpdir/content/blog/post3.page" )
|
55
|
+
|
56
|
+
File.open( "#@tmpdir/content/test.page", 'w' ) do |fh|
|
57
|
+
fh.print( SIMPLE_TEST_SOURCE )
|
58
|
+
end
|
59
|
+
|
60
|
+
File.open( "#@tmpdir/templates/autoindex/default.tmpl", 'w' ) do |fh|
|
61
|
+
fh.puts "<?for page in pages ?>"
|
62
|
+
fh.puts "-<?call page.relative_html_path ?>-"
|
63
|
+
fh.puts "<?end for ?>"
|
64
|
+
end
|
65
|
+
|
66
|
+
Inversion::Template.template_paths.replace( ["#@tmpdir/templates"] )
|
67
|
+
|
68
|
+
catalog = Strelka::CMS::PageCatalog.new( "#@tmpdir/content", '**/*.page' )
|
69
|
+
page = catalog.find {|page| page.relative_path.to_s == 'test.page' } or
|
70
|
+
raise "didn't find test.page in catalog %p" % [ catalog ]
|
71
|
+
|
72
|
+
filter = described_class.create( 'autoindex' )
|
73
|
+
output = filter.process( SIMPLE_TEST_SOURCE, page )
|
74
|
+
|
75
|
+
expect( output ).to match( /post1\.html/ )
|
76
|
+
expect( output ).to match( /post2\.html/ )
|
77
|
+
expect( output ).to match( /post3\.html/ )
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
end
|
83
|
+
|