rack-seo 0.0.1
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/.gitignore +63 -0
- data/.rspec +1 -0
- data/.rvmrc +38 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +20 -0
- data/README.md +145 -0
- data/Rakefile +1 -0
- data/config/rack_seo.default.yml +5 -0
- data/generators/rack_seo.sample.yml +32 -0
- data/lib/rack-seo/base.rb +57 -0
- data/lib/rack-seo/dispatcher.rb +19 -0
- data/lib/rack-seo/document.rb +107 -0
- data/lib/rack-seo/sanitize.rb +15 -0
- data/lib/rack-seo/summarizer.rb +40 -0
- data/lib/rack-seo/title_formatter.rb +9 -0
- data/lib/rack-seo/version.rb +5 -0
- data/lib/rack-seo.rb +16 -0
- data/lib/tasks/setup.rake +6 -0
- data/rack-seo.gemspec +24 -0
- data/spec/configuration_spec.rb +97 -0
- data/spec/fixtures/complex.html +437 -0
- data/spec/fixtures/simple.html +10 -0
- data/spec/rack-seo_spec.rb +107 -0
- data/spec/sample_configs/custom_paths.yml +16 -0
- data/spec/sample_configs/happy.yml +5 -0
- data/spec/sample_configs/sad.yml +5 -0
- data/spec/spec_helper.rb +45 -0
- metadata +104 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
describe "RackSeo" do
|
3
|
+
before do
|
4
|
+
@rack_seo = Rack::RackSeo::Base.new Apps.complex, :public => Fixtures.path
|
5
|
+
@env = Rack::MockRequest.env_for '/'
|
6
|
+
end
|
7
|
+
|
8
|
+
context "has sensible defaults" do
|
9
|
+
context "for a page with a #content div" do
|
10
|
+
before do
|
11
|
+
@example_page = Fixtures.complex
|
12
|
+
@orig_meta_title_text = @example_page.title_content
|
13
|
+
@orig_meta_description_text = @example_page.description_content
|
14
|
+
@orig_meta_keywords_text = @example_page.keywords_content
|
15
|
+
@orig_h1_text = @example_page.css('h1').text
|
16
|
+
@rack_seo.execute! @example_page
|
17
|
+
end
|
18
|
+
|
19
|
+
it "pulls the h1 tag into the meta title by default" do
|
20
|
+
@example_page.title_content.should == @orig_h1_text
|
21
|
+
@example_page.title_content.should_not == @orig_meta_title_text
|
22
|
+
end
|
23
|
+
|
24
|
+
it "summarises the description based on the text in #content if it exists" do
|
25
|
+
@example_page.description_content.should_not == @orig_meta_description_text
|
26
|
+
@example_page.description_content.should_not == ""
|
27
|
+
@example_page.description_content.should_not be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "summarises the keywords based on the text in #content if it exists" do
|
31
|
+
@example_page.keywords_content.should_not == @orig_meta_keywords_text
|
32
|
+
@example_page.keywords_content.should_not == ""
|
33
|
+
@example_page.keywords_content.should_not be_nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "for a page without #content div" do
|
38
|
+
before do
|
39
|
+
@example_page = Fixtures.simple
|
40
|
+
@orig_meta_description_text = @example_page.description_content
|
41
|
+
@orig_meta_keywords_text = @example_page.keywords_content
|
42
|
+
@rack_seo.execute! @example_page
|
43
|
+
end
|
44
|
+
it "summarises the description based on the text in the page if #content does not exist" do
|
45
|
+
@example_page.description_content.should_not == @orig_meta_description_text
|
46
|
+
@example_page.description_content.should_not == ""
|
47
|
+
@example_page.description_content.should_not be_nil
|
48
|
+
end
|
49
|
+
|
50
|
+
it "summarises the keywords based on the text in the page if #content does not exist" do
|
51
|
+
@example_page.keywords_content.should_not == @orig_meta_keywords_text
|
52
|
+
@example_page.keywords_content.should_not == ""
|
53
|
+
@example_page.keywords_content.should_not be_nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
context "validate output" do
|
60
|
+
before do
|
61
|
+
@example_page = Fixtures.complex
|
62
|
+
@rack_seo.execute! @example_page
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should have a head tag that is the first child of the root node" do
|
66
|
+
@example_page.root.children.first.should == @example_page.at('head')
|
67
|
+
end
|
68
|
+
it "should have a title that is less that 65 chars and 15 words" do
|
69
|
+
title = @example_page.title_tag
|
70
|
+
title.text.length.should be <= 65
|
71
|
+
title.text.split(/\b/).length.should be > 1
|
72
|
+
title.text.split(/\b/).length.should be <= 15
|
73
|
+
end
|
74
|
+
it "should have a meta description with content that is less than 150 chars and 30 words" do
|
75
|
+
description = @example_page.description_content
|
76
|
+
description.split(/\b/).length.should be > 1
|
77
|
+
pending("A better text summarizer with more control over length")
|
78
|
+
description.split(/\b/).length.should be <= 100
|
79
|
+
description.length.should be <= 150
|
80
|
+
description.split(/\b/).length.should be <= 30
|
81
|
+
end
|
82
|
+
it "has a title that is readable (no line breaks or leading/trailing spaces)" do
|
83
|
+
title = @example_page.title_tag
|
84
|
+
title.text.should_not match(/\A\s/)
|
85
|
+
title.text.should_not match(/\n+/)
|
86
|
+
title.text.should_not match(/\s\s+/)
|
87
|
+
title.text.should_not match(/\t+/)
|
88
|
+
title.text.should_not match(/\s\Z/)
|
89
|
+
end
|
90
|
+
it "has a readable meta_description (no line breaks or leading/trailing spaces)" do
|
91
|
+
meta_description = @example_page.description_content
|
92
|
+
meta_description.should_not match(/\A\s/)
|
93
|
+
meta_description.should_not match(/\n+/)
|
94
|
+
meta_description.should_not match(/\s\s+/)
|
95
|
+
meta_description.should_not match(/\t+/)
|
96
|
+
meta_description.should_not match(/\s\Z/)
|
97
|
+
end
|
98
|
+
it "should have meta keywords with content that is a lowercase, comma separated list, without leading/trailing commas" do
|
99
|
+
keywords = @example_page.keywords_content
|
100
|
+
keywords.should match /[a-z,]+/
|
101
|
+
keywords.should_not match /\A,/
|
102
|
+
keywords.should_not match /,\Z/
|
103
|
+
keywords.split(/,/).length.should be > 1
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
---
|
2
|
+
default:
|
3
|
+
title_format: "{{h1}} - Custom Path Test"
|
4
|
+
meta_description_selector: "#content"
|
5
|
+
meta_keywords_selector: "#banner"
|
6
|
+
custom:
|
7
|
+
-
|
8
|
+
matcher: '/test-path'
|
9
|
+
title_format: "Test one - {{h2}}"
|
10
|
+
meta_description_selector: "#sidebar"
|
11
|
+
meta_keywords_selector: "#banner"
|
12
|
+
-
|
13
|
+
matcher: !ruby/regexp '/\/test-regex-.*/'
|
14
|
+
title_format: "Test regex - {{h2}}"
|
15
|
+
meta_description_selector: "#sidebar"
|
16
|
+
meta_keywords_selector: "#banner"
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'pry'
|
4
|
+
require 'rspec'
|
5
|
+
require 'rack/test'
|
6
|
+
require 'fileutils'
|
7
|
+
require 'tmpdir'
|
8
|
+
require 'ostruct'
|
9
|
+
require 'rack-seo'
|
10
|
+
|
11
|
+
def fixture name
|
12
|
+
File.read(File.join(Fixtures.path, name))
|
13
|
+
end
|
14
|
+
|
15
|
+
module Apps
|
16
|
+
class << self
|
17
|
+
def complex
|
18
|
+
lambda { |env| [200, { 'Content-Type' => 'text/html' }, [fixture('complex.html')]] }
|
19
|
+
end
|
20
|
+
|
21
|
+
def simple
|
22
|
+
lambda { |env| [200, { 'Content-Type' => 'text/html' }, [fixture('simple.html')]] }
|
23
|
+
end
|
24
|
+
|
25
|
+
def plain_text
|
26
|
+
lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ['plain texto']] }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Requires supporting files with custom matchers and macros, etc,
|
32
|
+
# in ./support/ and its subdirectories.
|
33
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
34
|
+
|
35
|
+
RSpec.configure do |config|
|
36
|
+
include Rack::Test::Methods
|
37
|
+
config.before :each do
|
38
|
+
Fixtures = OpenStruct.new unless defined?(Fixtures)
|
39
|
+
Fixtures.path = File.join(File.dirname(__FILE__), 'fixtures')
|
40
|
+
Fixtures.complex = Rack::RackSeo::Document.new(fixture('complex.html'))
|
41
|
+
Fixtures.complex_copy = Rack::RackSeo::Document.new(fixture('complex.html'))
|
42
|
+
Fixtures.simple = Rack::RackSeo::Document.new(fixture('simple.html'))
|
43
|
+
Fixtures.simple_copy = Rack::RackSeo::Document.new(fixture('simple.html'))
|
44
|
+
end
|
45
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-seo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Xavier Riley
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nokogiri
|
16
|
+
requirement: &2156361000 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.5.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2156361000
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: summarize
|
27
|
+
requirement: &2156359840 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.3
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2156359840
|
36
|
+
description: Lets you extract sensible default content for meta tags using the markup
|
37
|
+
from that page.
|
38
|
+
email:
|
39
|
+
- xavriley@github.com
|
40
|
+
executables: []
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- .rspec
|
46
|
+
- .rvmrc
|
47
|
+
- Gemfile
|
48
|
+
- LICENSE.txt
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- config/rack_seo.default.yml
|
52
|
+
- generators/rack_seo.sample.yml
|
53
|
+
- lib/rack-seo.rb
|
54
|
+
- lib/rack-seo/base.rb
|
55
|
+
- lib/rack-seo/dispatcher.rb
|
56
|
+
- lib/rack-seo/document.rb
|
57
|
+
- lib/rack-seo/sanitize.rb
|
58
|
+
- lib/rack-seo/summarizer.rb
|
59
|
+
- lib/rack-seo/title_formatter.rb
|
60
|
+
- lib/rack-seo/version.rb
|
61
|
+
- lib/tasks/setup.rake
|
62
|
+
- rack-seo.gemspec
|
63
|
+
- spec/configuration_spec.rb
|
64
|
+
- spec/fixtures/complex.html
|
65
|
+
- spec/fixtures/simple.html
|
66
|
+
- spec/rack-seo_spec.rb
|
67
|
+
- spec/sample_configs/custom_paths.yml
|
68
|
+
- spec/sample_configs/happy.yml
|
69
|
+
- spec/sample_configs/sad.yml
|
70
|
+
- spec/spec_helper.rb
|
71
|
+
homepage: http://github.com/xavriley/rack-seo
|
72
|
+
licenses:
|
73
|
+
- MIT
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 1.8.10
|
93
|
+
signing_key:
|
94
|
+
specification_version: 3
|
95
|
+
summary: Generate and manage meta tags on the fly using Rack Middleware
|
96
|
+
test_files:
|
97
|
+
- spec/configuration_spec.rb
|
98
|
+
- spec/fixtures/complex.html
|
99
|
+
- spec/fixtures/simple.html
|
100
|
+
- spec/rack-seo_spec.rb
|
101
|
+
- spec/sample_configs/custom_paths.yml
|
102
|
+
- spec/sample_configs/happy.yml
|
103
|
+
- spec/sample_configs/sad.yml
|
104
|
+
- spec/spec_helper.rb
|