enki-engine 0.0.2

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 (206) hide show
  1. data/.gitignore +13 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +284 -0
  6. data/README.textile +112 -0
  7. data/Rakefile +13 -0
  8. data/TODO.textile +8 -0
  9. data/app/assets/images/admin/flash_bg.gif +0 -0
  10. data/app/assets/images/admin/future_bg.png +0 -0
  11. data/app/assets/images/admin/gray_bg.gif +0 -0
  12. data/app/assets/images/admin/new_button.png +0 -0
  13. data/app/assets/images/admin/silver_bg.gif +0 -0
  14. data/app/assets/images/admin/submit_bg.gif +0 -0
  15. data/app/assets/images/admin/subnav_bg.gif +0 -0
  16. data/app/assets/images/openid_icon.png +0 -0
  17. data/app/assets/images/rails.png +0 -0
  18. data/app/assets/images/silk/arrow_undo.png +0 -0
  19. data/app/assets/images/silk/delete.png +0 -0
  20. data/app/assets/images/silk/pencil.png +0 -0
  21. data/app/assets/javascripts/admin/actions.js +18 -0
  22. data/app/assets/javascripts/admin/comments.js +3 -0
  23. data/app/assets/javascripts/admin/common.js +109 -0
  24. data/app/assets/javascripts/admin/dashboard.js +33 -0
  25. data/app/assets/javascripts/admin/edit-preview.js +40 -0
  26. data/app/assets/javascripts/admin/pages.js +1 -0
  27. data/app/assets/javascripts/admin/posts.js +1 -0
  28. data/app/assets/javascripts/admin/shortcut.js +223 -0
  29. data/app/assets/javascripts/admin.js +17 -0
  30. data/app/assets/javascripts/application.js +15 -0
  31. data/app/assets/javascripts/common.js +22 -0
  32. data/app/assets/javascripts/enki.js +13 -0
  33. data/app/assets/javascripts/live-comment-preview.js +36 -0
  34. data/app/assets/stylesheets/admin.css +304 -0
  35. data/app/assets/stylesheets/application.css.scss +486 -0
  36. data/app/assets/stylesheets/humanmsg.css +112 -0
  37. data/app/assets/stylesheets/login.css +65 -0
  38. data/app/controllers/enki/admin/base_controller.rb +15 -0
  39. data/app/controllers/enki/admin/comments_controller.rb +52 -0
  40. data/app/controllers/enki/admin/dashboard_controller.rb +12 -0
  41. data/app/controllers/enki/admin/health_controller.rb +20 -0
  42. data/app/controllers/enki/admin/pages_controller.rb +97 -0
  43. data/app/controllers/enki/admin/posts_controller.rb +104 -0
  44. data/app/controllers/enki/admin/undo_items_controller.rb +43 -0
  45. data/app/controllers/enki/application_controller.rb +21 -0
  46. data/app/controllers/enki/archives_controller.rb +7 -0
  47. data/app/controllers/enki/base_controller.rb +5 -0
  48. data/app/controllers/enki/comments_controller.rb +43 -0
  49. data/app/controllers/enki/pages_controller.rb +7 -0
  50. data/app/controllers/enki/posts_controller.rb +27 -0
  51. data/app/helpers/enki/admin/navigation_helper.rb +10 -0
  52. data/app/helpers/enki/application_helper.rb +35 -0
  53. data/app/helpers/enki/date_helper.rb +15 -0
  54. data/app/helpers/enki/form_helper.rb +7 -0
  55. data/app/helpers/enki/host_helper.rb +19 -0
  56. data/app/helpers/enki/navigation_helper.rb +23 -0
  57. data/app/helpers/enki/page_title_helper.rb +33 -0
  58. data/app/helpers/enki/posts_helper.rb +9 -0
  59. data/app/helpers/enki/tag_helper.rb +7 -0
  60. data/app/helpers/enki/url_helper.rb +25 -0
  61. data/app/models/enki/base/post.rb +153 -0
  62. data/app/models/enki/comment.rb +75 -0
  63. data/app/models/enki/comment_activity.rb +33 -0
  64. data/app/models/enki/delete_comment_undo.rb +33 -0
  65. data/app/models/enki/delete_page_undo.rb +32 -0
  66. data/app/models/enki/delete_post_undo.rb +36 -0
  67. data/app/models/enki/page.rb +42 -0
  68. data/app/models/enki/post.rb +4 -0
  69. data/app/models/enki/stats.rb +19 -0
  70. data/app/models/enki/tag.rb +19 -0
  71. data/app/models/enki/tagging.rb +7 -0
  72. data/app/models/enki/undo_item.rb +10 -0
  73. data/app/views/enki/admin/comments/_comment.html.erb +12 -0
  74. data/app/views/enki/admin/comments/index.html.erb +30 -0
  75. data/app/views/enki/admin/comments/show.html.erb +9 -0
  76. data/app/views/enki/admin/dashboard/show.html.erb +61 -0
  77. data/app/views/enki/admin/health/index.html.erb +3 -0
  78. data/app/views/enki/admin/pages/_form.html.erb +3 -0
  79. data/app/views/enki/admin/pages/_page.html.erb +12 -0
  80. data/app/views/enki/admin/pages/index.html.erb +25 -0
  81. data/app/views/enki/admin/pages/new.html.erb +8 -0
  82. data/app/views/enki/admin/pages/show.html.erb +8 -0
  83. data/app/views/enki/admin/posts/_form.html.erb +11 -0
  84. data/app/views/enki/admin/posts/_post.html.erb +12 -0
  85. data/app/views/enki/admin/posts/_taggings_form.html.erb +4 -0
  86. data/app/views/enki/admin/posts/_upload_form.html.erb +0 -0
  87. data/app/views/enki/admin/posts/index.html.erb +25 -0
  88. data/app/views/enki/admin/posts/new.html.erb +8 -0
  89. data/app/views/enki/admin/posts/show.html.erb +8 -0
  90. data/app/views/enki/admin/undo_items/index.html.erb +24 -0
  91. data/app/views/enki/archives/index.html.erb +17 -0
  92. data/app/views/enki/comments/_comment.html.erb +4 -0
  93. data/app/views/enki/pages/_page.html.erb +3 -0
  94. data/app/views/enki/pages/show.html.erb +5 -0
  95. data/app/views/enki/posts/_post.html.erb +13 -0
  96. data/app/views/enki/posts/index.atom.builder +27 -0
  97. data/app/views/enki/posts/index.html.erb +15 -0
  98. data/app/views/enki/posts/show.html.erb +37 -0
  99. data/autotest/discover.rb +2 -0
  100. data/config/cucumber.yml +8 -0
  101. data/config/enki.yml.sample +16 -0
  102. data/config/initializers/enki_ext.rb +3 -0
  103. data/config/initializers/set_chronic_timezone.rb +1 -0
  104. data/config/initializers/verification.rb +135 -0
  105. data/config/routes.rb +34 -0
  106. data/db/migrate/20110709024316_initialize_db.rb +97 -0
  107. data/db/seeds.rb +8 -0
  108. data/enki-engine.gemspec +47 -0
  109. data/features/admin_dashboard.feature +10 -0
  110. data/features/admin_health.feature +10 -0
  111. data/features/admin_undo.feature +20 -0
  112. data/features/browsing.feature +16 -0
  113. data/features/step_definitions/admin.rb +27 -0
  114. data/features/step_definitions/browsing.rb +3 -0
  115. data/features/step_definitions/posts.rb +11 -0
  116. data/features/step_definitions/web_steps.rb +1 -0
  117. data/features/support/env.rb +59 -0
  118. data/features/support/paths.rb +35 -0
  119. data/features/support/selectors.rb +39 -0
  120. data/lib/core_extensions/object.rb +9 -0
  121. data/lib/core_extensions/string.rb +22 -0
  122. data/lib/enki/config.rb +44 -0
  123. data/lib/enki/engine.rb +19 -0
  124. data/lib/enki/html5_tags.rb +8 -0
  125. data/lib/enki/pagination_shim.rb +25 -0
  126. data/lib/enki/version.rb +3 -0
  127. data/lib/enki.rb +14 -0
  128. data/lib/enki_formatter.rb +11 -0
  129. data/lib/tag_list.rb +2 -0
  130. data/lib/tags_helper.rb +13 -0
  131. data/lib/tasks/cucumber.rake +65 -0
  132. data/lib/tasks/enki.rake +29 -0
  133. data/lib/undo_failed.rb +2 -0
  134. data/script/cucumber +10 -0
  135. data/spec/controllers/admin/comments_controller_spec.rb +140 -0
  136. data/spec/controllers/admin/dashboard_controller_spec.rb +47 -0
  137. data/spec/controllers/admin/health_controller_spec.rb +49 -0
  138. data/spec/controllers/admin/pages_controller_spec.rb +136 -0
  139. data/spec/controllers/admin/posts_controller_spec.rb +183 -0
  140. data/spec/controllers/admin/undo_items_controller_spec.rb +93 -0
  141. data/spec/controllers/archives_controller_spec.rb +37 -0
  142. data/spec/controllers/comments_controller_spec.rb +126 -0
  143. data/spec/controllers/pages_controller_spec.rb +46 -0
  144. data/spec/controllers/posts_controller_spec.rb +168 -0
  145. data/spec/dummy/Gemfile +5 -0
  146. data/spec/dummy/Rakefile +7 -0
  147. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  148. data/spec/dummy/config/application.rb +34 -0
  149. data/spec/dummy/config/boot.rb +10 -0
  150. data/spec/dummy/config/database.yml +6 -0
  151. data/spec/dummy/config/enki.yml +20 -0
  152. data/spec/dummy/config/environment.rb +5 -0
  153. data/spec/dummy/config/environments/development.rb +34 -0
  154. data/spec/dummy/config/environments/test.rb +32 -0
  155. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  156. data/spec/dummy/config/initializers/session_store.rb +8 -0
  157. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  158. data/spec/dummy/config/locales/en.yml +5 -0
  159. data/spec/dummy/config/routes.rb +14 -0
  160. data/spec/dummy/config.ru +6 -0
  161. data/spec/dummy/script/rails +6 -0
  162. data/spec/factories/factories.rb +36 -0
  163. data/spec/helpers/page_title_helper_spec.rb +54 -0
  164. data/spec/helpers/url_helper_spec.rb +23 -0
  165. data/spec/lib/slugorize_spec.rb +44 -0
  166. data/spec/models/comment_activity_spec.rb +60 -0
  167. data/spec/models/comment_spec.rb +125 -0
  168. data/spec/models/delete_comment_undo_spec.rb +52 -0
  169. data/spec/models/delete_post_undo_spec.rb +18 -0
  170. data/spec/models/page_spec.rb +75 -0
  171. data/spec/models/post_spec.rb +257 -0
  172. data/spec/models/stats_spec.rb +28 -0
  173. data/spec/models/tag_spec.rb +13 -0
  174. data/spec/models/tagging_spec.rb +30 -0
  175. data/spec/rcov.opts +2 -0
  176. data/spec/routing/admin/pages_routing_spec.rb +29 -0
  177. data/spec/routing/archives_routing_spec.rb +9 -0
  178. data/spec/routing/comments_routing_spec.rb +17 -0
  179. data/spec/routing/pages_routing_spec.rb +9 -0
  180. data/spec/routing/posts_routing_spec.rb +26 -0
  181. data/spec/spec.opts +4 -0
  182. data/spec/spec_helper.rb +60 -0
  183. data/spec/support/be_valid_html5.rb +150 -0
  184. data/spec/support/be_valid_xhtml.rb +148 -0
  185. data/spec/support/routes_override_helper.rb +12 -0
  186. data/spec/views/admin/comments/index.html_spec.rb +26 -0
  187. data/spec/views/admin/comments/show.html_spec.rb +28 -0
  188. data/spec/views/admin/dashboard/show.html_spec.rb +37 -0
  189. data/spec/views/admin/pages/index.html_spec.rb +23 -0
  190. data/spec/views/admin/pages/new.html_spec.rb +16 -0
  191. data/spec/views/admin/pages/show.html_spec.rb +16 -0
  192. data/spec/views/admin/posts/index.html_spec.rb +24 -0
  193. data/spec/views/admin/posts/new.html_spec.rb +16 -0
  194. data/spec/views/admin/posts/show.html_spec.rb +16 -0
  195. data/spec/views/admin/undo_items/index.html_spec.rb +19 -0
  196. data/spec/views/archives/index.html_spec.rb +34 -0
  197. data/spec/views/pages/show.html_spec.rb +23 -0
  198. data/spec/views/posts/index.atom.builder_spec.rb +36 -0
  199. data/spec/views/posts/index.html_spec.rb +39 -0
  200. data/spec/views/posts/show.html_spec.rb +49 -0
  201. data/vendor/assets/javascripts/humanmsg.js +86 -0
  202. data/vendor/assets/javascripts/jquery.easing.1.3.js +205 -0
  203. data/vendor/assets/javascripts/jquery.form.js +869 -0
  204. data/vendor/assets/javascripts/jquery.jfeed.js +143 -0
  205. data/vendor/assets/javascripts/jquery.livequery.js +250 -0
  206. metadata +464 -0
@@ -0,0 +1,27 @@
1
+ Given /I am logged in/ do
2
+ visit '/admin/session'
3
+ check "Bypass credentials check"
4
+ click_on "Login with OpenID"
5
+ end
6
+
7
+ Then /^the comment exists$/ do
8
+ Comment.count.should == 2
9
+ end
10
+
11
+ Given /^the following comments? exists:$/ do |comment_table|
12
+ comment_table.hashes.each do |hash|
13
+ Factory(:comment, hash)
14
+ end
15
+ end
16
+
17
+ Given /^a comment exists with attributes:$/ do |comment_table|
18
+ comment_table.hashes.each do |hash|
19
+ Comment.find(:first, :conditions => hash).should_not be_nil
20
+ end
21
+ end
22
+
23
+ Given /^a comment does not exist with attributes:$/ do |comment_table|
24
+ comment_table.hashes.each do |hash|
25
+ Comment.find(:first, :conditions => hash).should be_nil
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ Then /I should see a link to all posts tagged "([\w\s]+)"/ do |tag_name|
2
+ page.should have_xpath("//a[text()='#{tag_name}' and @href='/#{tag_name}']")
3
+ end
@@ -0,0 +1,11 @@
1
+ Given /there is at least one post tagged "([\w\s]+)"/ do |tag_name|
2
+ Factory(:post, :tags => [Factory(:tag, :name => tag_name)])
3
+ end
4
+
5
+ Given /there is at least one post titled "([\w\s]+)"/ do |title|
6
+ Factory(:post, :title => title)
7
+ end
8
+
9
+ Given /a post with comments exists/ do
10
+ Factory(:post, :comments => [Factory(:comment), Factory(:comment)])
11
+ end
@@ -0,0 +1 @@
1
+ require 'cucumber/websteps'
@@ -0,0 +1,59 @@
1
+ # IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
2
+ # It is recommended to regenerate this file in the future when you upgrade to a
3
+ # newer version of cucumber-rails. Consider adding your own code to a new file
4
+ # instead of editing this one. Cucumber will automatically load all features/**/*.rb
5
+ # files.
6
+
7
+ ENV["RAILS_ENV"] = "test"
8
+
9
+ require 'cucumber/rails'
10
+ require 'capybara/rspec'
11
+
12
+ # Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In
13
+ # order to ease the transition to Capybara we set the default here. If you'd
14
+ # prefer to use XPath just remove this line and adjust any selectors in your
15
+ # steps to use the XPath syntax.
16
+ Capybara.default_selector = :css
17
+
18
+ # By default, any exception happening in your Rails application will bubble up
19
+ # to Cucumber so that your scenario will fail. This is a different from how
20
+ # your application behaves in the production environment, where an error page will
21
+ # be rendered instead.
22
+ #
23
+ # Sometimes we want to override this default behaviour and allow Rails to rescue
24
+ # exceptions and display an error page (just like when the app is running in production).
25
+ # Typical scenarios where you want to do this is when you test your error pages.
26
+ # There are two ways to allow Rails to rescue exceptions:
27
+ #
28
+ # 1) Tag your scenario (or feature) with @allow-rescue
29
+ #
30
+ # 2) Set the value below to true. Beware that doing this globally is not
31
+ # recommended as it will mask a lot of errors for you!
32
+ #
33
+ ActionController::Base.allow_rescue = false
34
+
35
+ # Remove/comment out the lines below if your app doesn't have a database.
36
+ # For some databases (like MongoDB and CouchDB) you may need to use :truncation instead.
37
+ begin
38
+ DatabaseCleaner.strategy = :transaction
39
+ rescue NameError
40
+ raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
41
+ end
42
+
43
+ # You may also want to configure DatabaseCleaner to use different strategies for certain features and scenarios.
44
+ # See the DatabaseCleaner documentation for details. Example:
45
+ #
46
+ # Before('@no-txn,@selenium,@culerity,@celerity,@javascript') do
47
+ # DatabaseCleaner.strategy = :truncation, {:except => %w[widgets]}
48
+ # end
49
+ #
50
+ # Before('~@no-txn', '~@selenium', '~@culerity', '~@celerity', '~@javascript') do
51
+ # DatabaseCleaner.strategy = :transaction
52
+ # end
53
+ #
54
+
55
+ # Possible values are :truncation and :transaction
56
+ # The :transaction strategy is faster, but might give you threading problems.
57
+ # See https://github.com/cucumber/cucumber-rails/blob/master/features/choose_javascript_database_strategy.feature
58
+ Cucumber::Rails::Database.javascript_strategy = :truncation
59
+
@@ -0,0 +1,35 @@
1
+ module NavigationHelpers
2
+ # Maps a name to a path. Used by the
3
+ #
4
+ # When /^I go to (.+)$/ do |page_name|
5
+ #
6
+ # step definition in web_steps.rb
7
+ #
8
+ def path_to(page_name)
9
+ case page_name
10
+
11
+ when /the home\s?page/
12
+ '/'
13
+ when '/admin'
14
+ '/admin'
15
+
16
+ # Add more mappings here.
17
+ # Here is an example that pulls values out of the Regexp:
18
+ #
19
+ # when /^(.*)'s profile page$/i
20
+ # user_profile_path(User.find_by_login($1))
21
+
22
+ else
23
+ begin
24
+ page_name =~ /the (.*) page/
25
+ path_components = $1.split(/\s+/)
26
+ self.send(path_components.push('path').join('_').to_sym)
27
+ rescue Object => e
28
+ raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
29
+ "Now, go and add a mapping in #{__FILE__}"
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ World(NavigationHelpers)
@@ -0,0 +1,39 @@
1
+ module HtmlSelectorsHelpers
2
+ # Maps a name to a selector. Used primarily by the
3
+ #
4
+ # When /^(.+) within (.+)$/ do |step, scope|
5
+ #
6
+ # step definitions
7
+ #
8
+ def selector_for(locator)
9
+ case locator
10
+
11
+ when "the page"
12
+ "html > body"
13
+
14
+ # Add more mappings here.
15
+ # Here is an example that pulls values out of the Regexp:
16
+ #
17
+ # when /^the (notice|error|info) flash$/
18
+ # ".flash.#{$1}"
19
+
20
+ # You can also return an array to use a different selector
21
+ # type, like:
22
+ #
23
+ # when /the header/
24
+ # [:xpath, "//header"]
25
+
26
+ # This allows you to provide a quoted selector as the scope
27
+ # for "within" steps as was previously the default for the
28
+ # web steps:
29
+ when /^"(.+)"$/
30
+ $1
31
+
32
+ else
33
+ raise "Can't find mapping from \"#{locator}\" to a selector.\n" +
34
+ "Now, go and add a mapping in #{__FILE__}"
35
+ end
36
+ end
37
+ end
38
+
39
+ World(HtmlSelectorsHelpers)
@@ -0,0 +1,9 @@
1
+ module CoreExtensions
2
+ module Object
3
+ def send_with_default(method, default = nil, *args)
4
+ !self.nil? && self.respond_to?(method) ? self.send(*args.unshift(method)) : default
5
+ end
6
+ end
7
+ end
8
+
9
+ Object.send(:include, CoreExtensions::Object)
@@ -0,0 +1,22 @@
1
+ module CoreExtensions
2
+ module String
3
+
4
+ def slugorize
5
+ result = self.downcase
6
+ result.gsub!(/&([0-9a-z#])+;/, '') # Ditch Entities
7
+ result.gsub!('&', 'and') # Replace & with 'and'
8
+ result.gsub!(/[^a-z0-9\-']/, '-') # Get rid of anything we don't like
9
+ result.gsub!(/-+/, '-') # collapse dashes
10
+ result.gsub!(/-$/, '') # trim dashes
11
+ result.gsub!(/^-/, '') # trim dashes
12
+ result
13
+ end
14
+
15
+ def slugorize!
16
+ self.replace(self.slugorize)
17
+ end
18
+
19
+ end
20
+ end
21
+
22
+ String.send(:include, CoreExtensions::String)
@@ -0,0 +1,44 @@
1
+ require 'delegate'
2
+
3
+ module Enki
4
+ class Config < SimpleDelegator
5
+ def initialize(file_name)
6
+ super(symbolize_keys(YAML::load(IO.read(file_name))))
7
+ end
8
+
9
+ def [](*path)
10
+ path.inject(__getobj__()) {|config, item|
11
+ config[item]
12
+ }
13
+ end
14
+
15
+ def author_open_ids
16
+ [self[:author, :open_id]].flatten.map {|uri| URI.parse(uri)}
17
+ end
18
+
19
+ def self.default
20
+ @@default ||= Enki::Config.new(default_location)
21
+ end
22
+
23
+ def self.default_location
24
+ "#{Rails.root}/config/enki.yml"
25
+ end
26
+
27
+ def comments?
28
+ self[:features, :comments]
29
+ end
30
+
31
+ def tags?
32
+ self[:features, :tags]
33
+ end
34
+
35
+ private
36
+
37
+ def symbolize_keys(hash)
38
+ hash.inject({}) do |options, (key, value)|
39
+ options[(key.to_sym rescue key) || key] = value.is_a?(Hash) ? symbolize_keys(value) : value
40
+ options
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,19 @@
1
+ # Bundler 1.0.10 incorrectly activates the new experimental Psych YAML parser
2
+ # in 1.9.2, which breaks on RedCloth. This hack reverts it, but can be removed
3
+ # once it is all sorted out. The const_defined check is required for 1.8.7 compat.
4
+ YAML::ENGINE.yamler = "syck" if YAML.const_defined?("ENGINE")
5
+
6
+ require 'enki'
7
+ require 'rails'
8
+ require 'rubygems'
9
+ require 'redcloth'
10
+ require 'chronic'
11
+ require 'coderay'
12
+ require 'lesstile'
13
+
14
+ module Enki
15
+ class Engine < Rails::Engine
16
+ engine_name 'enki'
17
+ config.autoload_paths += %W(#{config.root}/lib)
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ # TagHelper will output HTML tags as opposed to self-closed XHTML tags.
2
+ # Shouldn't be needed for Rails >= version 3.
3
+ module ActionView::Helpers::TagHelper
4
+ def tag_with_html_patch(name, options = nil, open = true, escape = true)
5
+ tag_without_html_patch(name, options, true, escape)
6
+ end
7
+ alias_method_chain :tag, :html_patch
8
+ end
@@ -0,0 +1,25 @@
1
+ module Enki
2
+ module PaginationShim
3
+
4
+ def paginated(params)
5
+ if defined? ::Kaminari
6
+ page params[:page]
7
+ elsif defined? ::WillPagniate
8
+ paginate :page => params[:page]
9
+ else
10
+ all
11
+ end
12
+ end
13
+
14
+ def paginated_pages
15
+ if defined? ::Kaminari
16
+ num_pages
17
+ elsif defined? ::WillPagniate
18
+ total_pages
19
+ else
20
+ 1
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module Enki
2
+ VERSION = "0.0.2"
3
+ end
data/lib/enki.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'enki/config'
2
+ require 'enki/version'
3
+ require 'enki/engine' if defined?(Rails)
4
+ require 'acts-as-taggable-on'
5
+ require 'simple_form'
6
+
7
+ module Enki
8
+
9
+ class NotLoggedInError < StandardError; end
10
+
11
+ def self.config
12
+ @@config ||= Enki::Config.default
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ class EnkiFormatter
2
+ class << self
3
+ def format_as_xhtml(text)
4
+ Lesstile.format_as_xhtml(
5
+ text,
6
+ :text_formatter => lambda {|text| RedCloth.new(CGI::unescapeHTML(text)).to_html},
7
+ :code_formatter => Lesstile::CodeRayFormatter
8
+ )
9
+ end
10
+ end
11
+ end
data/lib/tag_list.rb ADDED
@@ -0,0 +1,2 @@
1
+ class TagList < ActsAsTaggableOn::TagList
2
+ end
@@ -0,0 +1,13 @@
1
+ module TagsHelper
2
+ # See the README for an example using tag_cloud.
3
+ def tag_cloud(tags, classes)
4
+ return if tags.empty?
5
+
6
+ max_count = tags.sort_by(&:count).last.count.to_f
7
+
8
+ tags.each do |tag|
9
+ index = ((tag.count / max_count) * (classes.size - 1)).round
10
+ yield tag, classes[index]
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,65 @@
1
+ # IMPORTANT: This file is generated by cucumber-rails - edit at your own peril.
2
+ # It is recommended to regenerate this file in the future when you upgrade to a
3
+ # newer version of cucumber-rails. Consider adding your own code to a new file
4
+ # instead of editing this one. Cucumber will automatically load all features/**/*.rb
5
+ # files.
6
+
7
+
8
+ unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks
9
+
10
+ vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
11
+ $LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
12
+
13
+ begin
14
+ require 'cucumber/rake/task'
15
+
16
+ namespace :cucumber do
17
+ Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t|
18
+ t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
19
+ t.fork = true # You may get faster startup if you set this to false
20
+ t.profile = 'default'
21
+ end
22
+
23
+ Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t|
24
+ t.binary = vendored_cucumber_bin
25
+ t.fork = true # You may get faster startup if you set this to false
26
+ t.profile = 'wip'
27
+ end
28
+
29
+ Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t|
30
+ t.binary = vendored_cucumber_bin
31
+ t.fork = true # You may get faster startup if you set this to false
32
+ t.profile = 'rerun'
33
+ end
34
+
35
+ desc 'Run all features'
36
+ task :all => [:ok, :wip]
37
+
38
+ task :statsetup do
39
+ require 'rails/code_statistics'
40
+ ::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features')
41
+ ::CodeStatistics::TEST_TYPES << "Cucumber features" if File.exist?('features')
42
+ end
43
+ end
44
+ desc 'Alias for cucumber:ok'
45
+ task :cucumber => 'cucumber:ok'
46
+
47
+ task :default => :cucumber
48
+
49
+ task :features => :cucumber do
50
+ STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
51
+ end
52
+
53
+ # In case we don't have ActiveRecord, append a no-op task that we can depend upon.
54
+ task 'db:test:prepare' do
55
+ end
56
+
57
+ task :stats => 'cucumber:statsetup'
58
+ rescue LoadError
59
+ desc 'cucumber rake task not available (cucumber not installed)'
60
+ task :cucumber do
61
+ abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,29 @@
1
+ namespace :enki do
2
+ desc "Generates public/yadis.xrdf from enki.yml, for OpenID delegation"
3
+ task :generate_yadis => :environment do
4
+ file = "public/yadis.xrdf"
5
+ raise "#{file} already exists, please remove it before running this task" if File.exists?(file)
6
+ raise "open_id_delegation section not provided in config/enki.yml" unless Enki.config[:open_id_delegation]
7
+ File.open("public/yadis.xrdf", "w") do |f|
8
+ f.write <<-EOS
9
+ <xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)"
10
+ xmlns:openid="http://openid.net/xmlns/1.0">
11
+ <XRD>
12
+
13
+ <Service priority="1">
14
+ <Type>http://openid.net/signon/1.0</Type>
15
+ <URI>#{Enki.config[:open_id_delegation, :server]}</URI>
16
+ <openid:Delegate>#{Enki.config[:open_id_delegation, :delegate]}</openid:Delegate>
17
+ </Service>
18
+
19
+ </XRD>
20
+ </xrds:XRDS>
21
+ EOS
22
+ end
23
+ end
24
+
25
+ desc "Cleans out actions older than 7 days"
26
+ task :clean_actions => :environment do
27
+ UndoItem.delete_all(["created_at < ?", 7.days.ago])
28
+ end
29
+ end
@@ -0,0 +1,2 @@
1
+ class UndoFailed < RuntimeError
2
+ end
data/script/cucumber ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ vendored_cucumber_bin = Dir["#{File.dirname(__FILE__)}/../vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
4
+ if vendored_cucumber_bin
5
+ load File.expand_path(vendored_cucumber_bin)
6
+ else
7
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
8
+ require 'cucumber'
9
+ load Cucumber::BINARY
10
+ end
@@ -0,0 +1,140 @@
1
+ require 'spec_helper'
2
+ require 'json'
3
+
4
+ module Enki
5
+
6
+ describe Admin::CommentsController do
7
+
8
+ before do
9
+ controller.stub!(:logged_in?).and_return(true)
10
+ end
11
+
12
+ describe 'handling GET to index' do
13
+ before(:each) do
14
+ @comments = [create(:comment), create(:comment)].extend(Enki::PaginationShim)
15
+ Comment.stub_chain(:order, :includes, :paginated).and_return(@comments)
16
+ get :index
17
+ end
18
+
19
+ it("is successful") { response.should be_success }
20
+ it("renders index template") { response.should render_template('index') }
21
+ it("finds comments for the view") { assigns[:comments].should == @comments }
22
+ end
23
+
24
+ describe 'handling GET to show' do
25
+ before(:each) do
26
+ @comment = Comment.new
27
+ Comment.stub!(:find).and_return(@comment)
28
+ get :show, :id => 1
29
+ end
30
+
31
+ it("is successful") { response.should be_success }
32
+ it("renders show template") { response.should render_template('show') }
33
+ it("finds comment for the view") { assigns[:comment].should == @comment }
34
+ end
35
+
36
+ describe 'handling PUT to update with valid attributes' do
37
+ before(:each) do
38
+ @comment = mock_model(Comment, :author => 'Don Alias')
39
+ @comment.stub!(:update_attributes).and_return(true)
40
+ Comment.stub!(:find).and_return(@comment)
41
+
42
+ @attributes = {'body' => 'a comment'}
43
+ end
44
+
45
+ def do_put
46
+ session[:logged_in] = true
47
+ put :update, :id => 1, :comment => @attributes
48
+ end
49
+
50
+ it("redirects to index") do
51
+ do_put
52
+ response.should be_redirect
53
+ response.should redirect_to(admin_comments_path)
54
+ end
55
+
56
+ it("updates comment") do
57
+ @comment.should_receive(:update_attributes).with(@attributes).and_return(true)
58
+ do_put
59
+ end
60
+
61
+ it("puts a message in the flash") do
62
+ do_put
63
+ flash[:notice].should_not be_blank
64
+ end
65
+ end
66
+
67
+ describe 'handling PUT to update with invalid attributes' do
68
+ before(:each) do
69
+ @comment = mock_model(Comment, :author => 'Don Alias')
70
+ @comment.stub!(:update_attributes).and_return(false)
71
+ Comment.stub!(:find).and_return(@comment)
72
+
73
+ @attributes = {:body => ''}
74
+ end
75
+
76
+ def do_put
77
+ session[:logged_in] = true
78
+ put :update, :id => 1, :comment => @attributes
79
+ end
80
+
81
+ it("renders show") do
82
+ do_put
83
+ response.should render_template('show')
84
+ end
85
+
86
+ it("assigns comment for the view") do
87
+ do_put
88
+ assigns(:comment).should == @comment
89
+ end
90
+ end
91
+
92
+ describe 'handling DELETE to destroy' do
93
+ before(:each) do
94
+ @comment = Comment.new
95
+ @comment.stub!(:destroy)
96
+ Comment.stub!(:find).and_return(@comment)
97
+ end
98
+
99
+ def do_delete
100
+ session[:logged_in] = true
101
+ delete :destroy, :id => 1
102
+ end
103
+
104
+ it("redirects to index") do
105
+ do_delete
106
+ response.should be_redirect
107
+ response.should redirect_to(:action => 'index')
108
+ end
109
+
110
+ it("deletes comment") do
111
+ @comment.should_receive(:destroy)
112
+ do_delete
113
+ end
114
+ end
115
+
116
+ describe 'handling DELETE to destroy, JSON request' do
117
+ before(:each) do
118
+ @comment = Comment.new(:author => 'xavier')
119
+ @comment.stub!(:destroy_with_undo).and_return(mock_model(UndoItem, :description => 'hello'))
120
+ Comment.stub!(:find).and_return(@comment)
121
+ end
122
+
123
+ def do_delete
124
+ session[:logged_in] = true
125
+ delete :destroy, :id => 1, :format => 'json'
126
+ end
127
+
128
+ it("deletes comment") do
129
+ @comment.should_receive(:destroy_with_undo).and_return(mock_model(UndoItem, :description => 'hello'))
130
+ do_delete
131
+ end
132
+
133
+ it("renders json including a description of the comment") do
134
+ do_delete
135
+ JSON.parse(response.body)['undo_message'].should == 'hello'
136
+ end
137
+ end
138
+ end
139
+
140
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ module Enki
4
+
5
+ describe Admin::DashboardController do
6
+
7
+ before do
8
+ controller.stub!(:logged_in?).and_return(true)
9
+ end
10
+
11
+ describe 'handling GET to show' do
12
+ before(:each) do
13
+ @pages = [create(:page), create(:page)]
14
+ @posts = [create(:post), create(:post)]
15
+ @comment_activity = @posts.map { |post| create(:comment, :post => post); CommentActivity.new(post) }
16
+ Page.stub!(:find_recent).and_return(@pages)
17
+ Post.stub!(:find_recent).and_return(@posts)
18
+ Stats.stub!(:new).and_return(@stats = Struct.new(:post_count, :page_count, :comment_count, :tag_count).new(3,4,2,1))
19
+
20
+ CommentActivity.stub!(:find_recent).and_return(@comment_activity)
21
+
22
+ get :show
23
+ end
24
+
25
+ it "is successful" do
26
+ response.should be_success
27
+ end
28
+
29
+ it "renders show template" do
30
+ response.should render_template('show')
31
+ end
32
+
33
+ it "finds posts for the view" do
34
+ assigns[:posts].should == @posts
35
+ end
36
+
37
+ it "assigns stats for the view" do
38
+ assigns[:stats].should == @stats
39
+ end
40
+
41
+ it "finds comment activity for the view" do
42
+ assigns[:comment_activity].should == @comment_activity
43
+ end
44
+ end
45
+ end
46
+
47
+ end