strelka-cms 0.2.0 → 0.3.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 +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
|
+
|