mars-nesta 0.9.4

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.
Files changed (61) hide show
  1. data/.gitignore +13 -0
  2. data/CHANGES +97 -0
  3. data/Gemfile +6 -0
  4. data/Gemfile.lock +44 -0
  5. data/LICENSE +19 -0
  6. data/README.md +42 -0
  7. data/Rakefile +12 -0
  8. data/bin/nesta +79 -0
  9. data/config.ru +9 -0
  10. data/config/deploy.rb.sample +62 -0
  11. data/lib/nesta/app.rb +167 -0
  12. data/lib/nesta/cache.rb +139 -0
  13. data/lib/nesta/commands.rb +188 -0
  14. data/lib/nesta/config.rb +86 -0
  15. data/lib/nesta/models.rb +364 -0
  16. data/lib/nesta/navigation.rb +60 -0
  17. data/lib/nesta/nesta.rb +7 -0
  18. data/lib/nesta/overrides.rb +59 -0
  19. data/lib/nesta/path.rb +11 -0
  20. data/lib/nesta/plugins.rb +15 -0
  21. data/lib/nesta/version.rb +3 -0
  22. data/nesta.gemspec +48 -0
  23. data/scripts/import-from-mephisto +207 -0
  24. data/spec/atom_spec.rb +138 -0
  25. data/spec/commands_spec.rb +292 -0
  26. data/spec/config_spec.rb +69 -0
  27. data/spec/model_factory.rb +94 -0
  28. data/spec/models_spec.rb +554 -0
  29. data/spec/overrides_spec.rb +114 -0
  30. data/spec/page_spec.rb +458 -0
  31. data/spec/path_spec.rb +28 -0
  32. data/spec/sitemap_spec.rb +102 -0
  33. data/spec/spec.opts +1 -0
  34. data/spec/spec_helper.rb +70 -0
  35. data/templates/Gemfile +8 -0
  36. data/templates/Rakefile +11 -0
  37. data/templates/config.ru +9 -0
  38. data/templates/config/config.yml +67 -0
  39. data/templates/config/deploy.rb +47 -0
  40. data/templates/index.haml +1 -0
  41. data/templates/themes/README.md +7 -0
  42. data/templates/themes/app.rb +19 -0
  43. data/views/analytics.haml +12 -0
  44. data/views/atom.haml +28 -0
  45. data/views/categories.haml +4 -0
  46. data/views/colors.sass +10 -0
  47. data/views/comments.haml +8 -0
  48. data/views/error.haml +12 -0
  49. data/views/feed.haml +3 -0
  50. data/views/footer.haml +5 -0
  51. data/views/header.haml +4 -0
  52. data/views/layout.haml +24 -0
  53. data/views/master.sass +246 -0
  54. data/views/mixins.sass +39 -0
  55. data/views/not_found.haml +12 -0
  56. data/views/page.haml +21 -0
  57. data/views/page_meta.haml +16 -0
  58. data/views/sidebar.haml +3 -0
  59. data/views/sitemap.haml +11 -0
  60. data/views/summaries.haml +15 -0
  61. metadata +235 -0
@@ -0,0 +1,292 @@
1
+ require File.expand_path("spec_helper", File.dirname(__FILE__))
2
+ require File.expand_path("../lib/nesta/commands", File.dirname(__FILE__))
3
+
4
+ describe "nesta" do
5
+ include FixtureHelper
6
+
7
+ before(:each) do
8
+ create_fixtures_directory
9
+ @project_path = File.join(FixtureHelper::FIXTURE_DIR, 'mysite.com')
10
+ end
11
+
12
+ after(:each) do
13
+ remove_fixtures
14
+ end
15
+
16
+ def project_path(path)
17
+ File.join(@project_path, path)
18
+ end
19
+
20
+ def should_exist(file)
21
+ File.exist?(project_path(file)).should be_true
22
+ end
23
+
24
+ def create_config_yaml(text)
25
+ File.open(Nesta::Config.yaml_path, 'w') { |f| f.puts(text) }
26
+ end
27
+
28
+ describe "new" do
29
+ def gemfile_source
30
+ File.read(project_path('Gemfile'))
31
+ end
32
+
33
+ def rakefile_source
34
+ File.read(project_path('Rakefile'))
35
+ end
36
+
37
+ describe "without options" do
38
+ before(:each) do
39
+ Nesta::Commands::New.new(@project_path).execute
40
+ end
41
+
42
+ it "should create the content directories" do
43
+ should_exist('content/attachments')
44
+ should_exist('content/pages')
45
+ end
46
+
47
+ it "should create the home page" do
48
+ should_exist('content/pages/index.haml')
49
+ end
50
+
51
+ it "should create the rackup file" do
52
+ should_exist('config.ru')
53
+ end
54
+
55
+ it "should create the config.yml file" do
56
+ should_exist('config/config.yml')
57
+ end
58
+
59
+ it "should add a Gemfile" do
60
+ should_exist('Gemfile')
61
+ gemfile_source.should match(/gem 'nesta', '#{Nesta::VERSION}'/)
62
+ end
63
+ end
64
+
65
+ describe "--git" do
66
+ before(:each) do
67
+ @command = Nesta::Commands::New.new(@project_path, 'git' => '')
68
+ @command.stub!(:system)
69
+ end
70
+
71
+ it "should create a .gitignore file" do
72
+ @command.execute
73
+ File.read(project_path('.gitignore')).should match(/\.bundle/)
74
+ end
75
+
76
+ it "should create a git repo" do
77
+ @command.should_receive(:system).with('git', 'init')
78
+ @command.execute
79
+ end
80
+
81
+ it "should commit the blank project" do
82
+ @command.should_receive(:system).with('git', 'add', '.')
83
+ @command.should_receive(:system).with(
84
+ 'git', 'commit', '-m', 'Initial commit')
85
+ @command.execute
86
+ end
87
+ end
88
+
89
+ describe "--vlad" do
90
+ before(:each) do
91
+ Nesta::Commands::New.new(@project_path, 'vlad' => '').execute
92
+ end
93
+
94
+ it "should add vlad to Gemfile" do
95
+ gemfile_source.should match(/gem 'vlad', '2.1.0'/)
96
+ gemfile_source.should match(/gem 'vlad-git', '2.2.0'/)
97
+ end
98
+
99
+ it "should configure the vlad rake tasks" do
100
+ should_exist('Rakefile')
101
+ rakefile_source.should match(/require 'vlad'/)
102
+ end
103
+
104
+ it "should create deploy.rb" do
105
+ should_exist('config/deploy.rb')
106
+ deploy_source = File.read(project_path('config/deploy.rb'))
107
+ deploy_source.should match(/set :application, 'mysite.com'/)
108
+ end
109
+ end
110
+ end
111
+
112
+ describe "demo:content" do
113
+ before(:each) do
114
+ @config_path = project_path('config/config.yml')
115
+ FileUtils.mkdir_p(File.dirname(@config_path))
116
+ Nesta::Config.stub!(:yaml_path).and_return(@config_path)
117
+ create_config_yaml('content: path/to/content')
118
+ Nesta::App.stub!(:root).and_return(@project_path)
119
+ @repo_url = 'git://github.com/gma/nesta-demo-content.git'
120
+ @demo_path = project_path('content-demo')
121
+ @command = Nesta::Commands::Demo::Content.new
122
+ @command.stub!(:system)
123
+ end
124
+
125
+ it "should clone the repository" do
126
+ @command.should_receive(:system).with(
127
+ 'git', 'clone', @repo_url, @demo_path)
128
+ @command.execute
129
+ end
130
+
131
+ it "should configure the content directory" do
132
+ @command.execute
133
+ File.read(@config_path).should match(/^content: content-demo/)
134
+ end
135
+
136
+ describe "when repository already exists" do
137
+ before(:each) do
138
+ FileUtils.mkdir_p(@demo_path)
139
+ end
140
+
141
+ it "should update the repository" do
142
+ @command.should_receive(:system).with('git', 'pull', 'origin', 'master')
143
+ @command.execute
144
+ end
145
+ end
146
+
147
+ describe "when site versioned with git" do
148
+ before(:each) do
149
+ @exclude_path = project_path('.git/info/exclude')
150
+ FileUtils.mkdir_p(File.dirname(@exclude_path))
151
+ File.open(@exclude_path, 'w') { |file| file.puts '# Excludes' }
152
+ end
153
+
154
+ it "should tell git to ignore content-demo" do
155
+ @command.execute
156
+ File.read(@exclude_path).should match(/content-demo/)
157
+ end
158
+
159
+ describe "and content-demo already ignored" do
160
+ before(:each) do
161
+ File.open(@exclude_path, 'w') { |file| file.puts 'content-demo' }
162
+ end
163
+
164
+ it "shouldn't tell git to ignore it twice" do
165
+ @command.execute
166
+ File.read(@exclude_path).scan('content-demo').size.should == 1
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+ describe "theme:install" do
173
+ before(:each) do
174
+ @repo_url = 'git://github.com/gma/nesta-theme-mine.git'
175
+ @theme_dir = 'themes/mine'
176
+ FileUtils.mkdir_p(File.join(@theme_dir, '.git'))
177
+ @command = Nesta::Commands::Theme::Install.new(@repo_url)
178
+ @command.stub!(:system)
179
+ end
180
+
181
+ after(:each) do
182
+ FileUtils.rm_r(@theme_dir)
183
+ end
184
+
185
+ it "should clone the repository" do
186
+ @command.should_receive(:system).with(
187
+ 'git', 'clone', @repo_url, @theme_dir)
188
+ @command.execute
189
+ end
190
+
191
+ it "should remove the theme's .git directory" do
192
+ @command.execute
193
+ File.exist?(@theme_dir).should be_true
194
+ File.exist?(File.join(@theme_dir, '.git')).should be_false
195
+ end
196
+
197
+ it "should enable the freshly installed theme" do
198
+ @command.should_receive(:enable).with('mine')
199
+ @command.execute
200
+ end
201
+
202
+ describe "when theme URL doesn't match recommendation" do
203
+ before(:each) do
204
+ @repo_url = 'git://foobar.com/path/to/mytheme.git'
205
+ @other_theme_dir = 'themes/mytheme'
206
+ FileUtils.mkdir_p(File.join(@other_theme_dir, '.git'))
207
+ @command = Nesta::Commands::Theme::Install.new(@repo_url)
208
+ end
209
+
210
+ after(:each) do
211
+ FileUtils.rm_r(@other_theme_dir)
212
+ end
213
+
214
+ it "should use the basename as theme dir" do
215
+ @command.should_receive(:system).with(
216
+ 'git', 'clone', @repo_url, @other_theme_dir)
217
+ @command.execute
218
+ end
219
+ end
220
+ end
221
+
222
+ describe "theme:enable" do
223
+ before(:each) do
224
+ config = File.join(FixtureHelper::FIXTURE_DIR, 'config.yml')
225
+ Nesta::Config.stub!(:yaml_path).and_return(config)
226
+ @name = 'mytheme'
227
+ @command = Nesta::Commands::Theme::Enable.new(@name)
228
+ end
229
+
230
+ shared_examples_for "command that configures the theme" do
231
+ it "should enable the theme" do
232
+ @command.execute
233
+ File.read(Nesta::Config.yaml_path).should match(/^theme: #{@name}/)
234
+ end
235
+ end
236
+
237
+ describe "when theme config is commented out" do
238
+ before(:each) do
239
+ create_config_yaml(' # theme: blah')
240
+ end
241
+
242
+ it_should_behave_like "command that configures the theme"
243
+ end
244
+
245
+ describe "when another theme is configured" do
246
+ before(:each) do
247
+ create_config_yaml('theme: another')
248
+ end
249
+
250
+ it_should_behave_like "command that configures the theme"
251
+ end
252
+
253
+ describe "when no theme config exists" do
254
+ before(:each) do
255
+ create_config_yaml('# I have no theme config')
256
+ end
257
+
258
+ it_should_behave_like "command that configures the theme"
259
+ end
260
+ end
261
+
262
+ describe "theme:create" do
263
+ def should_exist(file)
264
+ File.exist?(Nesta::Path.themes(@name, file)).should be_true
265
+ end
266
+
267
+ before(:each) do
268
+ Nesta::App.stub!(:root).and_return(FixtureHelper::FIXTURE_DIR)
269
+ @name = 'my-new-theme'
270
+ Nesta::Commands::Theme::Create.new(@name).execute
271
+ end
272
+
273
+ it "should create the theme directory" do
274
+ File.directory?(Nesta::Path.themes(@name)).should be_true
275
+ end
276
+
277
+ it "should create a dummy README file" do
278
+ should_exist('README.md')
279
+ text = File.read(Nesta::Path.themes(@name, 'README.md'))
280
+ text.should match(/#{@name} is a theme/)
281
+ end
282
+
283
+ it "should create a default app.rb file" do
284
+ should_exist('app.rb')
285
+ end
286
+
287
+ it "should create public and view directories" do
288
+ should_exist("public/#{@name}")
289
+ should_exist('views')
290
+ end
291
+ end
292
+ end
@@ -0,0 +1,69 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ describe "Config" do
4
+ include ConfigSpecHelper
5
+
6
+ after(:each) do
7
+ ENV.keys.each { |variable| ENV.delete(variable) if variable =~ /NESTA_/ }
8
+ end
9
+
10
+ describe "when settings defined in ENV" do
11
+ before(:each) do
12
+ @title = "Title from ENV"
13
+ ENV["NESTA_TITLE"] = @title
14
+ end
15
+
16
+ it "should never try and access config.yml" do
17
+ stub_config_key("subtitle", "Subtitle in YAML file")
18
+ Nesta::Config.subtitle.should be_nil
19
+ end
20
+
21
+ it "should override config.yml" do
22
+ stub_config_key("title", "Title in YAML file")
23
+ Nesta::Config.title.should == @title
24
+ end
25
+
26
+ it "should know how to cope with boolean values" do
27
+ ENV["NESTA_CACHE"] = "true"
28
+ Nesta::Config.cache.should be_true
29
+ ENV["NESTA_CACHE"] = "false"
30
+ Nesta::Config.cache.should be_false
31
+ end
32
+
33
+ it "should set author hash from ENV" do
34
+ name = "Name from ENV"
35
+ uri = "URI from ENV"
36
+ ENV["NESTA_AUTHOR__NAME"] = name
37
+ ENV["NESTA_AUTHOR__URI"] = uri
38
+ Nesta::Config.author["name"].should == name
39
+ Nesta::Config.author["uri"].should == uri
40
+ Nesta::Config.author["email"].should be_nil
41
+ end
42
+ end
43
+
44
+ describe "when settings only defined in config.yml" do
45
+ before(:each) do
46
+ @title = "Title in YAML file"
47
+ stub_config_key("subtitle", @title)
48
+ end
49
+
50
+ it "should read configuration from YAML" do
51
+ Nesta::Config.subtitle.should == @title
52
+ end
53
+
54
+ it "should set author hash from YAML" do
55
+ name = "Name from YAML"
56
+ uri = "URI from YAML"
57
+ stub_config_key("author", { "name" => name, "uri" => uri })
58
+ Nesta::Config.author["name"].should == name
59
+ Nesta::Config.author["uri"].should == uri
60
+ Nesta::Config.author["email"].should be_nil
61
+ end
62
+
63
+ it "should override top level settings with RACK_ENV specific settings" do
64
+ stub_config_key('content', 'general/path')
65
+ stub_config_key('content', 'rack_env/path', :rack_env => true)
66
+ Nesta::Config.content.should == 'rack_env/path'
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,94 @@
1
+ module ModelFactory
2
+ include FixtureHelper
3
+
4
+ def create_page(options)
5
+ extension = options[:ext] || :mdown
6
+ path = filename(Nesta::Config.page_path, options[:path], extension)
7
+ create_file(path, options)
8
+ yield(path) if block_given?
9
+ Nesta::Page.new(path)
10
+ end
11
+
12
+ def create_article(options = {}, &block)
13
+ o = {
14
+ :path => 'article-prefix/my-article',
15
+ :heading => 'My article',
16
+ :content => 'Content goes here',
17
+ :metadata => {
18
+ 'date' => '29 December 2008'
19
+ }.merge(options.delete(:metadata) || {})
20
+ }.merge(options)
21
+ create_page(o, &block)
22
+ end
23
+
24
+ def create_category(options = {}, &block)
25
+ o = {
26
+ :path => 'category-prefix/my-category',
27
+ :heading => 'My category',
28
+ :content => 'Content goes here'
29
+ }.merge(options)
30
+ create_page(o, &block)
31
+ end
32
+
33
+ def write_menu_item(indent, file, menu_item)
34
+ if menu_item.is_a?(Array)
35
+ indent.sub!(/^/, ' ')
36
+ menu_item.each { |path| write_menu_item(indent, file, path) }
37
+ indent.sub!(/^ /, '')
38
+ else
39
+ file.write("#{indent}#{menu_item}\n")
40
+ end
41
+ end
42
+
43
+ def create_menu(menu_text)
44
+ file = filename(Nesta::Config.content_path, 'menu', :txt)
45
+ File.open(file, 'w') { |file| file.write(menu_text) }
46
+ end
47
+
48
+ def delete_page(type, permalink, extension)
49
+ file = filename(Nesta::Config.page_path, permalink, extension)
50
+ FileUtils.rm(file)
51
+ end
52
+
53
+ def create_content_directories
54
+ FileUtils.mkdir_p(Nesta::Config.page_path)
55
+ FileUtils.mkdir_p(Nesta::Config.attachment_path)
56
+ end
57
+
58
+ def mock_file_stat(method, filename, time)
59
+ stat = mock(:stat)
60
+ stat.stub!(:mtime).and_return(Time.parse(time))
61
+ File.send(method, :stat).with(filename).and_return(stat)
62
+ end
63
+
64
+ private
65
+ def filename(directory, basename, extension = :mdown)
66
+ File.join(directory, "#{basename}.#{extension}")
67
+ end
68
+
69
+ def heading(options)
70
+ prefix = case options[:ext]
71
+ when :haml
72
+ "%div\n %h1"
73
+ when :textile
74
+ "<div>\nh1."
75
+ else
76
+ '# '
77
+ end
78
+ "#{prefix} #{options[:heading]}\n\n"
79
+ end
80
+
81
+ def create_file(path, options = {})
82
+ create_content_directories
83
+ metadata = options[:metadata] || {}
84
+ metatext = metadata.map { |key, value| "#{key}: #{value}" }.join("\n")
85
+ heading = options[:heading] ? heading(options) : ''
86
+ contents =<<-EOF
87
+ #{metatext}
88
+
89
+ #{heading}#{options[:content]}
90
+ EOF
91
+ FileUtils.mkdir_p(File.dirname(path))
92
+ File.open(path, 'w') { |file| file.write(contents) }
93
+ end
94
+ end