cortex-reaver 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/bin/cortex_reaver +9 -2
  2. data/lib/cortex_reaver.rb +61 -14
  3. data/lib/cortex_reaver/config.rb +6 -1
  4. data/lib/cortex_reaver/controller/journal.rb +3 -1
  5. data/lib/cortex_reaver/controller/main.rb +10 -9
  6. data/lib/cortex_reaver/controller/page.rb +4 -2
  7. data/lib/cortex_reaver/controller/photograph.rb +3 -1
  8. data/lib/cortex_reaver/controller/project.rb +1 -1
  9. data/lib/cortex_reaver/controller/tag.rb +1 -1
  10. data/lib/cortex_reaver/helper/canonical.rb +1 -1
  11. data/lib/cortex_reaver/helper/crud.rb +7 -15
  12. data/lib/cortex_reaver/helper/navigation.rb +16 -0
  13. data/lib/cortex_reaver/helper/pages.rb +62 -0
  14. data/lib/cortex_reaver/helper/tags.rb +2 -3
  15. data/lib/cortex_reaver/migrations/009_mysql.rb +8 -4
  16. data/lib/cortex_reaver/migrations/010_pageparents.rb +17 -0
  17. data/lib/cortex_reaver/model/page.rb +68 -7
  18. data/lib/cortex_reaver/plugin.rb +4 -0
  19. data/lib/cortex_reaver/public/css/main.css +4 -1
  20. data/lib/cortex_reaver/public/images/tag.gif +0 -0
  21. data/lib/cortex_reaver/public/js/autocompletefb.js +125 -0
  22. data/lib/cortex_reaver/snippets/ramaze/dispatcher/file.rb +1 -1
  23. data/lib/cortex_reaver/support/canonical.rb +42 -38
  24. data/lib/cortex_reaver/support/renderer.rb +10 -72
  25. data/lib/cortex_reaver/support/sequenceable.rb +1 -1
  26. data/lib/cortex_reaver/support/tags.rb +17 -6
  27. data/lib/cortex_reaver/version.rb +2 -2
  28. data/lib/cortex_reaver/view/journals/journal.rhtml +4 -3
  29. data/lib/cortex_reaver/view/pages/form.rhtml +1 -0
  30. data/lib/cortex_reaver/view/pages/list.rhtml +3 -3
  31. data/lib/cortex_reaver/view/pages/show.rhtml +2 -8
  32. data/lib/cortex_reaver/view/photographs/show.rhtml +1 -1
  33. data/lib/cortex_reaver/view/projects/show.rhtml +3 -2
  34. data/lib/cortex_reaver/view/tags/list.rhtml +4 -3
  35. data/lib/cortex_reaver/view/tags/show.rhtml +2 -2
  36. data/lib/cortex_reaver/view/text_layout.rhtml +12 -9
  37. data/lib/cortex_reaver/view/users/list.rhtml +2 -2
  38. metadata +11 -6
@@ -11,34 +11,11 @@ module CortexReaver
11
11
  require 'bluecloth'
12
12
  require 'hpricot'
13
13
  require 'coderay'
14
+ require 'sanitize'
14
15
 
15
- # Elements to allow in sanitized HTML.
16
- ELEMENTS = [
17
- 'a', 'b', 'blockquote', 'br', 'code', 'dd', 'dl', 'dt', 'em', 'i', 'li',
18
- 'ol', 'p', 'pre', 'small', 'strike', 'strong', 'sub', 'sup', 'u', 'ul'
19
- ]
20
-
21
- # Attributes to allow in sanitized HTML elements.
22
- ATTRIBUTES = {
23
- 'a' => ['href', 'title'],
24
- 'pre' => ['class']
25
- }
26
-
27
- # Attributes to add to sanitized HTML elements.
28
- ADD_ATTRIBUTES = {
29
- 'a' => {'rel' => 'nofollow'}
30
- }
31
-
32
- # Attributes that should be checked for valid protocols.
33
- PROTOCOL_ATTRIBUTES = {'a' => ['href']}
34
-
35
- # Valid protocols.
36
- PROTOCOLS = ['ftp', 'http', 'https', 'mailto']
37
-
38
-
39
16
  # Renders plain text and html to html. If parse_code isn't true, only
40
17
  # runs bluecloth on text *outside* any <code>...</code> blocks.
41
- def bluecloth(text, parse_code = true)
18
+ def bluecloth(text, parse_code = true, increment_headers = true)
42
19
  return text if text.nil?
43
20
 
44
21
  if parse_code
@@ -57,7 +34,12 @@ module CortexReaver
57
34
 
58
35
  if j != 0
59
36
  # Convert to bluecloth
60
- out << BlueCloth::new(text[0..j]).to_html
37
+ blue = BlueCloth::new(text[0..j]).to_html
38
+ if increment_headers
39
+ # Increment headings by two (h1, h2 are page/entry headers)
40
+ blue.gsub!(/<(\/)?h(\d)>/) { |match| "<#{$1}h#{$2.to_i + 2}>" }
41
+ end
42
+ out << blue
61
43
  end
62
44
  else
63
45
  # Find end of code block
@@ -129,7 +111,7 @@ module CortexReaver
129
111
  case prefix
130
112
  when 'image'
131
113
  # Create an inline image
132
- "<img src=\"#{target.public_path}\" alt=\"#{name.gsub('"', '&quot;')}\" title=\"#{name.gsub('"', '&quot')}\" />"
114
+ "<img class=\"attachment\" src=\"#{target.public_path}\" alt=\"#{name.gsub('"', '&quot;')}\" title=\"#{name.gsub('"', '&quot')}\" />"
133
115
  when 'url'
134
116
  # Create a URL
135
117
  target.public_path
@@ -171,54 +153,10 @@ module CortexReaver
171
153
  end
172
154
  end
173
155
 
174
- # Stolen wholesale from Ryan's Thoth (http://github.com/rgrove/thoth/)
175
- # Who adapted it from http://rid.onkulo.us/archives/14-sanitizing-html-with-ruby-and-hpricot
176
156
  def sanitize_html(html)
177
157
  return html if html.nil?
178
158
 
179
- h = Hpricot(html)
180
-
181
- h.search('*').each do |el|
182
- if el.elem?
183
- tag = el.name.downcase
184
-
185
- if ELEMENTS.include?(tag)
186
- if ATTRIBUTES.has_key?(tag)
187
- # Delete any attribute that isn't in the whitelist for this
188
- # particular element.
189
- el.raw_attributes.delete_if do |key, val|
190
- !ATTRIBUTES[tag].include?(key.downcase)
191
- end
192
-
193
- # Check applicable attributes for valid protocols.
194
- if PROTOCOL_ATTRIBUTES.has_key?(tag)
195
- el.raw_attributes.delete_if do |key, val|
196
- PROTOCOL_ATTRIBUTES[tag].include?(key.downcase) &&
197
- (!(val.downcase =~ /^([^:]+)\:/) || !PROTOCOLS.include?($1))
198
- end
199
- end
200
- else
201
- # Delete all attributes from elements with no whitelisted
202
- # attributes.
203
- el.raw_attributes = {}
204
- end
205
-
206
- # Add required attributes.
207
- if ADD_ATTRIBUTES.has_key?(tag)
208
- el.raw_attributes.merge!(ADD_ATTRIBUTES[tag])
209
- end
210
- else
211
- # Delete any element that isn't in the whitelist.
212
- el.parent.replace_child(el, el.children)
213
- end
214
- elsif el.comment?
215
- # Delete all comments, since it's possible to make IE execute JS
216
- # within conditional comments.
217
- el.swap('')
218
- end
219
- end
220
-
221
- h.to_s
159
+ Sanitize.clean(html, Sanitize::Config::BASIC)
222
160
  end
223
161
 
224
162
  # Default renderer
@@ -235,7 +235,7 @@ module CortexReaver
235
235
  # Returns a url for this record, viewed in an absolute window. TODO: handle non-default window sizes.
236
236
  def absolute_window_url(size = self.class.window_size)
237
237
  page = (Float(position) / size).floor
238
- self.class.url + '/page/' + page.to_s + '#' + self.class.to_s.underscore +
238
+ self.class.url + '/page/' + page.to_s + '#' + self.class.to_s.demodulize.underscore +
239
239
  '_' + send(self.class.canonical_name_attr)
240
240
  end
241
241
 
@@ -32,8 +32,13 @@ module CortexReaver
32
32
  remove_all_tags
33
33
  end
34
34
 
35
+ # Returns all models with ANY of the following tags
36
+ def self.tagged_with_any_of(tags)
37
+ tagged_with(tags, false)
38
+ end
39
+
35
40
  # Returns all models with ALL the following tags:
36
- def self.tagged_with(tags)
41
+ def self.tagged_with(tags, all=true)
37
42
  # Find map between this model and tags, e.g. pages_tags
38
43
  map = [table_name.to_s, 'tags'].sort.join('_').to_sym
39
44
 
@@ -48,11 +53,17 @@ module CortexReaver
48
53
  # to contain only rows with one of our interesting tags.
49
54
  #
50
55
  # Man, don't you wish MySQL had intersect?
51
- filter(:id =>
52
- CortexReaver.db[map].filter(:tag_id => ids).group(own_id).having(
53
- "count(*) = #{ids.size}"
54
- ).select(own_id)
55
- )
56
+ if all
57
+ filter(:id =>
58
+ CortexReaver.db[map].filter(:tag_id => ids).group(own_id).having(
59
+ "count(*) = #{ids.size}"
60
+ ).select(own_id)
61
+ )
62
+ else
63
+ filter(:id =>
64
+ CortexReaver.db[map].filter(:tag_id => ids).select(own_id)
65
+ )
66
+ end
56
67
  end
57
68
  end
58
69
  end
@@ -1,8 +1,8 @@
1
1
  module CortexReaver
2
2
  APP_NAME = 'Cortex Reaver'
3
- APP_VERSION = '0.0.6'
3
+ APP_VERSION = '0.0.7'
4
4
  APP_AUTHOR = 'aphyr'
5
5
  APP_EMAIL = 'aphyr@aphyr.com'
6
6
  APP_URL = 'http://aphyr.com'
7
- APP_COPYRIGHT = 'Copyright (c) 2008 aphyr <aphyr@aphyr.com>. All rights reserved.'
7
+ APP_COPYRIGHT = 'Copyright (c) 2009 aphyr <aphyr@aphyr.com>. All rights reserved.'
8
8
  end
@@ -1,4 +1,4 @@
1
- <div class="journal text-entry">
1
+ <div class="journal text-entry <%= @journal.tags.map {|t| 'tagged_' + t.name}.join(' ')%>">
2
2
  <h2><a id="journal_<%= @journal.name %>" href="<%= @journal.url %>"><%=h @journal.title %></a></h2>
3
3
  <div class="byline">
4
4
  <span class="written">
@@ -8,6 +8,7 @@
8
8
  </div>
9
9
  <div class="body">
10
10
  <%= @journal.body_cache %>
11
+ <div class="clear"></div>
11
12
  </div>
12
13
  <div class="footer">
13
14
  <ul class="actions">
@@ -16,11 +17,11 @@
16
17
  <%= @journal.comment_count %> <%= @journal.comment_count == 1 ? 'comment' : 'comments' %>
17
18
  </a></li>
18
19
  <% if admin? %>
19
- <li><a class="edit-link" href="/journals/edit/<%= @journal.name %>">
20
+ <li><a class="edit-link" href="/journals/edit/<%= @journal.id %>">
20
21
  <img src="/images/edit.gif" class="icon" alt="edit" /> Edit
21
22
  </a></li>
22
23
  <li >
23
- <%= A '<img src="/images/delete.gif" class="icon" alt="delete" /> Delete', :href => "/journals/delete/#{@journal.name}", :onclick => "return confirm('Are you sure you want to delete this journal?');" %>
24
+ <%= A '<img src="/images/delete.gif" class="icon" alt="delete" /> Delete', :href => "/journals/delete/#{@journal.id}", :onclick => "return confirm('Are you sure you want to delete this journal?');" %>
24
25
  </li>
25
26
  <% end %>
26
27
  </ul>
@@ -3,6 +3,7 @@
3
3
  <%= errors_on @page %>
4
4
 
5
5
  <form class="edit-form" action="<%= Rs(@form_action) %>" method="post" enctype="multipart/form-data">
6
+ <%= page_select 'page_id', :default_id => @page.page_id, :skip_id => @page.id, :description => 'Parent page' %>
6
7
  <%= form_p 'title', :model => @page %>
7
8
  <%= live_name_field @page %>
8
9
  <%= live_tags_field @page %>
@@ -11,13 +11,13 @@
11
11
  </tr>
12
12
  </thead>
13
13
  <tbody>
14
- <% @pages.each do |page| %>
14
+ <% @pages.all.each do |page| %>
15
15
  <tr>
16
16
  <td><%= A(page.name, :href => page.url) %></td>
17
17
  <td><%= page.title %></td>
18
18
  <% if admin? %>
19
- <td><a href="/pages/edit/<%= page.name %>">Edit</a></td>
20
- <td><%= A 'Delete', :href => "/page/delete/#{page.name}", :onclick => "return confirm('Are you sure you want to delete this page?');" %></td>
19
+ <td><a href="/pages/edit/<%= page.id %>">Edit</a></td>
20
+ <td><%= A 'Delete', :href => "/pages/delete/#{page.id}", :onclick => "return confirm('Are you sure you want to delete this page?');" %></td>
21
21
  <% end %>
22
22
  </tr>
23
23
  <% end %>
@@ -1,12 +1,6 @@
1
- <% if admin? %>
2
- <ul class="actions">
3
- <li><a href="/pages/edit/<%= @page.name %>">Edit</a></li>
4
- <li><a href="/pages/delete/<%= @page.name %>">Delete</a></li>
5
- </ul>
6
- <% end %>
7
-
8
- <div class="page" id="page_<%= @page.name %>">
1
+ <div class="page <%= @page.tags.map {|t| 'tagged_' + t.name}.join(' ')%>" id="page_<%= @page.name %>">
9
2
  <div class="body">
10
3
  <%= @page.body_cache %>
4
+ <div class="clear"></div>
11
5
  </div>
12
6
  </div>
@@ -20,7 +20,7 @@
20
20
  </li>
21
21
  <% if admin? %>
22
22
  <li>
23
- <%= A('Edit', :href => Rs(:edit, @photograph.name)) %>
23
+ <%= A('Edit', :href => Rs(:edit, @photograph.id)) %>
24
24
  </li>
25
25
  <% end %>
26
26
  <% if next_photo = @photograph.next %>
@@ -8,6 +8,7 @@
8
8
  </div>
9
9
  <div class="body">
10
10
  <%= @project.body_cache %>
11
+ <div class="clear"></div>
11
12
  </div>
12
13
  <%= attachment_list @project %>
13
14
  <div class="footer">
@@ -17,10 +18,10 @@
17
18
  <%= @project.comment_count %> <%= @project.comment_count == 1 ? 'comment' : 'comments' %>
18
19
  </a></li>
19
20
  <% if admin? %>
20
- <li><a href="/projects/edit/<%= @project.name %>">
21
+ <li><a href="/projects/edit/<%= @project.id %>">
21
22
  <img src="/images/edit.gif" class="icon" alt="edit" /> Edit
22
23
  </a></li>
23
- <li><%= A '<img src="/images/delete.gif" class="icon" alt="delete" /> Delete', :href => "/projects/delete/#{@project.name}", :onclick => "return confirm('Are you sure you want to delete this project?');" %></li>
24
+ <li><%= A '<img src="/images/delete.gif" class="icon" alt="delete" /> Delete', :href => "/projects/delete/#{@project.id}", :onclick => "return confirm('Are you sure you want to delete this project?');" %></li>
24
25
  <% end %>
25
26
  </ul>
26
27
  </div>
@@ -12,13 +12,14 @@
12
12
  </tr>
13
13
  </thead>
14
14
  <tbody>
15
- <% max_count = (@tags.order(:count).reverse.first || []).count %>
15
+ <% top_tag = @tags.order(:count).reverse.first %>
16
+ <% max_count = top_tag ? top_tag.count : 1 %>
16
17
  <% @tags.each do |tag| %>
17
18
  <tr>
18
19
  <td class="title"><%= A(tag.title, :href => tag.url) %></td>
19
20
  <% if admin? %>
20
- <td><a href="/tags/edit/<%= tag.name %>">Edit</a></td>
21
- <td><%= A 'Delete', :href => "/tags/delete/#{tag.name}", :onclick => "return confirm('Are you sure you want to delete this tag?');" %></td>
21
+ <td><a href="/tags/edit/<%= tag.id %>">Edit</a></td>
22
+ <td><%= A 'Delete', :href => "/tags/delete/#{tag.id}", :onclick => "return confirm('Are you sure you want to delete this tag?');" %></td>
22
23
  <% end %>
23
24
  <td class="count" style="width: <%= admin? ? 60 : 80 %>%"><div class="percent-bar" style="width: <%= tag.count.to_f / max_count * 100 %>%"><%= tag.count %></div></td>
24
25
  </tr>
@@ -41,10 +41,10 @@
41
41
  <div class="footer">
42
42
  <ul class="actions">
43
43
  <% if admin? and @tags.size == 1 %>
44
- <li><a href="/tags/edit/<%= @tags.first.name %>">
44
+ <li><a href="/tags/edit/<%= @tags.first.id %>">
45
45
  <img src="/images/edit.gif" class="icon" alt="comment" /> Edit
46
46
  </a></li>
47
- <li><%= A '<img src="/images/delete.gif" class="icon" alt="delete" /> Delete', :href => "/tags/delete/#{@tags.first.name}", :onclick => "return confirm('Are you sure you want to delete this tag?');" %></li>
47
+ <li><%= A '<img src="/images/delete.gif" class="icon" alt="delete" /> Delete', :href => "/tags/delete/#{@tags.first.id}", :onclick => "return confirm('Are you sure you want to delete this tag?');" %></li>
48
48
  <% end %>
49
49
  </ul>
50
50
  </div>
@@ -30,22 +30,25 @@
30
30
  <script type="text/javascript" src="/js/jquery.js"></script>
31
31
  <script type="text/javascript" defer="defer" src="/js/cookie.js"></script>
32
32
  <script type="text/javascript" defer="defer" src="/js/admin.js"></script>
33
+ <% if admin? %>
34
+ <script type="text/javascript" defer="defer" src="/js/autocompletefb.js"></script>
35
+ <% end %>
33
36
 
34
37
  <div id="top">
35
38
  <a href="/">
36
- <img id="header" src="/images/header.png" alt="Aphyr" />
39
+ <img id="header" src="/images/header.png" alt="<%= attr_h CortexReaver.config[:site][:name] %>" />
37
40
  </a>
38
41
  </div>
39
42
 
40
43
  <div id="sections">
41
- <ul>
42
- <li><a href="/journals">Journal</a></li>
43
- <li><a href="/photographs">Photography</a></li>
44
- <li><a href="/projects">Projects</a></li>
45
- <li><a href="/tags">Tags</a></li>
46
- <li><a href="/comments">Comments</a></li>
47
- <li><a href="/about">About</a></li>
48
- </ul>
44
+ <%= section_nav([
45
+ ['Journals', '/journals'],
46
+ ['Photographs', '/photographs'],
47
+ ['Projects', '/projects'],
48
+ ['Tags', '/tags'],
49
+ ['Comments', '/comments'],
50
+ ['About', '/about']
51
+ ]) %>
49
52
  </div>
50
53
 
51
54
  <div id="middle">
@@ -20,12 +20,12 @@
20
20
  <td><%= h user.name %></td>
21
21
  <% if admin? %>
22
22
  <td>
23
- <a class="edit-link" href="/users/edit/<%= user.login %>">
23
+ <a class="edit-link" href="/users/edit/<%= user.id %>">
24
24
  <img src="/images/edit.gif" class="icon" alt="edit" /> Edit
25
25
  </a>
26
26
  </td>
27
27
  <td>
28
- <%= A '<img src="/images/delete.gif" class="icon" alt="delete" /> Delete', :href => "/users/delete/#{user.login}", :onclick => "return confirm('Are you sure you want to delete this user?');" %>
28
+ <%= A '<img src="/images/delete.gif" class="icon" alt="delete" /> Delete', :href => "/users/delete/#{user.id}", :onclick => "return confirm('Are you sure you want to delete this user?');" %>
29
29
  </td>
30
30
  <% end %>
31
31
  </tr>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cortex-reaver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - aphyr
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-29 00:00:00 -06:00
12
+ date: 2009-03-18 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - "="
22
22
  - !ruby/object:Gem::Version
23
- version: "2008.11"
23
+ version: "2009.02"
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: builder
@@ -43,14 +43,14 @@ dependencies:
43
43
  version: 2.6.2
44
44
  version:
45
45
  - !ruby/object:Gem::Dependency
46
- name: hpricot
46
+ name: sanitize
47
47
  type: :runtime
48
48
  version_requirement:
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: "0.6"
53
+ version: 1.0.6
54
54
  version:
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: BlueCloth
@@ -70,7 +70,7 @@ dependencies:
70
70
  requirements:
71
71
  - - ~>
72
72
  - !ruby/object:Gem::Version
73
- version: 2.7.1
73
+ version: 2.11.0
74
74
  version:
75
75
  - !ruby/object:Gem::Dependency
76
76
  name: thin
@@ -124,6 +124,7 @@ files:
124
124
  - lib/cortex_reaver/helper/photographs.rb
125
125
  - lib/cortex_reaver/helper/date.rb
126
126
  - lib/cortex_reaver/helper/auth.rb
127
+ - lib/cortex_reaver/helper/pages.rb
127
128
  - lib/cortex_reaver/helper/workflow.rb
128
129
  - lib/cortex_reaver/helper/navigation.rb
129
130
  - lib/cortex_reaver/helper/error.rb
@@ -203,6 +204,7 @@ files:
203
204
  - lib/cortex_reaver/view/blank_layout.rhtml
204
205
  - lib/cortex_reaver/view/documentation
205
206
  - lib/cortex_reaver/view/documentation/formatting.rhtml
207
+ - lib/cortex_reaver/plugin.rb
206
208
  - lib/cortex_reaver/model
207
209
  - lib/cortex_reaver/model/comment.rb
208
210
  - lib/cortex_reaver/model/project.rb
@@ -228,6 +230,7 @@ files:
228
230
  - lib/cortex_reaver/public/images/border_bottom_right.png
229
231
  - lib/cortex_reaver/public/images/dark_trans.png
230
232
  - lib/cortex_reaver/public/images/border_bottom_left.png
233
+ - lib/cortex_reaver/public/images/tag.gif
231
234
  - lib/cortex_reaver/public/images/comment.gif
232
235
  - lib/cortex_reaver/public/images/body.png
233
236
  - lib/cortex_reaver/public/images/border_top_right.png
@@ -237,6 +240,7 @@ files:
237
240
  - lib/cortex_reaver/public/images/rss-xml-icon.png
238
241
  - lib/cortex_reaver/public/js
239
242
  - lib/cortex_reaver/public/js/jquery.js
243
+ - lib/cortex_reaver/public/js/autocompletefb.js
240
244
  - lib/cortex_reaver/public/js/admin.js
241
245
  - lib/cortex_reaver/public/js/photo.js
242
246
  - lib/cortex_reaver/public/js/cookie.js
@@ -264,6 +268,7 @@ files:
264
268
  - lib/cortex_reaver/migrations/005_projects.rb
265
269
  - lib/cortex_reaver/migrations/006_tags.rb
266
270
  - lib/cortex_reaver/migrations/008_config.rb
271
+ - lib/cortex_reaver/migrations/010_pageparents.rb
267
272
  - lib/cortex_reaver/migrations/007_comments.rb
268
273
  - lib/cortex_reaver/migrations/009_mysql.rb
269
274
  - lib/cortex_reaver/migrations/001_users.rb