cortex-reaver 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/LICENSE +25 -0
  2. data/README +48 -0
  3. data/bin/console +11 -0
  4. data/bin/cortex_reaver +110 -0
  5. data/bin/import.rb +78 -0
  6. data/lib/cortex_reaver.rb +114 -0
  7. data/lib/cortex_reaver/config.rb +21 -0
  8. data/lib/cortex_reaver/controller/comment.rb +113 -0
  9. data/lib/cortex_reaver/controller/config.rb +14 -0
  10. data/lib/cortex_reaver/controller/journal.rb +40 -0
  11. data/lib/cortex_reaver/controller/main.rb +56 -0
  12. data/lib/cortex_reaver/controller/page.rb +34 -0
  13. data/lib/cortex_reaver/controller/photograph.rb +45 -0
  14. data/lib/cortex_reaver/controller/project.rb +40 -0
  15. data/lib/cortex_reaver/controller/tag.rb +67 -0
  16. data/lib/cortex_reaver/controller/user.rb +71 -0
  17. data/lib/cortex_reaver/helper/activity.rb +9 -0
  18. data/lib/cortex_reaver/helper/attachments.rb +139 -0
  19. data/lib/cortex_reaver/helper/auth.rb +45 -0
  20. data/lib/cortex_reaver/helper/canonical.rb +55 -0
  21. data/lib/cortex_reaver/helper/crud.rb +317 -0
  22. data/lib/cortex_reaver/helper/date.rb +29 -0
  23. data/lib/cortex_reaver/helper/error.rb +14 -0
  24. data/lib/cortex_reaver/helper/feeds.rb +88 -0
  25. data/lib/cortex_reaver/helper/form.rb +114 -0
  26. data/lib/cortex_reaver/helper/navigation.rb +142 -0
  27. data/lib/cortex_reaver/helper/photographs.rb +25 -0
  28. data/lib/cortex_reaver/helper/tags.rb +47 -0
  29. data/lib/cortex_reaver/helper/workflow.rb +27 -0
  30. data/lib/cortex_reaver/migrations/001_users.rb +24 -0
  31. data/lib/cortex_reaver/migrations/002_pages.rb +29 -0
  32. data/lib/cortex_reaver/migrations/003_journals.rb +26 -0
  33. data/lib/cortex_reaver/migrations/004_photographs.rb +24 -0
  34. data/lib/cortex_reaver/migrations/005_projects.rb +27 -0
  35. data/lib/cortex_reaver/migrations/006_tags.rb +64 -0
  36. data/lib/cortex_reaver/migrations/007_comments.rb +40 -0
  37. data/lib/cortex_reaver/migrations/008_config.rb +23 -0
  38. data/lib/cortex_reaver/model/comment.rb +109 -0
  39. data/lib/cortex_reaver/model/journal.rb +53 -0
  40. data/lib/cortex_reaver/model/page.rb +87 -0
  41. data/lib/cortex_reaver/model/photograph.rb +133 -0
  42. data/lib/cortex_reaver/model/project.rb +49 -0
  43. data/lib/cortex_reaver/model/tag.rb +72 -0
  44. data/lib/cortex_reaver/model/user.rb +147 -0
  45. data/lib/cortex_reaver/public/css/admin.css +45 -0
  46. data/lib/cortex_reaver/public/css/custom.css +0 -0
  47. data/lib/cortex_reaver/public/css/form.css +51 -0
  48. data/lib/cortex_reaver/public/css/main.css +325 -0
  49. data/lib/cortex_reaver/public/css/photo.css +113 -0
  50. data/lib/cortex_reaver/public/css/ramaze_error.css +90 -0
  51. data/lib/cortex_reaver/public/css/text.css +25 -0
  52. data/lib/cortex_reaver/public/dispatch.fcgi +11 -0
  53. data/lib/cortex_reaver/public/images/CortexReaver.gif +0 -0
  54. data/lib/cortex_reaver/public/images/atom-xml-icon.png +0 -0
  55. data/lib/cortex_reaver/public/images/body.png +0 -0
  56. data/lib/cortex_reaver/public/images/border_bottom.png +0 -0
  57. data/lib/cortex_reaver/public/images/border_bottom_left.png +0 -0
  58. data/lib/cortex_reaver/public/images/border_bottom_right.png +0 -0
  59. data/lib/cortex_reaver/public/images/border_left.png +0 -0
  60. data/lib/cortex_reaver/public/images/border_right.png +0 -0
  61. data/lib/cortex_reaver/public/images/border_top.png +0 -0
  62. data/lib/cortex_reaver/public/images/border_top_left.png +0 -0
  63. data/lib/cortex_reaver/public/images/border_top_right.png +0 -0
  64. data/lib/cortex_reaver/public/images/comment.gif +0 -0
  65. data/lib/cortex_reaver/public/images/dark_trans.png +0 -0
  66. data/lib/cortex_reaver/public/images/delete.gif +0 -0
  67. data/lib/cortex_reaver/public/images/edit.gif +0 -0
  68. data/lib/cortex_reaver/public/images/header.png +0 -0
  69. data/lib/cortex_reaver/public/images/header.xcf +0 -0
  70. data/lib/cortex_reaver/public/images/header_background.png +0 -0
  71. data/lib/cortex_reaver/public/images/parent.gif +0 -0
  72. data/lib/cortex_reaver/public/images/rss-xml-icon.png +0 -0
  73. data/lib/cortex_reaver/public/images/sections.png +0 -0
  74. data/lib/cortex_reaver/public/images/sections_highlight.png +0 -0
  75. data/lib/cortex_reaver/public/js/admin.js +36 -0
  76. data/lib/cortex_reaver/public/js/cookie.js +27 -0
  77. data/lib/cortex_reaver/public/js/jquery.js +32 -0
  78. data/lib/cortex_reaver/public/js/photo.js +33 -0
  79. data/lib/cortex_reaver/snippets/array.rb +7 -0
  80. data/lib/cortex_reaver/snippets/ramaze/dispatcher/file.rb +37 -0
  81. data/lib/cortex_reaver/support/attachments.rb +235 -0
  82. data/lib/cortex_reaver/support/cached_rendering.rb +79 -0
  83. data/lib/cortex_reaver/support/canonical.rb +107 -0
  84. data/lib/cortex_reaver/support/comments.rb +69 -0
  85. data/lib/cortex_reaver/support/pagination.rb +38 -0
  86. data/lib/cortex_reaver/support/renderer.rb +196 -0
  87. data/lib/cortex_reaver/support/sequenceable.rb +248 -0
  88. data/lib/cortex_reaver/support/tags.rb +108 -0
  89. data/lib/cortex_reaver/support/timestamps.rb +33 -0
  90. data/lib/cortex_reaver/version.rb +8 -0
  91. data/lib/cortex_reaver/view/adminbox.rhtml +56 -0
  92. data/lib/cortex_reaver/view/blank_layout.rhtml +46 -0
  93. data/lib/cortex_reaver/view/comments/comment.rhtml +34 -0
  94. data/lib/cortex_reaver/view/comments/form.rhtml +25 -0
  95. data/lib/cortex_reaver/view/comments/list.rhtml +5 -0
  96. data/lib/cortex_reaver/view/comments/post_form.rhtml +36 -0
  97. data/lib/cortex_reaver/view/config/form.rhtml +10 -0
  98. data/lib/cortex_reaver/view/error.rhtml +72 -0
  99. data/lib/cortex_reaver/view/journals/form.rhtml +12 -0
  100. data/lib/cortex_reaver/view/journals/journal.rhtml +39 -0
  101. data/lib/cortex_reaver/view/journals/list.rhtml +33 -0
  102. data/lib/cortex_reaver/view/journals/short.rhtml +3 -0
  103. data/lib/cortex_reaver/view/journals/show.rhtml +5 -0
  104. data/lib/cortex_reaver/view/pages/form.rhtml +12 -0
  105. data/lib/cortex_reaver/view/pages/list.rhtml +26 -0
  106. data/lib/cortex_reaver/view/pages/show.rhtml +12 -0
  107. data/lib/cortex_reaver/view/photographs/atom_fragment.rhtml +82 -0
  108. data/lib/cortex_reaver/view/photographs/form.rhtml +19 -0
  109. data/lib/cortex_reaver/view/photographs/grid.rhtml +36 -0
  110. data/lib/cortex_reaver/view/photographs/list.rhtml +9 -0
  111. data/lib/cortex_reaver/view/photographs/short.rhtml +3 -0
  112. data/lib/cortex_reaver/view/photographs/show.rhtml +114 -0
  113. data/lib/cortex_reaver/view/photographs/sidebar.rhtml +7 -0
  114. data/lib/cortex_reaver/view/projects/form.rhtml +13 -0
  115. data/lib/cortex_reaver/view/projects/list.rhtml +27 -0
  116. data/lib/cortex_reaver/view/projects/show.rhtml +38 -0
  117. data/lib/cortex_reaver/view/tags/form.rhtml +9 -0
  118. data/lib/cortex_reaver/view/tags/list.rhtml +28 -0
  119. data/lib/cortex_reaver/view/tags/show.rhtml +51 -0
  120. data/lib/cortex_reaver/view/text_layout.rhtml +78 -0
  121. data/lib/cortex_reaver/view/users/form.rhtml +16 -0
  122. data/lib/cortex_reaver/view/users/list.rhtml +38 -0
  123. data/lib/cortex_reaver/view/users/login.rhtml +13 -0
  124. data/lib/cortex_reaver/view/users/register.rhtml +13 -0
  125. data/lib/cortex_reaver/view/users/show.rhtml +37 -0
  126. data/lib/cortex_reaver/view/users/user.rhtml +35 -0
  127. data/lib/proto/cortex_reaver.yaml +28 -0
  128. metadata +285 -0
@@ -0,0 +1,79 @@
1
+ module CortexReaver
2
+ module Model
3
+
4
+ # On save, calls a special rendering method on configured attributes, and
5
+ # saves the results to their cache.
6
+ module CachedRendering
7
+ require 'ostruct'
8
+
9
+ def self.included(base)
10
+ base.class_eval do
11
+ # Before save, render all changed caching fields
12
+ before_save(:render_to_cache) do
13
+ # Get changed fields to render
14
+ if new?
15
+ changed = columns.map { |c| c.to_sym }
16
+ else
17
+ changed = changed_columns.map { |c| c.to_sym }
18
+ end
19
+ fields = render_fields.select do |k, v|
20
+ changed.include? k.to_sym
21
+ end
22
+
23
+ fields.each do |name, field|
24
+ # Render and cache
25
+ self[field.to] = self.send(field.with, self[name])
26
+ end
27
+ end
28
+
29
+ # Refreshes all records with cached fields.
30
+ def self.refresh_render_caches
31
+ # TODO: inefficient, but Model.each breaks Sequel in validation
32
+ # "commands out of sync"
33
+ all.each do |record|
34
+ # Mark all caching columns as changed, so the before_save hook
35
+ # processes them.
36
+ record.skip_timestamp_update = true
37
+ render_fields.keys.each do |column|
38
+ record.changed_columns << column
39
+ end
40
+ record.save
41
+ end
42
+ nil
43
+ end
44
+
45
+ # Assigns a field to cache
46
+ #
47
+ # render :body, :with => 'wikify', :to => 'cached_body'
48
+ #
49
+ # ... calls #wikify on the value of self.body, and stores the result
50
+ # in self.cached_body. :to defaults to the field name with _cache
51
+ # appended. :with defaults to :render.
52
+ def self.render(field, params = {})
53
+ # Assign parameters
54
+ params = {
55
+ :to => (field.to_s + '_cache').to_sym,
56
+ :with => :render
57
+ }.merge!(params)
58
+
59
+ # Store field
60
+ render_fields[field] = OpenStruct.new(params)
61
+ end
62
+
63
+ def self.render_fields
64
+ @render_fields ||= {}
65
+ end
66
+ end
67
+ end
68
+
69
+ # Default renderer
70
+ def render(value)
71
+ value
72
+ end
73
+
74
+ def render_fields
75
+ self.class.render_fields
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,107 @@
1
+ module CortexReaver
2
+ module Model
3
+ # Supports canonical, url-safe identifiers for records, inferred from other
4
+ # fields.
5
+ module Canonical
6
+
7
+ # The canonical name attribute
8
+ CANONICAL_NAME_ATTR = :name
9
+ # The attribute we infer the canonical name from, if not set.
10
+ CANONICAL_INFERENCE_ATTR = :title
11
+
12
+ def self.included(base)
13
+ base.class_eval do
14
+ # Canonical names which cannot be reserved.
15
+ def self.reserved_canonical_names
16
+ @reserved_canonical_names ||= []
17
+ end
18
+
19
+ def self.reserved_canonical_names=(names)
20
+ @reserved_canonical_names = names
21
+ end
22
+
23
+ # Canonicalize a string. Optionally, ignore conflicts with the record
24
+ # with id.
25
+ def self.canonicalize(string, id = nil)
26
+ # Lower case, remove special chars, and replace with hyphens.
27
+ proper = string.downcase.gsub(/[^a-z0-9_]/, '-').squeeze('-')[0..250].sub(/-$/, '')
28
+
29
+ # If proper is blank, just return it at this point.
30
+ if proper.blank?
31
+ return proper
32
+ end
33
+
34
+ # Numeric suffix to append
35
+ suffix = nil
36
+
37
+ if proper != filter(:id => id).map(canonical_name_attr).first
38
+ # We don't already have this name.
39
+
40
+ similar = []
41
+
42
+ if filter(canonical_name_attr => proper).limit(1).count > 0
43
+ similar << proper
44
+ # This name already exists, and it's not ours!
45
+ similar += filter(canonical_name_attr.like(/^#{proper}\-[0-9]+$/)).map(canonical_name_attr)
46
+ end
47
+
48
+ # Check for reserved names
49
+ reserved_canonical_names.each do |name|
50
+ if name =~ /^#{proper}(-\d+)?$/
51
+ similar << name
52
+ end
53
+ end
54
+
55
+ # Find possible conflicting names from actions on this model's controller.
56
+ # if self.respond_to? :url and controller = Ramaze::Controller.at(self.url)
57
+ # similar += controller.action_methods.select do |action|
58
+ # action =~ /^#{proper}(-\d+)?$/
59
+ # end
60
+ # end
61
+
62
+ # Extract numeric suffices
63
+ suffices = {}
64
+ similar.each do |name|
65
+ suffices[name[/\d$/].to_i] = true
66
+ end
67
+
68
+ # Compute suffix
69
+ unless suffices.empty?
70
+ i = 1
71
+ while suffices.include? i
72
+ i += 1
73
+ end
74
+ suffix = i
75
+ end
76
+ end
77
+
78
+ if suffix
79
+ proper + '-' + suffix.to_s
80
+ else
81
+ proper
82
+ end
83
+ end
84
+
85
+ # Sets the attribute we infer the canonical name from to attr, or
86
+ # gets that attr if nil.
87
+ def self.canonical_inference_attr(attr = nil)
88
+ if attr
89
+ @canonical_inference_attr = attr.to_sym
90
+ else
91
+ @canonical_inference_attr || CANONICAL_INFERENCE_ATTR
92
+ end
93
+ end
94
+
95
+ # Sets the canonical name attribute to attr. Returns it if nil.
96
+ def self.canonical_name_attr(attr = nil)
97
+ if attr
98
+ @canonical_name_attr = attr.to_sym
99
+ else
100
+ @canonical_name_attr || CANONICAL_NAME_ATTR
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,69 @@
1
+ module CortexReaver
2
+ module Model
3
+ # Support methods for comments on models
4
+ module Comments
5
+ def self.included(base)
6
+ base.class_eval do
7
+ # When we delete a model that has comments, remove the comments too.
8
+ before_delete(:drop_comments) do
9
+ comments = self.comments
10
+ remove_all_comments
11
+ comments.each do |comment|
12
+ comment.destroy
13
+ end
14
+ end
15
+
16
+ # Refresh all comment counts
17
+ def self.refresh_comment_counts
18
+ all.each do |model|
19
+ model.refresh_comment_count
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ # Recalculates the number of comments on this record (and all comments
26
+ # below it, recursively) and saves those values. Returns the comment
27
+ # count on this record.
28
+ def refresh_comment_count
29
+ count = 0
30
+ comments.each do |comment|
31
+ # Recalculate for sub-comments and sum.
32
+ count += comment.refresh_comment_count + 1
33
+ end
34
+ self[:comment_count] = count
35
+ self.skip_timestamp_update = true
36
+
37
+ # Save and return
38
+ self.save
39
+ self[:comment_count]
40
+ end
41
+
42
+ # Returns the parent of a given comment. Caches, pass true to refresh.
43
+ def parent(refresh = false)
44
+ if refresh or @parent_cache.nil?
45
+ [:comment, :journal, :photograph, :project, :page].each do |p|
46
+ if self.respond_to?(p) and parent = self.send(p)
47
+ # We found an applicable parent.
48
+ @parent_cache = parent
49
+ return parent
50
+ end
51
+ end
52
+ # We didn't find any parent
53
+ nil
54
+ else
55
+ @parent_cache
56
+ end
57
+ end
58
+
59
+ # Returns the top-level parent of a given comment.
60
+ def root_parent
61
+ if parent
62
+ parent.root_parent
63
+ else
64
+ self
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,38 @@
1
+ module CortexReaver
2
+ module Model
3
+ # Defines class-level accessors for page size, order attribute, etc.
4
+ module Pagination
5
+ DEFAULT_SIZE = 16
6
+ DEFAULT_ORDER = 'created_on'
7
+ DEFAULT_REVERSE = false
8
+
9
+ def self.included(base)
10
+ base.class_eval do
11
+ class << self
12
+ attr_accessor :page_size, :page_order, :page_reverse
13
+ end
14
+
15
+ @page_size ||= CortexReaver::Model::Pagination::DEFAULT_SIZE
16
+ @page_order ||= CortexReaver::Model::Pagination::DEFAULT_ORDER
17
+ @page_reverse ||= CortexReaver::Model::Pagination::DEFAULT_REVERSE
18
+ end
19
+
20
+ # Returns a paginated dataset at page number. Optionally, filters on
21
+ # dataset instead of the whole model.
22
+ def page(number, dataset = self.dataset)
23
+ if reverse
24
+ dataset = dataset.reverse
25
+ end
26
+
27
+ dataset.order(@order).paginate(number, @page_size)
28
+ end
29
+ end
30
+
31
+ # Returns the page number for this model. Optionally, filters on dataset
32
+ # rather than the whole model.
33
+ def page_number(dataset = self.class.dataset)
34
+
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,196 @@
1
+ module CortexReaver
2
+ module Model
3
+ # Some common rendering methods, wrapped up for your convenience. Use in your model
4
+ # with something like:
5
+ #
6
+ # render :body, :with => :render_comment
7
+ #
8
+ # See CortexReaver::Model::CachedRendering for more details.
9
+ module Renderer
10
+ require 'bluecloth'
11
+ require 'hpricot'
12
+ require 'syntax'
13
+
14
+ # Elements to allow in sanitized HTML.
15
+ ELEMENTS = [
16
+ 'a', 'b', 'blockquote', 'br', 'code', 'dd', 'dl', 'dt', 'em', 'i', 'li',
17
+ 'ol', 'p', 'pre', 'small', 'strike', 'strong', 'sub', 'sup', 'u', 'ul'
18
+ ]
19
+
20
+ # Attributes to allow in sanitized HTML elements.
21
+ ATTRIBUTES = {
22
+ 'a' => ['href', 'title'],
23
+ 'pre' => ['class']
24
+ }
25
+
26
+ # Attributes to add to sanitized HTML elements.
27
+ ADD_ATTRIBUTES = {
28
+ 'a' => {'rel' => 'nofollow'}
29
+ }
30
+
31
+ # Attributes that should be checked for valid protocols.
32
+ PROTOCOL_ATTRIBUTES = {'a' => ['href']}
33
+
34
+ # Valid protocols.
35
+ PROTOCOLS = ['ftp', 'http', 'https', 'mailto']
36
+
37
+
38
+ # Renders plain text and html to html.
39
+ def bluecloth(text)
40
+ return text if text.nil?
41
+
42
+ BlueCloth::new(text).to_html
43
+ end
44
+
45
+ # Replace <% and %> to prevent Erubis injection.
46
+ def erubis_filter(text)
47
+ return text if text.nil?
48
+
49
+ t = text.dup
50
+ t.gsub!('<%', '&lt;%')
51
+ t.gsub!('%>', '%&rt;')
52
+ t
53
+ end
54
+
55
+ # Macro substitutions
56
+ #
57
+ # Expands [[type:resource][name]] macros. Right now, resource is just an attachment.
58
+ # Included types are:
59
+ #
60
+ # url: returns the URL to an attachment
61
+ # image: returns an image tag
62
+ # link: returns a link to an attachment
63
+ #
64
+ # The default action is a link, so
65
+ #
66
+ # [[foo.jpg]] => <a href="/data/.../foo.jpg">foo.jpg</a>
67
+ def macro(text)
68
+ return text if text.nil?
69
+
70
+ copy = text.dup
71
+
72
+ # Links
73
+ #
74
+ # Example [[image:foo.png][name]]
75
+ # 1. the link type prefix image:
76
+ # 2. the link type, sans-colon image
77
+ # 3. the link itself foo.png
78
+ # 4. the second half of the link [name]
79
+ # 5. the name name
80
+ copy.gsub!(/\[\[(([^\]]+):)?([^\]]+)(\]\[([^\]]+))?\]\]/) do |match|
81
+ prefix = $2
82
+ path = $3
83
+ name = $5
84
+
85
+ # Find the link target
86
+ target = attachment(path)
87
+
88
+ if target.exists?
89
+ # Name of the link
90
+ name ||= path
91
+
92
+ # Create link to this target
93
+ case prefix
94
+ when 'image'
95
+ # Create an inline image
96
+ "<img src=\"#{target.public_path}\" alt=\"#{name.gsub('"', '&quot;')}\" title=\"#{name.gsub('"', '&quot')}\" />"
97
+ when 'url'
98
+ # Create a URL
99
+ target.public_path
100
+ else
101
+ # Create a full link
102
+ "<a href=\"#{target.public_path}\">#{Rack::Utils.escape_html(name).gsub(/#([{@$]@?)/, '&#35;\1')}</a>"
103
+ end
104
+ else
105
+ # Don't create a link
106
+ match
107
+ end
108
+ end
109
+
110
+ copy
111
+ end
112
+
113
+ def syntax_highlight(text)
114
+ return text if text.nil?
115
+
116
+ h = Hpricot(text)
117
+
118
+ h.search('cr:code').replace do |code|
119
+ code[:lang]
120
+ end
121
+ end
122
+
123
+ # Stolen wholesale from Ryan's Thoth (http://github.com/rgrove/thoth/)
124
+ # Who adapted it from http://rid.onkulo.us/archives/14-sanitizing-html-with-ruby-and-hpricot
125
+ def sanitize_html(html)
126
+ return html if html.nil?
127
+
128
+ h = Hpricot(html)
129
+
130
+ h.search('*').each do |el|
131
+ if el.elem?
132
+ tag = el.name.downcase
133
+
134
+ if ELEMENTS.include?(tag)
135
+ if ATTRIBUTES.has_key?(tag)
136
+ # Delete any attribute that isn't in the whitelist for this
137
+ # particular element.
138
+ el.raw_attributes.delete_if do |key, val|
139
+ !ATTRIBUTES[tag].include?(key.downcase)
140
+ end
141
+
142
+ # Check applicable attributes for valid protocols.
143
+ if PROTOCOL_ATTRIBUTES.has_key?(tag)
144
+ el.raw_attributes.delete_if do |key, val|
145
+ PROTOCOL_ATTRIBUTES[tag].include?(key.downcase) &&
146
+ (!(val.downcase =~ /^([^:]+)\:/) || !PROTOCOLS.include?($1))
147
+ end
148
+ end
149
+ else
150
+ # Delete all attributes from elements with no whitelisted
151
+ # attributes.
152
+ el.raw_attributes = {}
153
+ end
154
+
155
+ # Add required attributes.
156
+ if ADD_ATTRIBUTES.has_key?(tag)
157
+ el.raw_attributes.merge!(ADD_ATTRIBUTES[tag])
158
+ end
159
+ else
160
+ # Delete any element that isn't in the whitelist.
161
+ el.parent.replace_child(el, el.children)
162
+ end
163
+ elsif el.comment?
164
+ # Delete all comments, since it's possible to make IE execute JS
165
+ # within conditional comments.
166
+ el.swap('')
167
+ end
168
+ end
169
+
170
+ h.to_s
171
+ end
172
+
173
+ # Default renderer
174
+ def render(text)
175
+ bluecloth(
176
+ macro(
177
+ erubis_filter(
178
+ text
179
+ )
180
+ )
181
+ ) # (((Feeling) LISPish yet)?)
182
+ end
183
+
184
+ # Comments render
185
+ def render_comment(text)
186
+ bluecloth(
187
+ erubis_filter(
188
+ sanitize_html(
189
+ text
190
+ )
191
+ )
192
+ )
193
+ end
194
+ end
195
+ end
196
+ end