content_spinning 0.0.1 → 0.0.2
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 +14 -2
- data/lib/content_spinning.rb +50 -35
- data/lib/content_spinning/version.rb +1 -1
- data/spec/content_spinning_spec.rb +152 -0
- data/spec/spec_helper.rb +8 -0
- metadata +30 -4
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Content Spinning
|
2
2
|
|
3
|
-
|
3
|
+
`ContentSpinning` is a ruby library made to spin some text.
|
4
|
+
It manages nested spinning.
|
4
5
|
|
5
6
|
## Example
|
6
7
|
|
@@ -13,7 +14,12 @@ ContentSpinning.spin "Hi {there|you}! I'm {efficient|productive}."
|
|
13
14
|
returns this array :
|
14
15
|
|
15
16
|
```ruby
|
16
|
-
[
|
17
|
+
[
|
18
|
+
"Hi there! I'm efficient.",
|
19
|
+
"Hi there! I'm productive.",
|
20
|
+
"Hi you! I'm efficient.",
|
21
|
+
"Hi you! I'm productive."
|
22
|
+
]
|
17
23
|
```
|
18
24
|
|
19
25
|
## Install
|
@@ -22,3 +28,9 @@ returns this array :
|
|
22
28
|
gem install content_spinning
|
23
29
|
```
|
24
30
|
|
31
|
+
## Todo
|
32
|
+
|
33
|
+
A few things to do :
|
34
|
+
|
35
|
+
* Executable
|
36
|
+
|
data/lib/content_spinning.rb
CHANGED
@@ -2,64 +2,79 @@ module ContentSpinning
|
|
2
2
|
class << self
|
3
3
|
|
4
4
|
def spin(text)
|
5
|
+
text = clean(text)
|
5
6
|
result = parse(text)
|
7
|
+
|
6
8
|
spin_all_level(result[:parsed], result[:max_level])
|
7
9
|
end
|
8
10
|
|
11
|
+
def clean(text)
|
12
|
+
begin
|
13
|
+
text_before_run = text.clone
|
14
|
+
|
15
|
+
# Strip empty spin
|
16
|
+
text.gsub!(/\{\|*\}/, '')
|
17
|
+
|
18
|
+
# Remove spin with only one choice
|
19
|
+
text.gsub!(/\{([^\{\}\|]+)\}/, '\1')
|
20
|
+
|
21
|
+
end while (text != text_before_run)
|
22
|
+
|
23
|
+
text
|
24
|
+
end
|
25
|
+
|
9
26
|
def parse(text, level = 1)
|
10
27
|
return {:parsed => text, :max_level => level - 1} unless text.include? "{"
|
11
28
|
|
12
|
-
text.gsub!(/\{\}/, '')
|
13
|
-
text.gsub!(/\{([^\{\}\|]+)\}/, '\1')
|
14
|
-
|
15
29
|
text.gsub!(/\{([^\{\}]+)\}/) do |match|
|
16
|
-
match.gsub!(/\{/, "__SPIN_BEGIN_
|
17
|
-
match.gsub!(/\}/, "__SPIN_END_
|
18
|
-
match.gsub!(/\|/, "__SPIN_OR_
|
30
|
+
match.gsub!(/\{/, "__SPIN_BEGIN_#{level}__")
|
31
|
+
match.gsub!(/\}/, "__SPIN_END_#{level}__")
|
32
|
+
match.gsub!(/\|/, "__SPIN_OR_#{level}__")
|
19
33
|
end
|
20
34
|
|
21
35
|
parse(text, level+1)
|
22
36
|
end
|
23
37
|
|
24
38
|
def spin_a_level(text_or_array, level)
|
25
|
-
|
26
|
-
|
27
|
-
spin_begin =
|
28
|
-
spin_end =
|
29
|
-
spin_or =
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
content_array = text_or_array.is_a?(Array) ? text_or_array : [text_or_array]
|
40
|
+
|
41
|
+
spin_begin = "__SPIN_BEGIN_#{level}__"
|
42
|
+
spin_end = "__SPIN_END_#{level}__"
|
43
|
+
spin_or = "__SPIN_OR_#{level}__"
|
44
|
+
|
45
|
+
content_array.map! do |text|
|
46
|
+
if text.include? spin_begin
|
47
|
+
# Spin a first one
|
48
|
+
before, vary, after = text.partition(Regexp.new(spin_begin + '.+?' + spin_end))
|
49
|
+
vary.gsub!(Regexp.union(spin_begin, spin_end), '')
|
50
|
+
|
51
|
+
varies = vary.split(Regexp.new(spin_or), -1)
|
52
|
+
varies.map! { |vary| before + vary + after }
|
53
|
+
|
54
|
+
# Continue spinning the level if there are other same level spin or just return
|
55
|
+
if after.include? spin_begin
|
56
|
+
spin_a_level(varies, level).flatten
|
57
|
+
else
|
58
|
+
varies
|
59
|
+
end
|
60
|
+
else
|
61
|
+
text
|
46
62
|
end
|
47
|
-
|
48
|
-
varies
|
49
63
|
end
|
50
64
|
|
51
|
-
|
65
|
+
content_array.flatten
|
52
66
|
end
|
53
67
|
|
54
68
|
def spin_all_level(text_or_array, from_level)
|
55
|
-
|
56
|
-
return text_or_array if from_level == 0
|
69
|
+
content_array = text_or_array.is_a?(Array) ? text_or_array : [text_or_array]
|
57
70
|
|
58
|
-
|
59
|
-
|
71
|
+
if from_level > 0
|
72
|
+
(1..from_level).reverse_each do |level|
|
73
|
+
content_array = spin_a_level(content_array, level)
|
74
|
+
end
|
60
75
|
end
|
61
76
|
|
62
|
-
|
77
|
+
content_array.delete_if(&:empty?).uniq
|
63
78
|
end
|
64
79
|
|
65
80
|
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe String do
|
5
|
+
|
6
|
+
describe "spin" do
|
7
|
+
it "should be defined" do
|
8
|
+
String.new.respond_to?(:spin).should be_true
|
9
|
+
end
|
10
|
+
it "should call the spin function of ContentSpinning module with the string in argument" do
|
11
|
+
ContentSpinning.should_receive(:spin).with("AaBb")
|
12
|
+
"AaBb".spin
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
describe ContentSpinning do
|
19
|
+
|
20
|
+
describe "clean" do
|
21
|
+
it "should return the string if there is no spin" do
|
22
|
+
ContentSpinning.clean("AaBb").should eq "AaBb"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should strip empty spin" do
|
26
|
+
ContentSpinning.clean("a{}").should eq "a"
|
27
|
+
ContentSpinning.clean("a{|}").should eq "a"
|
28
|
+
ContentSpinning.clean("a{||}").should eq "a"
|
29
|
+
ContentSpinning.clean("{}a{}").should eq "a"
|
30
|
+
ContentSpinning.clean("{}a{|}").should eq "a"
|
31
|
+
|
32
|
+
ContentSpinning.clean("a{{}}").should eq "a"
|
33
|
+
ContentSpinning.clean("a{{|}}").should eq "a"
|
34
|
+
ContentSpinning.clean("a{{}|}").should eq "a"
|
35
|
+
|
36
|
+
ContentSpinning.clean("a{a{}}").should eq "aa"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should remove spin with no choice" do
|
40
|
+
ContentSpinning.clean("{a}").should eq "a"
|
41
|
+
ContentSpinning.clean("a{b}").should eq "ab"
|
42
|
+
ContentSpinning.clean("a{b}c").should eq "abc"
|
43
|
+
ContentSpinning.clean("a{b}c{d}e").should eq "abcde"
|
44
|
+
|
45
|
+
ContentSpinning.clean("{{a}}").should eq "a"
|
46
|
+
ContentSpinning.clean("a{{b}}").should eq "ab"
|
47
|
+
ContentSpinning.clean("a{{b}}c").should eq "abc"
|
48
|
+
ContentSpinning.clean("a{{b}}c{{d}}e").should eq "abcde"
|
49
|
+
|
50
|
+
ContentSpinning.clean("{{{a}}}").should eq "a"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should keep legitimate spin" do
|
54
|
+
ContentSpinning.clean("{a|b}").should eq "{a|b}"
|
55
|
+
ContentSpinning.clean("a{b|c}").should eq "a{b|c}"
|
56
|
+
ContentSpinning.clean("{{a|b}|c}").should eq "{{a|b}|c}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "parse" do
|
61
|
+
it "should return the string if there is no spin" do
|
62
|
+
ContentSpinning.parse("AaBb").should eq :max_level => 0, :parsed => "AaBb"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should parse simple spin" do
|
66
|
+
ContentSpinning.parse("{a|b}").should eq :max_level => 1, :parsed => "__SPIN_BEGIN_1__a__SPIN_OR_1__b__SPIN_END_1__"
|
67
|
+
ContentSpinning.parse("a{b|c}").should eq :max_level => 1, :parsed => "a__SPIN_BEGIN_1__b__SPIN_OR_1__c__SPIN_END_1__"
|
68
|
+
ContentSpinning.parse("{a|b}c{d|e}").should eq :max_level => 1, :parsed => "__SPIN_BEGIN_1__a__SPIN_OR_1__b__SPIN_END_1__c__SPIN_BEGIN_1__d__SPIN_OR_1__e__SPIN_END_1__"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should manage recursive spin" do
|
72
|
+
ContentSpinning.parse("{{a|b}|c}").should eq :max_level => 2, :parsed => "__SPIN_BEGIN_2____SPIN_BEGIN_1__a__SPIN_OR_1__b__SPIN_END_1____SPIN_OR_2__c__SPIN_END_2__"
|
73
|
+
ContentSpinning.parse("{a|{b|c}}").should eq :max_level => 2, :parsed => "__SPIN_BEGIN_2__a__SPIN_OR_2____SPIN_BEGIN_1__b__SPIN_OR_1__c__SPIN_END_1____SPIN_END_2__"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "spin" do
|
78
|
+
it "should call the clean function of ContentSpinning module with the string in argument" do
|
79
|
+
ContentSpinning.should_receive(:clean).with("AaBb").and_return("AaBb")
|
80
|
+
ContentSpinning.spin("AaBb")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should return an array" do
|
84
|
+
"AaBb".spin.should eq ["AaBb"]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should return an empty array if the string to spin is empty" do
|
88
|
+
"".spin.should eq []
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should strip empty choices" do
|
92
|
+
"a{}".spin.should eq ["a"]
|
93
|
+
"a{|}".spin.should eq ["a"]
|
94
|
+
"a{||}".spin.should eq ["a"]
|
95
|
+
"{}a{}".spin.should eq ["a"]
|
96
|
+
"{}a{|}".spin.should eq ["a"]
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should strip empty strings from the returned array" do
|
100
|
+
"{|a}".spin.should eq ["a"]
|
101
|
+
"{a|}".spin.should eq ["a"]
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should manage one spin" do
|
105
|
+
"{a}".spin.should eq ["a"]
|
106
|
+
"a{b}".spin.should eq ["ab"]
|
107
|
+
"a{b}c".spin.should eq ["abc"]
|
108
|
+
"{a}{b}".spin.should eq ["ab"]
|
109
|
+
"a{b}{c}d".spin.should eq ["abcd"]
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should manage two spin" do
|
113
|
+
"{a}".spin.should eq ["a"]
|
114
|
+
"a{b}".spin.should eq ["ab"]
|
115
|
+
"a{b}c".spin.should eq ["abc"]
|
116
|
+
"{a}{b}".spin.should eq ["ab"]
|
117
|
+
"a{b}{c}d".spin.should eq ["abcd"]
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should manage spin with an empty choice" do
|
121
|
+
"{|a}".spin.should eq ["a"]
|
122
|
+
"{|a}b".spin.should eq ["b", "ab"]
|
123
|
+
"{a|}b".spin.should eq ["ab", "b"]
|
124
|
+
"{a|}{b|}".spin.should eq ["ab", "a", "b"]
|
125
|
+
"a{b|}{c|}d".spin.should eq ["abcd", "abd", "acd", "ad"]
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should manage spin with two choice" do
|
129
|
+
"{a|b}".spin.should eq ["a", "b"]
|
130
|
+
"{a|b}c".spin.should eq ["ac", "bc"]
|
131
|
+
"{a|b}{c|d}".spin.should eq ["ac", "ad", "bc", "bd"]
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should manage spin with three choice" do
|
135
|
+
"{a|b|c}".spin.should eq ["a", "b", "c"]
|
136
|
+
"{a|b|c}d".spin.should eq ["ad", "bd", "cd"]
|
137
|
+
"{a|b|c}{d|e}".spin.should eq ["ad", "ae", "bd", "be", "cd", "ce"]
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should manage recursive spin" do
|
141
|
+
"{a{b|c}|d}".spin.should eq ["ab", "ac", "d"]
|
142
|
+
"{{a|b}|c}".spin.should eq ["a", "b", "c"]
|
143
|
+
"{a|{b|c}}".spin.should eq ["a", "b", "c"]
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should not return twice the same result" do
|
147
|
+
"{a|a}".spin.should eq ["a"]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: content_spinning
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,30 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
13
|
-
dependencies:
|
12
|
+
date: 2012-03-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &11429000 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.8'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *11429000
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: guard-rspec
|
27
|
+
requirement: &11428420 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *11428420
|
14
36
|
description: ! " To spin some text, mainly for SEO purpose.\n\n Spinning the
|
15
37
|
string \"Hi {there|you}! I'm {efficient|productive}.\" gives\n these four strings
|
16
38
|
:\n\n * Hi there! I'm efficient.\n * Hi there! I'm productive.\n * Hi you!
|
@@ -25,6 +47,8 @@ files:
|
|
25
47
|
- LICENSE
|
26
48
|
- lib/content_spinning/version.rb
|
27
49
|
- lib/content_spinning.rb
|
50
|
+
- spec/content_spinning_spec.rb
|
51
|
+
- spec/spec_helper.rb
|
28
52
|
homepage: http://github.com/maximeg/content_spinning
|
29
53
|
licenses: []
|
30
54
|
post_install_message:
|
@@ -49,4 +73,6 @@ rubygems_version: 1.8.15
|
|
49
73
|
signing_key:
|
50
74
|
specification_version: 3
|
51
75
|
summary: Content Spinning
|
52
|
-
test_files:
|
76
|
+
test_files:
|
77
|
+
- spec/content_spinning_spec.rb
|
78
|
+
- spec/spec_helper.rb
|