radiant-search-extension 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +36 -0
- data/Rakefile +120 -0
- data/app/models/search_page.rb +157 -0
- data/lib/radiant-search-extension.rb +2 -0
- data/lib/radiant-search-extension/version.rb +3 -0
- data/lib/tasks/search_extension_tasks.rake +13 -0
- data/radiant-search-extension.gemspec +23 -0
- data/search_extension.rb +14 -0
- data/spec/datasets/searched_pages_dataset.rb +14 -0
- data/spec/models/search_page_spec.rb +63 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +36 -0
- data/test/fixtures/page_parts.yml +31 -0
- data/test/fixtures/pages.yml +26 -0
- data/test/functional/search_extension_test.rb +89 -0
- data/test/test_helper.rb +18 -0
- metadata +91 -0
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Radiant Search Extension
|
2
|
+
|
3
|
+
[](http://travis-ci.org/radiant/radiant-search-extension)
|
4
|
+
|
5
|
+
Version: 1.0
|
6
|
+
Description: A simple search extension for Radiant CMS
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add `gem "radiant-search-extension", "~> 1.0"` to your Gemfile and run `bundle install`
|
11
|
+
|
12
|
+
## Example
|
13
|
+
|
14
|
+
```
|
15
|
+
<r:search:form submit="Search"/>
|
16
|
+
|
17
|
+
<r:search:initial>
|
18
|
+
<strong>Enter a phrase above to search this website.</strong>
|
19
|
+
</r:search:initial>
|
20
|
+
|
21
|
+
<r:search:empty>
|
22
|
+
<strong>I couldn't find anything named "<r:search:query/>".</strong>
|
23
|
+
</r:search:empty>
|
24
|
+
|
25
|
+
<r:search:results>
|
26
|
+
Found the following pages that contain "<r:search:query/>".
|
27
|
+
<ul>
|
28
|
+
<r:search:results:each>
|
29
|
+
<li>
|
30
|
+
<r:link/><br/>
|
31
|
+
<r:search:highlight><r:content/></r:search:highlight>
|
32
|
+
</li>
|
33
|
+
</r:search:results:each>
|
34
|
+
</ul>
|
35
|
+
</r:search:results>
|
36
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# I think this is the one that should be moved to the extension Rakefile template
|
2
|
+
|
3
|
+
# In rails 1.2, plugins aren't available in the path until they're loaded.
|
4
|
+
# Check to see if the rspec plugin is installed first and require
|
5
|
+
# it if it is. If not, use the gem version.
|
6
|
+
|
7
|
+
# Determine where the RSpec plugin is by loading the boot
|
8
|
+
unless defined? RADIANT_ROOT
|
9
|
+
ENV["RAILS_ENV"] = "test"
|
10
|
+
case
|
11
|
+
when ENV["RADIANT_ENV_FILE"]
|
12
|
+
require File.dirname(ENV["RADIANT_ENV_FILE"]) + "/boot"
|
13
|
+
when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
|
14
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
|
15
|
+
else
|
16
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake'
|
21
|
+
require 'rake/rdoctask'
|
22
|
+
require 'rake/testtask'
|
23
|
+
|
24
|
+
rspec_base = File.expand_path(RADIANT_ROOT + '/vendor/plugins/rspec/lib')
|
25
|
+
$LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
|
26
|
+
require 'spec/rake/spectask'
|
27
|
+
# require 'spec/translator'
|
28
|
+
|
29
|
+
# Cleanup the RADIANT_ROOT constant so specs will load the environment
|
30
|
+
Object.send(:remove_const, :RADIANT_ROOT)
|
31
|
+
|
32
|
+
extension_root = File.expand_path(File.dirname(__FILE__))
|
33
|
+
|
34
|
+
task :default => :spec
|
35
|
+
task :stats => "spec:statsetup"
|
36
|
+
|
37
|
+
desc "Run all specs in spec directory"
|
38
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
39
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
40
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
41
|
+
end
|
42
|
+
|
43
|
+
namespace :spec do
|
44
|
+
desc "Run all specs in spec directory with RCov"
|
45
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
46
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
47
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
48
|
+
t.rcov = true
|
49
|
+
t.rcov_opts = ['--exclude', 'spec', '--rails']
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "Print Specdoc for all specs"
|
53
|
+
Spec::Rake::SpecTask.new(:doc) do |t|
|
54
|
+
t.spec_opts = ["--format", "specdoc", "--dry-run"]
|
55
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
56
|
+
end
|
57
|
+
|
58
|
+
[:models, :controllers, :views, :helpers].each do |sub|
|
59
|
+
desc "Run the specs under spec/#{sub}"
|
60
|
+
Spec::Rake::SpecTask.new(sub) do |t|
|
61
|
+
t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
|
62
|
+
t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Hopefully no one has written their extensions in pre-0.9 style
|
67
|
+
# desc "Translate specs from pre-0.9 to 0.9 style"
|
68
|
+
# task :translate do
|
69
|
+
# translator = ::Spec::Translator.new
|
70
|
+
# dir = RAILS_ROOT + '/spec'
|
71
|
+
# translator.translate(dir, dir)
|
72
|
+
# end
|
73
|
+
|
74
|
+
# Setup specs for stats
|
75
|
+
task :statsetup do
|
76
|
+
require 'code_statistics'
|
77
|
+
::STATS_DIRECTORIES << %w(Model\ specs spec/models)
|
78
|
+
::STATS_DIRECTORIES << %w(View\ specs spec/views)
|
79
|
+
::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
|
80
|
+
::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
|
81
|
+
::CodeStatistics::TEST_TYPES << "Model specs"
|
82
|
+
::CodeStatistics::TEST_TYPES << "View specs"
|
83
|
+
::CodeStatistics::TEST_TYPES << "Controller specs"
|
84
|
+
::CodeStatistics::TEST_TYPES << "Helper specs"
|
85
|
+
::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
|
86
|
+
end
|
87
|
+
|
88
|
+
namespace :db do
|
89
|
+
namespace :fixtures do
|
90
|
+
desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
|
91
|
+
task :load => :environment do
|
92
|
+
require 'active_record/fixtures'
|
93
|
+
ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
|
94
|
+
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
|
95
|
+
Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
desc 'Generate documentation for the search extension.'
|
103
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
104
|
+
rdoc.rdoc_dir = 'rdoc'
|
105
|
+
rdoc.title = 'SearchExtension'
|
106
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
107
|
+
rdoc.rdoc_files.include('README')
|
108
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
109
|
+
end
|
110
|
+
|
111
|
+
# For extensions that are in transition
|
112
|
+
desc 'Test the search extension.'
|
113
|
+
Rake::TestTask.new(:test) do |t|
|
114
|
+
t.libs << 'lib'
|
115
|
+
t.pattern = 'test/**/*_test.rb'
|
116
|
+
t.verbose = true
|
117
|
+
end
|
118
|
+
|
119
|
+
# Load any custom rakefiles for extension
|
120
|
+
Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
|
@@ -0,0 +1,157 @@
|
|
1
|
+
class SearchPage < Page
|
2
|
+
description "Provides tags and behavior to support searching Radiant. Based on Oliver Baltzer's search_behavior."
|
3
|
+
attr_accessor :query_result, :query
|
4
|
+
#### Tags ####
|
5
|
+
|
6
|
+
desc %{ Renders the passed query.}
|
7
|
+
tag 'search:query' do |tag|
|
8
|
+
CGI.escapeHTML(query)
|
9
|
+
end
|
10
|
+
|
11
|
+
desc %{ Renders the contained block when query is blank.}
|
12
|
+
tag 'search:initial' do |tag|
|
13
|
+
if query.empty?
|
14
|
+
tag.expand
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
desc %{ Renders the contained block if no results were returned.}
|
19
|
+
tag 'search:empty' do |tag|
|
20
|
+
if query_result.blank? && !query.empty?
|
21
|
+
tag.expand
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc %{ Renders the contained block if results were returned.}
|
26
|
+
tag 'search:results' do |tag|
|
27
|
+
unless query_result.blank?
|
28
|
+
if tag.double?
|
29
|
+
tag.expand
|
30
|
+
else
|
31
|
+
content = ''
|
32
|
+
query_result.each do |page|
|
33
|
+
content << "<p><a href='#{page.url}'>#{page.title}</a><br />"
|
34
|
+
content << helper.truncate(helper.strip_tags(page.parts.first.content).gsub(/\s+/," "), 100)
|
35
|
+
content << "</p>"
|
36
|
+
end
|
37
|
+
content
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc %{ Renders the contained block for each result page. The context
|
43
|
+
inside the tag refers to the found page.}
|
44
|
+
tag 'search:results:each' do |tag|
|
45
|
+
returning String.new do |content|
|
46
|
+
query_result.each do |page|
|
47
|
+
tag.locals.page = page
|
48
|
+
content << tag.expand unless page == tag.globals.page
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
desc %{ Quantity of search results fetched.}
|
54
|
+
tag 'search:results:quantity' do |tag|
|
55
|
+
query_result.blank? ? 0 : query_result.size
|
56
|
+
end
|
57
|
+
|
58
|
+
desc %{ <r:truncate_and_strip [length="100"] />
|
59
|
+
Truncates and strips all HTML tags from the content of the contained block.
|
60
|
+
Useful for displaying a snippet of a found page. The optional `length' attribute
|
61
|
+
specifies how many characters to truncate to.}
|
62
|
+
tag 'truncate_and_strip' do |tag|
|
63
|
+
tag.attr['length'] ||= 100
|
64
|
+
length = tag.attr['length'].to_i
|
65
|
+
helper.truncate(helper.strip_tags(tag.expand).gsub(/\s+/," "), :length => length)
|
66
|
+
end
|
67
|
+
|
68
|
+
desc %{ <r:search:highlight [length="100"] />
|
69
|
+
Highlights the search keywords from the content of the contained block.
|
70
|
+
Strips all HTML tags and truncates the relevant part.
|
71
|
+
Useful for displaying a snippet of a found page. The optional `length' attribute
|
72
|
+
specifies how many characters to truncate to.}
|
73
|
+
tag 'highlight' do |tag|
|
74
|
+
length = (tag.attr['length'] ||= 100).to_i
|
75
|
+
content = helper.strip_tags(tag.expand).gsub(/\s+/," ")
|
76
|
+
match = content.match(query.split(' ').first)
|
77
|
+
if match
|
78
|
+
start = match.begin(0)
|
79
|
+
begining = (start - length/2)
|
80
|
+
begining = 0 if begining < 0
|
81
|
+
chars = content.mb_chars
|
82
|
+
relevant_content = chars.length > length ? (chars[(begining)...(begining + length)]).to_s + "..." : content
|
83
|
+
helper.highlight(relevant_content, query.split)
|
84
|
+
else
|
85
|
+
helper.truncate(content, length)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
#### "Behavior" methods ####
|
90
|
+
def cache?
|
91
|
+
false
|
92
|
+
end
|
93
|
+
|
94
|
+
def render
|
95
|
+
@query_result = []
|
96
|
+
@query = ""
|
97
|
+
q = @request.parameters[:q]
|
98
|
+
exclude_pages = (@request.parameters[:exclude_pages] || '').split(',')
|
99
|
+
case Page.connection.adapter_name.downcase
|
100
|
+
when 'postgresql'
|
101
|
+
sql_content_check = "((lower(page_parts.content) ILIKE ?) OR (lower(title) ILIKE ?))"
|
102
|
+
else
|
103
|
+
sql_content_check = "((LOWER(page_parts.content) LIKE ?) OR (LOWER(title) LIKE ?))"
|
104
|
+
end
|
105
|
+
unless (@query = q.to_s.strip).blank?
|
106
|
+
tokens = query.split.collect { |c| "%#{c.downcase}%"}
|
107
|
+
pages = Page.find(:all, :order => 'published_at DESC', :include => [ :parts ],
|
108
|
+
:conditions => [(["#{sql_content_check}"] * tokens.size).join(" AND "),
|
109
|
+
*tokens.collect { |token| [token] * 2 }.flatten])
|
110
|
+
@query_result = pages.delete_if { |p| !p.published? ||
|
111
|
+
exclude_pages.include?(p.url)}
|
112
|
+
end
|
113
|
+
lazy_initialize_parser_and_context
|
114
|
+
if layout
|
115
|
+
parse_object(layout)
|
116
|
+
else
|
117
|
+
render_part(:body)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def helper
|
122
|
+
@helper ||= ActionView::Base.new
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
class Page
|
128
|
+
#### Tags ####
|
129
|
+
desc %{ The namespace for all search tags.}
|
130
|
+
tag 'search' do |tag|
|
131
|
+
tag.expand
|
132
|
+
end
|
133
|
+
|
134
|
+
desc %{
|
135
|
+
Renders a search form, with the optional label, submit text and url.
|
136
|
+
|
137
|
+
If you need to exclude some pages from the search results you can specify their URLs in exclude_pages attribute separated by comma. Don't forget trailing slash
|
138
|
+
|
139
|
+
Optionally allows setting the CSS class of the button and text inputs for formatting.
|
140
|
+
|
141
|
+
<pre><code><r:search:form [label=""] [url="/search"]
|
142
|
+
[submit="Search"] [exclude_pages=""]
|
143
|
+
[box_class="CSS class name"]
|
144
|
+
[button_class="CSS class name"] /></code></pre>}
|
145
|
+
tag 'search:form' do |tag|
|
146
|
+
label = tag.attr['label'].nil? ? "" : "<label for=\"q\">#{tag.attr['label']}</label> "
|
147
|
+
button_class = tag.attr['button_class'].nil? ? "" : " class=\"#{tag.attr['button_class']}\""
|
148
|
+
box_class = tag.attr['box_class'].nil? ? "" : " class=\"#{tag.attr['box_class']}\""
|
149
|
+
submit = "<input#{button_class} value=\"#{tag.attr['submit'] || "Search"}\" type=\"submit\" />"
|
150
|
+
url = tag.attr['url'].nil? ? self.url.chop : tag.attr['url']
|
151
|
+
exclude_pages_input = %{<input type="hidden" name="exclude_pages" value="#{CGI.escapeHTML(tag.attr['exclude_pages'])}" />}
|
152
|
+
@query ||= ""
|
153
|
+
content = %{<form action="#{url}" method="get" id="search_form">#{exclude_pages_input}<p>#{label}<input type="text"#{box_class} id="q" name="q" value="#{CGI.escapeHTML(@query)}" size="15" alt="search"/> #{submit}</p></form>}
|
154
|
+
content << "\n"
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
namespace :radiant do
|
2
|
+
namespace :extensions do
|
3
|
+
namespace :search do
|
4
|
+
|
5
|
+
desc "Runs the migration of the Search extension"
|
6
|
+
task :migrate => :environment do
|
7
|
+
require 'radiant/extension_migrator'
|
8
|
+
SearchExtension.migrator.migrate
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "radiant-search-extension/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "radiant-search-extension"
|
7
|
+
s.version = RadiantSearchExtension::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Radiant CMS Dev Team"]
|
10
|
+
s.email = ["radiant@radiantcms.org"]
|
11
|
+
s.homepage = "http://radiantcms.org/"
|
12
|
+
s.summary = %q{Simple search for Radiant CMS}
|
13
|
+
s.description = %q{An extension for Radiant CMS to support searching pages}
|
14
|
+
|
15
|
+
ignores = if File.exist?(".gitignore")
|
16
|
+
File.read(".gitignore").split("\n").inject([]) {|a,p| a + Dir[p] }
|
17
|
+
else
|
18
|
+
[]
|
19
|
+
end
|
20
|
+
s.files = Dir["**/*"] - ignores
|
21
|
+
s.test_files = Dir["test/**/*","spec/**/*","features/**/*"] - ignores
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
end
|
data/search_extension.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class SearchExtension < Radiant::Extension
|
2
|
+
version "1.0.0"
|
3
|
+
description %{Provides a page type that allows you to search for pages in
|
4
|
+
Radiant. Based on Oliver Baltzer's search_behavior.}
|
5
|
+
url "http://github.com/radiant/radiant-search-extension"
|
6
|
+
|
7
|
+
def activate
|
8
|
+
SearchPage
|
9
|
+
end
|
10
|
+
|
11
|
+
def deactivate
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class SearchedPagesDataset < Dataset::Base
|
2
|
+
uses :home_page
|
3
|
+
|
4
|
+
def load
|
5
|
+
create_page "Ruby Home Page" do
|
6
|
+
create_page_part :ruby_home_page_body, :content => 'This is the body portion of the Ruby home page.'
|
7
|
+
create_page_part :ruby_home_page_extended, :content => 'This is an extended portion of the Ruby home page.'
|
8
|
+
create_page_part :ruby_home_page_summary, :content => 'This is a summary.'
|
9
|
+
create_page_part :ruby_home_page_sidebar, :content => '<r:title /> sidebar.'
|
10
|
+
end
|
11
|
+
create_page "Documentation", :body => 'This is the documentation section.'
|
12
|
+
create_page "Search", :body => "This is the search section.", :class_name => 'SearchPage'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe SearchPage do
|
4
|
+
dataset :searched_pages
|
5
|
+
describe "<r:truncate_and_strip>" do
|
6
|
+
it "should truncate the contents to the given length" do
|
7
|
+
pages(:search).should render('<r:truncate_and_strip length="10">abcde fghij klmno</r:truncate_and_strip>').as('abcde f...')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "<r:search:form />" do
|
12
|
+
it "should add exclude_pages parameter in hidden input" do
|
13
|
+
pages(:search).should render('<r:search:form exclude_pages="/page/" />').matching(%r{<input type="hidden" name="exclude_pages" value="/page/"})
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should escape value of exclude_pages field" do
|
17
|
+
pages(:search).should render('<r:search:form exclude_pages=">" />').matching(%r{name="exclude_pages" value=">"})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "render" do
|
22
|
+
before :each do
|
23
|
+
@page = SearchPage.new
|
24
|
+
@page.request = ActionController::TestRequest.new
|
25
|
+
@page.response = ActionController::TestResponse.new
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return pages containing search term" do
|
29
|
+
@page.request.query_parameters = {:q => 'documentation'}
|
30
|
+
@page.render
|
31
|
+
@page.query_result.should include pages(:documentation)
|
32
|
+
end
|
33
|
+
it "should not return pages not containing search term" do
|
34
|
+
@page.request.query_parameters = {:q => "documentation"}
|
35
|
+
@page.render
|
36
|
+
@page.query_result.should_not include pages(:ruby_home_page)
|
37
|
+
end
|
38
|
+
it "should not include pages with URL specified in exclude_page" do
|
39
|
+
exclude_page = pages(:documentation)
|
40
|
+
@page.request.query_parameters = {
|
41
|
+
:q => "documentation",
|
42
|
+
:exclude_pages => exclude_page.url
|
43
|
+
}
|
44
|
+
Rails::logger.info "Query_parameters set to #{@page.request.query_parameters}"
|
45
|
+
|
46
|
+
@page.render
|
47
|
+
@page.query_result.should_not include pages(:documentation)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "accepts multiple pages in exclude_page separated by comma" do
|
51
|
+
exclude_pages = "#{pages(:documentation).url},#{pages(:ruby_home_page).url}"
|
52
|
+
@page.request.query_parameters = {
|
53
|
+
:q => ".",
|
54
|
+
:exclude_pages => exclude_pages
|
55
|
+
}
|
56
|
+
Rails::logger.info "Query_parameters set to #{@page.request.query_parameters}"
|
57
|
+
|
58
|
+
@page.render
|
59
|
+
@page.query_result.should_not include pages(:documentation)
|
60
|
+
@page.query_result.should_not include pages(:ruby_home_page)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
unless defined? RADIANT_ROOT
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
3
|
+
case
|
4
|
+
when ENV["RADIANT_ENV_FILE"]
|
5
|
+
require ENV["RADIANT_ENV_FILE"]
|
6
|
+
when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
|
7
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../../")}/config/environment"
|
8
|
+
else
|
9
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../")}/config/environment"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
require "#{RADIANT_ROOT}/spec/spec_helper"
|
13
|
+
|
14
|
+
Dataset::Resolver.default << (File.dirname(__FILE__) + "/datasets")
|
15
|
+
|
16
|
+
if File.directory?(File.dirname(__FILE__) + "/matchers")
|
17
|
+
Dir[File.dirname(__FILE__) + "/matchers/*.rb"].each {|file| require file }
|
18
|
+
end
|
19
|
+
|
20
|
+
Spec::Runner.configure do |config|
|
21
|
+
# config.use_transactional_fixtures = true
|
22
|
+
# config.use_instantiated_fixtures = false
|
23
|
+
# config.fixture_path = RAILS_ROOT + '/spec/fixtures'
|
24
|
+
|
25
|
+
# You can declare fixtures for each behaviour like this:
|
26
|
+
# describe "...." do
|
27
|
+
# fixtures :table_a, :table_b
|
28
|
+
#
|
29
|
+
# Alternatively, if you prefer to declare them only once, you can
|
30
|
+
# do so here, like so ...
|
31
|
+
#
|
32
|
+
# config.global_fixtures = :table_a, :table_b
|
33
|
+
#
|
34
|
+
# If you declare global fixtures, be aware that they will be declared
|
35
|
+
# for all of your examples, even those that don't use them.
|
36
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
2
|
+
body:
|
3
|
+
id: 1
|
4
|
+
name: body
|
5
|
+
content: This is the body portion of the Ruby home page.
|
6
|
+
page_id: 1
|
7
|
+
extended:
|
8
|
+
id: 2
|
9
|
+
name: extended
|
10
|
+
content: This is an extended portion of the Ruby home page.
|
11
|
+
page_id: 1
|
12
|
+
summary:
|
13
|
+
id: 3
|
14
|
+
name: summary
|
15
|
+
content: This is a summary.
|
16
|
+
page_id: 1
|
17
|
+
sidebar:
|
18
|
+
id: 4
|
19
|
+
name: sidebar
|
20
|
+
content: <r:title /> sidebar.
|
21
|
+
page_id: 1
|
22
|
+
documentation_body:
|
23
|
+
id: 5
|
24
|
+
name: body
|
25
|
+
content: This is the documentation section.
|
26
|
+
page_id: 2
|
27
|
+
search_body:
|
28
|
+
id: 6
|
29
|
+
name: body
|
30
|
+
content: This is the search section.
|
31
|
+
page_id: 3
|
@@ -0,0 +1,26 @@
|
|
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-30 08:41:07
|
18
|
+
search:
|
19
|
+
id: 3
|
20
|
+
class_name: SearchPage
|
21
|
+
title: Search
|
22
|
+
breadcrumb: search
|
23
|
+
slug: search
|
24
|
+
status_id: 100
|
25
|
+
parent_id: 1
|
26
|
+
published_at: 2006-01-30 08:41:07
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class SearchExtensionTest < ActiveSupport::TestCase
|
4
|
+
fixtures :pages
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@controller = SiteController.new
|
8
|
+
@request = ActionController::TestRequest.new
|
9
|
+
@response = ActionController::TestResponse.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_initialization
|
13
|
+
assert_equal RAILS_ROOT + '/vendor/extensions/search', SearchExtension.root
|
14
|
+
assert_equal 'Search', SearchExtension.extension_name
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class SearchTagsTest < ActiveSupport::TestCase
|
20
|
+
test_helper :pages, :render
|
21
|
+
fixtures :pages
|
22
|
+
|
23
|
+
def test_search_form_works_for_regular_page
|
24
|
+
@page = pages(:documentation)
|
25
|
+
form = "<form action=\"/documentation\" method=\"get\" id=\"search_form\"><p><input type=\"text\" id=\"q\" name=\"q\" value=\"\" size=\"15\" alt=\"search\"/> <input value=\"Search\" type=\"submit\" /></p></form>\n"
|
26
|
+
assert_renders form,'<r:search:form />'
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_search_form_with_query
|
30
|
+
@page = pages(:search)
|
31
|
+
@page.query = 'test'
|
32
|
+
form = "<form action=\"/search\" method=\"get\" id=\"search_form\"><p><input type=\"text\" id=\"q\" name=\"q\" value=\"test\" size=\"15\" alt=\"search\"/> <input value=\"Search\" type=\"submit\" /></p></form>\n"
|
33
|
+
assert_renders form, '<r:search:form />'
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_search_form_with_url
|
37
|
+
@page = pages(:search)
|
38
|
+
form = "<form action=\"/other_url\" method=\"get\" id=\"search_form\"><p><input type=\"text\" id=\"q\" name=\"q\" value=\"\" size=\"15\" alt=\"search\"/> <input value=\"Search\" type=\"submit\" /></p></form>\n"
|
39
|
+
assert_renders form, '<r:search:form url="/other_url" />'
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_search_form_with_label
|
43
|
+
@page = pages(:search)
|
44
|
+
form = "<form action=\"/search\" method=\"get\" id=\"search_form\"><p><label for=\"q\">Search:</label> <input type=\"text\" id=\"q\" name=\"q\" value=\"\" size=\"15\" alt=\"search\"/> <input value=\"Search\" type=\"submit\" /></p></form>\n"
|
45
|
+
assert_renders form, '<r:search:form label="Search:" />'
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_search_form_with_submit
|
49
|
+
@page = pages(:search)
|
50
|
+
form = "<form action=\"/search\" method=\"get\" id=\"search_form\"><p><input type=\"text\" id=\"q\" name=\"q\" value=\"\" size=\"15\" alt=\"search\"/> <input value=\"Go!\" type=\"submit\" /></p></form>\n"
|
51
|
+
assert_renders form, '<r:search:form submit="Go!" />'
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_truncate_and_strip
|
55
|
+
@page = pages(:search)
|
56
|
+
assert_renders 'abcde f...', '<r:truncate_and_strip length="10">abcde fghij klmno</r:truncate_and_strip>'
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_highlight
|
60
|
+
@page = pages(:search)
|
61
|
+
@page.query = 'abc'
|
62
|
+
assert_renders '<strong class="highlight">abc</strong>de fghij klmno', '<r:search:highlight>abcde fghij klmno</r:search:highlight>'
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_highlight_only_highlights_first_word
|
66
|
+
@page = pages(:search)
|
67
|
+
@page.query = 'cde fgh'
|
68
|
+
assert_renders 'ab<strong class="highlight">cde</strong> <strong class="highlight">fgh</strong>ij klmno', '<r:search:highlight>abcde fghij klmno</r:search:highlight>'
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_highlight_renders_truncated_content_if_content_does_not_match_query
|
72
|
+
@page = pages(:search)
|
73
|
+
@page.query = 'X'
|
74
|
+
assert_renders 'abcde f...', '<r:search:highlight length="10">abcde fghij klmno</r:search:highlight>'
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_highlight_with_uneven_length
|
78
|
+
@page = pages(:search)
|
79
|
+
@page.query = 'X'
|
80
|
+
assert_renders 'abcde ...', '<r:search:highlight length="9">abcde fghij klmno</r:search:highlight>'
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_highlight_with_small_length
|
84
|
+
@page = pages(:search)
|
85
|
+
@page.query = 'abc'
|
86
|
+
assert_renders '<strong class="highlight">abc</strong>de fgh...', '<r:search:highlight length="9">abcde fghij klmno</r:search:highlight>'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Load the environment
|
2
|
+
unless defined? RADIANT_ROOT
|
3
|
+
ENV["RAILS_ENV"] = "test"
|
4
|
+
require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../")}/config/environment"
|
5
|
+
end
|
6
|
+
require "#{RADIANT_ROOT}/test/test_helper"
|
7
|
+
|
8
|
+
class ActiveSupport::TestCase
|
9
|
+
|
10
|
+
# Include a helper to make testing Radius tags easier
|
11
|
+
#test_helper :extension_tags
|
12
|
+
|
13
|
+
# Add the fixture directory to the fixture path
|
14
|
+
self.fixture_path = File.dirname(__FILE__) + "/fixtures"
|
15
|
+
|
16
|
+
# Add more helper methods to be used by all extension tests here...
|
17
|
+
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: radiant-search-extension
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Radiant CMS Dev Team
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-01-08 00:00:00 -06:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: An extension for Radiant CMS to support searching pages
|
23
|
+
email:
|
24
|
+
- radiant@radiantcms.org
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- app/models/search_page.rb
|
33
|
+
- lib/radiant-search-extension/version.rb
|
34
|
+
- lib/radiant-search-extension.rb
|
35
|
+
- lib/tasks/search_extension_tasks.rake
|
36
|
+
- radiant-search-extension-1.0.0.gem
|
37
|
+
- radiant-search-extension.gemspec
|
38
|
+
- Rakefile
|
39
|
+
- README.md
|
40
|
+
- search_extension.rb
|
41
|
+
- spec/datasets/searched_pages_dataset.rb
|
42
|
+
- spec/models/search_page_spec.rb
|
43
|
+
- spec/spec.opts
|
44
|
+
- spec/spec_helper.rb
|
45
|
+
- test/fixtures/page_parts.yml
|
46
|
+
- test/fixtures/pages.yml
|
47
|
+
- test/functional/search_extension_test.rb
|
48
|
+
- test/test_helper.rb
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: http://radiantcms.org/
|
51
|
+
licenses: []
|
52
|
+
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
hash: 3
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
version: "0"
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
hash: 3
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
requirements: []
|
77
|
+
|
78
|
+
rubyforge_project:
|
79
|
+
rubygems_version: 1.3.9.3
|
80
|
+
signing_key:
|
81
|
+
specification_version: 3
|
82
|
+
summary: Simple search for Radiant CMS
|
83
|
+
test_files:
|
84
|
+
- test/fixtures/page_parts.yml
|
85
|
+
- test/fixtures/pages.yml
|
86
|
+
- test/functional/search_extension_test.rb
|
87
|
+
- test/test_helper.rb
|
88
|
+
- spec/datasets/searched_pages_dataset.rb
|
89
|
+
- spec/models/search_page_spec.rb
|
90
|
+
- spec/spec.opts
|
91
|
+
- spec/spec_helper.rb
|