zen 0.2.3 → 0.2.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 (56) hide show
  1. data/CHANGELOG.md +12 -2
  2. data/MANIFEST +17 -10
  3. data/ROADMAP.md +8 -4
  4. data/bin/zen +2 -3
  5. data/lib/zen.rb +20 -14
  6. data/lib/zen/bin/{zen_binary.rb → base.rb} +0 -0
  7. data/lib/zen/controller/main_controller.rb +7 -4
  8. data/lib/zen/{base/database.rb → database.rb} +3 -2
  9. data/lib/zen/error/language_error.rb +10 -0
  10. data/lib/zen/error/package_error.rb +10 -0
  11. data/lib/zen/error/plugin_error.rb +10 -0
  12. data/lib/zen/error/theme_error.rb +10 -0
  13. data/lib/zen/helper/acl.rb +11 -4
  14. data/lib/zen/{base/language.rb → language.rb} +11 -3
  15. data/lib/zen/layout/admin.xhtml +21 -12
  16. data/lib/zen/layout/login.xhtml +17 -11
  17. data/lib/zen/liquid/general.rb +1 -27
  18. data/lib/zen/{base/logger.rb → logger.rb} +0 -0
  19. data/lib/zen/{base/package.rb → package.rb} +65 -55
  20. data/lib/zen/package/all.rb +5 -0
  21. data/lib/zen/package/categories/lib/categories.rb +7 -8
  22. data/lib/zen/package/comments/lib/comments.rb +7 -8
  23. data/lib/zen/package/comments/lib/comments/controller/comments_form.rb +1 -1
  24. data/lib/zen/package/comments/lib/comments/liquid/comments.rb +3 -1
  25. data/lib/zen/package/custom_fields/lib/custom_fields.rb +7 -8
  26. data/lib/zen/package/custom_fields/lib/custom_fields/model/custom_field_value.rb +14 -0
  27. data/lib/zen/package/custom_fields/migrations/1295255665_create_schema.rb +1 -1
  28. data/lib/zen/package/menus/lib/menus.rb +5 -6
  29. data/lib/zen/package/sections/lib/sections.rb +4 -5
  30. data/lib/zen/package/sections/lib/sections/language/en/section_entries.yml +2 -2
  31. data/lib/zen/package/sections/lib/sections/liquid/section_entries.rb +9 -2
  32. data/lib/zen/package/settings/lib/settings.rb +7 -8
  33. data/lib/zen/package/users/lib/users.rb +7 -8
  34. data/lib/zen/package/users/lib/users/view/admin/access-rules/form.xhtml +5 -5
  35. data/lib/zen/package/users/lib/users/view/admin/access-rules/index.xhtml +4 -4
  36. data/lib/zen/plugin.rb +172 -0
  37. data/lib/zen/plugin/markup.rb +30 -0
  38. data/lib/zen/public/admin/css/layout.css +17 -0
  39. data/lib/zen/strict_struct.rb +36 -0
  40. data/lib/zen/task/db.rb +14 -4
  41. data/lib/zen/task/package.rb +13 -8
  42. data/lib/zen/task/theme.rb +88 -0
  43. data/lib/zen/theme.rb +129 -0
  44. data/lib/zen/{base/version.rb → version.rb} +1 -1
  45. data/proto/app/config/config.rb +19 -6
  46. data/proto/app/config/database.rb +58 -2
  47. data/proto/app/config/middlewares.rb +69 -4
  48. data/proto/app/config/requires.rb +9 -2
  49. data/proto/app/{logs → log}/.gitkeep +0 -0
  50. data/proto/package/lib/package.rb +3 -13
  51. data/proto/package/lib/package/controller/controllers.rb +5 -9
  52. data/proto/package/lib/package/language/en/languages.yml +4 -0
  53. metadata +66 -26
  54. data/proto/package/LICENSE +0 -0
  55. data/proto/package/README.textile +0 -0
  56. data/proto/package/lib/package/language/en/languages.rb +0 -3
@@ -196,7 +196,12 @@ module Sections
196
196
  end
197
197
  end
198
198
 
199
- values['comment'] = markup_to_html(values['comment'], entry.section.comment_format)
199
+ values['comment'] = Zen::Plugin.call(
200
+ 'com.zen.plugin.markup',
201
+ entry.section.comment_format.to_sym,
202
+ values['comment']
203
+ )
204
+
200
205
  context['comments'].push(values)
201
206
  end
202
207
 
@@ -204,7 +209,9 @@ module Sections
204
209
  entry.custom_field_values.each do |field_value|
205
210
  field = field_value.custom_field
206
211
  name = field.slug
207
- value = markup_to_html(field_value.value, field.format.to_sym)
212
+ value = ::Zen::Plugin.call(
213
+ 'com.zen.plugin.markup', field.format.to_sym, field_value.value
214
+ )
208
215
 
209
216
  context[name.to_s] = value
210
217
  end
@@ -6,14 +6,13 @@ require __DIR__ 'settings/liquid/setting'
6
6
  Liquid::Template.register_tag('setting', Settings::Liquid::Setting)
7
7
 
8
8
  Zen::Package.add do |p|
9
- p.type = 'extension'
10
- p.name = 'Settings'
11
- p.author = 'Yorick Peterse'
12
- p.url = 'http://yorickpeterse.com/'
13
- p.version = 1.0
14
- p.about = 'Module for managing settings such as the default module, whether or not to allow registration, etc.'
15
- p.identifier = 'com.zen.settings'
16
- p.directory = __DIR__('settings')
9
+ p.name = 'Settings'
10
+ p.author = 'Yorick Peterse'
11
+ p.url = 'http://yorickpeterse.com/'
12
+ p.about = 'Module for managing settings such as the default module, whether or not to allow registration, etc.'
13
+ p.identifier = 'com.zen.settings'
14
+ p.directory = __DIR__('settings')
15
+ p.migration_dir = __DIR__('../migrations')
17
16
 
18
17
  p.menu = [{
19
18
  :title => "Settings",
@@ -18,15 +18,14 @@ Liquid::Template.register_tag('user' , Users::Liquid::User)
18
18
  Zen::Controllers::BaseController.trait(:user_model => Users::Models::User)
19
19
 
20
20
  Zen::Package.add do |p|
21
- p.type = 'extension'
22
- p.name = 'Users'
23
- p.author = 'Yorick Peterse'
24
- p.url = 'http://yorickpeterse.com/'
25
- p.version = '1.0'
26
- p.about = "Module for managing users along with handling authentication and authorization."
21
+ p.name = 'Users'
22
+ p.author = 'Yorick Peterse'
23
+ p.url = 'http://yorickpeterse.com/'
24
+ p.about = "Module for managing users along with handling authentication and authorization."
27
25
 
28
- p.identifier = 'com.zen.users'
29
- p.directory = __DIR__('users')
26
+ p.identifier = 'com.zen.users'
27
+ p.directory = __DIR__('users')
28
+ p.migration_dir = __DIR__('../migrations')
30
29
 
31
30
  p.menu = [{
32
31
  :title => "Users",
@@ -18,7 +18,7 @@
18
18
  users[user.id.to_s] = user.name
19
19
  end
20
20
 
21
- Zen::Package.extensions.each do |ident, ext|
21
+ Zen::Package.packages.each do |ident, ext|
22
22
  extensions[ident] = ext.name
23
23
  end
24
24
 
@@ -74,28 +74,28 @@
74
74
  lang('access_rules.labels.create'),
75
75
  :create_access,
76
76
  @access_rule.create_access,
77
- :values => @boolean_hash.invert
77
+ :values => @boolean_hash
78
78
  )
79
79
 
80
80
  f.input_radio(
81
81
  lang('access_rules.labels.read'),
82
82
  :read_access,
83
83
  @access_rule.read_access,
84
- :values => @boolean_hash.invert
84
+ :values => @boolean_hash
85
85
  )
86
86
 
87
87
  f.input_radio(
88
88
  lang('access_rules.labels.update'),
89
89
  :update_access,
90
90
  @access_rule.update_access,
91
- :values => @boolean_hash.invert
91
+ :values => @boolean_hash
92
92
  )
93
93
 
94
94
  f.input_radio(
95
95
  lang('access_rules.labels.delete'),
96
96
  :delete_access,
97
97
  @access_rule.delete_access,
98
- :values => @boolean_hash.invert
98
+ :values => @boolean_hash
99
99
  )
100
100
 
101
101
  f.g.div(:class => 'clearfix') do
@@ -49,10 +49,10 @@
49
49
  <td>#{rule.extension}</td>
50
50
  <?r end ?>
51
51
 
52
- <td>#{@boolean_hash[rule.create_access]}</td>
53
- <td>#{@boolean_hash[rule.read_access]}</td>
54
- <td>#{@boolean_hash[rule.update_access]}</td>
55
- <td>#{@boolean_hash[rule.delete_access]}</td>
52
+ <td>#{@boolean_hash.invert[rule.create_access]}</td>
53
+ <td>#{@boolean_hash.invert[rule.read_access]}</td>
54
+ <td>#{@boolean_hash.invert[rule.update_access]}</td>
55
+ <td>#{@boolean_hash.invert[rule.delete_access]}</td>
56
56
  <td>
57
57
  <?r if !rule.user_id.nil? ?>
58
58
  #{rule.user.name}
@@ -0,0 +1,172 @@
1
+ require __DIR__('error/plugin_error')
2
+
3
+ #:nodoc:
4
+ module Zen
5
+ ##
6
+ # Plugins in Zen are quite similar to packages except for a few differences. The biggest
7
+ # difference is that plugins won't update any Ramaze root directories or language
8
+ # direactories. This means that they can't have controllers, models and so on. On top
9
+ # of that they're nothing more than lambda's. Plugins are useful for supporting multiple
10
+ # markup formats (Markdown, Textile, etc) and other small tasks such as replacing Email
11
+ # addresses and so on.
12
+ #
13
+ # ## Creating Plugins
14
+ #
15
+ # Creating plugins works in a similar way as creating packages. Plugins are added by
16
+ # calling Zen::Plugin#add and passing a block to it with details such as the name of
17
+ # the plugin, the author, the identifier and a list of actions. The last two are very
18
+ # important as the plugin won't work without them.
19
+ #
20
+ # ### Actions
21
+ #
22
+ # Each plugin has a getter/setter called "actions", this is just a simple key/value
23
+ # hash where the keys are the names of the actions and the values lambda's. The keys
24
+ # should always be symbols. Example:
25
+ #
26
+ # actions = {
27
+ # :downcase => lambda do |string|
28
+ # string.downcase
29
+ # end
30
+ # }
31
+ #
32
+ # Note that you don't *have to* use lambda's, anything that responds to call() will do.
33
+ #
34
+ # Because the actions method contains just a hash you can easily add functionality to
35
+ # existing plugins as following:
36
+ #
37
+ # # First retrieve our plugin
38
+ # plugin = Zen::Plugin['com.something.plugin.name']
39
+ # plugin.actions[:my_action] = lamda do
40
+ # # Do something....
41
+ # end
42
+ #
43
+ # This can be very useful for extending plugins such as the markup plugin that's used to
44
+ # convert Markdown or Textile to HTML. By default this plugin only converts Markdown and
45
+ # Textile or HTML (it escapes all HTML) but by modifying the actions hash we can easily
46
+ # add new markup engines such as RDoc or even Latex.
47
+ #
48
+ # ## Calling Plugins
49
+ #
50
+ # Plugins can be called using Zen::Plugin#call, this method requires you to specify the
51
+ # plugin identifier, the action to call and optionally any data to send to the plugin.
52
+ # An example of calling a plugin would look like the following:
53
+ #
54
+ # Zen::Plugin.call('com.zen.plugin.markup', :markdown, 'hello **world**')
55
+ #
56
+ # ## Identifiers
57
+ #
58
+ # Plugin identifiers should always have the following format:
59
+ #
60
+ # com.VENDOR.plugin.NAME
61
+ #
62
+ # For example:
63
+ #
64
+ # com.zen.plugin.markup
65
+ #
66
+ # @author Yorick Peterse
67
+ # @since 0.2.4
68
+ # @attr_reader [Hash] plugins Hash containing all plugins.
69
+ #
70
+ module Plugin
71
+ class << self
72
+ attr_reader :plugins
73
+ end
74
+
75
+ ##
76
+ # Adds a new plugin with the given details.
77
+ #
78
+ # @example
79
+ # Zen::Plugin.add do |p|
80
+ # p.name = 'Markup'
81
+ # p.author = 'Yorick Peterse'
82
+ # p.actions = {
83
+ # :markdown => lambda do |markup|
84
+ # RDiscount.new(markup).to_html
85
+ # end
86
+ # end
87
+ #
88
+ # @author Yorick Peterse
89
+ # @since 0.2.4
90
+ # @yield [plugin] Struct object containing all the details of a plugin.
91
+ # @raise [Zen::PluginError] Error raised whenever the plugin already exists or is missing
92
+ # a certain setter.
93
+ #
94
+ def self.add
95
+ @plugins ||= {}
96
+ required = [:name, :author, :about, :identifier, :actions]
97
+ plugin = Zen::StrictStruct.new(
98
+ :name, :author, :about, :url, :identifier, :actions
99
+ ).new
100
+
101
+ yield plugin
102
+
103
+ # Check if all the required keys have been set
104
+ plugin.validate(required) do |k|
105
+ raise(Zen::PluginError, "The following plugin key is missing: #{k}")
106
+ end
107
+
108
+ # The actions getter should be a hash
109
+ if plugin.actions.class != Hash
110
+ raise(Zen::PluginError, "The actions setter/getter should be an instance of Hash.")
111
+ end
112
+
113
+ # Add our plugin
114
+ if !@plugins[plugin.identifier].nil?
115
+ raise(Zen::PluginError, "The plugin #{plugin.name} already exists.")
116
+ end
117
+
118
+ @plugins[plugin.identifier] = plugin
119
+ end
120
+
121
+ ##
122
+ # Returns a plugin for the given identifier.
123
+ #
124
+ # @example
125
+ # Zen::Plugin['com.zen.plugin.markup']
126
+ #
127
+ # @author Yorick Peterse
128
+ # @since 0.2.4
129
+ # @param [String] ident The plugin identifier.
130
+ # @raise Zen::PluginError Error that's raised when no plugins have been added yet or
131
+ # the specified plugin doesn't exist.
132
+ # @return [Struct] Instance of the plugin.
133
+ #
134
+ def self.[](ident)
135
+ if @plugins.nil?
136
+ raise(Zen::PluginError, "No plugins have been added.")
137
+ end
138
+
139
+ if !@plugins[ident]
140
+ raise(Zen::PluginError, "The plugin #{ident} doesn't exist.")
141
+ end
142
+
143
+ return @plugins[ident]
144
+ end
145
+
146
+ ##
147
+ # Calls the plugin for the given identifier and executes the action.
148
+ #
149
+ # @example
150
+ # Zen::Plugin.call('com.zen.foobar', :markdown, 'hello **world**')
151
+ #
152
+ # @author Yorick Peterse
153
+ # @since 0.2.4
154
+ # @param [String] ident The plugin identifier.
155
+ # @param [Symbol] action The plugin action to call.
156
+ # @param [Array] data Any data to pass to the plugin's action (a lambda).
157
+ # @return [Mixed]
158
+ #
159
+ def self.call(ident, action, *data)
160
+ plugin = self[ident]
161
+ action = action.to_sym
162
+
163
+ if !plugin.actions[action]
164
+ raise(Zen::PluginError, "The action #{action} doesn't exist for #{ident}.")
165
+ end
166
+
167
+ # Call the plugin and return it's value
168
+ return plugin.actions[action].call(*data)
169
+ end
170
+
171
+ end
172
+ end
@@ -0,0 +1,30 @@
1
+ Zen::Plugin.add do |plugin|
2
+ plugin.name = 'Markup'
3
+ plugin.author = 'Yorick Peterse'
4
+ plugin.about = 'Plugin used for converting various markup formats to HTML.'
5
+ plugin.identifier = 'com.zen.plugin.markup'
6
+ plugin.actions = {
7
+
8
+ # Converts HTML to, well, HTML.
9
+ :html => lambda do |markup|
10
+ markup
11
+ end,
12
+
13
+ # Converts the given markup to plain text by escaping all HTML
14
+ :plain => lambda do |markup|
15
+ include Ramaze::Helper::CGI
16
+ h(markup)
17
+ end,
18
+
19
+ # Comvert Markdown documents to HTML
20
+ :markdown => lambda do |markup|
21
+ RDiscount.new(markup).to_html
22
+ end,
23
+
24
+ # Convert Textile documents to HTML
25
+ :textile => lambda do |markup|
26
+ RedCloth.new(markup).to_html
27
+ end
28
+
29
+ }
30
+ end
@@ -103,6 +103,7 @@
103
103
  margin: 20px auto;
104
104
  width: 500px;
105
105
  }
106
+
106
107
  #login #container
107
108
  {
108
109
  margin-top: 50px;
@@ -116,7 +117,23 @@
116
117
  margin-top: 20px;
117
118
  text-align: center;
118
119
  }
120
+
119
121
  #main_footer p
120
122
  {
121
123
  margin-bottom: 8px;
124
+ margin: 0 auto 8px auto;
125
+ width: 300px;
126
+ }
127
+
128
+ #main_footer ul
129
+ {
130
+ list-style-type: none;
131
+ margin: 0 auto;
132
+ width: 300px;
122
133
  }
134
+ #main_footer ul li
135
+ {
136
+ float: left;
137
+ margin: 0px 8px;
138
+ text-align: center;
139
+ }
@@ -0,0 +1,36 @@
1
+ #:nodoc:
2
+ module Zen
3
+ ##
4
+ # StrictStruct is a simple extension of the Struct class, it provides a method that
5
+ # checks if all getters/setters have a value and if one doesn't it will call the
6
+ # appropriate block.
7
+ #
8
+ # @author Yorick Peterse
9
+ # @since 0.2.4
10
+ #
11
+ class StrictStruct < Struct
12
+
13
+ ##
14
+ # Validates all getter/setters in the current class to see if all values are set.
15
+ #
16
+ # @example
17
+ # struct = Zen::StrictStruct.new(:name, :age).new
18
+ # struct.validate([:name, :age]) do |k|
19
+ # puts "The key #{k} is required!"
20
+ # end
21
+ #
22
+ # @author Yorick Peterse
23
+ # @since 0.2.4
24
+ # @param [Array] required Array of getters that should return a value.
25
+ # @param [Block] block The block to call whenever an item doesn't have a value.
26
+ #
27
+ def validate(required, &block)
28
+ required.each do |k|
29
+ if !self.respond_to?(k) or self.send(k).nil?
30
+ block.call(k)
31
+ end
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -22,12 +22,17 @@ module Zen
22
22
  # @since 0.2
23
23
  #
24
24
  def migrate(show_output = true)
25
- exts = Zen::Package.extensions
25
+ exts = Zen::Package.packages
26
26
 
27
27
  puts "Migrating..." if show_output === true
28
28
 
29
29
  exts.each do |ident, ext|
30
- dir = ext.directory + '/../../migrations'
30
+ if ext.respond_to?(:migration_dir) and !ext.migration_dir.nil?
31
+ dir = ext.migration_dir
32
+ else
33
+ dir = ext.directory + '/../../migrations'
34
+ end
35
+
31
36
  table = ext.identifier.gsub('.', '_').to_sym
32
37
 
33
38
  if File.directory?(dir)
@@ -49,10 +54,15 @@ module Zen
49
54
  # @since 0.2
50
55
  #
51
56
  def delete
52
- exts = Zen::Package.extensions.map { |ident, ext| [ident, ext] }
57
+ exts = Zen::Package.packages.map { |ident, ext| [ident, ext] }
53
58
 
54
59
  exts.reverse.each do |ident, ext|
55
- dir = ext.directory + '/../../migrations'
60
+ if ext.respond_to?(:migration_dir) and !ext.migration_dir.nil?
61
+ dir = ext.migration_dir
62
+ else
63
+ dir = ext.directory + '/../../migrations'
64
+ end
65
+
56
66
  table = ext.identifier.gsub('.', '_').to_sym
57
67
 
58
68
  if File.directory?(dir)
@@ -14,19 +14,18 @@ module Zen
14
14
  desc('list', 'Lists all installed packages')
15
15
 
16
16
  ##
17
- # Lists all installed extensions.
17
+ # Lists all installed packages
18
18
  #
19
19
  # @author Yorick Peterse
20
20
  # @since 0.2
21
21
  #
22
22
  def list
23
23
  table = []
24
- table.push(['Name', 'Author', 'Identifier', 'Version', 'Type', 'Directory'])
25
- table.push(['------', '------', '------', '------', '------','------'])
26
- packages = Zen::Package.extensions.merge(Zen::Package.themes)
24
+ table.push(['Name', 'Author', 'Identifier', 'Directory'])
25
+ table.push(['------', '------', '------', '------'])
27
26
 
28
- packages.each do |ident, ext|
29
- table.push([ext.name, ext.author, ext.identifier, ext.version.to_s, ext.type, ext.directory])
27
+ Zen::Package.packages.each do |ident, ext|
28
+ table.push([ext.name, ext.author, ext.identifier, ext.directory])
30
29
  end
31
30
 
32
31
  print_table(table)
@@ -47,7 +46,7 @@ module Zen
47
46
  version = options[:version]
48
47
  ident = options[:identifier]
49
48
 
50
- if Zen::Package.extensions.nil? or Zen::Package.extensions.empty?
49
+ if Zen::Package.packages.nil? or Zen::Package.extensions.empty?
51
50
  abort "No packages have been loaded. Be sure to add them to config/requires.rb."
52
51
  end
53
52
 
@@ -61,7 +60,13 @@ module Zen
61
60
  abort "You specified an invalid identifier."
62
61
  end
63
62
 
64
- dir = install_ext.directory + '/../../migrations'
63
+ # Get the directory from the migration_dir getter, generate it if it isn't there.
64
+ if install_ext.respond_to?(:migration_dir) and !install_ext.migration_dir.nil?
65
+ dir = install_ext.migration_dir
66
+ else
67
+ dir = install_ext.directory + '/../../migrations'
68
+ end
69
+
65
70
  table = install_ext.identifier.gsub('.', '_').to_sym
66
71
 
67
72
  puts "Migrating package..."