radiant-taginator-extension 2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +1 -0
- data/.gitmodules +3 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +79 -0
- data/HELP.md +50 -0
- data/HELP_admin.md +30 -0
- data/README +38 -0
- data/Rakefile +27 -0
- data/app/models/tag_search_page.rb +88 -0
- data/app/views/admin/help/_using_tags.html.haml +4 -0
- data/app/views/admin/pages/_tag_field.html.haml +8 -0
- data/config/routes.rb +22 -0
- data/db/migrate/001_acts_as_taggable_on_migration.rb +29 -0
- data/db/migrate/002_acts_as_taggable_on_private_tags.rb +13 -0
- data/lib/taginator.rb +4 -0
- data/lib/taginator/tags.rb +324 -0
- data/lib/taginator/version.rb +3 -0
- data/lib/tasks/tags_extension_tasks.rake +32 -0
- data/public/stylesheets/tags.css +11 -0
- data/radiant-taginator-extension.gemspec +26 -0
- data/taginator_extension.rb +43 -0
- data/test/fixtures/meta_tags.yml +12 -0
- data/test/fixtures/page_parts.yml +17 -0
- data/test/fixtures/pages.yml +43 -0
- data/test/fixtures/taggings.yml +20 -0
- data/test/functional/tag_search_page_test.rb +44 -0
- data/test/functional/tags_extension_test.rb +19 -0
- data/test/helpers/render_test_helper.rb +60 -0
- data/test/test_helper.rb +20 -0
- data/test/unit/page_taggability_test.rb +20 -0
- metadata +111 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZmNiN2ZmYzBiMjMxYTAzNDUyYTU2MzMzMjFlOWU3ODRkMDA5YzQ1NA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YzkxYTk0Mzk1M2JlOWYyMTcyZTVkZDg4OTQ2YzE3NzIzYTAyODk2Nw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NTQ3OTI0NmJiZWVlMmM3ZDZlODY0NTIxNWI2YzM0OTI4NjkwZWNhZmNhMmZl
|
10
|
+
ZjlkZjhmMTNiNDRkNjhjOTVkNWQ5ODM0ZWZkN2E4NDY2MjhlOTVkZDNkOGU1
|
11
|
+
NTdlZmI2M2FlNDYwZmQyOGY2OGVhYzVmYTA0NmFmMjc1NzI0ZTU=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NjM1YjkzZDkyNWI2ZWQ4ODFmNGRiMjFmZmE0NmMzYzQ3MmE2ZTkyODA1YWQy
|
14
|
+
MmM1NjkzYTBjODRmNzRiOWYyOTI4NGUzNTQ4NmY1OGY3YmEzM2NlZjljZWYz
|
15
|
+
NTVjODIyZDIwYTA4NWMzNWNhYTc2Y2I1Y2E2NDE1ZGQ5Mzg2ZTk=
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
radiant-*-extension-*.gem
|
data/.gitmodules
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
radiant-taginator-extension (2.0.beta1)
|
5
|
+
acts-as-taggable-on
|
6
|
+
radiant
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
RedCloth (4.2.9)
|
12
|
+
actionmailer (2.3.18)
|
13
|
+
actionpack (= 2.3.18)
|
14
|
+
actionpack (2.3.18)
|
15
|
+
activesupport (= 2.3.18)
|
16
|
+
rack (~> 1.1.0)
|
17
|
+
activerecord (2.3.18)
|
18
|
+
activesupport (= 2.3.18)
|
19
|
+
activeresource (2.3.18)
|
20
|
+
activesupport (= 2.3.18)
|
21
|
+
activesupport (2.3.18)
|
22
|
+
acts-as-taggable-on (2.1.1)
|
23
|
+
rails
|
24
|
+
acts_as_tree (0.1.1)
|
25
|
+
chunky_png (1.2.8)
|
26
|
+
compass (0.12.2)
|
27
|
+
chunky_png (~> 1.2)
|
28
|
+
fssm (>= 0.2.7)
|
29
|
+
sass (~> 3.1)
|
30
|
+
compass-rails (1.0.3)
|
31
|
+
compass (>= 0.12.2, < 0.14)
|
32
|
+
delocalize (0.2.6)
|
33
|
+
fssm (0.2.10)
|
34
|
+
haml (3.1.8)
|
35
|
+
highline (1.6.19)
|
36
|
+
json (1.8.0)
|
37
|
+
rack (1.1.6)
|
38
|
+
rack-cache (1.2)
|
39
|
+
rack (>= 0.4)
|
40
|
+
radiant (1.1.4)
|
41
|
+
RedCloth (~> 4.2.0)
|
42
|
+
acts_as_tree (~> 0.1.1)
|
43
|
+
bundler (>= 1.0.0)
|
44
|
+
compass (~> 0.12.2)
|
45
|
+
compass-rails (~> 1.0.3)
|
46
|
+
delocalize (~> 0.2.3)
|
47
|
+
haml (~> 3.1.1)
|
48
|
+
highline (~> 1.6.10)
|
49
|
+
rack (~> 1.1.6)
|
50
|
+
rack-cache (~> 1.2)
|
51
|
+
radius (~> 0.7.3)
|
52
|
+
rails (~> 2.3.18)
|
53
|
+
rake (>= 0.8.7)
|
54
|
+
rdoc (>= 3.9.2)
|
55
|
+
stringex (~> 1.3.0)
|
56
|
+
tzinfo (~> 0.3.31)
|
57
|
+
will_paginate (~> 2.3.11)
|
58
|
+
radius (0.7.4)
|
59
|
+
rails (2.3.18)
|
60
|
+
actionmailer (= 2.3.18)
|
61
|
+
actionpack (= 2.3.18)
|
62
|
+
activerecord (= 2.3.18)
|
63
|
+
activeresource (= 2.3.18)
|
64
|
+
activesupport (= 2.3.18)
|
65
|
+
rake (>= 0.8.3)
|
66
|
+
rake (0.9.6)
|
67
|
+
rdoc (4.0.1)
|
68
|
+
json (~> 1.4)
|
69
|
+
sass (3.2.11)
|
70
|
+
stringex (1.3.3)
|
71
|
+
tzinfo (0.3.37)
|
72
|
+
will_paginate (2.3.16)
|
73
|
+
|
74
|
+
PLATFORMS
|
75
|
+
ruby
|
76
|
+
|
77
|
+
DEPENDENCIES
|
78
|
+
radiant-taginator-extension!
|
79
|
+
rake (~> 0.9)
|
data/HELP.md
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
The Tags extension provides a way for you to easily categorize your pages.
|
2
|
+
|
3
|
+
== Results page
|
4
|
+
|
5
|
+
<r:search:empty>
|
6
|
+
<h2>I couldn't find anything tagged with "<r:search:query/>".</h2>
|
7
|
+
</r:search:empty>
|
8
|
+
|
9
|
+
<r:search:results>
|
10
|
+
<h2>Found the following pages that are tagged with "<em><r:search:query/></em>".</h2>
|
11
|
+
|
12
|
+
<ul>
|
13
|
+
<r:search:results:each>
|
14
|
+
<li><r:link/> - <r:author/> - <r:date/></li>
|
15
|
+
</r:search:results:each>
|
16
|
+
</ul>
|
17
|
+
</r:search:results>
|
18
|
+
|
19
|
+
|
20
|
+
== Tag cloud
|
21
|
+
|
22
|
+
Use `<r:tag_cloud />` anywhere you like.
|
23
|
+
I made a stab at building the 'perfect' tag cloud markup, as inspired by a post on 24ways.org; http://24ways.org/2006/marking-up-a-tag-cloud
|
24
|
+
|
25
|
+
== Tag list
|
26
|
+
|
27
|
+
Use `<r:tag_list />` to get a list of tags for the current page.
|
28
|
+
Also works through children:each.
|
29
|
+
|
30
|
+
== All tags
|
31
|
+
|
32
|
+
Use `<r:all_tags />` to get a list of all tags. You may iterate through them with
|
33
|
+
`<r:all_tags:each>` and access their associated pages with `<r:all_tags:each:pages:each>`
|
34
|
+
|
35
|
+
== Collections
|
36
|
+
|
37
|
+
You can grab a collection of pages with a certain tag like so;
|
38
|
+
|
39
|
+
<r:tagged with="sometag" [scope="/some/page"] [with_any="true"]>
|
40
|
+
<r:link />
|
41
|
+
</r:tagged>
|
42
|
+
|
43
|
+
Which would iterate over all the resulting pages, like you do with children:each.
|
44
|
+
When you define scope, only this page and any of it's (grand)children will be used.
|
45
|
+
Using scope="current_page" will use the page that is currently being rendered as scope.
|
46
|
+
You can also set limit, offset etc like with children:each.
|
47
|
+
|
48
|
+
Using r:tagged in it's default setting searches for pages that have all of the given tags.
|
49
|
+
Using r:tagged with the attribute 'with_any' set to 'true' will find pages that have any of
|
50
|
+
the given tags.
|
data/HELP_admin.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
The Tags extension allows you to configure the style of tagging between 2 options:
|
2
|
+
simple or complex strings.
|
3
|
+
|
4
|
+
== Simple Tagging
|
5
|
+
|
6
|
+
By default you may add tags to a page in a string such as "this that other". That string
|
7
|
+
will be parsed and turned into 3 separate tags.
|
8
|
+
|
9
|
+
== Complex Tagging
|
10
|
+
|
11
|
+
You may set `Radiant::Config['tags.complex_strings'] = true` to allow you to enter more
|
12
|
+
complex tags for your pages.
|
13
|
+
|
14
|
+
When this setting is `true` the tags are delimited by a semi-colon, allowing you to enter
|
15
|
+
a string of tags such as "My Summer Vacation (2008); Entertainment/Nonsense; Miscellaneous 2.0".
|
16
|
+
The result of that string will return 3 tags: `My Summer Vacation (2008)`,
|
17
|
+
`Entertainment/Nonsense` and 'Miscellaneous 2.0'
|
18
|
+
|
19
|
+
== Making the choice
|
20
|
+
|
21
|
+
You'll need to restart the application server after changing this setting. Please keep in
|
22
|
+
mind that any changes to this setting may affect any tags you currently have in the database.
|
23
|
+
It is recommended that you choose either Simple or Complex, but that you do not switch
|
24
|
+
after creating your tags.
|
25
|
+
|
26
|
+
== Tag Clouds
|
27
|
+
|
28
|
+
Some styles are provided in tags.css for the <r:tag_cloud>. To use it, add this to your layout:
|
29
|
+
|
30
|
+
<link rel="stylesheet" type="text/css" href="/stylesheets/tags.css" />
|
data/README
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
= Tags extension
|
2
|
+
|
3
|
+
Created by: Keith Bingman - keithbingman.com
|
4
|
+
Revived by: Benny Degezelle - gorilla-webdesign.be
|
5
|
+
New features by: Jim Gay - saturnflyer.com
|
6
|
+
Rewrite by: Michal Cichra - blog.o2h.cz
|
7
|
+
|
8
|
+
Version: 2.0.beta
|
9
|
+
|
10
|
+
This extension enhances the page model with tagging capabilities, tagging as in "2.0" and tagclouds.
|
11
|
+
|
12
|
+
== Requirements
|
13
|
+
|
14
|
+
This extension depends on the acts-as-taggable-on plugin (included in vendor/plugins)
|
15
|
+
|
16
|
+
== Installation
|
17
|
+
|
18
|
+
1. Copy the extension to your vendor/extensions directory as you would any other extension.
|
19
|
+
2. Run 'rake radiant:extensions:tags:install'
|
20
|
+
3. Make a page to sit in '/t', and give it the "Tag Search" pagetype.
|
21
|
+
If you want to change this location, it's in Radiant::Config['tags.results_page_url'].
|
22
|
+
|
23
|
+
Done!
|
24
|
+
Here's a sample results page to get you started;
|
25
|
+
|
26
|
+
<r:search:empty>
|
27
|
+
<h2>I couldn't find anything tagged with "<r:search:query/>".</h2>
|
28
|
+
</r:search:empty>
|
29
|
+
|
30
|
+
<r:search:results>
|
31
|
+
<h2>Found the following pages that are tagged with "<em><r:search:query/></em>".</h2>
|
32
|
+
|
33
|
+
<ul>
|
34
|
+
<r:search:results:each>
|
35
|
+
<li><r:link/> - <r:author/> - <r:date/></li>
|
36
|
+
</r:search:results:each>
|
37
|
+
</ul>
|
38
|
+
</r:search:results>
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require "bundler/gem_tasks"
|
5
|
+
|
6
|
+
|
7
|
+
desc 'Default: run unit tests.'
|
8
|
+
task :default => :test
|
9
|
+
|
10
|
+
desc 'Test the tags extension.'
|
11
|
+
Rake::TestTask.new(:test) do |t|
|
12
|
+
t.libs << 'lib'
|
13
|
+
t.pattern = 'test/**/*_test.rb'
|
14
|
+
t.verbose = true
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Generate documentation for the tags extension.'
|
18
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
19
|
+
rdoc.rdoc_dir = 'rdoc'
|
20
|
+
rdoc.title = 'TagsExtension'
|
21
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
22
|
+
rdoc.rdoc_files.include('README')
|
23
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
24
|
+
end
|
25
|
+
|
26
|
+
# Load any custom rakefiles for extension
|
27
|
+
Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
|
@@ -0,0 +1,88 @@
|
|
1
|
+
class TagSearchPage < Page
|
2
|
+
|
3
|
+
attr_accessor :requested_tag
|
4
|
+
#### Tags ####
|
5
|
+
desc %{ The namespace for all search tags.}
|
6
|
+
tag 'search' do |tag|
|
7
|
+
tag.expand
|
8
|
+
end
|
9
|
+
|
10
|
+
desc %{ Renders the passed query.}
|
11
|
+
tag 'search:query' do |tag|
|
12
|
+
requested_tag
|
13
|
+
end
|
14
|
+
|
15
|
+
desc %{ Renders the contained block if no results were returned.}
|
16
|
+
tag 'search:empty' do |tag|
|
17
|
+
if found_tags.blank?
|
18
|
+
tag.expand
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc %{ Renders the contained block if results were returned.}
|
23
|
+
tag 'search:results' do |tag|
|
24
|
+
unless found_tags.blank?
|
25
|
+
tag.expand
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
desc %{ <r:search:results:each [sort_by="id"] [order="asc"]/>
|
30
|
+
Renders the contained block for each result page. The context
|
31
|
+
inside the tag refers to the found page.
|
32
|
+
|
33
|
+
Optionaly can pass <em>conditions</em>, <em>order</em> and such attributes.
|
34
|
+
}
|
35
|
+
tag 'search:results:each' do |tag|
|
36
|
+
# Ordering in Ruby because we already fetched our resultset before
|
37
|
+
tags = found_tags tag.attr.symbolize_keys
|
38
|
+
|
39
|
+
returning String.new do |content|
|
40
|
+
tags.each do |page|
|
41
|
+
tag.locals.page = page
|
42
|
+
content << tag.expand
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
desc %{ <r:truncate_and_strip [length="100"] />
|
48
|
+
Truncates and strips all HTML tags from the content of the contained block.
|
49
|
+
Useful for displaying a snippet of a found page. The optional `length' attribute
|
50
|
+
specifies how many characters to truncate to.}
|
51
|
+
tag 'truncate_and_strip' do |tag|
|
52
|
+
tag.attr['length'] ||= 100
|
53
|
+
length = tag.attr['length'].to_i
|
54
|
+
helper = ActionView::Base.new
|
55
|
+
helper.truncate(helper.strip_tags(tag.expand).gsub(/\s+/," "), length)
|
56
|
+
end
|
57
|
+
|
58
|
+
#### "Behavior" methods ####
|
59
|
+
def cache?
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
def found_tags(options = {:order => 'published_at DESC'})
|
64
|
+
return @found_tags if @found_tags
|
65
|
+
return [] if requested_tag.blank?
|
66
|
+
|
67
|
+
options.reverse_merge! :state => 'published'
|
68
|
+
@found_tags = Page.tagged_with(requested_tag, options)
|
69
|
+
end
|
70
|
+
|
71
|
+
def render
|
72
|
+
self.requested_tag = @request.parameters[:tag] unless requested_tag
|
73
|
+
self.title = "Tagged with #{requested_tag}" if requested_tag
|
74
|
+
|
75
|
+
super
|
76
|
+
end
|
77
|
+
|
78
|
+
def find_by_url(url, live = true, clean = false)
|
79
|
+
url = clean_url(url).chop # chop off trailing slash added by clean_url
|
80
|
+
if url =~ /^#{self.url}(.*?)\/?$/
|
81
|
+
self.requested_tag = $1.gsub(/\b\+\b/, " ")
|
82
|
+
self
|
83
|
+
else
|
84
|
+
super
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,4 @@
|
|
1
|
+
%h4 Tags
|
2
|
+
%p Tags that you list on your pages are ad-hoc categories and tags that you apply to your pages are as flexible as you want them to be. Rather than selecting a category for your page from a pre-defined list of categories, you can create whatever you need.
|
3
|
+
%p Tags are delimited (separated) by a space, so if you want to tag a page with Totally Awesome as one tag, be sure to put it in quotes such as 'Totally Awesome', otherwise you'll create two tags: one called Totally and one called Awesome.
|
4
|
+
%p These tags may be used by the site developers to provide a list of links (for example) to a group of pages with the same tag.
|
data/config/routes.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
ActionController::Routing::Routes.draw do |map|
|
2
|
+
# FIME: it doesn't work with namespace admin and without :name_prefix and path_prefix (only on production). :(
|
3
|
+
#map.namespace(:admin) do |admin|
|
4
|
+
map.resources :galleries,
|
5
|
+
:name_prefix =>'admin_',
|
6
|
+
:path_prefix => 'admin',
|
7
|
+
:member => {
|
8
|
+
:clear_thumbs => :get,
|
9
|
+
:reorder => :get,
|
10
|
+
:update_order => :post
|
11
|
+
},
|
12
|
+
:collection => {
|
13
|
+
:children => :get,
|
14
|
+
:reorder => :get,
|
15
|
+
:update_order => :post
|
16
|
+
} do |galleries|
|
17
|
+
galleries.resources :children, :controller => 'galleries', :path_prefix => '/admin/galleries/:parent_id'
|
18
|
+
galleries.resources :items, :controller => 'gallery_items', :member => { :move => :put }
|
19
|
+
galleries.resources :importings, :controller => 'gallery_importings', :member => { :import => :put }
|
20
|
+
galleries.resources :keywords, :controller => 'gallery_keywords', :only => [ :edit, :update, :destroy ]
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class ActsAsTaggableOnMigration < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :tags do |t|
|
4
|
+
t.column :name, :string
|
5
|
+
end
|
6
|
+
|
7
|
+
create_table :taggings do |t|
|
8
|
+
t.column :tag_id, :integer
|
9
|
+
t.column :taggable_id, :integer
|
10
|
+
t.column :tagger_id, :integer
|
11
|
+
t.column :tagger_type, :string
|
12
|
+
|
13
|
+
# You should make sure that the column created is
|
14
|
+
# long enough to store the required class names.
|
15
|
+
t.column :taggable_type, :string
|
16
|
+
t.column :context, :string
|
17
|
+
|
18
|
+
t.column :created_at, :datetime
|
19
|
+
end
|
20
|
+
|
21
|
+
add_index :taggings, :tag_id
|
22
|
+
add_index :taggings, [:taggable_id, :taggable_type, :context]
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.down
|
26
|
+
drop_table :taggings
|
27
|
+
drop_table :tags
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class ActsAsTaggableOnPrivateTags < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
change_table :tags do |t|
|
4
|
+
t.boolean :private, :null => false, :default => false
|
5
|
+
end
|
6
|
+
|
7
|
+
add_index :tags, :private
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.down
|
11
|
+
remove_column :tags, :private
|
12
|
+
end
|
13
|
+
end
|
data/lib/taginator.rb
ADDED
@@ -0,0 +1,324 @@
|
|
1
|
+
module Taginator::Tags
|
2
|
+
include Radiant::Taggable
|
3
|
+
include ActionView::Helpers::TextHelper
|
4
|
+
|
5
|
+
class TagError < StandardError; end
|
6
|
+
|
7
|
+
desc %{
|
8
|
+
Expands if a <pre><r:tagged with="" /></pre> call would return items. Takes the same options as the 'tagged' tag.
|
9
|
+
The <pre><r:unless_tagged with="" /></pre> is also available.
|
10
|
+
}
|
11
|
+
tag 'if_tagged' do |tag|
|
12
|
+
if tag.attr[:with]
|
13
|
+
tag.locals.tagged_results = find_with_tag_options(tag)
|
14
|
+
tag.expand unless tag.locals.tagged_results.empty?
|
15
|
+
else
|
16
|
+
tag.expand unless tag.locals.page.tag_list.empty?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
tag 'unless_tagged' do |tag|
|
21
|
+
if tag.attr[:with]
|
22
|
+
tag.expand if find_with_tag_options(tag).empty?
|
23
|
+
else
|
24
|
+
tag.expand if tag.locals.page.tag_list.empty?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
desc %{
|
29
|
+
Find all pages with certain tags, within in an optional scope. Additionally, you may set with_any to true to select pages that have any of the listed tags (opposed to all listed tags which is the provided default).
|
30
|
+
|
31
|
+
*Usage:*
|
32
|
+
<pre><code><r:tagged with="shoes diesel" [scope="/fashion/cult-update"] [with_any="true"] [offset="number"] [limit="number"] [by="attribute"] [order="asc|desc"]>...</r:tagged></code></pre>
|
33
|
+
}
|
34
|
+
tag 'tagged' do |tag|
|
35
|
+
tag.attr[:exclude_id] ||= tag.locals.page.id
|
36
|
+
tag.locals.tagged_results ||= find_with_tag_options(tag)
|
37
|
+
|
38
|
+
tag.locals.tagged_results.map do |page|
|
39
|
+
tag.locals.page = page
|
40
|
+
tag.expand
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
desc %{
|
45
|
+
Find all pages related to the current page, based on all or any of the current page's tags. A scope attribute may be given to limit results to a certain site area.
|
46
|
+
|
47
|
+
*Usage:*
|
48
|
+
<pre><code><r:related_by_tags [scope="/fashion/cult-update"] [offset="number"] [limit="number"] [by="attribute"] [order="asc|desc"]>...</r:related_by_tags></code></pre>
|
49
|
+
}
|
50
|
+
tag "related_by_tags" do |tag|
|
51
|
+
options = tag.attr.slice(:offset, :limit, :order).symbolize_keys
|
52
|
+
results = tag.locals.page.find_related_on_categories(options).to_a
|
53
|
+
return if results.size < 1
|
54
|
+
|
55
|
+
if scope = tag.attr[:scope].presence
|
56
|
+
results.reject! {|page| not page.url.starts_with?(scope) }
|
57
|
+
end
|
58
|
+
|
59
|
+
results.map do |page|
|
60
|
+
tag.locals.page = page
|
61
|
+
tag.locals.first = results.first == page
|
62
|
+
tag.expand
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
tag "if_has_related_by_tags" do |tag|
|
67
|
+
options = tag.attr.slice(:offset, :limit, :order).symbolize_keys
|
68
|
+
results = tag.locals.page.find_related_on_categories(options)
|
69
|
+
tag.expand if results.size > 0
|
70
|
+
end
|
71
|
+
|
72
|
+
tag "related_by_tags:if_first" do |tag|
|
73
|
+
tag.expand if tag.locals.first
|
74
|
+
end
|
75
|
+
|
76
|
+
desc %{
|
77
|
+
Render a Tag cloud
|
78
|
+
The results_page attribute will default to #{Radiant::Config['tags.results_page_url']}
|
79
|
+
* :start_at - Restrict the tags to those created after a certain time
|
80
|
+
* :end_at - Restrict the tags to those created before a certain time
|
81
|
+
* :conditions - A piece of SQL conditions to add to the query
|
82
|
+
* :limit - The maximum number of tags to return
|
83
|
+
* :order - A piece of SQL to order by. Eg 'tags.count desc' or 'taggings.created_at desc'
|
84
|
+
* :at_least - Exclude tags with a frequency less than the given value
|
85
|
+
* :at_most - Exclude tags with a frequency greater than the given value
|
86
|
+
*Usage:*
|
87
|
+
<pre><code><r:tag_cloud_list [limit="number"] [results_page="/some/url"] [scope="/some/url"]/></code></pre>
|
88
|
+
}
|
89
|
+
tag "tag_cloud" do |tag|
|
90
|
+
options = tag.attr.except(:scope, :results_page).symbolize_keys
|
91
|
+
tags = tag.locals.page.class.tag_counts_on(:categories, options)
|
92
|
+
|
93
|
+
tags = filter_tags_to_url_scope(tags, tag.attr['scope']) unless tag.attr['scope'].nil?
|
94
|
+
|
95
|
+
content_tag :ol, :class => :tag_cloud do
|
96
|
+
if tags.length > 0
|
97
|
+
build_tag_cloud(tags, %w(size1 size2 size3 size4 size5 size6 size7 size8 size9)) do |t, cloud_class, amount|
|
98
|
+
puts t, cloud_class, amount
|
99
|
+
content_tag :li, :class => cloud_class do
|
100
|
+
content_tag(:span, pluralize(amount, 'page is', 'pages are') << ' tagged with ') +
|
101
|
+
link_to(t, results_page(tag) << t, :class => :tag)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
else
|
105
|
+
return "<p>No tags found.</p>"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
desc %{
|
111
|
+
Render a Tag list, more for 'categories'-ish usage, i.e.: Cats (2) Logs (1) ...
|
112
|
+
The results_page attribute will default to #{Radiant::Config['tags.results_page_url']}
|
113
|
+
|
114
|
+
*Usage:*
|
115
|
+
<pre><code><r:tag_cloud_list [results_page="/some/url"] [scope="/some/url"]/></code></pre>
|
116
|
+
}
|
117
|
+
tag "tag_cloud_list" do |tag|
|
118
|
+
options = {}
|
119
|
+
tags = tag.locals.page.class.all_tag_counts(options).order('count desc')
|
120
|
+
tags = filter_tags_to_url_scope(tags, tag.attr[:scope]) unless tag.attr[:scope].nil?
|
121
|
+
|
122
|
+
results_page = tag.attr[:results_page] || Radiant::Config['tags.results_page_url']
|
123
|
+
|
124
|
+
content_tag :ul, :class => :tag_list do
|
125
|
+
if tags.length > 0
|
126
|
+
build_tag_cloud(tags, %w(size1 size2 size3 size4 size5 size6 size7 size8 size9)) do |t, cloud_class, amount|
|
127
|
+
content_tag :li, :class => cloud_class do
|
128
|
+
link_to("#{t} (#{amount})", results_page(tag) << t, :class => :tag)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
else
|
132
|
+
return "<p>No tags found.</p>"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
desc "List the current page's tags"
|
138
|
+
tag "tag_list" do |tag|
|
139
|
+
tag.locals.page.tag_list.map{|t| link_to(t, results_page(tag) << t, :class => :tag)}.join(", ")
|
140
|
+
end
|
141
|
+
|
142
|
+
desc "List the current page's tagsi as technorati tags. this should be included in the body of a post or in your rss feed"
|
143
|
+
tag "tag_list_technorati" do |tag|
|
144
|
+
tag.locals.page.tag_list.map{|t| link_to(t, 'http://technorati.com/tag/' << t, :rel => :tag)}.join(", ")
|
145
|
+
end
|
146
|
+
|
147
|
+
tag "tags" do |tag|
|
148
|
+
tag.expand
|
149
|
+
end
|
150
|
+
|
151
|
+
#desc "Iterates over the tags of the current page"
|
152
|
+
tag "tags:each" do |tag|
|
153
|
+
tag.locals.page.categories.map do |category|
|
154
|
+
tag.locals.category = category
|
155
|
+
tag.expand
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
tag "tags:each:name" do |tag|
|
160
|
+
tag.locals.category.name
|
161
|
+
end
|
162
|
+
|
163
|
+
tag "tags:each:link" do |tag|
|
164
|
+
name = tag.locals.category.name
|
165
|
+
link_to name, results_page(tag) << name, :class => 'tag'
|
166
|
+
end
|
167
|
+
|
168
|
+
#desc "Set the scope for all tags in the database"
|
169
|
+
tag "all_tags" do |tag|
|
170
|
+
tag.expand
|
171
|
+
end
|
172
|
+
|
173
|
+
desc %{
|
174
|
+
Iterates through each tag and allows you to specify the order: by popularity or by name.
|
175
|
+
The default is by name. You may also limit the search; the default is 5 results.
|
176
|
+
|
177
|
+
Usage: <pre><code><r:all_tags:each order="popularity" limit="5">...</r:all_tags:each></code></pre>
|
178
|
+
}
|
179
|
+
tag "all_tags:each" do |tag|
|
180
|
+
options = tag.attr.slice(:order, :limit).symbolize_keys
|
181
|
+
|
182
|
+
if names = tag.attr[:names]
|
183
|
+
names = names.split(",").map{|t| t.strip }
|
184
|
+
options[:conditions] = ["name IN (?)", names] if names.length > 0
|
185
|
+
end
|
186
|
+
|
187
|
+
Page.all_tag_counts(options).map do |t|
|
188
|
+
tag.locals.tag = t
|
189
|
+
tag.expand
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
desc "Renders the tag's name"
|
194
|
+
tag "all_tags:each:name" do |tag|
|
195
|
+
tag.locals.tag.name
|
196
|
+
end
|
197
|
+
|
198
|
+
tag "all_tags:each:link" do |tag|
|
199
|
+
name = tag.locals.tag.name
|
200
|
+
link_to tag.expand.presence || name,
|
201
|
+
results_page(tag) << name,
|
202
|
+
tag.attr.reverse_merge(:class => 'tag')
|
203
|
+
end
|
204
|
+
|
205
|
+
desc "Set the scope for the tag's pages"
|
206
|
+
tag "all_tags:each:pages" do |tag|
|
207
|
+
tag.expand
|
208
|
+
end
|
209
|
+
|
210
|
+
desc "Iterates through each page"
|
211
|
+
tag "all_tags:each:pages:each" do |tag|
|
212
|
+
Page.tagged_with(tag.locals.tag.name, tag.attr.symbolize_keys).map do |page|
|
213
|
+
tag.locals.page = page
|
214
|
+
tag.expand
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
private
|
219
|
+
|
220
|
+
def build_tag_cloud(tag_cloud, style_list)
|
221
|
+
max, min = 0, 0
|
222
|
+
counts = tag_cloud.map(&:count)
|
223
|
+
min, max = counts.min, counts.max
|
224
|
+
|
225
|
+
divisor = ((max - min) / style_list.size) + 1
|
226
|
+
|
227
|
+
tag_cloud.map do |tag|
|
228
|
+
yield tag.name, style_list[(tag.count - min) / divisor], tag.count
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def tag_item_url(name)
|
233
|
+
"#{Radiant::Config['tags.results_page_url']}/#{name}"
|
234
|
+
end
|
235
|
+
|
236
|
+
def find_with_tag_options(tag)
|
237
|
+
options = tagged_with_options(tag)
|
238
|
+
with_any = tag.attr[:with_any] || false
|
239
|
+
scope_attr = tag.attr[:scope] || '/'
|
240
|
+
|
241
|
+
raise TagError, "`tagged' tag must contain a `with' attribute." unless (tag.attr['with'] || tag.locals.page.class_name = TagSearchPage)
|
242
|
+
ttag = tag.attr['with'] || @request.parameters[:tag]
|
243
|
+
|
244
|
+
scope = scope_attr == 'current_page' ? Page.find_by_url(@request.request_uri) : Page.find_by_url(scope_attr)
|
245
|
+
return "The scope attribute must be a valid url to an existing page." if scope.nil? || scope.class_name.eql?('FileNotFoundPage')
|
246
|
+
|
247
|
+
|
248
|
+
page_ids = Page.tagged_with(ttag, options.merge(:any => with_any)).map do |page|
|
249
|
+
page.id if page.ancestors.include?(scope) || page == scope
|
250
|
+
end.compact
|
251
|
+
|
252
|
+
Page.find_all_by_id page_ids, options
|
253
|
+
end
|
254
|
+
|
255
|
+
def tagged_with_options(tag)
|
256
|
+
|
257
|
+
options = {}
|
258
|
+
|
259
|
+
[:limit, :offset].each do |symbol|
|
260
|
+
if number = tag.attr[symbol]
|
261
|
+
if number =~ /^\d{1,4}$/
|
262
|
+
options[symbol] = number.to_i
|
263
|
+
else
|
264
|
+
raise TagError.new("`#{symbol}' attribute of `each' tag must be a positive number between 1 and 4 digits")
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
by = (tag.attr[:by] || 'published_at').strip
|
270
|
+
order = (tag.attr[:order] || 'desc').strip
|
271
|
+
order_string = ''
|
272
|
+
|
273
|
+
if self.attributes.keys.include?(by)
|
274
|
+
order_string << by
|
275
|
+
else
|
276
|
+
raise TagError.new("`by' attribute of `each' tag must be set to a valid field name")
|
277
|
+
end
|
278
|
+
|
279
|
+
if order =~ /^(asc|desc)$/i
|
280
|
+
order_string << " #{$1.upcase}"
|
281
|
+
else
|
282
|
+
raise TagError.new(%{`order' attribute of `each' tag must be set to either "asc" or "desc"})
|
283
|
+
end
|
284
|
+
|
285
|
+
options[:order] = order_string
|
286
|
+
|
287
|
+
status = (tag.attr[:status] || 'published').downcase
|
288
|
+
exclude = tag.attr[:exclude_id] ? "AND pages.id != #{tag.attr[:exclude_id]}" : ""
|
289
|
+
|
290
|
+
unless status == 'all'
|
291
|
+
stat = Status[status]
|
292
|
+
unless stat.nil?
|
293
|
+
options[:conditions] = ["(virtual = ?) and (status_id = ?) #{exclude} and (published_at <= ?)", false, stat.id, Time.current]
|
294
|
+
else
|
295
|
+
raise TagError.new(%{`status' attribute of `each' tag must be set to a valid status})
|
296
|
+
end
|
297
|
+
else
|
298
|
+
options[:conditions] = ["virtual = ? #{exclude}", false]
|
299
|
+
end
|
300
|
+
|
301
|
+
options
|
302
|
+
end
|
303
|
+
|
304
|
+
def filter_tags_to_url_scope(tags, scope)
|
305
|
+
tags.select{ |tag|
|
306
|
+
tag.taggings.any?{ |tagging|
|
307
|
+
tagging.taggable.url.starts_with? scope
|
308
|
+
}
|
309
|
+
}
|
310
|
+
end
|
311
|
+
|
312
|
+
delegate :template, :to => :response
|
313
|
+
# delegate :link_to, :to => :template, :allow_nil => true
|
314
|
+
delegate :content_tag, :to => :template
|
315
|
+
|
316
|
+
def link_to *args
|
317
|
+
args.second.gsub!(' ', '+') if args.second.respond_to?(:gsub)
|
318
|
+
template.send(:link_to, *args)
|
319
|
+
end
|
320
|
+
|
321
|
+
def results_page(tag)
|
322
|
+
(tag.attr['results_page'] || Radiant::Config['tags.results_page_url']).dup << "/"
|
323
|
+
end
|
324
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
namespace :radiant do
|
2
|
+
namespace :extensions do
|
3
|
+
namespace :tags do
|
4
|
+
|
5
|
+
desc "Runs the migration and update tasks of the Tags extension"
|
6
|
+
task :install => [:environment, :migrate, :update]
|
7
|
+
|
8
|
+
desc "Runs the migration of the Tags extension"
|
9
|
+
task :migrate => :environment do
|
10
|
+
require 'radiant/extension_migrator'
|
11
|
+
if ENV["VERSION"]
|
12
|
+
TagsExtension.migrator.migrate(ENV["VERSION"].to_i)
|
13
|
+
else
|
14
|
+
TagsExtension.migrator.migrate
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Copy needed files to public dir"
|
19
|
+
task :update => :environment do
|
20
|
+
is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
|
21
|
+
Dir[TagsExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
|
22
|
+
path = file.sub(TagsExtension.root, '')
|
23
|
+
directory = File.dirname(path)
|
24
|
+
puts "Copying #{path}..."
|
25
|
+
mkdir_p RAILS_ROOT + directory
|
26
|
+
cp file, RAILS_ROOT + path
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
ol.tag_cloud { list-style: none; }
|
2
|
+
.tag_cloud li { display: inline; }
|
3
|
+
/* hide the extra context from CSS-enabled browsers, but not screenreaders */
|
4
|
+
.tag_cloud span { position: absolute; left: 0px; top: -500px; width: 1px; height: 1px; overflow: hidden; }
|
5
|
+
|
6
|
+
.tag_cloud .size1 { font-size: 1em; }
|
7
|
+
.tag_cloud .size2 { font-size: 1.3em; }
|
8
|
+
.tag_cloud .size3 { font-size: 1.6em; }
|
9
|
+
.tag_cloud .size4 { font-size: 1.9em; }
|
10
|
+
.tag_cloud .size5 { font-size: 2.2em; }
|
11
|
+
.tag_cloud .size6 { font-size: 2.5em; }
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require 'taginator'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'radiant-taginator-extension'
|
7
|
+
s.version = Taginator::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["mikz"]
|
10
|
+
s.email = ["mikz@o2h.cz"]
|
11
|
+
s.homepage = 'http://github.com/mikz/radiant-taginator-extension'
|
12
|
+
s.summary = "This extension enhances the page model with tagging capabilities, tagging as in \"2.0\" and tagclouds."
|
13
|
+
s.description = %q{Original extension - https://github.com/jomz/radiant-tags-extension}
|
14
|
+
s.require_paths = ['lib']
|
15
|
+
|
16
|
+
#s.rubyforge_project = "radiant_tools"
|
17
|
+
#s.add_dependency 'rack-rewrite', '~> 1.1.0'
|
18
|
+
#s.add_dependency 'radiant', '~> 0.9.0'
|
19
|
+
s.add_dependency 'acts-as-taggable-on'
|
20
|
+
s.add_dependency 'radiant'
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_dependency 'application_controller'
|
2
|
+
|
3
|
+
class TaginatorExtension < Radiant::Extension
|
4
|
+
version Taginator::VERSION
|
5
|
+
description "This extension enhances the page model with tagging capabilities, tagging as in \"2.0\" and tagclouds."
|
6
|
+
url "http://github.com/mikz/radiant-taginator-extension"
|
7
|
+
|
8
|
+
DEFAULT_RESULTS_URL = '/t'
|
9
|
+
|
10
|
+
def activate
|
11
|
+
config = Radiant::Config
|
12
|
+
if config.table_exists?
|
13
|
+
config['tags.results_page_url'] = config['tags.results_page_url'].presence || DEFAULT_RESULTS_URL
|
14
|
+
config['tags.complex_strings'] = config['tags.complex_strings'].presence || false
|
15
|
+
end
|
16
|
+
|
17
|
+
Page.class_eval do
|
18
|
+
acts_as_taggable_on :categories
|
19
|
+
|
20
|
+
def category_names
|
21
|
+
categories.map &:name
|
22
|
+
end
|
23
|
+
|
24
|
+
alias :tag_list :category_list
|
25
|
+
alias :tag_list= :category_list=
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
TagSearchPage
|
30
|
+
Page.send :include, Taginator::Tags
|
31
|
+
admin.page.edit.add :extended_metadata, 'tag_field'
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
# HELP
|
36
|
+
if admin.respond_to?(:help)
|
37
|
+
admin.help.index.add :page_details, 'using_tags', :after => 'breadcrumbs'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def deactivate
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
display_tags_part:
|
2
|
+
id: 1
|
3
|
+
page_id: 5
|
4
|
+
name: body
|
5
|
+
content:
|
6
|
+
<h1>Results for <r:search:query /></h1>
|
7
|
+
<r:search:empty>
|
8
|
+
<h2>No pages tagged with "<r:search:query/>".</h2>
|
9
|
+
</r:search:empty>
|
10
|
+
<r:search:results>
|
11
|
+
<h2>These pages are tagged with "<r:search:query/>".</h2>
|
12
|
+
<ul>
|
13
|
+
<r:search:results:each order="desc" by="published_at">
|
14
|
+
<li><r:link/> door <r:author/> op <r:date/></li>
|
15
|
+
</r:search:results:each>
|
16
|
+
</ul>
|
17
|
+
</r:search:results>
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
2
|
+
homepage:
|
3
|
+
id: 1
|
4
|
+
title: Ruby Home Page
|
5
|
+
breadcrumb: Home
|
6
|
+
slug: /
|
7
|
+
status_id: 100
|
8
|
+
parent_id:
|
9
|
+
published_at: 2006-01-30 08:41:07
|
10
|
+
documentation:
|
11
|
+
id: 2
|
12
|
+
title: Documentation
|
13
|
+
breadcrumb: Documentation
|
14
|
+
slug: documentation
|
15
|
+
status_id: 100
|
16
|
+
parent_id: 1
|
17
|
+
published_at: 2006-01-31 08:41:07
|
18
|
+
books:
|
19
|
+
id: 3
|
20
|
+
title: Books
|
21
|
+
breadcrumb: Books
|
22
|
+
slug: books
|
23
|
+
status_id: 100
|
24
|
+
parent_id: 2
|
25
|
+
published_at: 2006-01-30 08:41:07
|
26
|
+
textile:
|
27
|
+
id: 4
|
28
|
+
title: Textile
|
29
|
+
breadcrumb: Textile
|
30
|
+
slug: textile
|
31
|
+
status_id: 100
|
32
|
+
parent_id: 1
|
33
|
+
published_at: 2006-01-30 08:41:07
|
34
|
+
|
35
|
+
tags_page:
|
36
|
+
id: 5
|
37
|
+
title: Tags Page
|
38
|
+
breadcrumb: tags
|
39
|
+
slug: tags
|
40
|
+
status_id: 100
|
41
|
+
parent_id: 1
|
42
|
+
class_name: TagSearchPage
|
43
|
+
published_at: 2006-01-30 08:41:07
|
@@ -0,0 +1,20 @@
|
|
1
|
+
1:
|
2
|
+
meta_tag_id: 1
|
3
|
+
taggable_id: 1
|
4
|
+
taggable_type: Page
|
5
|
+
2:
|
6
|
+
meta_tag_id: 2
|
7
|
+
taggable_id: 1
|
8
|
+
taggable_type: Page
|
9
|
+
3:
|
10
|
+
meta_tag_id: 3
|
11
|
+
taggable_id: 1
|
12
|
+
taggable_type: Page
|
13
|
+
4:
|
14
|
+
meta_tag_id: 1
|
15
|
+
taggable_id: 2
|
16
|
+
taggable_type: Page
|
17
|
+
5:
|
18
|
+
meta_tag_id: 2
|
19
|
+
taggable_id: 2
|
20
|
+
taggable_type: Page
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class TagSearchPageTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
fixtures :pages, :meta_tags, :taggings, :page_parts
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@page = pages(:tags_page)
|
9
|
+
@page.request = ActionController::TestRequest.new
|
10
|
+
@page.response = ActionController::TestResponse.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_title_gets_set_ok
|
14
|
+
@page.request.request_parameters = {:tag => "foo"}
|
15
|
+
@page.render
|
16
|
+
assert_equal "Tagged with foo", @page.title
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_no_title_means_no_title_change
|
20
|
+
@page.render
|
21
|
+
assert_equal "Tags Page", @page.title
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_page_should_show_posts_tagged_with_tag
|
25
|
+
@page.request.request_parameters = {:tag => "lorem"}
|
26
|
+
output = @page.render
|
27
|
+
assert_match /These pages are tagged with "lorem"/, output
|
28
|
+
assert_match /Ruby Home Page/, output
|
29
|
+
assert_match /Documentation/, output
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_resulting_pages_should_be_sorted
|
33
|
+
@page.request.request_parameters = {:tag => "lorem"}
|
34
|
+
output = @page.render
|
35
|
+
assert_match /Documentation.*Ruby Home Page/, output
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_unknown_tag_should_say_so
|
39
|
+
@page.request.request_parameters = {:tag => "foobarbar"}
|
40
|
+
output = @page.render
|
41
|
+
assert_match /No pages tagged with "foobarbar"/, output
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class TagsExtensionTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
fixtures :pages, :meta_tags, :taggings
|
6
|
+
test_helper :render
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@page = pages(:documentation)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_cloud_tag
|
13
|
+
assert_renders "<ol class=\"tag_cloud\"><li class=\"size2\"><span>1 page is tagged with </span><a href=\"?q=dolor\" class=\"tag\">dolor</a></li><li class=\"size3\"><span>2 pages are tagged with </span><a href=\"?q=ipsum\" class=\"tag\">ipsum</a></li><li class=\"size3\"><span>2 pages are tagged with </span><a href=\"?q=lorem\" class=\"tag\">lorem</a></li></ol>", "<r:tag_cloud />"
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_tag_list
|
17
|
+
assert_renders "<a href=\"?q=ipsum\" class=\"tag\">ipsum</a>, <a href=\"?q=lorem\" class=\"tag\">lorem</a>", "<r:tag_list />"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module RenderTestHelper
|
2
|
+
|
3
|
+
def assert_renders(expected, input, url = nil, host = nil)
|
4
|
+
output = get_render_output(input, url, host)
|
5
|
+
message = "<#{expected.inspect}> expected but was <#{output.inspect}>"
|
6
|
+
assert_block(message) { expected == output }
|
7
|
+
end
|
8
|
+
|
9
|
+
def assert_render_match(regexp, input, url = nil)
|
10
|
+
regexp = Regexp.new(regexp) if regexp.kind_of? String
|
11
|
+
output = get_render_output(input, url)
|
12
|
+
message = "<#{output.inspect}> expected to be =~ <#{regexp.inspect}>"
|
13
|
+
assert_block(message) { output =~ regexp }
|
14
|
+
end
|
15
|
+
|
16
|
+
def assert_render_error(expected_error_message, input, url = nil)
|
17
|
+
output = get_render_output(input, url)
|
18
|
+
message = "expected error message <#{expected_error_message.inspect}> expected but none was thrown"
|
19
|
+
assert_block(message) { false }
|
20
|
+
rescue => e
|
21
|
+
message = "expected error message <#{expected_error_message.inspect}> but was <#{e.message.inspect}>"
|
22
|
+
assert_block(message) { expected_error_message === e.message }
|
23
|
+
end
|
24
|
+
|
25
|
+
def assert_headers(expected_headers, url = nil)
|
26
|
+
setup_page(url)
|
27
|
+
headers = @page.headers
|
28
|
+
message = "<#{expected_headers.inspect}> expected but was <#{headers.inspect}>"
|
29
|
+
assert_block(message) { expected_headers == headers }
|
30
|
+
end
|
31
|
+
|
32
|
+
def assert_page_renders(page_name, expected, message = nil)
|
33
|
+
page = pages(page_name)
|
34
|
+
output = page.render
|
35
|
+
message = "<#{expected.inspect}> expected, but was <#{output.inspect}>"
|
36
|
+
assert_block(message) { expected == output }
|
37
|
+
end
|
38
|
+
|
39
|
+
def assert_snippet_renders(snippet_name, expected, message = nil)
|
40
|
+
snippet = snippets(snippet_name)
|
41
|
+
output = @page.render_snippet(snippet)
|
42
|
+
message = "<#{expected.inspect}> expected, but was <#{output.inspect}>"
|
43
|
+
assert_block(message) { expected == output }
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def get_render_output(input, url, host = nil)
|
49
|
+
setup_page(url, host)
|
50
|
+
@page.send(:parse, input)
|
51
|
+
end
|
52
|
+
|
53
|
+
def setup_page(url = nil, host = nil)
|
54
|
+
@page.request = ActionController::TestRequest.new
|
55
|
+
@page.request.request_uri = (url || @page.url)
|
56
|
+
@page.request.host = host || "testhost.tld"
|
57
|
+
@page.response = ActionController::TestResponse.new
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
# Load the the environment
|
3
|
+
unless defined? RADIANT_ROOT
|
4
|
+
ENV["RAILS_ENV"] = "test"
|
5
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../")}/config/environment"
|
6
|
+
end
|
7
|
+
require "#{RADIANT_ROOT}/test/test_helper"
|
8
|
+
|
9
|
+
class ActiveSupport::TestCase
|
10
|
+
|
11
|
+
# Include a helper to make testing Radius tags easier
|
12
|
+
test_helper :render
|
13
|
+
|
14
|
+
# Add the fixture directory to the fixture path
|
15
|
+
self.fixture_path << File.dirname(__FILE__) + "/fixtures"
|
16
|
+
|
17
|
+
fixtures :users, :pages
|
18
|
+
# Add more helper methods to be used by all extension tests here...
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class PageTaggabilityTest < ActiveSupport::TestCase
|
4
|
+
def setup
|
5
|
+
@page = Page.find 1
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_page_should_be_taggable
|
9
|
+
assert true, @page.respond_to?("tag_with")
|
10
|
+
assert_difference MetaTag, :count, 2 do
|
11
|
+
@page.tag_with 'lorem ipsum'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def assert_difference(object, method = nil, difference = 1)
|
16
|
+
initial_value = object.send(method)
|
17
|
+
yield
|
18
|
+
assert_equal initial_value + difference, object.send(method), "#{object}##{method}"
|
19
|
+
end
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: radiant-taginator-extension
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.beta1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- mikz
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: acts-as-taggable-on
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: radiant
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Original extension - https://github.com/jomz/radiant-tags-extension
|
42
|
+
email:
|
43
|
+
- mikz@o2h.cz
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- .gitmodules
|
50
|
+
- Gemfile
|
51
|
+
- Gemfile.lock
|
52
|
+
- HELP.md
|
53
|
+
- HELP_admin.md
|
54
|
+
- README
|
55
|
+
- Rakefile
|
56
|
+
- app/models/tag_search_page.rb
|
57
|
+
- app/views/admin/help/_using_tags.html.haml
|
58
|
+
- app/views/admin/pages/_tag_field.html.haml
|
59
|
+
- config/routes.rb
|
60
|
+
- db/migrate/001_acts_as_taggable_on_migration.rb
|
61
|
+
- db/migrate/002_acts_as_taggable_on_private_tags.rb
|
62
|
+
- lib/taginator.rb
|
63
|
+
- lib/taginator/tags.rb
|
64
|
+
- lib/taginator/version.rb
|
65
|
+
- lib/tasks/tags_extension_tasks.rake
|
66
|
+
- public/stylesheets/tags.css
|
67
|
+
- radiant-taginator-extension.gemspec
|
68
|
+
- taginator_extension.rb
|
69
|
+
- test/fixtures/meta_tags.yml
|
70
|
+
- test/fixtures/page_parts.yml
|
71
|
+
- test/fixtures/pages.yml
|
72
|
+
- test/fixtures/taggings.yml
|
73
|
+
- test/functional/tag_search_page_test.rb
|
74
|
+
- test/functional/tags_extension_test.rb
|
75
|
+
- test/helpers/render_test_helper.rb
|
76
|
+
- test/test_helper.rb
|
77
|
+
- test/unit/page_taggability_test.rb
|
78
|
+
homepage: http://github.com/mikz/radiant-taginator-extension
|
79
|
+
licenses: []
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ! '>'
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 1.3.1
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 2.0.6
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: This extension enhances the page model with tagging capabilities, tagging
|
101
|
+
as in "2.0" and tagclouds.
|
102
|
+
test_files:
|
103
|
+
- test/fixtures/meta_tags.yml
|
104
|
+
- test/fixtures/page_parts.yml
|
105
|
+
- test/fixtures/pages.yml
|
106
|
+
- test/fixtures/taggings.yml
|
107
|
+
- test/functional/tag_search_page_test.rb
|
108
|
+
- test/functional/tags_extension_test.rb
|
109
|
+
- test/helpers/render_test_helper.rb
|
110
|
+
- test/test_helper.rb
|
111
|
+
- test/unit/page_taggability_test.rb
|