radiant-taggable-extension 2.0.0.rc2 → 2.0.0
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.
- data/README.md +17 -30
- data/app/helpers/taggable_helper.rb +7 -6
- data/app/models/tag.rb +19 -20
- data/lib/radiant-taggable-extension.rb +1 -1
- data/lib/radius/library_tags.rb +102 -136
- data/lib/radius/taggable_tags.rb +47 -2
- data/lib/taggable/admin_ui.rb +8 -6
- data/radiant-taggable-extension.gemspec +3 -2
- data/spec/models/tag_spec.rb +3 -0
- data/taggable_extension.rb +2 -2
- metadata +29 -16
data/README.md
CHANGED
@@ -10,26 +10,33 @@ This extension differs from `tags` in a few ways that matter to me but may not t
|
|
10
10
|
|
11
11
|
* We're not so focused on tag clouds - though you can still make them - but more on archival and linking functions.
|
12
12
|
* It provides faceted search of any tagged class.
|
13
|
-
* We subvert the keywords mechanism on pages rather than adding another one. I
|
13
|
+
* We subvert the keywords mechanism on pages rather than adding another one. I am likely to change this soon to play more nicely with page fields.
|
14
14
|
* The tag-choosing and tag-removal interface is (about to be) quite nice.
|
15
15
|
* It's editorially versatile: tags can be used as page pointers and their visibility is controllable
|
16
|
-
* Anything can be tagged. By default we only do pages but other extensions can participate with a single line in a model class. See the [taggable_events](https://github.com/spanner/radiant-taggable_events-extension) extension for a minimal example or just put `has_tags` at the top of a model class.
|
16
|
+
* Anything can be tagged. By default we only do pages and assets but other extensions can participate with a single line in a model class. See the [taggable_events](https://github.com/spanner/radiant-taggable_events-extension) extension for a minimal example or just put `has_tags` at the top of a model class.
|
17
17
|
* We don't use `has_many_polymorphs` (it burns!)
|
18
18
|
* Or any of the tagging libraries: it only takes a few scopes
|
19
|
+
* Because the library is entirely scope-based it's easy to add more retrieval filters. Want a tagged and faceted googlemap of your calendar events? `event_calendar` + `event_map` * `taggable` + `taggable_events`.
|
19
20
|
|
20
|
-
When you first install the extension you shouldn't see much difference: all we do out of the box is to take over (and make more prominent) the keywords field in the page
|
21
|
+
When you first install the extension you shouldn't see much difference: all we do out of the box is to take over (and make more prominent) the keywords field in the page and asset editing views.
|
21
22
|
|
22
|
-
##
|
23
|
+
## Compatibility
|
23
24
|
|
24
|
-
|
25
|
+
Versions 2.x of taggable are meant for use with radiant 1. They expect to be included in your application as a bundled gem. There is a '0.9.1' tag in the repository for the latest version compatible with older versions of radiant.
|
25
26
|
|
26
|
-
|
27
|
+
## Installation
|
28
|
+
|
29
|
+
Install the gem:
|
30
|
+
|
31
|
+
sudo gem install radiant-taggable-extension
|
32
|
+
|
33
|
+
and add it to your application's Gemfile:
|
27
34
|
|
28
|
-
|
35
|
+
gem radiant-taggable-extension, '~>2.0.0'
|
29
36
|
|
30
37
|
## Status
|
31
38
|
|
32
|
-
Apart from any crumpling caused by the recent
|
39
|
+
Apart from any crumpling caused by the recent re-incorporation of Library and all its asset tags, this is all mature code that has been in use for years.
|
33
40
|
|
34
41
|
## Efficiency
|
35
42
|
|
@@ -51,11 +58,11 @@ The **LibraryPage** page type is a handy cache-friendly way of catching tag para
|
|
51
58
|
|
52
59
|
/archive/lasagne/chips/pudding
|
53
60
|
|
54
|
-
|
61
|
+
The right tags will be retrieved, if they exist, and with the radius tags below they can be used to populate the page.
|
55
62
|
|
56
63
|
## Radius tags
|
57
64
|
|
58
|
-
This extension creates a great many radius tags. There are
|
65
|
+
This extension creates a great many radius tags but in an orderly way. There are four kinds:
|
59
66
|
|
60
67
|
### Tag information
|
61
68
|
|
@@ -168,26 +175,6 @@ Seek venture capital immediately.
|
|
168
175
|
<r:assets:image size="standard" />
|
169
176
|
<p class="caption"><r:assets:caption /></p>
|
170
177
|
</r:related_images:each>
|
171
|
-
|
172
|
-
## Requirements
|
173
|
-
|
174
|
-
* Radiant 1 or radiant 0.9.x with the paperclipped extension.
|
175
|
-
|
176
|
-
Radiant 1 is strongly recommended.
|
177
|
-
|
178
|
-
## Installation
|
179
|
-
|
180
|
-
As usual:
|
181
|
-
|
182
|
-
git clone git://github.com/spanner/radiant-taggable-extension.git vendor/extensions/taggable
|
183
|
-
rake radiant:extensions:taggable:migrate
|
184
|
-
rake radiant:extensions:taggable:update
|
185
|
-
|
186
|
-
The update task will bring over a couple of CSS files for styling tags but you'll want to improve those.
|
187
|
-
|
188
|
-
## Bugs
|
189
|
-
|
190
|
-
Quite likely. [Github issues](http://github.com/spanner/radiant-taggable-extension/issues), please, or for little things an email or github message is fine.
|
191
178
|
|
192
179
|
## Author and copyright
|
193
180
|
|
@@ -1,21 +1,22 @@
|
|
1
|
+
require 'sanitize'
|
2
|
+
|
1
3
|
module TaggableHelper
|
2
4
|
|
3
5
|
def clean_html(text)
|
4
6
|
Sanitize.clean(text, Sanitize::Config::RELAXED)
|
5
7
|
end
|
6
8
|
|
7
|
-
def
|
9
|
+
def scrub_html(text)
|
8
10
|
Sanitize.clean(text)
|
9
11
|
end
|
10
12
|
|
11
13
|
def truncate_words(text='', options={})
|
12
14
|
return '' if text.blank?
|
13
|
-
|
14
|
-
limit = (options[:limit] || 64).to_i
|
15
|
-
text = strip_html(text) if options[:strip]
|
15
|
+
options.reverse_merge!(:length => 30, :omission => '…')
|
16
16
|
words = text.split
|
17
|
-
|
18
|
-
|
17
|
+
length = options[:length].to_i
|
18
|
+
options[:omission] = '' unless words.size > length
|
19
|
+
words[0..(length-1)].join(" ") + options[:omission]
|
19
20
|
end
|
20
21
|
|
21
22
|
def available_pointer_pages()
|
data/app/models/tag.rb
CHANGED
@@ -102,6 +102,23 @@ class Tag < ActiveRecord::Base
|
|
102
102
|
}
|
103
103
|
}
|
104
104
|
|
105
|
+
# returns all the tags that have been applied alongside any of these tags: that is, the
|
106
|
+
# set of tags that if applied will reduce further a set of tagged objects.
|
107
|
+
|
108
|
+
named_scope :coincident_with, lambda { |tags|
|
109
|
+
tag_ids = tags.map(&:id).join(',')
|
110
|
+
{
|
111
|
+
:select => "your_tags.*, COUNT(your_tags.id) AS use_count",
|
112
|
+
:joins => %{
|
113
|
+
INNER JOIN taggings AS my_taggings ON my_taggings.tag_id = tags.id
|
114
|
+
INNER JOIN taggings AS your_taggings ON my_taggings.tagged_type = your_taggings.tagged_type AND my_taggings.tagged_id = your_taggings.tagged_id
|
115
|
+
INNER JOIN tags AS your_tags ON your_taggings.tag_id = your_tags.id
|
116
|
+
},
|
117
|
+
:conditions => "tags.id IN (#{tag_ids}) AND NOT your_tags.id IN (#{tag_ids})",
|
118
|
+
:group => "your_tags.id"
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
105
122
|
def <=>(othertag)
|
106
123
|
String.natcmp(self.title, othertag.title) # natural sort method defined in lib/natcomp.rb
|
107
124
|
end
|
@@ -152,27 +169,9 @@ class Tag < ActiveRecord::Base
|
|
152
169
|
# Returns a list of all the tags that have been applied alongside this one.
|
153
170
|
|
154
171
|
def coincident_tags
|
155
|
-
|
156
|
-
self.tagged.each do |t|
|
157
|
-
tags += t.attached_tags if t
|
158
|
-
end
|
159
|
-
tags.uniq - [self]
|
172
|
+
self.class.coincident_with(self)
|
160
173
|
end
|
161
|
-
|
162
|
-
# Returns a list of all the tags that have been applied alongside _all_ of the supplied tags.
|
163
|
-
# used to offer reductive facets on library pages
|
164
|
-
# not very efficient at the moment, largely thanks to polymorphic tagging relationship
|
165
|
-
# TODO: omit tags with no reductive power (ie those applied to all the tagged items)
|
166
|
-
|
167
|
-
def self.coincident_with(tags)
|
168
|
-
related_tags = []
|
169
|
-
tagged = Tagging.with_all_of_these(tags).map(&:tagged)
|
170
|
-
tagged.each do |t|
|
171
|
-
related_tags += t.attached_tags if t
|
172
|
-
end
|
173
|
-
related_tags.uniq - tags
|
174
|
-
end
|
175
|
-
|
174
|
+
|
176
175
|
# returns true if tags are site-scoped
|
177
176
|
|
178
177
|
def self.sited?
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module RadiantTaggableExtension
|
2
|
-
VERSION = '2.0.0
|
2
|
+
VERSION = '2.0.0'
|
3
3
|
SUMMARY = %q{Tagging, clouding and faceting extension for Radiant CMS}
|
4
4
|
DESCRIPTION = %q{General purpose tagging and retrieval extension: more versatile but less focused than the tags extension. A good way to support faceted search.}
|
5
5
|
URL = "http://spanner.org/radiant/taggable"
|
data/lib/radius/library_tags.rb
CHANGED
@@ -174,11 +174,11 @@ module Radius
|
|
174
174
|
</code></pre>
|
175
175
|
}
|
176
176
|
tag "library:assets" do |tag|
|
177
|
-
tag.locals.assets = _get_assets(tag)
|
178
177
|
tag.expand
|
179
178
|
end
|
180
179
|
tag "library:assets:each" do |tag|
|
181
|
-
tag.
|
180
|
+
tag.locals.assets = _get_assets(tag)
|
181
|
+
tag.render('asset_list', tag.attr.dup, &tag.block)
|
182
182
|
end
|
183
183
|
|
184
184
|
desc %{
|
@@ -206,10 +206,10 @@ module Radius
|
|
206
206
|
</code></pre>
|
207
207
|
}
|
208
208
|
tag "library:#{these}" do |tag|
|
209
|
-
tag.locals.assets = _get_assets(tag).send(these.intern)
|
210
209
|
tag.expand
|
211
210
|
end
|
212
211
|
tag "library:#{these}:each" do |tag|
|
212
|
+
tag.locals.assets = _get_assets(tag).send(these.to_sym)
|
213
213
|
tag.render('asset_list', tag.attr.dup, &tag.block)
|
214
214
|
end
|
215
215
|
|
@@ -222,166 +222,132 @@ module Radius
|
|
222
222
|
</code></pre>
|
223
223
|
}
|
224
224
|
tag "library:if_#{these}" do |tag|
|
225
|
-
tag.locals.assets = _get_assets(tag).send(these.
|
225
|
+
tag.locals.assets = _get_assets(tag).send(these.to_sym)
|
226
226
|
tag.expand if tag.locals.assets.any?
|
227
227
|
end
|
228
|
+
end
|
228
229
|
|
229
|
-
|
230
|
+
############### extra tags:* tags that only make sense on library pages
|
230
231
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
end
|
232
|
+
desc %{
|
233
|
+
Summarises in a sentence the list of tags currently active, with each one presented as a defaceting link.
|
234
|
+
}
|
235
|
+
tag 'tags:unlink_list' do |tag|
|
236
|
+
requested = _get_requested_tags(tag)
|
237
|
+
if requested.any?
|
238
|
+
requested.map { |t|
|
239
|
+
tag.locals.tag = t
|
240
|
+
tag.render('tag:unlink', tag.attr.dup)
|
241
|
+
}.to_sentence
|
242
|
+
else
|
243
|
+
""
|
244
244
|
end
|
245
|
+
end
|
245
246
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
*Usage:*
|
250
|
-
<pre><code><r:tag:unlink linkto='/library' /></code></pre>
|
251
|
-
}
|
252
|
-
tag 'tag:unlink' do |tag|
|
253
|
-
raise TagError, "tag must be defined for tag:unlink tag" unless tag.locals.tag
|
254
|
-
options = tag.attr.dup
|
255
|
-
options['class'] ||= 'detag'
|
256
|
-
anchor = options['anchor'] ? "##{options.delete('anchor')}" : ''
|
257
|
-
attributes = options.inject('') { |s, (k, v)| s << %{#{k.downcase}="#{v}" } }.strip
|
258
|
-
attributes = " #{attributes}" unless attributes.empty?
|
259
|
-
text = tag.double? ? tag.expand : tag.render('tag:name')
|
260
|
-
|
261
|
-
if tag.locals.page.is_a?(LibraryPage)
|
262
|
-
href = tag.locals.page.url(tag.locals.page.requested_tags - [tag.locals.tag])
|
263
|
-
elsif page_url = (options.delete('tagpage') || Radiant::Config['tags.page'])
|
264
|
-
href = clean_url(page_url + '/-' + tag.locals.tag.clean_title)
|
265
|
-
else
|
266
|
-
href ||= Rack::Utils.escape("-#{tag.locals.tag.title}") + '/'
|
267
|
-
end
|
247
|
+
desc %{
|
248
|
+
Makes a link that removes the current tag from the active set. Other options as for tag:link.
|
268
249
|
|
269
|
-
|
250
|
+
*Usage:*
|
251
|
+
<pre><code><r:tag:unlink linkto='/library' /></code></pre>
|
252
|
+
}
|
253
|
+
tag 'tag:unlink' do |tag|
|
254
|
+
raise TagError, "tag must be defined for tag:unlink tag" unless tag.locals.tag
|
255
|
+
options = tag.attr.dup
|
256
|
+
options['class'] ||= 'detag'
|
257
|
+
anchor = options['anchor'] ? "##{options.delete('anchor')}" : ''
|
258
|
+
attributes = options.inject('') { |s, (k, v)| s << %{#{k.downcase}="#{v}" } }.strip
|
259
|
+
attributes = " #{attributes}" unless attributes.empty?
|
260
|
+
text = tag.double? ? tag.expand : tag.render('tag:name')
|
261
|
+
|
262
|
+
if tag.locals.page.is_a?(LibraryPage)
|
263
|
+
href = tag.locals.page.url(tag.locals.page.requested_tags - [tag.locals.tag])
|
264
|
+
elsif page_url = (options.delete('tagpage') || Radiant::Config['tags.page'])
|
265
|
+
href = clean_url(page_url + '/-' + tag.locals.tag.clean_title)
|
266
|
+
else
|
267
|
+
href ||= Rack::Utils.escape("-#{tag.locals.tag.title}") + '/'
|
270
268
|
end
|
271
269
|
|
270
|
+
%{<a href="#{href}#{anchor}"#{attributes}>#{text}</a>}
|
271
|
+
end
|
272
272
|
|
273
|
-
|
273
|
+
private
|
274
274
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
* `ellipsis` is the suffix used to indicate truncation. Default is '…'
|
279
|
-
* `strip="true"` will cause all html tags to be stripped from the contained text before it is truncated. Default is false.
|
280
|
-
}
|
281
|
-
tag "truncate" do |tag|
|
282
|
-
# truncate_words is in LibraryHelper
|
283
|
-
truncate_words tag.expand, :limit => tag.attr['limit'], :ellipsis => tag.attr['ellipsis'], :strip => tag.attr['strip'] == 'true'
|
284
|
-
end
|
275
|
+
def _get_requested_tags(tag)
|
276
|
+
tag.locals.page.requested_tags
|
277
|
+
end
|
285
278
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
279
|
+
def _get_coincident_tags(tag)
|
280
|
+
requested = _get_requested_tags(tag)
|
281
|
+
limit = tag.attr['limit'] || 50
|
282
|
+
if requested.any?
|
283
|
+
Tag.coincident_with(requested)
|
284
|
+
else
|
285
|
+
Tag.most_popular(limit)
|
293
286
|
end
|
287
|
+
end
|
294
288
|
|
295
|
-
|
296
|
-
|
289
|
+
# a bit of extra logic so that in the absence of any requested tags we default to all, not none
|
290
|
+
|
291
|
+
def _default_library_find_options
|
292
|
+
{
|
293
|
+
:by => 'created_at',
|
294
|
+
:order => 'desc'
|
297
295
|
}
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
296
|
+
end
|
297
|
+
|
298
|
+
def _get_pages(tag)
|
299
|
+
options = children_find_options(tag)
|
300
|
+
requested = _get_requested_tags(tag)
|
301
|
+
pages = Page.scoped(options)
|
302
|
+
pages = pages.tagged_with(requested) if requested.any?
|
303
|
+
pages
|
304
|
+
end
|
304
305
|
|
305
|
-
|
306
|
+
def _get_assets(tag)
|
307
|
+
options = asset_find_options(tag)
|
308
|
+
requested = _get_requested_tags(tag)
|
309
|
+
assets = Asset.scoped(options)
|
310
|
+
assets = assets.tagged_with(requested) if requested.any?
|
311
|
+
assets
|
312
|
+
end
|
313
|
+
|
314
|
+
# duplicate of children_find_options except:
|
315
|
+
# no virtual or status options
|
316
|
+
# defaults to chronological descending
|
317
|
+
|
318
|
+
def asset_find_options(tag)
|
319
|
+
attr = tag.attr.symbolize_keys
|
306
320
|
|
307
|
-
|
308
|
-
tag.locals.page.requested_tags
|
309
|
-
end
|
321
|
+
options = {}
|
310
322
|
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
Tag.coincident_with(requested)
|
323
|
+
[:limit, :offset].each do |symbol|
|
324
|
+
if number = attr[symbol]
|
325
|
+
if number =~ /^\d{1,4}$/
|
326
|
+
options[symbol] = number.to_i
|
316
327
|
else
|
317
|
-
|
328
|
+
raise TagError.new("`#{symbol}' attribute of `each' tag must be a positive number between 1 and 4 digits")
|
318
329
|
end
|
319
330
|
end
|
320
331
|
end
|
321
332
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
end
|
330
|
-
|
331
|
-
def _get_pages(tag)
|
332
|
-
options = children_find_options(tag)
|
333
|
-
requested = _get_requested_tags(tag)
|
334
|
-
pages = Page.scoped(options)
|
335
|
-
pages = pages.tagged_with(requested) if requested.any?
|
336
|
-
pages
|
337
|
-
end
|
338
|
-
|
339
|
-
def _get_assets(tag)
|
340
|
-
options = asset_find_options(tag)
|
341
|
-
requested = _get_requested_tags(tag)
|
342
|
-
assets = Asset.scoped(options)
|
343
|
-
assets = assets.tagged_with(requested) if requested.any?
|
344
|
-
assets
|
333
|
+
by = (attr[:by] || 'created_at').strip
|
334
|
+
order = (attr[:order] || 'desc').strip
|
335
|
+
order_string = ''
|
336
|
+
if self.attributes.keys.include?(by)
|
337
|
+
order_string << by
|
338
|
+
else
|
339
|
+
raise TagError.new("`by' attribute of `each' tag must be set to a valid field name")
|
345
340
|
end
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
def asset_find_options(tag)
|
352
|
-
attr = tag.attr.symbolize_keys
|
353
|
-
|
354
|
-
options = {}
|
355
|
-
|
356
|
-
[:limit, :offset].each do |symbol|
|
357
|
-
if number = attr[symbol]
|
358
|
-
if number =~ /^\d{1,4}$/
|
359
|
-
options[symbol] = number.to_i
|
360
|
-
else
|
361
|
-
raise TagError.new("`#{symbol}' attribute of `each' tag must be a positive number between 1 and 4 digits")
|
362
|
-
end
|
363
|
-
end
|
364
|
-
end
|
365
|
-
|
366
|
-
by = (attr[:by] || 'created_at').strip
|
367
|
-
order = (attr[:order] || 'desc').strip
|
368
|
-
order_string = ''
|
369
|
-
if self.attributes.keys.include?(by)
|
370
|
-
order_string << by
|
371
|
-
else
|
372
|
-
raise TagError.new("`by' attribute of `each' tag must be set to a valid field name")
|
373
|
-
end
|
374
|
-
if order =~ /^(asc|desc)$/i
|
375
|
-
order_string << " #{$1.upcase}"
|
376
|
-
else
|
377
|
-
raise TagError.new(%{`order' attribute of `each' tag must be set to either "asc" or "desc"})
|
378
|
-
end
|
379
|
-
options[:order] = order_string
|
380
|
-
options
|
341
|
+
if order =~ /^(asc|desc)$/i
|
342
|
+
order_string << " #{$1.upcase}"
|
343
|
+
else
|
344
|
+
raise TagError.new(%{`order' attribute of `each' tag must be set to either "asc" or "desc"})
|
381
345
|
end
|
382
|
-
|
346
|
+
options[:order] = order_string
|
347
|
+
options
|
383
348
|
end
|
384
349
|
|
350
|
+
end
|
385
351
|
end
|
386
352
|
|
387
353
|
|
data/lib/radius/taggable_tags.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module Radius
|
2
2
|
module TaggableTags
|
3
3
|
include Radiant::Taggable
|
4
|
-
|
4
|
+
include TaggableHelper
|
5
|
+
|
5
6
|
class TagError < StandardError; end
|
6
7
|
|
7
8
|
################# general purpose lister utilities and dryers-out
|
@@ -609,7 +610,52 @@ module Radius
|
|
609
610
|
tag.expand unless tag.locals.assets.any?
|
610
611
|
end
|
611
612
|
|
613
|
+
############### libraryish utility tags that don't really belong here
|
614
|
+
# btw. the truncation tags are duplicated from the reader extension, which may
|
615
|
+
# or may not be installed here. I'll move them into radiant proper in the end
|
612
616
|
|
617
|
+
desc %{
|
618
|
+
Truncates the contained text or html to the specified length. Unless you supply a
|
619
|
+
html="true" parameter, all html tags will be removed before truncation. You probably
|
620
|
+
don't want to do that: open tags will not be closed and the truncated
|
621
|
+
text length will vary.
|
622
|
+
|
623
|
+
<pre><code>
|
624
|
+
<r:truncated words="30"><r:content part="body" /></r:truncated>
|
625
|
+
<r:truncated chars="100" omission=" (continued)"><r:post:body /></r:truncated>
|
626
|
+
<r:truncated words="100" allow_html="true"><r:reader:description /></r:truncated>
|
627
|
+
</code></pre>
|
628
|
+
}
|
629
|
+
tag "truncated" do |tag|
|
630
|
+
content = tag.expand
|
631
|
+
tag.attr['words'] ||= tag.attr['length']
|
632
|
+
omission = tag.attr['omission'] || '…'
|
633
|
+
content = scrub_html(content) unless tag.attr['allow_html'] == 'true'
|
634
|
+
if tag.attr['chars']
|
635
|
+
truncate(content, :length => tag.attr['chars'].to_i, :omission => omission)
|
636
|
+
else
|
637
|
+
truncate_words(content, :length => tag.attr['words'].to_i, :omission => omission) # defined in TaggableHelper
|
638
|
+
end
|
639
|
+
end
|
640
|
+
|
641
|
+
deprecated_tag "truncate", :substitute => "truncated"
|
642
|
+
|
643
|
+
desc %{
|
644
|
+
Strips all html tags from the contained text, leaving the text itself unchanged.
|
645
|
+
Useful when, for example, using a page part to populate a meta tag.
|
646
|
+
}
|
647
|
+
tag "strip" do |tag|
|
648
|
+
# strip_html is in TaggableHelper
|
649
|
+
scrub_html tag.expand
|
650
|
+
end
|
651
|
+
|
652
|
+
desc %{
|
653
|
+
Removes all unsafe html tags and attributes from the enclosed text, protecting from cross-site scripting attacks while leaving the text intact.
|
654
|
+
}
|
655
|
+
tag "clean" do |tag|
|
656
|
+
# clean_html is in TaggableHelper
|
657
|
+
clean_html tag.expand
|
658
|
+
end
|
613
659
|
|
614
660
|
private
|
615
661
|
|
@@ -642,7 +688,6 @@ module Radius
|
|
642
688
|
tag.locals.tags = tags.uniq.compact
|
643
689
|
end
|
644
690
|
|
645
|
-
|
646
691
|
def _asset_finder(tag)
|
647
692
|
if (tag.locals.tags)
|
648
693
|
Asset.from_all_tags(tag.locals.tags).not_furniture
|
data/lib/taggable/admin_ui.rb
CHANGED
@@ -7,12 +7,15 @@ module Taggable
|
|
7
7
|
attr_accessor :tag
|
8
8
|
alias_method :tags, :tag
|
9
9
|
|
10
|
-
def
|
11
|
-
load_default_regions_without_tags
|
10
|
+
def load_taggable_regions
|
12
11
|
@tag = load_default_tag_regions
|
13
12
|
end
|
14
|
-
|
15
|
-
|
13
|
+
|
14
|
+
# def load_default_regions_with_tags
|
15
|
+
# load_default_regions_without_tags
|
16
|
+
# load_taggable_regions
|
17
|
+
# end
|
18
|
+
# alias_method_chain :load_default_regions, :tags
|
16
19
|
|
17
20
|
protected
|
18
21
|
|
@@ -35,9 +38,8 @@ module Taggable
|
|
35
38
|
tag.new = tag.edit
|
36
39
|
end
|
37
40
|
end
|
38
|
-
|
41
|
+
|
39
42
|
end
|
40
43
|
end
|
41
44
|
end
|
42
|
-
|
43
45
|
end
|
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.homepage = RadiantTaggableExtension::URL
|
12
12
|
s.summary = RadiantTaggableExtension::SUMMARY
|
13
13
|
s.description = RadiantTaggableExtension::DESCRIPTION
|
14
|
+
s.add_dependency 'sanitize', "~> 2.0.1"
|
14
15
|
|
15
16
|
ignores = if File.exist?('.gitignore')
|
16
17
|
File.read('.gitignore').split("\n").inject([]) {|a,p| a + Dir[p] }
|
@@ -23,9 +24,9 @@ Gem::Specification.new do |s|
|
|
23
24
|
s.require_paths = ["lib"]
|
24
25
|
|
25
26
|
s.post_install_message = %{
|
26
|
-
Add this to your
|
27
|
+
Add this to your Gemfile with:
|
27
28
|
|
28
|
-
|
29
|
+
gem 'radiant-taggable-extension', '~> #{RadiantTaggableExtension::VERSION}'
|
29
30
|
|
30
31
|
}
|
31
32
|
end
|
data/spec/models/tag_spec.rb
CHANGED
data/taggable_extension.rb
CHANGED
@@ -5,7 +5,7 @@ class TaggableExtension < Radiant::Extension
|
|
5
5
|
version RadiantTaggableExtension::VERSION
|
6
6
|
description RadiantTaggableExtension::DESCRIPTION
|
7
7
|
url RadiantTaggableExtension::URL
|
8
|
-
|
8
|
+
|
9
9
|
def activate
|
10
10
|
require 'natcmp' # a natural sort algorithm. possibly not that efficient.
|
11
11
|
ActiveRecord::Base.send :include, Taggable::Model # provide has_tags for everything but don't call it for anything
|
@@ -20,7 +20,7 @@ class TaggableExtension < Radiant::Extension
|
|
20
20
|
|
21
21
|
unless defined? admin.tag
|
22
22
|
Radiant::AdminUI.send :include, Taggable::AdminUI
|
23
|
-
|
23
|
+
Radiant::AdminUI.load_taggable_regions
|
24
24
|
end
|
25
25
|
|
26
26
|
tab("Content") do
|
metadata
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: radiant-taggable-extension
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 15
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 0
|
9
9
|
- 0
|
10
|
-
|
11
|
-
- 2
|
12
|
-
version: 2.0.0.rc2
|
10
|
+
version: 2.0.0
|
13
11
|
platform: ruby
|
14
12
|
authors:
|
15
13
|
- William Ross
|
@@ -17,9 +15,25 @@ autorequire:
|
|
17
15
|
bindir: bin
|
18
16
|
cert_chain: []
|
19
17
|
|
20
|
-
date: 2011-
|
21
|
-
|
22
|
-
|
18
|
+
date: 2011-09-06 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: sanitize
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 13
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 0
|
33
|
+
- 1
|
34
|
+
version: 2.0.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
23
37
|
description: "General purpose tagging and retrieval extension: more versatile but less focused than the tags extension. A good way to support faceted search."
|
24
38
|
email:
|
25
39
|
- radiant@spanner.org
|
@@ -86,10 +100,11 @@ files:
|
|
86
100
|
- spec/spec.opts
|
87
101
|
- spec/spec_helper.rb
|
88
102
|
- taggable_extension.rb
|
103
|
+
has_rdoc: true
|
89
104
|
homepage: http://spanner.org/radiant/taggable
|
90
105
|
licenses: []
|
91
106
|
|
92
|
-
post_install_message: "\n Add this to your
|
107
|
+
post_install_message: "\n Add this to your Gemfile with:\n\n gem 'radiant-taggable-extension', '~> 2.0.0'\n\n "
|
93
108
|
rdoc_options: []
|
94
109
|
|
95
110
|
require_paths:
|
@@ -106,18 +121,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
106
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
122
|
none: false
|
108
123
|
requirements:
|
109
|
-
- - "
|
124
|
+
- - ">="
|
110
125
|
- !ruby/object:Gem::Version
|
111
|
-
hash:
|
126
|
+
hash: 3
|
112
127
|
segments:
|
113
|
-
-
|
114
|
-
|
115
|
-
- 1
|
116
|
-
version: 1.3.1
|
128
|
+
- 0
|
129
|
+
version: "0"
|
117
130
|
requirements: []
|
118
131
|
|
119
132
|
rubyforge_project:
|
120
|
-
rubygems_version: 1.
|
133
|
+
rubygems_version: 1.5.3
|
121
134
|
signing_key:
|
122
135
|
specification_version: 3
|
123
136
|
summary: Tagging, clouding and faceting extension for Radiant CMS
|