aslakjo-aslakjo-comatose 2.0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/CHANGELOG +195 -0
  2. data/INSTALL +20 -0
  3. data/LICENSE +20 -0
  4. data/MANIFEST +91 -0
  5. data/README.markdown +159 -0
  6. data/Rakefile +176 -0
  7. data/SPECS +61 -0
  8. data/about.yml +7 -0
  9. data/bin/comatose +112 -0
  10. data/comatose.gemspec +113 -0
  11. data/generators/comatose_migration/USAGE +15 -0
  12. data/generators/comatose_migration/comatose_migration_generator.rb +74 -0
  13. data/generators/comatose_migration/templates/migration.rb +35 -0
  14. data/generators/comatose_migration/templates/v4_upgrade.rb +15 -0
  15. data/generators/comatose_migration/templates/v6_upgrade.rb +23 -0
  16. data/generators/comatose_migration/templates/v7_upgrade.rb +22 -0
  17. data/init.rb +2 -0
  18. data/install.rb +18 -0
  19. data/lib/acts_as_versioned.rb +543 -0
  20. data/lib/comatose.rb +33 -0
  21. data/lib/comatose/comatose_drop.rb +79 -0
  22. data/lib/comatose/configuration.rb +69 -0
  23. data/lib/comatose/page_wrapper.rb +119 -0
  24. data/lib/comatose/processing_context.rb +69 -0
  25. data/lib/comatose/tasks/admin.rb +60 -0
  26. data/lib/comatose/tasks/data.rb +82 -0
  27. data/lib/comatose/tasks/setup.rb +52 -0
  28. data/lib/comatose/version.rb +4 -0
  29. data/lib/comatose_admin_controller.rb +395 -0
  30. data/lib/comatose_admin_helper.rb +37 -0
  31. data/lib/comatose_controller.rb +138 -0
  32. data/lib/comatose_helper.rb +3 -0
  33. data/lib/comatose_page.rb +141 -0
  34. data/lib/liquid.rb +52 -0
  35. data/lib/liquid/block.rb +96 -0
  36. data/lib/liquid/context.rb +190 -0
  37. data/lib/liquid/document.rb +17 -0
  38. data/lib/liquid/drop.rb +48 -0
  39. data/lib/liquid/errors.rb +7 -0
  40. data/lib/liquid/extensions.rb +53 -0
  41. data/lib/liquid/file_system.rb +62 -0
  42. data/lib/liquid/htmltags.rb +64 -0
  43. data/lib/liquid/standardfilters.rb +111 -0
  44. data/lib/liquid/standardtags.rb +399 -0
  45. data/lib/liquid/strainer.rb +42 -0
  46. data/lib/liquid/tag.rb +25 -0
  47. data/lib/liquid/template.rb +88 -0
  48. data/lib/liquid/variable.rb +39 -0
  49. data/lib/redcloth.rb +1129 -0
  50. data/lib/support/class_options.rb +36 -0
  51. data/lib/support/inline_rendering.rb +48 -0
  52. data/lib/support/route_mapper.rb +50 -0
  53. data/lib/text_filters.rb +140 -0
  54. data/lib/text_filters/markdown.rb +14 -0
  55. data/lib/text_filters/markdown_smartypants.rb +15 -0
  56. data/lib/text_filters/none.rb +8 -0
  57. data/lib/text_filters/rdoc.rb +13 -0
  58. data/lib/text_filters/simple.rb +8 -0
  59. data/lib/text_filters/textile.rb +15 -0
  60. data/rails/init.rb +3 -0
  61. data/resources/layouts/comatose_admin_template.html.erb +28 -0
  62. data/resources/public/images/collapsed.gif +0 -0
  63. data/resources/public/images/expanded.gif +0 -0
  64. data/resources/public/images/no-children.gif +0 -0
  65. data/resources/public/images/page.gif +0 -0
  66. data/resources/public/images/spinner.gif +0 -0
  67. data/resources/public/images/title-hover-bg.gif +0 -0
  68. data/resources/public/javascripts/comatose_admin.js +401 -0
  69. data/resources/public/stylesheets/comatose_admin.css +404 -0
  70. data/tasks/comatose.rake +9 -0
  71. data/test/behaviors.rb +106 -0
  72. data/test/fixtures/comatose_pages.yml +96 -0
  73. data/test/functional/comatose_admin_controller_test.rb +114 -0
  74. data/test/functional/comatose_controller_test.rb +44 -0
  75. data/test/javascripts/test.html +26 -0
  76. data/test/javascripts/test_runner.js +307 -0
  77. data/test/test_helper.rb +55 -0
  78. data/test/unit/class_options_test.rb +52 -0
  79. data/test/unit/comatose_page_test.rb +136 -0
  80. data/test/unit/processing_context_test.rb +108 -0
  81. data/test/unit/text_filters_test.rb +52 -0
  82. data/views/comatose_admin/_form.html.erb +96 -0
  83. data/views/comatose_admin/_page_list_item.html.erb +60 -0
  84. data/views/comatose_admin/delete.html.erb +18 -0
  85. data/views/comatose_admin/edit.html.erb +5 -0
  86. data/views/comatose_admin/index.html.erb +29 -0
  87. data/views/comatose_admin/new.html.erb +5 -0
  88. data/views/comatose_admin/reorder.html.erb +30 -0
  89. data/views/comatose_admin/versions.html.erb +40 -0
  90. data/views/layouts/comatose_admin.html.erb +837 -0
  91. data/views/layouts/comatose_admin_customize.html.erb +28 -0
  92. data/views/layouts/comatose_content.html.erb +17 -0
  93. metadata +148 -0
@@ -0,0 +1,33 @@
1
+
2
+ module Comatose
3
+
4
+ # DEPRECATED
5
+ # Loads extensions from RAILS_ROOT/lib/comatose/*.rb
6
+ def self.load_extensions
7
+ Dir[File.join(RAILS_ROOT, 'lib', 'comatose', '*.rb')].each do |path|
8
+ require "comatose/#{File.basename(path)}"
9
+ end
10
+ end
11
+
12
+ end
13
+
14
+ require 'acts_as_versioned'
15
+ require 'redcloth' unless defined?(RedCloth)
16
+ require 'liquid' unless defined?(Liquid)
17
+
18
+ require 'support/class_options'
19
+ require 'text_filters'
20
+
21
+ require 'comatose/configuration'
22
+ require 'comatose/comatose_drop'
23
+ require 'comatose/processing_context'
24
+ require 'comatose/page_wrapper'
25
+ require 'comatose/version'
26
+
27
+ require 'support/inline_rendering'
28
+ require 'support/route_mapper'
29
+
30
+ require 'dispatcher' unless defined?(::Dispatcher)
31
+ ::Dispatcher.to_prepare :comatose do
32
+ Comatose.config.after_setup.call
33
+ end
@@ -0,0 +1,79 @@
1
+ module Comatose
2
+
3
+ class ComatoseDrop < ::Liquid::Drop
4
+
5
+ private :initialize
6
+
7
+ def before_method(method)
8
+ self.send(method.to_sym)
9
+ rescue
10
+ ComatoseController.logger.debug "Error calling #{method}: #{$!}"
11
+ raise $!
12
+ end
13
+
14
+ class << self
15
+ # Define a new ComatoseDrop by name
16
+ def define( name, &block )
17
+ d = ComatoseDrop.new
18
+ d.instance_eval(&block)
19
+ Comatose.registered_drops[name] = d
20
+ rescue
21
+ ComatoseController.logger.debug "Drop '#{name}' was not included: #{$!}"
22
+ end
23
+ end
24
+ end
25
+
26
+ class << self
27
+
28
+ # Returns/initializes a hash for storing ComatoseDrops
29
+ def registered_drops
30
+ @registered_drops ||= {}
31
+ end
32
+
33
+ # Simple wrapper around the ProcessingContext.define method
34
+ # I think Comatose.define_drop is probably simpler to remember too
35
+ def define_drop(name, &block)
36
+ ComatoseDrop.define(name, &block)
37
+ end
38
+
39
+ # Registers a 'filter' for Liquid use
40
+ def register_filter(module_name)
41
+ Liquid::Template.register_filter(module_name)
42
+ end
43
+
44
+ end
45
+ end
46
+
47
+
48
+ #
49
+ # Some Default Filters/Drops
50
+ #
51
+
52
+ module IncludeFilter
53
+ def include(input)
54
+ page = ComatosePage.find_by_path(input)
55
+ params = @context['params']
56
+ # TODO: Add more of the context into the included page's context...
57
+ page.to_html( { 'params' => params } )
58
+ rescue
59
+ "Page at <tt>#{input}</tt> could not be found. <pre>#{$!}</pre>"
60
+ end
61
+ end
62
+
63
+ Comatose.register_filter IncludeFilter
64
+
65
+
66
+ module TimeagoFilter
67
+ class Helpers
68
+ extend ActionView::Helpers::DateHelper
69
+ end
70
+
71
+ def time_ago(input)
72
+ TimeagoFilter::Helpers.distance_of_time_in_words_to_now( input, true )
73
+ rescue
74
+ #puts "Oops! -- #{$!}"
75
+ input
76
+ end
77
+ end
78
+
79
+ Comatose.register_filter TimeagoFilter
@@ -0,0 +1,69 @@
1
+ module Comatose
2
+
3
+ def self.config
4
+ @@config ||= Configuration.new
5
+ end
6
+
7
+ def self.configure(&block)
8
+ raise "#configure must be sent a block" unless block_given?
9
+ yield config
10
+ config.validate!
11
+ end
12
+
13
+ # All of the 'mount' points for Comatose
14
+ def self.mount_points
15
+ @@mount_points ||= []
16
+ end
17
+
18
+ # Adds a 'mount' point to the list of known roots...
19
+ def self.add_mount_point(path, info={:index=>''})
20
+ path = "/#{path}" unless path.starts_with? '/'
21
+ info[:root]=path
22
+ mount_points << info
23
+ end
24
+
25
+ class Configuration
26
+
27
+ attr_accessor_with_default :admin_title, 'Comatose'
28
+ attr_accessor_with_default :admin_includes, []
29
+ attr_accessor_with_default :admin_helpers, []
30
+ attr_accessor_with_default :admin_sub_title, 'The Micro CMS'
31
+ attr_accessor_with_default :content_type, 'utf-8'
32
+ attr_accessor_with_default :default_filter, 'Textile'
33
+ attr_accessor_with_default :default_processor, :liquid
34
+ attr_accessor_with_default :default_tree_level, 2
35
+ attr_accessor_with_default :disable_caching, false
36
+ attr_accessor_with_default :hidden_meta_fields, []
37
+ attr_accessor_with_default :helpers, []
38
+ attr_accessor_with_default :includes, []
39
+ attr_accessor_with_default :allow_import_export, true
40
+
41
+ # 'Blockable' setters
42
+ blockable_attr_accessor :authorization
43
+ blockable_attr_accessor :admin_authorization
44
+ blockable_attr_accessor :admin_get_author
45
+ blockable_attr_accessor :admin_get_root_page
46
+ blockable_attr_accessor :after_setup
47
+
48
+ def initialize
49
+ # Default procs for blockable attrs....
50
+ @authorization = Proc.new { true }
51
+ @admin_authorization = Proc.new { true }
52
+ @admin_get_author = Proc.new { request.env['REMOTE_ADDR'] }
53
+ @admin_get_root_page = Proc.new { ComatosePage.root }
54
+ @after_setup = Proc.new { true }
55
+ end
56
+
57
+ def validate!
58
+ # Rips through the config and validates it's, er, valid
59
+ raise ConfigurationError.new( "admin_get_author must be a Proc or Symbol" ) unless @admin_get_author.is_a? Proc or @admin_get_author.is_a? Symbol
60
+ raise ConfigurationError.new( "admin_authorization must be a Proc or Symbol" ) unless @admin_authorization.is_a? Proc or @admin_authorization.is_a? Symbol
61
+ raise ConfigurationError.new( "authorization must be a Proc or Symbol" ) unless @authorization.is_a? Proc or @authorization.is_a? Symbol
62
+ true
63
+ end
64
+
65
+ class ConfigurationError < StandardError; end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,119 @@
1
+ # Giving direct access to the AR model is disconcerting, so this wraps the AR
2
+ # Model to prevent access to certain, destructive behavior
3
+ class Comatose::PageWrapper
4
+
5
+ @@allowed_methods = %w(id full_path uri slug keywords title to_html filter_type author updated_on created_on)
6
+ @@custom_methods = %w(link content parent next previous children rchildren first_child last_child has_keyword)
7
+
8
+ attr_accessor :page
9
+ private :page
10
+
11
+ def initialize( page, locals={} )
12
+ @page = page
13
+ @keyword_lst = []
14
+ @keyword_hsh = {}
15
+ unless page.nil?
16
+ @keyword_lst = (page.keywords || '').downcase.split(',').map {|k| k.strip }
17
+ @keyword_lst.each {|kw| @keyword_hsh[kw] = true}
18
+ end
19
+ @locals = locals
20
+ end
21
+
22
+ def has_keyword?(keyword)
23
+ @page.has_keyword?(keyword)
24
+ end
25
+
26
+ def has_keyword
27
+ @keyword_hsh
28
+ end
29
+
30
+ def next
31
+ @next_page ||= begin
32
+ if @page.lower_item.nil?
33
+ nil
34
+ else
35
+ Comatose::PageWrapper.new( @page.lower_item )
36
+ end
37
+ end
38
+ end
39
+
40
+ def previous
41
+ @prev_page ||= begin
42
+ if @page.higher_item.nil?
43
+ nil
44
+ else
45
+ Comatose::PageWrapper.new( @page.higher_item )
46
+ end
47
+ end
48
+ end
49
+
50
+ def first_child
51
+ children.first
52
+ end
53
+
54
+ def def last_child
55
+ children.last
56
+ end
57
+
58
+ # Generates a link to this page... You can pass in the link text,
59
+ # otherwise it will default to the page title.
60
+ def link( title=nil )
61
+ title = @page.title if title.nil?
62
+ TextFilters[@page.filter_type].create_link(title, @page.uri)
63
+ end
64
+
65
+ def content
66
+ @page.to_html( @locals )
67
+ end
68
+
69
+ def parent
70
+ @parent ||= begin
71
+ if @page.parent.nil?
72
+ nil
73
+ else
74
+ Comatose::PageWrapper.new( @page.parent )
75
+ end
76
+ end
77
+ end
78
+
79
+ def children
80
+ # Cache the results so that you can have multiple calls to #children without a penalty
81
+ @children ||= @page.children.to_a.collect {|child| Comatose::PageWrapper.new( child, @locals )}
82
+ end
83
+
84
+ # Children, in reverse order
85
+ def rchildren
86
+ children.reverse
87
+ end
88
+
89
+ def [](key)
90
+ if @@allowed_methods.include? key.to_s #or page.attributes.has_key? key.to_s
91
+ page.send( key )
92
+ elsif @@custom_methods.include? key
93
+ self.send(key.to_sym)
94
+ end
95
+ end
96
+
97
+ def has_key?(key)
98
+ @@allowed_methods.include? key or @@custom_methods.include? key
99
+ end
100
+
101
+ def to_s
102
+ @page.title
103
+ end
104
+
105
+ def to_liquid
106
+ self
107
+ end
108
+
109
+ def method_missing(method_id, *args)
110
+ #STDERR.puts "Looking for method: #{method_id} (#{method_id.class.to_s}) in [#{@@allowed_methods.join(', ')}] or [#{page.attributes.keys.join(', ')}]"
111
+ if @@allowed_methods.include? method_id.to_s or page.attributes.has_key? method_id.to_s
112
+ page.send( method_id, *args)
113
+ else
114
+ # Access nazi says: NO ACCESS FOR YOU!!
115
+ # but he says it silently...
116
+ end
117
+ end
118
+
119
+ end
@@ -0,0 +1,69 @@
1
+ # This is the rendering context object you have access to in text processing...
2
+ class Comatose::ProcessingContext
3
+ @@supported_methods = %w(page include)
4
+
5
+ def initialize( page, locals={} )
6
+ @locals = locals.stringify_keys if locals.respond_to? :stringify_keys
7
+ @page = Comatose::PageWrapper.new(page, @locals)
8
+ end
9
+
10
+ def page
11
+ @page
12
+ end
13
+
14
+ def include(path, locals={})
15
+ begin
16
+ page = ComatosePage.find_by_path(path)
17
+ page.to_html( @locals.merge(locals) )
18
+ rescue
19
+ "<p>Page at <tt>#{path}</tt> could not be found.</p>"
20
+ end
21
+ end
22
+
23
+ def find_by_path(path)
24
+ begin
25
+ page = ComatosePage.find_by_path(path)
26
+ Comatose::PageWrapper.new(page, @locals)
27
+ rescue
28
+ "<p>Page at <tt>#{path}</tt> could not be found.</p>"
29
+ end
30
+ end
31
+
32
+ def [](key)
33
+ if key.to_s.downcase == 'page'
34
+ @page
35
+ elsif @locals.has_key? key
36
+ @locals[key]
37
+ elsif Comatose.registered_drops.has_key? key
38
+ Comatose.registered_drops[key]
39
+ end
40
+ end
41
+
42
+ def has_key?(key)
43
+ @@supported_methods.include?(key) or @locals.has_key?(key) or Comatose.registered_drops.has_key?(key)
44
+ end
45
+
46
+ def to_liquid
47
+ self
48
+ end
49
+
50
+ def get_binding
51
+ binding
52
+ end
53
+
54
+ def method_missing(method_id, *args)
55
+ method_name = method_id.to_s
56
+ if @locals.has_key? method_name
57
+ @locals[method_name]
58
+ elsif Comatose.registered_drops.has_key? method_name
59
+ Comatose.registered_drops[method_name].context = self
60
+ Comatose.registered_drops[method_name]
61
+ else
62
+ "<!-- ProcessingContext: Couldn't find #{method_id} -->"
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+
69
+
@@ -0,0 +1,60 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+
4
+ namespace :comatose do
5
+ #
6
+ # Customization Tasks
7
+ #
8
+ namespace :admin do
9
+
10
+ desc "Create Comatose views, layouts, and public files..."
11
+ task :customize do
12
+ puts "Copying public files..."
13
+ plugin_dir = File.join(File.dirname(__FILE__), '../../..')
14
+ FileUtils.cp(
15
+ Dir[File.join(plugin_dir, 'resources', 'public', 'stylesheets', '*.css')],
16
+ File.join(RAILS_ROOT, 'public', 'stylesheets'),
17
+ :verbose => true
18
+ )
19
+ FileUtils.cp(
20
+ Dir[File.join(plugin_dir, 'resources', 'public', 'javascripts', '*.js')],
21
+ File.join(RAILS_ROOT, 'public', 'javascripts'),
22
+ :verbose => true
23
+ )
24
+ puts "Copying application views..."
25
+ FileUtils.mkdir_p(File.join(RAILS_ROOT, 'app', 'views', 'comatose_admin'))
26
+ FileUtils.cp(
27
+ Dir[File.join(plugin_dir, 'views', 'comatose_admin', '*.html.erb')],
28
+ File.join(RAILS_ROOT, 'app', 'views', 'comatose_admin'),
29
+ :verbose => true
30
+ )
31
+ puts "Copying application layout..."
32
+ FileUtils.cp(
33
+ File.join(plugin_dir, 'views', 'layouts', 'comatose_admin_customize.html.erb'),
34
+ File.join(RAILS_ROOT, 'app', 'views', 'layouts', 'comatose_admin.html.erb'),
35
+ :verbose => true
36
+ )
37
+ puts "Finished."
38
+ end
39
+
40
+
41
+ desc "Removes the customized files... It doesn't ask for any confirmation, nor is it Subversion-safe -- so be warned!"
42
+ task :teardown do
43
+ puts "Removing public files..."
44
+ FileUtils.rm(
45
+ File.join(RAILS_ROOT, 'public', 'stylesheets', 'comatose_admin.css')
46
+ )
47
+ FileUtils.rm(
48
+ File.join(RAILS_ROOT, 'public', 'javascripts', 'comatose_admin.js')
49
+ )
50
+
51
+ puts "Removing application views..."
52
+ FileUtils.rm_rf(
53
+ File.join(RAILS_ROOT, 'app', 'views', 'comatose_admin')
54
+ )
55
+ FileUtils.rm(
56
+ File.join(RAILS_ROOT, 'app', 'views', 'layouts', 'comatose_admin.html.erb')
57
+ )
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,82 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+
4
+ namespace :comatose do
5
+ #
6
+ # Data Migration Tasks
7
+ #
8
+ namespace :data do
9
+
10
+ def page_to_hash(page)
11
+ data = page.attributes.clone
12
+ # Pull out the specific, or unnecessary fields
13
+ %w(id parent_id updated_on author position version created_on full_path).each {|key| data.delete(key)}
14
+ if !page.children.empty?
15
+ data['children'] = []
16
+ page.children.each do |child|
17
+ data['children'] << page_to_hash(child)
18
+ end
19
+ end
20
+ data
21
+ end
22
+
23
+ def hash_to_page_tree(hsh, page)
24
+ child_ary = hsh.delete 'children'
25
+ page.update_attributes(hsh)
26
+ page.save
27
+ child_ary.each do |child_hsh|
28
+ if child_pg = page.children.find_by_slug( child_hsh['slug'] )
29
+ hash_to_page_tree( child_hsh, child_pg )
30
+ else
31
+ hash_to_page_tree( child_hsh, page.children.create )
32
+ end
33
+ end if child_ary
34
+ end
35
+
36
+ desc "Saves a page tree from page FROM or '' to file TO_FILE or db/comatose-pages.yml"
37
+ task :export do
38
+ require "#{RAILS_ROOT}/config/environment"
39
+
40
+ root = ENV['FROM'] || ''
41
+ target = ENV['TO_FILE'] || 'db/comatose-pages.yml'
42
+ # Nested hash of the page tree...
43
+ from = ComatosePage.find_by_path(root)
44
+ if from
45
+ data = page_to_hash( from )
46
+ File.open(target, 'w') {|f| f.write data.to_yaml }
47
+ else
48
+ puts "Could not find the page at '#{root}', export aborted!"
49
+ end
50
+
51
+ puts "Finished."
52
+ end
53
+
54
+ desc "Loads page tree data FROM_FILE or db/comatose-pages.yml in to TO or ComatosePage.root"
55
+ task :import do
56
+ require "#{RAILS_ROOT}/config/environment"
57
+
58
+ src = ENV['FROM_FILE'] || 'db/comatose-pages.yml'
59
+ root = ENV['TO'] || ''
60
+ target = (root == '') ? ComatosePage.root : ComatosePage.find_by_path(root)
61
+ data = YAML::load( File.open(src) )
62
+ #hash_to_page(data, target)
63
+ if target
64
+ if root == ''
65
+ hash_to_page_tree(data, target)
66
+ else
67
+ if page = target.children.find_by_slug(data['slug'])
68
+ hash_to_page_tree(data, page)
69
+ else
70
+ hash_to_page_tree(data, target.children.create)
71
+ end
72
+ end
73
+ else
74
+ puts "Could not find the page at '#{root}', import aborted!"
75
+ # TODO: Ask to create the specified path if it doesn't exist?
76
+ end
77
+ puts "Finished."
78
+ end
79
+
80
+ end
81
+
82
+ end