nesta 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +13 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +58 -0
- data/LICENSE +19 -0
- data/README.md +45 -0
- data/Rakefile +12 -0
- data/bin/nesta +67 -0
- data/config.ru +9 -0
- data/config/config.yml.sample +73 -0
- data/config/deploy.rb.sample +62 -0
- data/lib/nesta/app.rb +199 -0
- data/lib/nesta/cache.rb +139 -0
- data/lib/nesta/commands.rb +135 -0
- data/lib/nesta/config.rb +87 -0
- data/lib/nesta/models.rb +313 -0
- data/lib/nesta/nesta.rb +0 -0
- data/lib/nesta/overrides.rb +59 -0
- data/lib/nesta/path.rb +11 -0
- data/lib/nesta/plugins.rb +15 -0
- data/lib/nesta/version.rb +3 -0
- data/nesta.gemspec +49 -0
- data/scripts/import-from-mephisto +207 -0
- data/spec/atom_spec.rb +138 -0
- data/spec/commands_spec.rb +220 -0
- data/spec/config_spec.rb +69 -0
- data/spec/model_factory.rb +94 -0
- data/spec/models_spec.rb +445 -0
- data/spec/overrides_spec.rb +113 -0
- data/spec/page_spec.rb +428 -0
- data/spec/path_spec.rb +28 -0
- data/spec/sitemap_spec.rb +102 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +72 -0
- data/templates/Gemfile +8 -0
- data/templates/Rakefile +35 -0
- data/templates/config.ru +9 -0
- data/templates/config/config.yml +73 -0
- data/templates/config/deploy.rb +47 -0
- data/views/analytics.haml +12 -0
- data/views/atom.builder +28 -0
- data/views/categories.haml +3 -0
- data/views/comments.haml +8 -0
- data/views/error.haml +13 -0
- data/views/feed.haml +3 -0
- data/views/index.haml +5 -0
- data/views/layout.haml +27 -0
- data/views/master.sass +246 -0
- data/views/not_found.haml +13 -0
- data/views/page.haml +29 -0
- data/views/sidebar.haml +3 -0
- data/views/sitemap.builder +15 -0
- data/views/summaries.haml +14 -0
- metadata +302 -0
data/spec/path_spec.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
|
3
|
+
describe 'Nesta::Path' do
|
4
|
+
before(:each) do
|
5
|
+
@root = File.expand_path('..', File.dirname(__FILE__))
|
6
|
+
@local_foo_bar = File.join(@root, 'foo/bar')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should return local path' do
|
10
|
+
Nesta::Path.local.should == @root
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should return path for file within local directory' do
|
14
|
+
Nesta::Path.local('foo/bar').should == @local_foo_bar
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should combine path components' do
|
18
|
+
Nesta::Path.local('foo', 'bar').should == @local_foo_bar
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should return themes path' do
|
22
|
+
Nesta::Path.themes.should == File.expand_path('themes', @root)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should return path for file within themes directory' do
|
26
|
+
Nesta::Path.themes('foo/bar').should == File.join(@root, 'themes/foo/bar')
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require File.expand_path('spec_helper', File.dirname(__FILE__))
|
2
|
+
require File.expand_path('model_factory', File.dirname(__FILE__))
|
3
|
+
|
4
|
+
describe "sitemap XML" do
|
5
|
+
include ConfigSpecHelper
|
6
|
+
include RequestSpecHelper
|
7
|
+
include ModelFactory
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
stub_configuration
|
11
|
+
@category = create_category do |path|
|
12
|
+
mock_file_stat(:stub!, path, "3 Jan 2009, 15:07")
|
13
|
+
end
|
14
|
+
@article = create_article do |path|
|
15
|
+
mock_file_stat(:stub!, path, "3 Jan 2009, 15:10")
|
16
|
+
end
|
17
|
+
get "/sitemap.xml"
|
18
|
+
end
|
19
|
+
|
20
|
+
after(:each) do
|
21
|
+
Nesta::FileModel.purge_cache
|
22
|
+
remove_fixtures
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should render successfully" do
|
26
|
+
last_response.should be_ok
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should have a urlset tag" do
|
30
|
+
namespace = "http://www.sitemaps.org/schemas/sitemap/0.9"
|
31
|
+
body.should have_tag("/urlset[@xmlns=#{namespace}]")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should reference the home page" do
|
35
|
+
body.should have_tag("/urlset/url/loc", "http://example.org")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should configure home page to be checked frequently" do
|
39
|
+
body.should have_tag("/urlset/url") do |url|
|
40
|
+
url.should have_tag("loc", "http://example.org")
|
41
|
+
url.should have_tag("changefreq", "daily")
|
42
|
+
url.should have_tag("priority", "1.0")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should set the homepage lastmod from latest article" do
|
47
|
+
body.should have_tag("/urlset/url") do |url|
|
48
|
+
url.should have_tag("loc", "http://example.org")
|
49
|
+
url.should have_tag("lastmod", /^2009-01-03T15:10:00/)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should reference category pages" do
|
54
|
+
body.should have_tag(
|
55
|
+
"/urlset/url/loc", "http://example.org/#{@category.path}")
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should reference article pages" do
|
59
|
+
body.should have_tag(
|
60
|
+
"/urlset/url/loc", "http://example.org/#{@article.path}")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "sitemap XML lastmod" do
|
65
|
+
include ConfigSpecHelper
|
66
|
+
include ModelFactory
|
67
|
+
include RequestSpecHelper
|
68
|
+
|
69
|
+
before(:each) do
|
70
|
+
stub_configuration
|
71
|
+
end
|
72
|
+
|
73
|
+
after(:each) do
|
74
|
+
remove_fixtures
|
75
|
+
Nesta::FileModel.purge_cache
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should be set for file based page" do
|
79
|
+
create_article do |path|
|
80
|
+
mock_file_stat(:stub!, path, "3 January 2009, 15:37:01")
|
81
|
+
end
|
82
|
+
get "/sitemap.xml"
|
83
|
+
body.should have_tag("url") do |url|
|
84
|
+
url.should have_tag("loc", /my-article$/)
|
85
|
+
url.should have_tag("lastmod", /^2009-01-03T15:37:01/)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should be set to latest page for home page" do
|
90
|
+
create_article(:path => "article-1") do |path|
|
91
|
+
mock_file_stat(:stub!, path, "4 January 2009")
|
92
|
+
end
|
93
|
+
create_article(:path => "article-2") do |path|
|
94
|
+
mock_file_stat(:stub!, path, "3 January 2009")
|
95
|
+
end
|
96
|
+
get "/sitemap.xml"
|
97
|
+
body.should have_tag("url") do |url|
|
98
|
+
url.should have_tag("loc", "http://example.org")
|
99
|
+
url.should have_tag("lastmod", /^2009-01-04/)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "spec"
|
3
|
+
require "spec/interop/test"
|
4
|
+
require "rack/test"
|
5
|
+
require "rspec_hpricot_matchers"
|
6
|
+
require "sinatra"
|
7
|
+
|
8
|
+
Test::Unit::TestCase.send :include, Rack::Test::Methods
|
9
|
+
|
10
|
+
Spec::Runner.configure do |config|
|
11
|
+
config.include(RspecHpricotMatchers)
|
12
|
+
end
|
13
|
+
|
14
|
+
module Nesta
|
15
|
+
class App < Sinatra::Base
|
16
|
+
set :environment, :test
|
17
|
+
set :reload_templates, true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
require File.expand_path("../lib/nesta/app", File.dirname(__FILE__))
|
22
|
+
|
23
|
+
module FixtureHelper
|
24
|
+
FIXTURE_DIR = File.expand_path("fixtures", File.dirname(__FILE__))
|
25
|
+
|
26
|
+
def create_fixtures_directory
|
27
|
+
FileUtils.mkdir_p(FixtureHelper::FIXTURE_DIR)
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove_fixtures
|
31
|
+
FileUtils.rm_r(FixtureHelper::FIXTURE_DIR, :force => true)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module RequestSpecHelper
|
36
|
+
def app
|
37
|
+
Nesta::App
|
38
|
+
end
|
39
|
+
|
40
|
+
def body
|
41
|
+
last_response.body
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module ConfigSpecHelper
|
46
|
+
include FixtureHelper
|
47
|
+
|
48
|
+
def stub_yaml_config
|
49
|
+
@config = {}
|
50
|
+
Nesta::Config.stub!(:yaml_exists?).and_return(true)
|
51
|
+
Nesta::Config.stub!(:yaml_conf).and_return(@config)
|
52
|
+
end
|
53
|
+
|
54
|
+
def stub_config_key(key, value, options = {})
|
55
|
+
stub_yaml_config unless @config
|
56
|
+
if options[:rack_env]
|
57
|
+
@config['test'] ||= {}
|
58
|
+
@config['test'][key] = value
|
59
|
+
else
|
60
|
+
@config[key] = value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def stub_configuration(options = {})
|
65
|
+
stub_config_key("title", "My blog", options)
|
66
|
+
stub_config_key("subtitle", "about stuff", options)
|
67
|
+
stub_config_key("description", "great web site", options)
|
68
|
+
stub_config_key("keywords", "home, page", options)
|
69
|
+
content_path = File.join(FixtureHelper::FIXTURE_DIR, "content")
|
70
|
+
stub_config_key("content", content_path, options.merge(:rack_env => true))
|
71
|
+
end
|
72
|
+
end
|
data/templates/Gemfile
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
|
3
|
+
gem 'nesta', '<%= Nesta::VERSION %>'
|
4
|
+
<% if @options['heroku'] %>gem 'heroku'<% end %>
|
5
|
+
<% if @options['vlad'] %>gem 'vlad', '2.1.0'
|
6
|
+
gem 'vlad-git', '2.2.0'<% end %>
|
7
|
+
|
8
|
+
# gem (RUBY_VERSION =~ /^1.9/) ? 'ruby-debug19': 'ruby-debug'
|
data/templates/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
|
4
|
+
Bundler.require(:default, :test)
|
5
|
+
<% if @options['vlad'] %>
|
6
|
+
begin
|
7
|
+
require 'vlad'
|
8
|
+
# Set :app to :passenger if you're using Phusion Passenger.
|
9
|
+
Vlad.load(:scm => :git, :app => nil, :web => nil)
|
10
|
+
rescue LoadError
|
11
|
+
end<% end %>
|
12
|
+
<% if @options['heroku'] %>
|
13
|
+
require 'nesta/config'
|
14
|
+
require 'nesta/models'
|
15
|
+
|
16
|
+
namespace :heroku do
|
17
|
+
desc "Set Heroku config vars from config.yml"
|
18
|
+
task :config do
|
19
|
+
Nesta::App.environment = ENV['RACK_ENV'] || 'production'
|
20
|
+
settings = {}
|
21
|
+
Nesta::Config.settings.map do |variable|
|
22
|
+
value = Nesta::Config.send(variable)
|
23
|
+
value && settings["NESTA_#{variable.upcase}"] = value
|
24
|
+
end
|
25
|
+
if Nesta::Config.author
|
26
|
+
Nesta::Config.author_settings.map do |author_var|
|
27
|
+
value = Nesta::Config.author[author_var]
|
28
|
+
if value
|
29
|
+
value && settings["NESTA_AUTHOR__#{author_var.upcase}"] = value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
params = settings.map { |k, v| %Q{#{k}="#{v}"} }.join(" ")
|
33
|
+
system("heroku config:add #{params}")
|
34
|
+
end
|
35
|
+
end<% end %>
|
data/templates/config.ru
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# Title and subheading for your site. Used on the home page and in page
|
2
|
+
# titles.
|
3
|
+
#
|
4
|
+
title: "My Site"
|
5
|
+
subtitle: "(change this text in config/config.yml)"
|
6
|
+
|
7
|
+
# If you want to set the descrition or keywords meta tags on your site's
|
8
|
+
# home page, do it here.
|
9
|
+
#
|
10
|
+
# description: "Set this to something that describes your home page"
|
11
|
+
# keywords: "enter 3 or 4, comma separated, keywords"
|
12
|
+
|
13
|
+
# You should really specify your content's author when generating an
|
14
|
+
# Atom feed. Specify at least one of name, uri or email, and Nesta will
|
15
|
+
# include it in your feed. See the Atom spec for more info:
|
16
|
+
#
|
17
|
+
# http://www.atomenabled.org/developers/syndication/atom-format-spec.php#element.feed
|
18
|
+
#
|
19
|
+
# author:
|
20
|
+
# name: Your Name
|
21
|
+
# uri: http://yourhomepage.com
|
22
|
+
# email: you@yourdomain.com
|
23
|
+
|
24
|
+
# You can stick with the default look and feel, or use a theme. Themes are
|
25
|
+
# easy to create or install, and live inside the themes directory. You
|
26
|
+
# can also use scripts/theme to install them.
|
27
|
+
#
|
28
|
+
# theme: name-of-theme
|
29
|
+
|
30
|
+
# If you want to use the Disqus service (http://disqus.com) to display
|
31
|
+
# comments on your site, register a Disqus account and then specify your
|
32
|
+
# site's short name here. A comment form will automatically be added to
|
33
|
+
# the bottom of your pages.
|
34
|
+
#
|
35
|
+
# disqus_short_name: mysite
|
36
|
+
|
37
|
+
# cache
|
38
|
+
# Set it to true if you'd like Nesta to cache your pages in ./public.
|
39
|
+
# Useful if you're deploying Nesta with a proxy server such as Nginx,
|
40
|
+
# but not in the least bit helpful if your pages are dynamic, or you're
|
41
|
+
# deploying Nesta to Heroku.
|
42
|
+
#
|
43
|
+
cache: false
|
44
|
+
|
45
|
+
# content
|
46
|
+
# The root directory where nesta will look for your article files.
|
47
|
+
# Should contain "pages" and "attachments" subdirectories that contain
|
48
|
+
# your actual content and the (optional) menu.txt file that links to your
|
49
|
+
# main category pages.
|
50
|
+
#
|
51
|
+
content: content
|
52
|
+
|
53
|
+
# google_analytics_code
|
54
|
+
# Set this if you want Google Analytics to track traffic on your site.
|
55
|
+
# Probably best not to set a default value, but to set it in production.
|
56
|
+
#
|
57
|
+
# The production settings are used if you're deploying to Heroku, so
|
58
|
+
# scroll down a bit to set it in production even if you're not deploying
|
59
|
+
# to your own server.
|
60
|
+
#
|
61
|
+
# google_analytics_code: "UA-???????-?"
|
62
|
+
|
63
|
+
# Overriding "cache" and "content" in production is recommended if you're
|
64
|
+
# deploying Nesta to your own server (but see the deployment documentation
|
65
|
+
# on the Nesta site). Setting google_analytics_code in production is
|
66
|
+
# recommended regardless of how you're deploying (if you have a GA account!).
|
67
|
+
#
|
68
|
+
# Don't forget to uncomment the "production:" line too...
|
69
|
+
|
70
|
+
# production:
|
71
|
+
# cache: true
|
72
|
+
# content: /var/apps/nesta/shared/content
|
73
|
+
# google_analytics_code: "UA-???????-?"
|
@@ -0,0 +1,47 @@
|
|
1
|
+
set :application, '<%= File.basename(@path) %>'
|
2
|
+
set :repository, "set this to URL of your site's repo"
|
3
|
+
|
4
|
+
# Set :user if you want to connect (via ssh) to your server using a
|
5
|
+
# different username. You will also need to include the user in :domain
|
6
|
+
# (see below).
|
7
|
+
#
|
8
|
+
#set :user, "deploy"
|
9
|
+
#set :domain, "#{user}@example.com"
|
10
|
+
set :domain, "example.com"
|
11
|
+
|
12
|
+
set :deploy_to, "/var/apps/#{application}"
|
13
|
+
|
14
|
+
# ============================================================================
|
15
|
+
# You probably don't need to worry about anything beneath this point...
|
16
|
+
# ============================================================================
|
17
|
+
|
18
|
+
require "tempfile"
|
19
|
+
require "vlad"
|
20
|
+
|
21
|
+
namespace :vlad do
|
22
|
+
remote_task :symlink_attachments do
|
23
|
+
run "ln -s #{shared_path}/content/attachments #{current_path}/public/attachments"
|
24
|
+
end
|
25
|
+
|
26
|
+
task :update do
|
27
|
+
Rake::Task["vlad:symlink_attachments"].invoke
|
28
|
+
end
|
29
|
+
|
30
|
+
remote_task :bundle do
|
31
|
+
run "cd #{current_path} && sudo bundle install --without development test"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Depending on how you host Nesta, you might want to swap :start_app
|
35
|
+
# with :start below. The :start_app task will tell your application
|
36
|
+
# server (e.g. Passenger) to restart once your new code is deployed by
|
37
|
+
# :update. Passenger is the default app server; tell Vlad that you're
|
38
|
+
# using a different app server in the call to Vlad.load in Rakefile.
|
39
|
+
#
|
40
|
+
desc "Deploy the code and restart the server"
|
41
|
+
task :deploy => [:update, :start_app]
|
42
|
+
|
43
|
+
# If you use bundler to manage the installation of gems on your server
|
44
|
+
# you can use this definition of the deploy task instead:
|
45
|
+
#
|
46
|
+
# task :deploy => [:update, :bundle, :start_app]
|
47
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
- if @google_analytics_code
|
2
|
+
:plain
|
3
|
+
<script type="text/javascript">
|
4
|
+
var _gaq = _gaq || [];
|
5
|
+
_gaq.push(['_setAccount', '#{@google_analytics_code}']);
|
6
|
+
_gaq.push(['_trackPageview']);
|
7
|
+
(function() {
|
8
|
+
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
9
|
+
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
10
|
+
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
11
|
+
})();
|
12
|
+
</script>
|
data/views/atom.builder
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
xml.instruct!
|
2
|
+
xml.feed :xmlns => "http://www.w3.org/2005/Atom" do
|
3
|
+
xml.title @title, :type => "text"
|
4
|
+
xml.generator "Nesta", :uri => "http://effectif.com/nesta"
|
5
|
+
xml.id atom_id
|
6
|
+
xml.link :href => "#{base_url}/articles.xml", :rel => "self"
|
7
|
+
xml.link :href => base_url, :rel => "alternate"
|
8
|
+
xml.subtitle @subtitle, :type => "text"
|
9
|
+
xml.author do
|
10
|
+
xml.name @author["name"] if @author["name"]
|
11
|
+
xml.uri @author["uri"] if @author["uri"]
|
12
|
+
xml.email @author["email"] if @author["email"]
|
13
|
+
end if @author
|
14
|
+
@articles.each do |article|
|
15
|
+
xml.entry do
|
16
|
+
xml.title article.heading
|
17
|
+
xml.link :href => url_for(article),
|
18
|
+
:type => "text/html",
|
19
|
+
:rel => "alternate"
|
20
|
+
xml.id atom_id(article)
|
21
|
+
xml.content absolute_urls(article.body), :type => "html"
|
22
|
+
xml.published article.date(:xmlschema)
|
23
|
+
article.categories.each do |category|
|
24
|
+
xml.category :term => category.permalink
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/views/comments.haml
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
- if short_name = Nesta::Config.disqus_short_name
|
2
|
+
#disqus_thread
|
3
|
+
- if Sinatra::Application.environment == :development
|
4
|
+
%script{ :type => "text/javascript" }
|
5
|
+
var disqus_developer = true;
|
6
|
+
%script{ :type => "text/javascript", :src => "http://disqus.com/forums/#{short_name}/embed.js" }
|
7
|
+
%noscript
|
8
|
+
%a{ :href => "http://disqus.com/forums/#{short_name}/?url=ref" } View comments.
|