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.
@@ -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=
@@ -0,0 +1 @@
1
+ radiant-*-extension-*.gem
@@ -0,0 +1,3 @@
1
+ [submodule "vendor/plugins/acts-as-taggable-on"]
2
+ path = vendor/plugins/acts-as-taggable-on
3
+ url = https://github.com/mikz/acts-as-taggable-on.git
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rake', '~> 0.9'
@@ -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.
@@ -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>
@@ -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.
@@ -0,0 +1,8 @@
1
+ %tr
2
+ %th.label
3
+ %label{:for => "page_categories_list"}
4
+ Tags
5
+ %td.field
6
+ = f.text_field :category_list, :class => 'textbox'
7
+ - unless model.errors.on_base.nil?
8
+ %span.error= model.errors.on_base
@@ -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
@@ -0,0 +1,4 @@
1
+ module Taginator
2
+ autoload :VERSION, 'taginator/version'
3
+ autoload :Tags, 'taginator/tags'
4
+ end
@@ -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,3 @@
1
+ module Taginator
2
+ VERSION = "2.0.beta1"
3
+ 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,12 @@
1
+ lorem:
2
+ id: 1
3
+ name: lorem
4
+ ipsum:
5
+ id: 2
6
+ name: ipsum
7
+ dolor:
8
+ id: 3
9
+ name: dolor
10
+ sit:
11
+ id: 4
12
+ name: sit
@@ -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
@@ -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