radiant-taggable-extension 1.2.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 +125 -0
- data/Rakefile +136 -0
- data/VERSION +1 -0
- data/app/controllers/admin/taggings_controller.rb +8 -0
- data/app/controllers/admin/tags_controller.rb +17 -0
- data/app/models/tag.rb +200 -0
- data/app/models/tagging.rb +50 -0
- data/app/views/admin/pages/_edit_title.html.haml +28 -0
- data/app/views/admin/tags/_form.html.haml +23 -0
- data/app/views/admin/tags/_search_results.html.haml +10 -0
- data/app/views/admin/tags/cloud.html.haml +17 -0
- data/app/views/admin/tags/edit.html.haml +14 -0
- data/app/views/admin/tags/index.html.haml +53 -0
- data/app/views/admin/tags/new.html.haml +13 -0
- data/app/views/admin/tags/show.html.haml +32 -0
- data/config/routes.rb +6 -0
- data/db/migrate/001_create_tags.rb +26 -0
- data/db/migrate/002_import_keywords.rb +11 -0
- data/lib/taggable_admin_page_controller.rb +18 -0
- data/lib/taggable_admin_ui.rb +41 -0
- data/lib/taggable_model.rb +128 -0
- data/lib/taggable_page.rb +48 -0
- data/lib/taggable_tags.rb +456 -0
- data/lib/tasks/taggable_extension_tasks.rake +55 -0
- data/pkg/radiant-taggable-extension-1.2.0.gem +0 -0
- data/public/images/admin/new-tag.png +0 -0
- data/public/images/admin/tag.png +0 -0
- data/public/images/furniture/detag.png +0 -0
- data/public/stylesheets/admin/tags.css +20 -0
- data/public/stylesheets/sass/tagcloud.sass +29 -0
- data/radiant-taggable-extension.gemspec +84 -0
- data/spec/datasets/tag_sites_dataset.rb +9 -0
- data/spec/datasets/tags_dataset.rb +43 -0
- data/spec/lib/taggable_page_spec.rb +93 -0
- data/spec/models/tag_spec.rb +39 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +36 -0
- data/taggable_extension.rb +36 -0
- metadata +123 -0
@@ -0,0 +1,456 @@
|
|
1
|
+
module TaggableTags
|
2
|
+
include Radiant::Taggable
|
3
|
+
|
4
|
+
class TagError < StandardError; end
|
5
|
+
|
6
|
+
# tag sets.
|
7
|
+
|
8
|
+
desc %{
|
9
|
+
The root 'tags' is not usually called directly.
|
10
|
+
All it does is default to the list of page tags.
|
11
|
+
Most tags:* methods are called indirectly: eg 'requested_tags:list'
|
12
|
+
will set context to the requested tags and then render tags:list.
|
13
|
+
In that case we just oblige by expanding.
|
14
|
+
}
|
15
|
+
tag 'tags' do |tag|
|
16
|
+
tags ||= _get_tags(tag);
|
17
|
+
tag.expand
|
18
|
+
end
|
19
|
+
|
20
|
+
desc %{
|
21
|
+
Contents are rendered only if a set of tags is available.
|
22
|
+
|
23
|
+
*Usage:*
|
24
|
+
<pre><code><r:if_tags>...</r:if_tags></code></pre>
|
25
|
+
}
|
26
|
+
tag 'if_tags' do |tag|
|
27
|
+
tag.expand if tag.locals.tags && tag.locals.tags.any?
|
28
|
+
end
|
29
|
+
|
30
|
+
desc %{
|
31
|
+
Contents are rendered only if no set of tags is available.
|
32
|
+
|
33
|
+
*Usage:*
|
34
|
+
<pre><code><r:unless_tags>...</r:unless_tags></code></pre>
|
35
|
+
}
|
36
|
+
tag 'unless_tags' do |tag|
|
37
|
+
tag.expand unless tag.locals.tags && tag.locals.tags.any?
|
38
|
+
end
|
39
|
+
|
40
|
+
################# list-display tags: take a set and display it somehow. Because they're in the tags: namespace they default to tag.locals.page.tags.
|
41
|
+
|
42
|
+
desc %{
|
43
|
+
Summarises in a sentence the list of tags currently active.
|
44
|
+
|
45
|
+
*Usage:*
|
46
|
+
<pre><code>Pages tagged with <r:tags:summary />:</code></pre>
|
47
|
+
|
48
|
+
And the output would be "Pages tagged with tag1, tag2 and tag3:".
|
49
|
+
}
|
50
|
+
tag 'tags:summary' do |tag|
|
51
|
+
if tag.locals.tags && tag.locals.tags.any?
|
52
|
+
options = tag.attr.dup
|
53
|
+
tag.locals.tags.map { |t|
|
54
|
+
tag.locals.tag = t
|
55
|
+
tag.render('tag:title', options)
|
56
|
+
}.to_sentence
|
57
|
+
else
|
58
|
+
"no tags"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
desc %{
|
63
|
+
Cycles through all tags in context. You can also specify a set of tags, which is occasionally
|
64
|
+
a useful shortcut for building a topic list.
|
65
|
+
|
66
|
+
*Usage:*
|
67
|
+
<pre><code><r:tags:each tags="foo, bar">...</r:tags:each></code></pre>
|
68
|
+
}
|
69
|
+
tag 'tags:each' do |tag|
|
70
|
+
result = []
|
71
|
+
tag.locals.tags.each do |item|
|
72
|
+
tag.locals.tag = item
|
73
|
+
result << tag.expand
|
74
|
+
end
|
75
|
+
result
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
# These are never called directly: but are separated here to dry out the tag handling
|
80
|
+
# see r:tag_cloud, or in the library extension, compound forms like r:coincident_tags:tag_cloud and r:requested_tags:list
|
81
|
+
# same goes for r:tags:summary but that's occasionally useful on a page too.
|
82
|
+
|
83
|
+
tag 'tags:cloud' do |tag|
|
84
|
+
if tag.locals.tags && tag.locals.tags.length > 1
|
85
|
+
options = tag.attr.dup
|
86
|
+
tag.locals.tags = Tag.for_cloud(tag.locals.tags).sort_by{|t| t.title.downcase} # nb. for_cloud immediately returns list if already sized
|
87
|
+
result = []
|
88
|
+
result << %{<div class="cloud">}
|
89
|
+
tag.locals.tags.each do |t|
|
90
|
+
tag.locals.tag = t
|
91
|
+
result << tag.render("tag:link", options.merge('style' => "font-size: #{t.cloud_size.to_f * 2.5}em;"))
|
92
|
+
end
|
93
|
+
result << "</div>"
|
94
|
+
result.join(" ")
|
95
|
+
else
|
96
|
+
"No tags"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
tag 'tags:list' do |tag|
|
101
|
+
if tag.locals.tags && tag.locals.tags.any?
|
102
|
+
options = tag.attr.dup
|
103
|
+
show_checkboxes = (options.delete('checklist') == 'true')
|
104
|
+
listclass = options.delete('listclass') || 'taglist'
|
105
|
+
result = %{<ul class="#{listclass}">}
|
106
|
+
tag.locals.tags.each do |t|
|
107
|
+
tag.locals.tag = t
|
108
|
+
result << %{<li>#{tag.render('tag:link', options)}</li>}
|
109
|
+
end
|
110
|
+
result << "</ul>"
|
111
|
+
result
|
112
|
+
else
|
113
|
+
"No tags"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
################# page-candy: these are high level tags that bring in a whole block of stuff.
|
120
|
+
# most can be built out of the smaller tags if you need them to work differently
|
121
|
+
|
122
|
+
desc %{
|
123
|
+
Returns a tag-cloud showing all the tags attached to this page and its descendants,
|
124
|
+
with cloud band css classes determined by popularity *within the group*. This is intended as a way to
|
125
|
+
show what subjects are relevant here, as in the original delicio.us tag clouds. You can achieve similar
|
126
|
+
results with tags like r:all_tags:cloud, but with important differences:
|
127
|
+
|
128
|
+
* here prominence depends on popularity within the retrieved set of tags (not overall)
|
129
|
+
* here we climb down the page tree to build the set of tags: useful for eg. a section front page.
|
130
|
+
|
131
|
+
*Usage:*
|
132
|
+
<pre><code><r:tag_cloud /></code></pre>
|
133
|
+
|
134
|
+
You can supply a url parameter to work from a page other than the present one.
|
135
|
+
|
136
|
+
<pre><code><r:tag_cloud url="/elsewhere" /></code></pre>
|
137
|
+
|
138
|
+
So if you want to show all the tags attached to any page (but ignore their attachment to anything else):
|
139
|
+
|
140
|
+
<pre><code><r:tag_cloud url="/" /></code></pre>
|
141
|
+
|
142
|
+
As usual you can limit the size of the cloud (the most popular will be shown) and set the destination of tag links:
|
143
|
+
|
144
|
+
<pre><code><r:tag_cloud limit="200" linkto="/archive" /></code></pre>
|
145
|
+
}
|
146
|
+
tag 'tag_cloud' do |tag|
|
147
|
+
options = tag.attr.dup
|
148
|
+
limit = options.delete('limit')
|
149
|
+
if url = options.delete('url')
|
150
|
+
found = Page.find_by_url(absolute_path_for(tag.locals.page.url, url))
|
151
|
+
raise TagError, "no page at url #{url}" unless page_found?(found)
|
152
|
+
tag.locals.page = found
|
153
|
+
end
|
154
|
+
raise TagError, "no page for tag_cloud" unless tag.locals.page
|
155
|
+
tag.locals.tags = tag.locals.page.tags_for_cloud(limit) # page.tags_for_cloud does a lot of inheritance work
|
156
|
+
tag.render('tags:cloud', options)
|
157
|
+
end
|
158
|
+
|
159
|
+
desc %{
|
160
|
+
Returns a list of tags showing all the tags attached to this page and its descendants. It's essentially the same
|
161
|
+
as the tag cloud without the band formatting, but accepts the same options as tags:list.
|
162
|
+
|
163
|
+
*Usage:*
|
164
|
+
<pre><code><r:tag_list /></code></pre>
|
165
|
+
|
166
|
+
As usual you can limit the size of the list (the most popular will be shown) and set the destination of tag links:
|
167
|
+
|
168
|
+
<pre><code><r:tag_list limit="200" linkto="/archive" /></code></pre>
|
169
|
+
}
|
170
|
+
tag 'tag_list' do |tag|
|
171
|
+
options = tag.attr.dup
|
172
|
+
limit = options.delete('limit')
|
173
|
+
if url = options.delete('url')
|
174
|
+
found = Page.find_by_url(absolute_path_for(tag.locals.page.url, url))
|
175
|
+
raise TagError, "no page at url #{url}" unless page_found?(found)
|
176
|
+
tag.locals.page = found
|
177
|
+
end
|
178
|
+
raise TagError, "no page for tag_list" unless tag.locals.page
|
179
|
+
tag.locals.tags = tag.locals.page.tags_for_cloud(limit) # page.tags_for_cloud does a lot of inheritance work
|
180
|
+
tag.render('tags:list', options)
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
|
185
|
+
################# tagged pages. Other extensions define similar tags for eg tagged assets.
|
186
|
+
|
187
|
+
# general purpose pages lister
|
188
|
+
|
189
|
+
desc %{
|
190
|
+
This is a general purpose page lister. It wouldn't normally be accessed directly but a lot of other tags make use of it.
|
191
|
+
}
|
192
|
+
tag 'page_list' do |tag|
|
193
|
+
raise TagError, "no pages for page_list" unless tag.locals.pages
|
194
|
+
result = []
|
195
|
+
tag.locals.pages.each do |page|
|
196
|
+
tag.locals.page = page
|
197
|
+
result << tag.expand
|
198
|
+
end
|
199
|
+
result
|
200
|
+
end
|
201
|
+
|
202
|
+
desc %{
|
203
|
+
Lists all the pages associated with a set of tags, in descending order of relatedness.
|
204
|
+
|
205
|
+
*Usage:*
|
206
|
+
<pre><code><r:tags:pages:each>...</r:tags:pages:each></code></pre>
|
207
|
+
}
|
208
|
+
tag 'tags:pages' do |tag|
|
209
|
+
tag.locals.pages = Page.from_tags(tag.locals.tags)
|
210
|
+
tag.expand
|
211
|
+
end
|
212
|
+
tag 'tags:pages:each' do |tag|
|
213
|
+
tag.render('pages:each', tag.attr.dup, &tag.block)
|
214
|
+
end
|
215
|
+
|
216
|
+
desc %{
|
217
|
+
Renders the contained elements only if there are any pages associated with the current set of tags.
|
218
|
+
|
219
|
+
*Usage:*
|
220
|
+
<pre><code><r:tags:if_pages>...</r:tags:if_pages></code></pre>
|
221
|
+
}
|
222
|
+
tag "tags:if_pages" do |tag|
|
223
|
+
tag.locals.pages = Page.from_tags(tag.locals.tags)
|
224
|
+
tag.expand if tag.locals.pages.to_a.any?
|
225
|
+
end
|
226
|
+
|
227
|
+
desc %{
|
228
|
+
Renders the contained elements only if there are no pages associated with the current set of tags.
|
229
|
+
|
230
|
+
*Usage:*
|
231
|
+
<pre><code><r:tags:unless_pages>...</r:tags:unless_pages></code></pre>
|
232
|
+
}
|
233
|
+
tag "tags:unless_pages" do |tag|
|
234
|
+
tag.locals.pages = Page.from_tags(tag.locals.tags)
|
235
|
+
tag.expand unless tag.locals.pages.to_a.any?
|
236
|
+
end
|
237
|
+
|
238
|
+
# just a shortcut, but a useful one
|
239
|
+
|
240
|
+
desc %{
|
241
|
+
Lists all the pages similar to this page (based on its tagging), in descending order of relatedness.
|
242
|
+
|
243
|
+
*Usage:*
|
244
|
+
<pre><code><r:related_pages:each>...</r:related_pages:each></code></pre>
|
245
|
+
}
|
246
|
+
tag 'related_pages' do |tag|
|
247
|
+
raise TagError, "page must be defined for related_pages tag" unless tag.locals.page
|
248
|
+
tag.locals.pages = tag.locals.page.related_pages
|
249
|
+
tag.expand
|
250
|
+
end
|
251
|
+
tag 'related_pages:each' do |tag|
|
252
|
+
tag.render('pages:each', tag.attr.dup, &tag.block)
|
253
|
+
end
|
254
|
+
|
255
|
+
|
256
|
+
desc %{
|
257
|
+
Shows a link to the target page with a (non-linked) breadcrumb trail to give it context.
|
258
|
+
This is the opposite of r:breadcrumbs, which shows a linked trail but doesn't link the current page.
|
259
|
+
Link and breadcrumb attributes should work in the usual way, and by default we omit the home page
|
260
|
+
from the list since it adds no information. pass omit_root='false' to show the whole chain.
|
261
|
+
|
262
|
+
*Usage:*
|
263
|
+
<pre><code><r:tag:pages:each>
|
264
|
+
<r:crumbed_link [omit_root="false"] [separator=" → "] />
|
265
|
+
<r:crumbed_link>Link text</r:crumbed_link>
|
266
|
+
etc
|
267
|
+
</r:tag:pages:each></code></pre>
|
268
|
+
}
|
269
|
+
tag 'crumbed_link' do |tag|
|
270
|
+
page = tag.locals.page
|
271
|
+
ancestors = page.ancestors
|
272
|
+
ancestors.pop unless tag.attr['omit_root'] == 'false'
|
273
|
+
breadcrumbs = [tag.render('link')]
|
274
|
+
ancestors.each do |ancestor|
|
275
|
+
tag.locals.page = ancestor
|
276
|
+
breadcrumbs.unshift tag.render('breadcrumb')
|
277
|
+
end
|
278
|
+
separator = tag.attr['separator'] || ' > '
|
279
|
+
breadcrumbs.join(separator)
|
280
|
+
end
|
281
|
+
|
282
|
+
|
283
|
+
|
284
|
+
################# single tag expansion for simple lists of tagged items or for customised display of each item in a list or cloud context
|
285
|
+
|
286
|
+
desc %{
|
287
|
+
This is the namespace for referencing a single tag. It's not usually called directly,
|
288
|
+
but you can supply a 'title' or 'id' attribute.
|
289
|
+
|
290
|
+
*Usage:*
|
291
|
+
<pre><code><r:tag [title="tag_title"]>...</r:tag></code></pre>
|
292
|
+
}
|
293
|
+
tag 'tag' do |tag|
|
294
|
+
tag.locals.tag ||= _get_tag(tag, tag.attr.dup)
|
295
|
+
tag.expand
|
296
|
+
end
|
297
|
+
|
298
|
+
desc %{
|
299
|
+
Contents are rendered if a tag is currently defined. Useful on a LibraryPage page where you may or
|
300
|
+
may not have received a tag parameter.
|
301
|
+
|
302
|
+
*Usage:*
|
303
|
+
<pre><code><r:if_tag>...</r:if_tag></code></pre>
|
304
|
+
}
|
305
|
+
tag 'if_tag' do |tag|
|
306
|
+
tag.locals.tag ||= _get_tag(tag, tag.attr.dup)
|
307
|
+
tag.expand if tag.locals.tag
|
308
|
+
end
|
309
|
+
|
310
|
+
desc %{
|
311
|
+
Contents are rendered if no tag is currently defined. Useful on a LibraryPage page where you may or
|
312
|
+
may not have a tag parameter.
|
313
|
+
|
314
|
+
*Usage:*
|
315
|
+
<pre><code><r:unless_tag>...</r:unless_tag></code></pre>
|
316
|
+
}
|
317
|
+
tag 'unless_tag' do |tag|
|
318
|
+
tag.locals.tag ||= _get_tag(tag, tag.attr.dup)
|
319
|
+
tag.expand unless tag.locals.tag
|
320
|
+
end
|
321
|
+
|
322
|
+
desc %{
|
323
|
+
Shows name of current tag.
|
324
|
+
|
325
|
+
*Usage:*
|
326
|
+
<pre><code><r:tag:name /></code></pre>
|
327
|
+
}
|
328
|
+
tag 'tag:name' do |tag|
|
329
|
+
raise TagError, "tag must be defined for tag:title tag" unless tag.locals.tag
|
330
|
+
tag.locals.tag.title
|
331
|
+
end
|
332
|
+
|
333
|
+
desc %{
|
334
|
+
Makes a link to the current tag. If the current page is a library page, we amend the
|
335
|
+
list of requested tags. Otherwise, the 'linkto' parameter can be the address of a
|
336
|
+
LibraryPage, or you can specify a global tags page with a 'library.path' config entry.
|
337
|
+
|
338
|
+
If no destination is specified we return a relative link to the escaped name of the tag.
|
339
|
+
|
340
|
+
*Usage:*
|
341
|
+
<pre><code><r:tag:link linkto='/library' /></code></pre>
|
342
|
+
}
|
343
|
+
tag 'tag:link' do |tag|
|
344
|
+
raise TagError, "tag must be defined for tag:link tag" unless tag.locals.tag
|
345
|
+
options = tag.attr.dup
|
346
|
+
anchor = options['anchor'] ? "##{options.delete('anchor')}" : ''
|
347
|
+
attributes = options.inject('') { |s, (k, v)| s << %{#{k.downcase}="#{v}" } }.strip
|
348
|
+
attributes = " #{attributes}" unless attributes.empty?
|
349
|
+
text = tag.double? ? tag.expand : tag.render('tag:name')
|
350
|
+
if tag.locals.page.is_a? LibraryPage
|
351
|
+
tagset = tag.locals.page.requested_tags + [tag.locals.tag]
|
352
|
+
destination = tag.locals.page.url(tagset)
|
353
|
+
elsif page_url = (options.delete('linkto') || Radiant::Config['library.path'])
|
354
|
+
destination = clean_url(page_url + '/' + tag.locals.tag.clean_title)
|
355
|
+
else
|
356
|
+
# note that this only works if you're at a url with a trailing slash...
|
357
|
+
destination = Rack::Utils.escape("#{tag.locals.tag.title}") + '/'
|
358
|
+
end
|
359
|
+
%{<a href="#{destination}#{anchor}"#{attributes}>#{text}</a>}
|
360
|
+
end
|
361
|
+
|
362
|
+
desc %{
|
363
|
+
Shows description of current tag.
|
364
|
+
|
365
|
+
*Usage:*
|
366
|
+
<pre><code><r:tag:description /></code></pre>
|
367
|
+
}
|
368
|
+
tag 'tag:description' do |tag|
|
369
|
+
raise TagError, "tag must be defined for tag:description tag" unless tag.locals.tag
|
370
|
+
tag.locals.tag.description
|
371
|
+
end
|
372
|
+
|
373
|
+
desc %{
|
374
|
+
Shows use_count of current tag (which will normally only be set if we're within a tag_cloud tag)
|
375
|
+
|
376
|
+
*Usage:*
|
377
|
+
<pre><code><r:tag:use_count /></code></pre>
|
378
|
+
}
|
379
|
+
tag 'tag:use_count' do |tag|
|
380
|
+
raise TagError, "tag must be defined for tag:use_count tag" unless tag.locals.tag
|
381
|
+
tag.locals.tag.use_count
|
382
|
+
end
|
383
|
+
|
384
|
+
desc %{
|
385
|
+
Contents are rendered if the current tag has been applied to any pages.
|
386
|
+
|
387
|
+
*Usage:*
|
388
|
+
<pre><code><r:tag:if_pages>...</r:tag:if_pages></code></pre>
|
389
|
+
}
|
390
|
+
tag 'tag:if_pages' do |tag|
|
391
|
+
tag.expand if tag.locals.tag.pages.any?
|
392
|
+
end
|
393
|
+
|
394
|
+
desc %{
|
395
|
+
Contents are rendered unless the current tag has been applied to any pages.
|
396
|
+
|
397
|
+
*Usage:*
|
398
|
+
<pre><code><r:tag:unless_pages>...</r:tag:unless_pages></code></pre>
|
399
|
+
}
|
400
|
+
tag 'tag:unless_pages' do |tag|
|
401
|
+
tag.expand unless tag.locals.tag.pages.any?
|
402
|
+
end
|
403
|
+
|
404
|
+
desc %{
|
405
|
+
Loops through the pages to which this tag has been applied
|
406
|
+
setting page context for all contained tags. Works just like children:each
|
407
|
+
or other page tags.
|
408
|
+
|
409
|
+
*Usage:*
|
410
|
+
<pre><code><r:tag:pages:each>...</r:tag:pages:each></code></pre>
|
411
|
+
}
|
412
|
+
tag 'tag:pages' do |tag|
|
413
|
+
raise TagError, "tag must be defined for tag:pages tag" unless tag.locals.tag
|
414
|
+
tag.expand
|
415
|
+
end
|
416
|
+
tag 'tag:pages:each' do |tag|
|
417
|
+
result = []
|
418
|
+
tag.locals.tag.pages.each do |page|
|
419
|
+
tag.locals.page = page
|
420
|
+
result << tag.expand
|
421
|
+
end
|
422
|
+
result
|
423
|
+
end
|
424
|
+
|
425
|
+
|
426
|
+
|
427
|
+
private
|
428
|
+
|
429
|
+
def _get_tag(tag, options)
|
430
|
+
if title = options.delete('title')
|
431
|
+
tag.locals.tag ||= Tag.find_by_title(title)
|
432
|
+
end
|
433
|
+
if tag.locals.page.respond_to? :requested_tags
|
434
|
+
tag.locals.tag ||= tag.locals.page.requested_tags.first
|
435
|
+
end
|
436
|
+
tag.locals.tag
|
437
|
+
end
|
438
|
+
|
439
|
+
# this is the default used for bare tags:* tags.
|
440
|
+
# among other things it catches the tags="" attribute
|
441
|
+
# but change is likely here and anything not documented shouldn't be relied upon.
|
442
|
+
|
443
|
+
def _get_tags(tag)
|
444
|
+
tags = if tag.attr['tags'] && !tag.attr['tags'].blank?
|
445
|
+
Tag.from_list(tag.attr['tags'], false) # false parameter -> not to create missing tags
|
446
|
+
elsif tag.locals.page.respond_to?(:requested_tags)
|
447
|
+
tag.locals.page.requested_tags
|
448
|
+
elsif tag.locals.page
|
449
|
+
tag.locals.page.attached_tags
|
450
|
+
else
|
451
|
+
[]
|
452
|
+
end
|
453
|
+
tags = tags.uniq.select{|t| !t.nil? }
|
454
|
+
end
|
455
|
+
|
456
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
namespace :radiant do
|
2
|
+
namespace :extensions do
|
3
|
+
namespace :taggable do
|
4
|
+
|
5
|
+
desc "Runs the migration of the Taggable extension"
|
6
|
+
task :migrate => :environment do
|
7
|
+
require 'radiant/extension_migrator'
|
8
|
+
if ENV["VERSION"]
|
9
|
+
TaggableExtension.migrator.migrate(ENV["VERSION"].to_i)
|
10
|
+
Rake::Task['db:schema:dump'].invoke
|
11
|
+
else
|
12
|
+
TaggableExtension.migrator.migrate
|
13
|
+
Rake::Task['db:schema:dump'].invoke
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Copies public assets of the Taggable to the instance public/ directory."
|
18
|
+
task :update => :environment do
|
19
|
+
is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
|
20
|
+
puts "Copying assets from TaggableExtension"
|
21
|
+
Dir[TaggableExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
|
22
|
+
path = file.sub(TaggableExtension.root, '')
|
23
|
+
directory = File.dirname(path)
|
24
|
+
mkdir_p RAILS_ROOT + directory, :verbose => false
|
25
|
+
cp file, RAILS_ROOT + path, :verbose => false
|
26
|
+
end
|
27
|
+
unless TaggableExtension.root.starts_with? RAILS_ROOT # don't need to copy vendored tasks
|
28
|
+
puts "Copying rake tasks from TaggableExtension"
|
29
|
+
local_tasks_path = File.join(RAILS_ROOT, %w(lib tasks))
|
30
|
+
mkdir_p local_tasks_path, :verbose => false
|
31
|
+
Dir[File.join TaggableExtension.root, %w(lib tasks *.rake)].each do |file|
|
32
|
+
cp file, local_tasks_path, :verbose => false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Syncs all available translations for this ext to the English ext master"
|
38
|
+
task :sync => :environment do
|
39
|
+
# The main translation root, basically where English is kept
|
40
|
+
language_root = TaggableExtension.root + "/config/locales"
|
41
|
+
words = TranslationSupport.get_translation_keys(language_root)
|
42
|
+
|
43
|
+
Dir["#{language_root}/*.yml"].each do |filename|
|
44
|
+
next if filename.match('_available_tags')
|
45
|
+
basename = File.basename(filename, '.yml')
|
46
|
+
puts "Syncing #{basename}"
|
47
|
+
(comments, other) = TranslationSupport.read_file(filename, basename)
|
48
|
+
words.each { |k,v| other[k] ||= words[k] } # Initializing hash variable as empty if it does not exist
|
49
|
+
other.delete_if { |k,v| !words[k] } # Remove if not defined in en.yml
|
50
|
+
TranslationSupport.write_file(filename, basename, comments, other)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#tags-table table { margin-bottom: 0; }
|
2
|
+
td.tag-title { font-size: 115%; font-weight: bold;}
|
3
|
+
td.tag-title a { text-decoration: none; color: black; }
|
4
|
+
td.tag-description {
|
5
|
+
font-size: 80%;
|
6
|
+
color: #999;
|
7
|
+
}
|
8
|
+
|
9
|
+
ul.cloud {
|
10
|
+
list-style: none;
|
11
|
+
margin: 0;
|
12
|
+
padding: 0;
|
13
|
+
line-height: 20px; }
|
14
|
+
ul.cloud li {
|
15
|
+
display: inline;
|
16
|
+
font-family: "Lucida Grande", "Bitstream Vera Sans", Helvetica, Verdana, Arial, sans-serif;
|
17
|
+
letter-spacing: -0.04em;
|
18
|
+
white-space: nowrap;
|
19
|
+
line-height: 20px;
|
20
|
+
margin: 0; }
|
@@ -0,0 +1,29 @@
|
|
1
|
+
ul.cloud
|
2
|
+
:position relative
|
3
|
+
:list-style none
|
4
|
+
:margin 0
|
5
|
+
:padding 0
|
6
|
+
:overflow hidden
|
7
|
+
:line-height 1.6em
|
8
|
+
:margin-left -5px
|
9
|
+
|
10
|
+
li
|
11
|
+
:display inline
|
12
|
+
:float left
|
13
|
+
:letter-spacing -0.04em
|
14
|
+
:height 1.6em
|
15
|
+
|
16
|
+
a
|
17
|
+
:display inline
|
18
|
+
:white-space nowrap
|
19
|
+
:padding 5px
|
20
|
+
|
21
|
+
a.filter, a.defilter
|
22
|
+
:padding-left 11px
|
23
|
+
:font-size 12px
|
24
|
+
a.filter
|
25
|
+
:background transparent url(/images/furniture/entag.png) no-repeat top left
|
26
|
+
:color #5da454
|
27
|
+
a.defilter
|
28
|
+
:background transparent url(/images/furniture/detag.png) no-repeat top left
|
29
|
+
:color #9d313d
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{radiant-taggable-extension}
|
8
|
+
s.version = "1.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["spanner"]
|
12
|
+
s.date = %q{2010-09-10}
|
13
|
+
s.description = %q{General purpose tagging extension: more versatile but less focused than the tags extension}
|
14
|
+
s.email = %q{will@spanner.org}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.md"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
"README.md",
|
20
|
+
"Rakefile",
|
21
|
+
"VERSION",
|
22
|
+
"app/controllers/admin/taggings_controller.rb",
|
23
|
+
"app/controllers/admin/tags_controller.rb",
|
24
|
+
"app/models/tag.rb",
|
25
|
+
"app/models/tagging.rb",
|
26
|
+
"app/views/admin/pages/_edit_title.html.haml",
|
27
|
+
"app/views/admin/tags/_form.html.haml",
|
28
|
+
"app/views/admin/tags/_search_results.html.haml",
|
29
|
+
"app/views/admin/tags/cloud.html.haml",
|
30
|
+
"app/views/admin/tags/edit.html.haml",
|
31
|
+
"app/views/admin/tags/index.html.haml",
|
32
|
+
"app/views/admin/tags/new.html.haml",
|
33
|
+
"app/views/admin/tags/show.html.haml",
|
34
|
+
"config/routes.rb",
|
35
|
+
"db/migrate/001_create_tags.rb",
|
36
|
+
"db/migrate/002_import_keywords.rb",
|
37
|
+
"lib/taggable_admin_page_controller.rb",
|
38
|
+
"lib/taggable_admin_ui.rb",
|
39
|
+
"lib/taggable_model.rb",
|
40
|
+
"lib/taggable_page.rb",
|
41
|
+
"lib/taggable_tags.rb",
|
42
|
+
"lib/tasks/taggable_extension_tasks.rake",
|
43
|
+
"pkg/radiant-taggable-extension-1.2.0.gem",
|
44
|
+
"public/images/admin/new-tag.png",
|
45
|
+
"public/images/admin/tag.png",
|
46
|
+
"public/images/furniture/detag.png",
|
47
|
+
"public/stylesheets/admin/tags.css",
|
48
|
+
"public/stylesheets/sass/tagcloud.sass",
|
49
|
+
"radiant-taggable-extension.gemspec",
|
50
|
+
"spec/datasets/tag_sites_dataset.rb",
|
51
|
+
"spec/datasets/tags_dataset.rb",
|
52
|
+
"spec/lib/taggable_page_spec.rb",
|
53
|
+
"spec/models/tag_spec.rb",
|
54
|
+
"spec/spec.opts",
|
55
|
+
"spec/spec_helper.rb",
|
56
|
+
"taggable_extension.rb"
|
57
|
+
]
|
58
|
+
s.homepage = %q{http://github.com/spanner/radiant-taggable-extension}
|
59
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
60
|
+
s.require_paths = ["lib"]
|
61
|
+
s.rubygems_version = %q{1.3.7}
|
62
|
+
s.summary = %q{Taggable Extension for Radiant CMS}
|
63
|
+
s.test_files = [
|
64
|
+
"spec/datasets/tag_sites_dataset.rb",
|
65
|
+
"spec/datasets/tags_dataset.rb",
|
66
|
+
"spec/lib/taggable_page_spec.rb",
|
67
|
+
"spec/models/tag_spec.rb",
|
68
|
+
"spec/spec_helper.rb"
|
69
|
+
]
|
70
|
+
|
71
|
+
if s.respond_to? :specification_version then
|
72
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
73
|
+
s.specification_version = 3
|
74
|
+
|
75
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
76
|
+
s.add_runtime_dependency(%q<radiant>, [">= 0.9.0"])
|
77
|
+
else
|
78
|
+
s.add_dependency(%q<radiant>, [">= 0.9.0"])
|
79
|
+
end
|
80
|
+
else
|
81
|
+
s.add_dependency(%q<radiant>, [">= 0.9.0"])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
class TagSitesDataset < Dataset::Base
|
2
|
+
|
3
|
+
def load
|
4
|
+
create_record Site, :mysite, :name => 'My Site', :domain => 'mysite.domain.com', :base_domain => 'mysite.domain.com', :position => 1
|
5
|
+
create_record Site, :yoursite, :name => 'Your Site', :domain => '^yoursite', :base_domain => 'yoursite.test.com', :position => 2
|
6
|
+
create_record Site, :test, :name => 'Test host', :domain => '^test\.', :base_domain => 'test.host', :position => 3
|
7
|
+
Page.current_site = sites(:test) if defined? Site
|
8
|
+
end
|
9
|
+
end
|