radiant-taginator-extension 2.0.beta1
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.
- 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
|