content_spinning 0.0.2 → 0.1.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.
- checksums.yaml +7 -0
- data/lib/content_spinning/core_ext/string.rb +7 -0
- data/lib/content_spinning/version.rb +5 -2
- data/lib/content_spinning.rb +16 -17
- data/spec/content_spinning/core_ext/string_spec.rb +21 -0
- data/spec/content_spinning_spec.rb +93 -104
- data/spec/spec_helper.rb +3 -6
- metadata +33 -33
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 79295ec814e234e885f05f6a026177cc49384acf
|
4
|
+
data.tar.gz: b0cee4376b527d0b7a1d1ef0373ff51e385fb8b4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3b44c72fddeafdd9fda092eb44c38f2a30547f974be9771ebf7fe2e92085ebdaaf6ba25991ce213bd4eb1e1c9db4f619d787ff5986b9e2b26528fce5dd5b0381
|
7
|
+
data.tar.gz: 22b09a4e78ccc4686a9387fe5b4313f35abf5d92bf7fe8ff490b2d6569424db83dac152770d66f05c7719ad518a027fc846bd10df7006656abad6e54787036bf
|
data/lib/content_spinning.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
require "content_spinning/core_ext/string"
|
2
|
+
|
1
3
|
module ContentSpinning
|
4
|
+
|
2
5
|
class << self
|
3
6
|
|
4
7
|
def spin(text)
|
8
|
+
text = text.dup
|
5
9
|
text = clean(text)
|
6
10
|
result = parse(text)
|
7
11
|
|
@@ -9,22 +13,23 @@ module ContentSpinning
|
|
9
13
|
end
|
10
14
|
|
11
15
|
def clean(text)
|
12
|
-
|
13
|
-
text_before_run = text.
|
16
|
+
loop do
|
17
|
+
text_before_run = text.dup
|
14
18
|
|
15
19
|
# Strip empty spin
|
16
|
-
text.gsub!(/\{\|*\}/,
|
20
|
+
text.gsub!(/\{\|*\}/, "")
|
17
21
|
|
18
22
|
# Remove spin with only one choice
|
19
23
|
text.gsub!(/\{([^\{\}\|]+)\}/, '\1')
|
20
24
|
|
21
|
-
|
25
|
+
break if text == text_before_run
|
26
|
+
end
|
22
27
|
|
23
28
|
text
|
24
29
|
end
|
25
30
|
|
26
31
|
def parse(text, level = 1)
|
27
|
-
return {:
|
32
|
+
return { parsed: text, max_level: level - 1 } unless text.include?("{")
|
28
33
|
|
29
34
|
text.gsub!(/\{([^\{\}]+)\}/) do |match|
|
30
35
|
match.gsub!(/\{/, "__SPIN_BEGIN_#{level}__")
|
@@ -32,7 +37,7 @@ module ContentSpinning
|
|
32
37
|
match.gsub!(/\|/, "__SPIN_OR_#{level}__")
|
33
38
|
end
|
34
39
|
|
35
|
-
parse(text, level+1)
|
40
|
+
parse(text, level + 1)
|
36
41
|
end
|
37
42
|
|
38
43
|
def spin_a_level(text_or_array, level)
|
@@ -43,16 +48,16 @@ module ContentSpinning
|
|
43
48
|
spin_or = "__SPIN_OR_#{level}__"
|
44
49
|
|
45
50
|
content_array.map! do |text|
|
46
|
-
if text.include?
|
51
|
+
if text.include?(spin_begin)
|
47
52
|
# Spin a first one
|
48
|
-
before, vary, after = text.partition(Regexp.new(spin_begin +
|
49
|
-
vary.gsub!(Regexp.union(spin_begin, spin_end),
|
53
|
+
before, vary, after = text.partition(Regexp.new(spin_begin + ".+?" + spin_end))
|
54
|
+
vary.gsub!(Regexp.union(spin_begin, spin_end), "")
|
50
55
|
|
51
56
|
varies = vary.split(Regexp.new(spin_or), -1)
|
52
|
-
varies.map! { |
|
57
|
+
varies.map! { |choice| before + choice + after }
|
53
58
|
|
54
59
|
# Continue spinning the level if there are other same level spin or just return
|
55
|
-
if after.include?
|
60
|
+
if after.include?(spin_begin)
|
56
61
|
spin_a_level(varies, level).flatten
|
57
62
|
else
|
58
63
|
varies
|
@@ -78,11 +83,5 @@ module ContentSpinning
|
|
78
83
|
end
|
79
84
|
|
80
85
|
end
|
81
|
-
end
|
82
86
|
|
83
|
-
String.class_eval do
|
84
|
-
def spin
|
85
|
-
ContentSpinning.spin(self)
|
86
|
-
end
|
87
87
|
end
|
88
|
-
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe String do
|
4
|
+
describe "#spin" do
|
5
|
+
it "is defined" do
|
6
|
+
expect("").to respond_to(:spin)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "calls the spin function of ContentSpinning module with the string in argument" do
|
10
|
+
expect(ContentSpinning).to receive(:spin).with("AaBb")
|
11
|
+
"AaBb".spin
|
12
|
+
end
|
13
|
+
|
14
|
+
it "does not modify the source string" do
|
15
|
+
source = "{a|b}"
|
16
|
+
expect {
|
17
|
+
source.spin
|
18
|
+
}.not_to change { source }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,152 +1,141 @@
|
|
1
|
-
|
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
|
1
|
+
require "spec_helper"
|
17
2
|
|
18
3
|
describe ContentSpinning do
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
ContentSpinning.clean("AaBb").should eq "AaBb"
|
4
|
+
describe "#clean" do
|
5
|
+
it "returns the string if there is no spin" do
|
6
|
+
expect(ContentSpinning.clean("AaBb")).to eq("AaBb")
|
23
7
|
end
|
24
8
|
|
25
|
-
it "
|
26
|
-
ContentSpinning.clean("a{}").
|
27
|
-
ContentSpinning.clean("a{|}").
|
28
|
-
ContentSpinning.clean("a{||}").
|
29
|
-
ContentSpinning.clean("{}a{}").
|
30
|
-
ContentSpinning.clean("{}a{|}").
|
9
|
+
it "strips empty spin" do
|
10
|
+
expect(ContentSpinning.clean("a{}")).to eq("a")
|
11
|
+
expect(ContentSpinning.clean("a{|}")).to eq("a")
|
12
|
+
expect(ContentSpinning.clean("a{||}")).to eq("a")
|
13
|
+
expect(ContentSpinning.clean("{}a{}")).to eq("a")
|
14
|
+
expect(ContentSpinning.clean("{}a{|}")).to eq("a")
|
31
15
|
|
32
|
-
ContentSpinning.clean("a{{}}").
|
33
|
-
ContentSpinning.clean("a{{|}}").
|
34
|
-
ContentSpinning.clean("a{{}|}").
|
16
|
+
expect(ContentSpinning.clean("a{{}}")).to eq("a")
|
17
|
+
expect(ContentSpinning.clean("a{{|}}")).to eq("a")
|
18
|
+
expect(ContentSpinning.clean("a{{}|}")).to eq("a")
|
35
19
|
|
36
|
-
ContentSpinning.clean("a{a{}}").
|
20
|
+
expect(ContentSpinning.clean("a{a{}}")).to eq("aa")
|
37
21
|
end
|
38
22
|
|
39
|
-
it "
|
40
|
-
ContentSpinning.clean("{a}").
|
41
|
-
ContentSpinning.clean("a{b}").
|
42
|
-
ContentSpinning.clean("a{b}c").
|
43
|
-
ContentSpinning.clean("a{b}c{d}e").
|
23
|
+
it "remove spin with no choice" do
|
24
|
+
expect(ContentSpinning.clean("{a}")).to eq("a")
|
25
|
+
expect(ContentSpinning.clean("a{b}")).to eq("ab")
|
26
|
+
expect(ContentSpinning.clean("a{b}c")).to eq("abc")
|
27
|
+
expect(ContentSpinning.clean("a{b}c{d}e")).to eq("abcde")
|
44
28
|
|
45
|
-
ContentSpinning.clean("{{a}}").
|
46
|
-
ContentSpinning.clean("a{{b}}").
|
47
|
-
ContentSpinning.clean("a{{b}}c").
|
48
|
-
ContentSpinning.clean("a{{b}}c{{d}}e").
|
29
|
+
expect(ContentSpinning.clean("{{a}}")).to eq("a")
|
30
|
+
expect(ContentSpinning.clean("a{{b}}")).to eq("ab")
|
31
|
+
expect(ContentSpinning.clean("a{{b}}c")).to eq("abc")
|
32
|
+
expect(ContentSpinning.clean("a{{b}}c{{d}}e")).to eq("abcde")
|
49
33
|
|
50
|
-
ContentSpinning.clean("{{{a}}}").
|
34
|
+
expect(ContentSpinning.clean("{{{a}}}")).to eq("a")
|
51
35
|
end
|
52
36
|
|
53
|
-
it "
|
54
|
-
ContentSpinning.clean("{a|b}").
|
55
|
-
ContentSpinning.clean("a{b|c}").
|
56
|
-
ContentSpinning.clean("{{a|b}|c}").
|
37
|
+
it "keep legitimate spin" do
|
38
|
+
expect(ContentSpinning.clean("{a|b}")).to eq("{a|b}")
|
39
|
+
expect(ContentSpinning.clean("a{b|c}")).to eq("a{b|c}")
|
40
|
+
expect(ContentSpinning.clean("{{a|b}|c}")).to eq("{{a|b}|c}")
|
57
41
|
end
|
58
42
|
end
|
59
43
|
|
60
|
-
describe "parse" do
|
61
|
-
it "
|
62
|
-
ContentSpinning.parse("AaBb").
|
44
|
+
describe "#parse" do
|
45
|
+
it "returns the string if there is no spin" do
|
46
|
+
expect(ContentSpinning.parse("AaBb")).to eq(max_level: 0, parsed: "AaBb")
|
63
47
|
end
|
64
48
|
|
65
|
-
it "
|
66
|
-
ContentSpinning.parse("{a|b}").
|
67
|
-
ContentSpinning.parse("a{b|c}").
|
68
|
-
ContentSpinning.parse("{a|b}c{d|e}").
|
49
|
+
it "parses simple spin" do
|
50
|
+
expect(ContentSpinning.parse("{a|b}")).to eq(max_level: 1, parsed: "__SPIN_BEGIN_1__a__SPIN_OR_1__b__SPIN_END_1__")
|
51
|
+
expect(ContentSpinning.parse("a{b|c}")).to eq(max_level: 1, parsed: "a__SPIN_BEGIN_1__b__SPIN_OR_1__c__SPIN_END_1__")
|
52
|
+
expect(ContentSpinning.parse("{a|b}c{d|e}")).to 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
53
|
end
|
70
54
|
|
71
|
-
it "
|
72
|
-
ContentSpinning.parse("{{a|b}|c}").
|
73
|
-
ContentSpinning.parse("{a|{b|c}}").
|
55
|
+
it "manages recursive spin" do
|
56
|
+
expect(ContentSpinning.parse("{{a|b}|c}")).to 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__")
|
57
|
+
expect(ContentSpinning.parse("{a|{b|c}}")).to 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
58
|
end
|
75
59
|
end
|
76
60
|
|
77
|
-
describe "spin" do
|
78
|
-
it "
|
79
|
-
ContentSpinning.
|
61
|
+
describe "#spin" do
|
62
|
+
it "calls the clean function of ContentSpinning module with the string in argument" do
|
63
|
+
expect(ContentSpinning).to receive(:clean).with("AaBb").and_return("AaBb")
|
80
64
|
ContentSpinning.spin("AaBb")
|
81
65
|
end
|
82
66
|
|
83
|
-
it "
|
84
|
-
"AaBb".
|
67
|
+
it "returns an array" do
|
68
|
+
expect(ContentSpinning.spin("AaBb")).to eq(["AaBb"])
|
85
69
|
end
|
86
70
|
|
87
|
-
it "
|
88
|
-
"".
|
71
|
+
it "returns an empty array if the string to spin is empty" do
|
72
|
+
expect(ContentSpinning.spin("")).to eq([])
|
89
73
|
end
|
90
74
|
|
91
|
-
it "
|
92
|
-
"a{}".
|
93
|
-
"a{|}".
|
94
|
-
"a{||}".
|
95
|
-
"{}a{}".
|
96
|
-
"{}a{|}".
|
75
|
+
it "strips empty choices" do
|
76
|
+
expect(ContentSpinning.spin("a{}")).to eq(["a"])
|
77
|
+
expect(ContentSpinning.spin("a{|}")).to eq(["a"])
|
78
|
+
expect(ContentSpinning.spin("a{||}")).to eq(["a"])
|
79
|
+
expect(ContentSpinning.spin("{}a{}")).to eq(["a"])
|
80
|
+
expect(ContentSpinning.spin("{}a{|}")).to eq(["a"])
|
97
81
|
end
|
98
82
|
|
99
|
-
it "
|
100
|
-
"{|a}".
|
101
|
-
"{a|}".
|
83
|
+
it "strips empty strings from the returned array" do
|
84
|
+
expect(ContentSpinning.spin("{|a}")).to eq(["a"])
|
85
|
+
expect(ContentSpinning.spin("{a|}")).to eq(["a"])
|
102
86
|
end
|
103
87
|
|
104
|
-
it "
|
105
|
-
"{a}".
|
106
|
-
"a{b}".
|
107
|
-
"a{b}c".
|
108
|
-
"{a}{b}".
|
109
|
-
"a{b}{c}d".
|
88
|
+
it "manages one spin" do
|
89
|
+
expect(ContentSpinning.spin("{a}")).to eq(["a"])
|
90
|
+
expect(ContentSpinning.spin("a{b}")).to eq(["ab"])
|
91
|
+
expect(ContentSpinning.spin("a{b}c")).to eq(["abc"])
|
92
|
+
expect(ContentSpinning.spin("{a}{b}")).to eq(["ab"])
|
93
|
+
expect(ContentSpinning.spin("a{b}{c}d")).to eq(["abcd"])
|
110
94
|
end
|
111
95
|
|
112
|
-
it "
|
113
|
-
"{a}".
|
114
|
-
"a{b}".
|
115
|
-
"a{b}c".
|
116
|
-
"{a}{b}".
|
117
|
-
"a{b}{c}d".
|
96
|
+
it "manages two spin" do
|
97
|
+
expect(ContentSpinning.spin("{a}")).to eq(["a"])
|
98
|
+
expect(ContentSpinning.spin("a{b}")).to eq(["ab"])
|
99
|
+
expect(ContentSpinning.spin("a{b}c")).to eq(["abc"])
|
100
|
+
expect(ContentSpinning.spin("{a}{b}")).to eq(["ab"])
|
101
|
+
expect(ContentSpinning.spin("a{b}{c}d")).to eq(["abcd"])
|
118
102
|
end
|
119
103
|
|
120
|
-
it "
|
121
|
-
"{|a}".
|
122
|
-
"{|a}b".
|
123
|
-
"{a|}b".
|
124
|
-
"{a|}{b|}".
|
125
|
-
"a{b|}{c|}d".
|
104
|
+
it "manages spin with an empty choice" do
|
105
|
+
expect(ContentSpinning.spin("{|a}")).to eq(["a"])
|
106
|
+
expect(ContentSpinning.spin("{|a}b")).to eq(%w(b ab))
|
107
|
+
expect(ContentSpinning.spin("{a|}b")).to eq(%w(ab b))
|
108
|
+
expect(ContentSpinning.spin("{a|}{b|}")).to eq(%w(ab a b))
|
109
|
+
expect(ContentSpinning.spin("a{b|}{c|}d")).to eq(%w(abcd abd acd ad))
|
126
110
|
end
|
127
111
|
|
128
|
-
it "
|
129
|
-
"{a|b}".
|
130
|
-
"{a|b}c".
|
131
|
-
"{a|b}{c|d}".
|
112
|
+
it "manages spin with two choice" do
|
113
|
+
expect(ContentSpinning.spin("{a|b}")).to eq(%w(a b))
|
114
|
+
expect(ContentSpinning.spin("{a|b}c")).to eq(%w(ac bc))
|
115
|
+
expect(ContentSpinning.spin("{a|b}{c|d}")).to eq(%w(ac ad bc bd))
|
132
116
|
end
|
133
117
|
|
134
|
-
it "
|
135
|
-
"{a|b|c}".
|
136
|
-
"{a|b|c}d".
|
137
|
-
"{a|b|c}{d|e}".
|
118
|
+
it "manages spin with three choice" do
|
119
|
+
expect(ContentSpinning.spin("{a|b|c}")).to eq(%w(a b c))
|
120
|
+
expect(ContentSpinning.spin("{a|b|c}d")).to eq(%w(ad bd cd))
|
121
|
+
expect(ContentSpinning.spin("{a|b|c}{d|e}")).to eq(%w(ad ae bd be cd ce))
|
138
122
|
end
|
139
123
|
|
140
|
-
it "
|
141
|
-
"{a{b|c}|d}".
|
142
|
-
"{{a|b}|c}".
|
143
|
-
"{a|{b|c}}".
|
124
|
+
it "manages recursive spin" do
|
125
|
+
expect(ContentSpinning.spin("{a{b|c}|d}")).to eq(%w(ab ac d))
|
126
|
+
expect(ContentSpinning.spin("{{a|b}|c}")).to eq(%w(a b c))
|
127
|
+
expect(ContentSpinning.spin("{a|{b|c}}")).to eq(%w(a b c))
|
144
128
|
end
|
145
129
|
|
146
|
-
it "
|
147
|
-
"{a|a}".
|
130
|
+
it "does not return twice the same result" do
|
131
|
+
expect(ContentSpinning.spin("{a|a}")).to eq(["a"])
|
148
132
|
end
|
149
|
-
end
|
150
133
|
|
134
|
+
it "does not modify the source string" do
|
135
|
+
source = "{a|b}"
|
136
|
+
expect {
|
137
|
+
ContentSpinning.spin(source)
|
138
|
+
}.not_to change { source }
|
139
|
+
end
|
140
|
+
end
|
151
141
|
end
|
152
|
-
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,78 +1,78 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: content_spinning
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Maxime Garcia
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2016-05-15 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rspec
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: '
|
19
|
+
version: '3.4'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: guard-rspec
|
27
|
-
requirement: &11428420 !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
29
23
|
requirements:
|
30
|
-
- -
|
24
|
+
- - "~>"
|
31
25
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
26
|
+
version: '3.4'
|
27
|
+
description: |
|
28
|
+
To spin some text, mainly for SEO purpose.
|
29
|
+
|
30
|
+
Spinning the string "Hi {there|you}! I'm {efficient|productive}." gives
|
31
|
+
these four strings :
|
32
|
+
|
33
|
+
* Hi there! I'm efficient.
|
34
|
+
* Hi there! I'm productive.
|
35
|
+
* Hi you! I'm efficient.
|
36
|
+
* Hi you! I'm productive.
|
40
37
|
email:
|
41
|
-
- maxime.garcia@
|
38
|
+
- maxime.garcia@gmail.com
|
42
39
|
executables: []
|
43
40
|
extensions: []
|
44
41
|
extra_rdoc_files: []
|
45
42
|
files:
|
46
|
-
- README.md
|
47
43
|
- LICENSE
|
48
|
-
-
|
44
|
+
- README.md
|
49
45
|
- lib/content_spinning.rb
|
46
|
+
- lib/content_spinning/core_ext/string.rb
|
47
|
+
- lib/content_spinning/version.rb
|
48
|
+
- spec/content_spinning/core_ext/string_spec.rb
|
50
49
|
- spec/content_spinning_spec.rb
|
51
50
|
- spec/spec_helper.rb
|
52
51
|
homepage: http://github.com/maximeg/content_spinning
|
53
|
-
licenses:
|
52
|
+
licenses:
|
53
|
+
- MIT
|
54
|
+
metadata: {}
|
54
55
|
post_install_message:
|
55
56
|
rdoc_options: []
|
56
57
|
require_paths:
|
57
58
|
- lib
|
58
59
|
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
-
none: false
|
60
60
|
requirements:
|
61
|
-
- -
|
61
|
+
- - ">="
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: '
|
63
|
+
version: '1.9'
|
64
64
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
65
|
requirements:
|
67
|
-
- -
|
66
|
+
- - ">="
|
68
67
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
68
|
+
version: 1.3.6
|
70
69
|
requirements: []
|
71
70
|
rubyforge_project:
|
72
|
-
rubygems_version:
|
71
|
+
rubygems_version: 2.6.4
|
73
72
|
signing_key:
|
74
|
-
specification_version:
|
73
|
+
specification_version: 4
|
75
74
|
summary: Content Spinning
|
76
75
|
test_files:
|
76
|
+
- spec/content_spinning/core_ext/string_spec.rb
|
77
77
|
- spec/content_spinning_spec.rb
|
78
78
|
- spec/spec_helper.rb
|