content_spinning 0.1.0 → 0.2.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 +4 -4
- data/lib/content_spinning/version.rb +1 -1
- data/lib/content_spinning.rb +75 -45
- data/spec/content_spinning_spec.rb +10 -8
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c13ac04efa5b45c6a59cf3bbea6a47ea9bace674
|
|
4
|
+
data.tar.gz: 32b6b31adbc605a54d3b7673250f3a307c3cc167
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f91381ee1a24e4218b403be1ce88cb2201e456077d110e7db07157af5163783d66a46906c13bdff0fb24badce6b3347809e0da338615c3fe7b03a8babb2827d7
|
|
7
|
+
data.tar.gz: e95ff3c4eb4435172f871ad9ce119c3fb915bb0cc1cdb0141d81a339475008046aac51042a37ed36e2d9f53e0fabb1a7475fc982b1f53883d440ac0bcd0c2036
|
data/lib/content_spinning.rb
CHANGED
|
@@ -2,84 +2,114 @@ require "content_spinning/core_ext/string"
|
|
|
2
2
|
|
|
3
3
|
module ContentSpinning
|
|
4
4
|
|
|
5
|
+
SPIN_BEGIN_FOR_LEVEL = Hash.new { |h, level| h[level] = "__SPIN_BEGIN_#{level}__" }
|
|
6
|
+
SPIN_END_FOR_LEVEL = Hash.new { |h, level| h[level] = "__SPIN_END_#{level}__" }
|
|
7
|
+
SPIN_OR_FOR_LEVEL = Hash.new { |h, level| h[level] = "__SPIN_OR_#{level}__" }
|
|
8
|
+
|
|
9
|
+
PARTITIONNER_REGEXP_FOR_LEVEL = Hash.new do |h, level|
|
|
10
|
+
h[level] = /#{SPIN_BEGIN_FOR_LEVEL[level]}.+?#{SPIN_END_FOR_LEVEL[level]}/
|
|
11
|
+
end
|
|
12
|
+
|
|
5
13
|
class << self
|
|
6
14
|
|
|
7
15
|
def spin(text)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
16
|
+
result = parse(clean(text))
|
|
17
|
+
|
|
18
|
+
contents = if result[:max_level] == 0
|
|
19
|
+
[result[:parsed]]
|
|
20
|
+
else
|
|
21
|
+
spin_a_level([result[:parsed]], level: result[:max_level])
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
contents.reject!(&:empty?)
|
|
25
|
+
contents.uniq!
|
|
11
26
|
|
|
12
|
-
|
|
27
|
+
contents
|
|
13
28
|
end
|
|
14
29
|
|
|
30
|
+
EMPTY_SPIN_REGEXP = /\{\|*\}/
|
|
31
|
+
ONE_CHOICE_SPIN_REGEXP = /\{([^\{\}\|]+)\}/
|
|
32
|
+
|
|
15
33
|
def clean(text)
|
|
34
|
+
cleaned = text.dup
|
|
35
|
+
|
|
16
36
|
loop do
|
|
17
|
-
text_before_run =
|
|
37
|
+
text_before_run = cleaned.dup
|
|
18
38
|
|
|
19
39
|
# Strip empty spin
|
|
20
|
-
|
|
40
|
+
cleaned.gsub!(EMPTY_SPIN_REGEXP, "")
|
|
21
41
|
|
|
22
42
|
# Remove spin with only one choice
|
|
23
|
-
|
|
43
|
+
cleaned.gsub!(ONE_CHOICE_SPIN_REGEXP, '\1')
|
|
24
44
|
|
|
25
|
-
break if
|
|
45
|
+
break if cleaned == text_before_run
|
|
26
46
|
end
|
|
27
47
|
|
|
28
|
-
|
|
48
|
+
cleaned
|
|
29
49
|
end
|
|
30
50
|
|
|
31
|
-
|
|
32
|
-
return { parsed: text, max_level: level - 1 } unless text.include?("{")
|
|
51
|
+
INNER_SPIN_REGEXP = /\{([^\{\}]+)\}/
|
|
33
52
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
match.gsub!(/\}/, "__SPIN_END_#{level}__")
|
|
37
|
-
match.gsub!(/\|/, "__SPIN_OR_#{level}__")
|
|
38
|
-
end
|
|
53
|
+
def parse(text)
|
|
54
|
+
parsed = text.dup
|
|
39
55
|
|
|
40
|
-
|
|
41
|
-
|
|
56
|
+
level = 0
|
|
57
|
+
loop do
|
|
58
|
+
level += 1
|
|
42
59
|
|
|
43
|
-
|
|
44
|
-
|
|
60
|
+
modification_happened = parsed.gsub!(INNER_SPIN_REGEXP) do |match|
|
|
61
|
+
match.sub!("{", SPIN_BEGIN_FOR_LEVEL[level])
|
|
62
|
+
match.sub!("}", SPIN_END_FOR_LEVEL[level])
|
|
63
|
+
match.gsub!("|", SPIN_OR_FOR_LEVEL[level])
|
|
64
|
+
end
|
|
45
65
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
66
|
+
break unless modification_happened
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
{ parsed: parsed, max_level: level - 1 }
|
|
70
|
+
end
|
|
49
71
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
before, vary, after = text.partition(Regexp.new(spin_begin + ".+?" + spin_end))
|
|
54
|
-
vary.gsub!(Regexp.union(spin_begin, spin_end), "")
|
|
72
|
+
def spin_a_level(contents, level:)
|
|
73
|
+
contents.flat_map do |text|
|
|
74
|
+
parts = extract_parts(text, level: level)
|
|
55
75
|
|
|
56
|
-
|
|
57
|
-
|
|
76
|
+
parts.map! do |part|
|
|
77
|
+
spin_a_level(part, level: level - 1)
|
|
78
|
+
end if level >= 2
|
|
58
79
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
else
|
|
63
|
-
varies
|
|
80
|
+
if parts.length > 1
|
|
81
|
+
parts[0].product(*parts[1..-1]).tap do |products|
|
|
82
|
+
products.map!(&:join)
|
|
64
83
|
end
|
|
65
84
|
else
|
|
66
|
-
|
|
85
|
+
parts[0]
|
|
67
86
|
end
|
|
68
87
|
end
|
|
69
|
-
|
|
70
|
-
content_array.flatten
|
|
71
88
|
end
|
|
72
89
|
|
|
73
|
-
|
|
74
|
-
content_array = text_or_array.is_a?(Array) ? text_or_array : [text_or_array]
|
|
90
|
+
private
|
|
75
91
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
92
|
+
def extract_parts(text, level:)
|
|
93
|
+
parts = []
|
|
94
|
+
|
|
95
|
+
loop do
|
|
96
|
+
before, spin, after = text.partition(PARTITIONNER_REGEXP_FOR_LEVEL[level])
|
|
97
|
+
|
|
98
|
+
# Before
|
|
99
|
+
parts << [before] if before != ""
|
|
100
|
+
|
|
101
|
+
break if spin == ""
|
|
102
|
+
|
|
103
|
+
# Let's vary
|
|
104
|
+
spin.sub!(SPIN_BEGIN_FOR_LEVEL[level], "")
|
|
105
|
+
spin.sub!(SPIN_END_FOR_LEVEL[level], "")
|
|
106
|
+
parts << spin.split(SPIN_OR_FOR_LEVEL[level], -1)
|
|
107
|
+
|
|
108
|
+
# After
|
|
109
|
+
text = after
|
|
80
110
|
end
|
|
81
111
|
|
|
82
|
-
|
|
112
|
+
parts
|
|
83
113
|
end
|
|
84
114
|
|
|
85
115
|
end
|
|
@@ -37,6 +37,7 @@ describe ContentSpinning do
|
|
|
37
37
|
it "keep legitimate spin" do
|
|
38
38
|
expect(ContentSpinning.clean("{a|b}")).to eq("{a|b}")
|
|
39
39
|
expect(ContentSpinning.clean("a{b|c}")).to eq("a{b|c}")
|
|
40
|
+
expect(ContentSpinning.clean("a{b|}")).to eq("a{b|}")
|
|
40
41
|
expect(ContentSpinning.clean("{{a|b}|c}")).to eq("{{a|b}|c}")
|
|
41
42
|
end
|
|
42
43
|
end
|
|
@@ -89,19 +90,14 @@ describe ContentSpinning do
|
|
|
89
90
|
expect(ContentSpinning.spin("{a}")).to eq(["a"])
|
|
90
91
|
expect(ContentSpinning.spin("a{b}")).to eq(["ab"])
|
|
91
92
|
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"])
|
|
94
93
|
end
|
|
95
94
|
|
|
96
95
|
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
96
|
expect(ContentSpinning.spin("{a}{b}")).to eq(["ab"])
|
|
101
97
|
expect(ContentSpinning.spin("a{b}{c}d")).to eq(["abcd"])
|
|
102
98
|
end
|
|
103
99
|
|
|
104
|
-
it "manages spin with an empty
|
|
100
|
+
it "manages spin with an empty choices" do
|
|
105
101
|
expect(ContentSpinning.spin("{|a}")).to eq(["a"])
|
|
106
102
|
expect(ContentSpinning.spin("{|a}b")).to eq(%w(b ab))
|
|
107
103
|
expect(ContentSpinning.spin("{a|}b")).to eq(%w(ab b))
|
|
@@ -109,13 +105,14 @@ describe ContentSpinning do
|
|
|
109
105
|
expect(ContentSpinning.spin("a{b|}{c|}d")).to eq(%w(abcd abd acd ad))
|
|
110
106
|
end
|
|
111
107
|
|
|
112
|
-
it "manages spin with two
|
|
108
|
+
it "manages spin with two choices" do
|
|
113
109
|
expect(ContentSpinning.spin("{a|b}")).to eq(%w(a b))
|
|
114
110
|
expect(ContentSpinning.spin("{a|b}c")).to eq(%w(ac bc))
|
|
115
111
|
expect(ContentSpinning.spin("{a|b}{c|d}")).to eq(%w(ac ad bc bd))
|
|
112
|
+
expect(ContentSpinning.spin("{a|b}c{d|e}")).to eq(%w(acd ace bcd bce))
|
|
116
113
|
end
|
|
117
114
|
|
|
118
|
-
it "manages spin with three
|
|
115
|
+
it "manages spin with three choices" do
|
|
119
116
|
expect(ContentSpinning.spin("{a|b|c}")).to eq(%w(a b c))
|
|
120
117
|
expect(ContentSpinning.spin("{a|b|c}d")).to eq(%w(ad bd cd))
|
|
121
118
|
expect(ContentSpinning.spin("{a|b|c}{d|e}")).to eq(%w(ad ae bd be cd ce))
|
|
@@ -125,6 +122,11 @@ describe ContentSpinning do
|
|
|
125
122
|
expect(ContentSpinning.spin("{a{b|c}|d}")).to eq(%w(ab ac d))
|
|
126
123
|
expect(ContentSpinning.spin("{{a|b}|c}")).to eq(%w(a b c))
|
|
127
124
|
expect(ContentSpinning.spin("{a|{b|c}}")).to eq(%w(a b c))
|
|
125
|
+
expect(ContentSpinning.spin("{a|{b|c}}{d|e}")).to eq(%w(ad ae bd be cd ce))
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "manages recursive spin with empty choices" do
|
|
129
|
+
expect(ContentSpinning.spin("{a|{b|{c|{d|e}}}}")).to eq(%w(a b c d e))
|
|
128
130
|
end
|
|
129
131
|
|
|
130
132
|
it "does not return twice the same result" do
|