wptemplates 0.0.3
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 +20 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +92 -0
- data/README.rdoc +8 -0
- data/Rakefile +4 -0
- data/lib/wptemplates.rb +20 -0
- data/lib/wptemplates/ast.rb +91 -0
- data/lib/wptemplates/parser.rb +112 -0
- data/lib/wptemplates/preprocessor.rb +17 -0
- data/lib/wptemplates/regexes.rb +95 -0
- data/lib/wptemplates/utils.rb +38 -0
- data/lib/wptemplates/version.rb +3 -0
- data/spec/regexes_spec.rb +458 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/utils_spec.rb +90 -0
- data/spec/wptemplates_links_spec.rb +249 -0
- data/spec/wptemplates_mixed_spec.rb +82 -0
- data/spec/wptemplates_templates_spec.rb +161 -0
- data/spec/wptemplates_text_spec.rb +75 -0
- data/tasks/browser.rake +4 -0
- data/tasks/bundler_gem.rake +1 -0
- data/tasks/console.rake +7 -0
- data/tasks/irbrc.rb +22 -0
- data/tasks/rdoc.rake +16 -0
- data/tasks/readme_examples.rake +23 -0
- data/tasks/readme_html.rake +22 -0
- data/tasks/rspec.rake +10 -0
- data/wptemplates.gemspec +29 -0
- metadata +167 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
module Wptemplates
|
2
|
+
module Utils
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def normalize_link string, anchor = false
|
6
|
+
normalized = string.clone
|
7
|
+
normalized.tr!('_',' ')
|
8
|
+
normalized.strip!
|
9
|
+
normalized.squeeze!(' ')
|
10
|
+
normalized[0] = normalized[0,1].upcase unless anchor
|
11
|
+
normalized
|
12
|
+
end
|
13
|
+
|
14
|
+
def normalize_linklabel string
|
15
|
+
normalized = string.clone
|
16
|
+
normalized.strip!
|
17
|
+
normalized.squeeze!(' ')
|
18
|
+
normalized
|
19
|
+
end
|
20
|
+
|
21
|
+
def symbolize string
|
22
|
+
symbolized = normalize_link(string)
|
23
|
+
symbolized.tr!(' ','_')
|
24
|
+
symbolized.downcase.to_sym
|
25
|
+
end
|
26
|
+
|
27
|
+
def fixpoint options = {}
|
28
|
+
clone = options[:clone] || false
|
29
|
+
cur = options[:start]
|
30
|
+
begin
|
31
|
+
pre = clone && !cur.nil? ? cur.clone : cur
|
32
|
+
cur = yield(cur)
|
33
|
+
end while cur != pre
|
34
|
+
cur
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,458 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'strscan'
|
3
|
+
|
4
|
+
def ScanShortcutFor(regex)
|
5
|
+
Module.new do
|
6
|
+
define_method :scan do |text|
|
7
|
+
StringScanner.new(text).scan(Wptemplates::Regexes.send(regex))
|
8
|
+
end
|
9
|
+
define_method :scanner_after do |text|
|
10
|
+
s = StringScanner.new(text)
|
11
|
+
s.scan(Wptemplates::Regexes.send(regex))
|
12
|
+
s
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Wptemplates::Regexes do
|
18
|
+
|
19
|
+
describe '.till_doublebrace_doubleopenbrackets_or_pipe' do
|
20
|
+
include ScanShortcutFor(:till_doublebrace_doubleopenbrackets_or_pipe)
|
21
|
+
|
22
|
+
it 'consumes a string with no doublebraces or doubleopenbrackets or pipes at all' do
|
23
|
+
expect(scan "abc").to eq("abc")
|
24
|
+
end
|
25
|
+
it 'consumes until doublebraces or doubleopenbrackets or pipe' do
|
26
|
+
expect(scan "abc{{d").to eq("abc")
|
27
|
+
expect(scan "abc|d").to eq("abc")
|
28
|
+
expect(scan "abc}}d").to eq("abc")
|
29
|
+
expect(scan "abc[[d").to eq("abc")
|
30
|
+
end
|
31
|
+
it 'ignores starting doubleopenbrackets' do
|
32
|
+
expect(scan "[[abc").to eq("[[abc")
|
33
|
+
expect(scan "[[abc{{d").to eq("[[abc")
|
34
|
+
expect(scan "[[abc|d").to eq("[[abc")
|
35
|
+
expect(scan "[[abc}}d").to eq("[[abc")
|
36
|
+
expect(scan "[[abc[[d").to eq("[[abc")
|
37
|
+
end
|
38
|
+
it 'does not accept an empty string (epsilon transition)' do
|
39
|
+
expect(scan "{{d").to be_false
|
40
|
+
expect(scan "|d").to be_false
|
41
|
+
expect(scan "}}d").to be_false
|
42
|
+
end
|
43
|
+
it 'consumes until doublebraces or doubleopenbrackets or pipe even if other braces and pipes show up (not greedy)' do
|
44
|
+
expect(scan "ab|c{{d}}e").to eq("ab")
|
45
|
+
expect(scan "ab|c|d|e").to eq("ab")
|
46
|
+
expect(scan "ab{{c|d}}e").to eq("ab")
|
47
|
+
expect(scan "ab}}c|d{{e").to eq("ab")
|
48
|
+
expect(scan "ab[[c|d}}e").to eq("ab")
|
49
|
+
expect(scan "ab[[c|d{{e").to eq("ab")
|
50
|
+
end
|
51
|
+
it 'ignores lone braces' do
|
52
|
+
expect(scan "ab{c|d}}e").to eq("ab{c")
|
53
|
+
expect(scan "ab}c|d{{e").to eq("ab}c")
|
54
|
+
end
|
55
|
+
it 'ignores lone openbrackets' do
|
56
|
+
expect(scan "ab[c|d}}e").to eq("ab[c")
|
57
|
+
end
|
58
|
+
it 'ignores closebrackets' do
|
59
|
+
expect(scan "ab]]c|d}}e").to eq("ab]]c")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '.till_doubleopenbrace_or_doubleopenbrackets' do
|
64
|
+
include ScanShortcutFor(:till_doubleopenbrace_or_doubleopenbrackets)
|
65
|
+
|
66
|
+
it 'consumes a string with no doubleopenbraces or doubleopenbrackets at all' do
|
67
|
+
expect(scan "abc").to eq("abc")
|
68
|
+
expect(scan "ab}}c").to eq("ab}}c")
|
69
|
+
expect(scan "ab|c").to eq("ab|c")
|
70
|
+
expect(scan "ab]]c").to eq("ab]]c")
|
71
|
+
end
|
72
|
+
it 'consumes until doubleopenbraces' do
|
73
|
+
expect(scan "abc{{d").to eq("abc")
|
74
|
+
expect(scan "abc|d{{").to eq("abc|d")
|
75
|
+
expect(scan "abc}}d{{").to eq("abc}}d")
|
76
|
+
end
|
77
|
+
it 'ignores starting doubleopenbrackets' do
|
78
|
+
expect(scan "[[abc").to eq("[[abc")
|
79
|
+
expect(scan "[[abc{{d").to eq("[[abc")
|
80
|
+
expect(scan "[[abc|d{{").to eq("[[abc|d")
|
81
|
+
expect(scan "[[abc}}d{{").to eq("[[abc}}d")
|
82
|
+
end
|
83
|
+
it 'consumes until doubleopenbrackets' do
|
84
|
+
expect(scan "abc[[d").to eq("abc")
|
85
|
+
expect(scan "abc|d[[").to eq("abc|d")
|
86
|
+
expect(scan "abc]]d[[").to eq("abc]]d")
|
87
|
+
end
|
88
|
+
it 'does not accept an empty string (epsilon transition)' do
|
89
|
+
expect(scan "{{d").to be_false
|
90
|
+
end
|
91
|
+
it 'consumes until doubleopenbraces/brackets if other doubleopenbraces/brackets show up (not greedy)' do
|
92
|
+
expect(scan "ab{{d{{e").to eq("ab")
|
93
|
+
expect(scan "ab[[d{{e").to eq("ab")
|
94
|
+
expect(scan "ab[[d[[e").to eq("ab")
|
95
|
+
expect(scan "ab{{d[[e").to eq("ab")
|
96
|
+
end
|
97
|
+
it 'ignores lone braces and brackets' do
|
98
|
+
expect(scan "ab[{c{{e").to eq("ab[{c")
|
99
|
+
expect(scan "ab[{c[[e").to eq("ab[{c")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '.till_doubleclosebrace_or_pipe' do
|
104
|
+
include ScanShortcutFor(:till_doubleclosebrace_or_pipe)
|
105
|
+
|
106
|
+
it 'consumes a string with no doubleclosebraces or pipes at all' do
|
107
|
+
expect(scan "abc").to eq("abc")
|
108
|
+
expect(scan "ab{{c").to eq("ab{{c")
|
109
|
+
end
|
110
|
+
it 'consumes until doubleclosebraces' do
|
111
|
+
expect(scan "abc}}d").to eq("abc")
|
112
|
+
expect(scan "a{{bc}}d").to eq("a{{bc")
|
113
|
+
end
|
114
|
+
it 'consumes until a pipe' do
|
115
|
+
expect(scan "abc|d").to eq("abc")
|
116
|
+
expect(scan "a{{bc|d").to eq("a{{bc")
|
117
|
+
end
|
118
|
+
it 'does not accept an empty string (epsilon transition)' do
|
119
|
+
expect(scan "}}d").to be_false
|
120
|
+
expect(scan "|d").to be_false
|
121
|
+
end
|
122
|
+
it 'consumes until doubleclosebracees even if other doubleclosebrace show up (not greedy)' do
|
123
|
+
expect(scan "ab}}d}}e").to eq("ab")
|
124
|
+
end
|
125
|
+
it 'consumes until a pipe even if other pipes show up (not greedy)' do
|
126
|
+
expect(scan "ab|d|e").to eq("ab")
|
127
|
+
end
|
128
|
+
it 'ignores lone braces' do
|
129
|
+
expect(scan "ab}c}}e").to eq("ab}c")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe '.from_pipe_till_equals_no_doubleclosebrace_or_pipe' do
|
134
|
+
include ScanShortcutFor(:from_pipe_till_equals_no_doubleclosebrace_or_pipe)
|
135
|
+
|
136
|
+
context 'when there is an equals sign and a pipe' do
|
137
|
+
it 'consumes a string including equals with no doubleclosebraces or pipes at all' do
|
138
|
+
expect(scan "|abc=").to eq("|abc=")
|
139
|
+
expect(scan "|abc=d").to eq("|abc=")
|
140
|
+
expect(scan "|ab{{c=d").to eq("|ab{{c=")
|
141
|
+
end
|
142
|
+
it 'fails when doubleclosebraces occur before equals' do
|
143
|
+
expect(scan "|abc}}d=e").to be_false
|
144
|
+
expect(scan "|a{{bc}}d=e").to be_false
|
145
|
+
end
|
146
|
+
it 'ignores single closebraces' do
|
147
|
+
expect(scan "|abc}d=e").to eq("|abc}d=")
|
148
|
+
expect(scan "|a{{bc}d=e").to eq("|a{{bc}d=")
|
149
|
+
end
|
150
|
+
it 'fails when a pipe occurs before equals' do
|
151
|
+
expect(scan "|abc|d=e").to be_false
|
152
|
+
expect(scan "|a{{bc|d=e").to be_false
|
153
|
+
end
|
154
|
+
it 'does actually accept an empty string (epsilon transition)' do
|
155
|
+
expect(scan "|=d").to eq("|=")
|
156
|
+
expect(scan "|=").to eq("|=")
|
157
|
+
end
|
158
|
+
it 'consumes until equals even if other equals show up (not greedy)' do
|
159
|
+
expect(scan "|ab=d=e").to eq("|ab=")
|
160
|
+
end
|
161
|
+
it 'provides us with the stuff between pipe and equals in the first index' do
|
162
|
+
expect(scanner_after("|ab=c")[1]).to eq("ab")
|
163
|
+
expect(scanner_after("|=c")[1]).to eq("")
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context 'when there is no equals sign' do
|
168
|
+
it 'fails on plain string' do
|
169
|
+
expect(scan "|abc").to be_false
|
170
|
+
end
|
171
|
+
it 'fails when there is a pipe' do
|
172
|
+
expect(scan "abc|d").to be_false
|
173
|
+
expect(scan "abcd|").to be_false
|
174
|
+
expect(scan "|abcd").to be_false
|
175
|
+
end
|
176
|
+
it 'fails when there are doubleclosebraces' do
|
177
|
+
expect(scan "abc}}d").to be_false
|
178
|
+
expect(scan "abcd}}").to be_false
|
179
|
+
expect(scan "}}abcd").to be_false
|
180
|
+
end
|
181
|
+
end
|
182
|
+
context 'when the pipe is not a the beginning or there is no pipe' do
|
183
|
+
it 'fails' do
|
184
|
+
expect(scan "abc").to be_false
|
185
|
+
expect(scan "abc=").to be_false
|
186
|
+
expect(scan "a|bc=d").to be_false
|
187
|
+
expect(scan " |bc=d").to be_false
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
describe '.a_pipe' do
|
194
|
+
include ScanShortcutFor(:a_pipe)
|
195
|
+
|
196
|
+
it 'consumes a pipe' do
|
197
|
+
expect(scan "|").to eq("|")
|
198
|
+
expect(scan "|a").to eq("|")
|
199
|
+
end
|
200
|
+
it 'consumes only one pipe even if there are others around (not greedy)' do
|
201
|
+
expect(scan "|||").to eq("|")
|
202
|
+
expect(scan "|a|").to eq("|")
|
203
|
+
expect(scan "|a|a").to eq("|")
|
204
|
+
end
|
205
|
+
it 'fails when there is stuff before the pipe' do
|
206
|
+
expect(scan "a|").to be_false
|
207
|
+
expect(scan "a|b").to be_false
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
describe '.a_doubleopenbrace' do
|
212
|
+
include ScanShortcutFor(:a_doubleopenbrace)
|
213
|
+
|
214
|
+
it 'consumes a doubleopenbrace' do
|
215
|
+
expect(scan "{{").to eq("{{")
|
216
|
+
expect(scan "{{a").to eq("{{")
|
217
|
+
end
|
218
|
+
it 'consumes only one doubleopenbrace even if there are others around (not greedy)' do
|
219
|
+
expect(scan "{{a{{").to eq("{{")
|
220
|
+
expect(scan "{{a{{a").to eq("{{")
|
221
|
+
end
|
222
|
+
it 'fails when there is stuff before the doubleopenbrace' do
|
223
|
+
expect(scan "a{{").to be_false
|
224
|
+
expect(scan "a{{b").to be_false
|
225
|
+
end
|
226
|
+
it 'ignores singleopenbrace' do
|
227
|
+
expect(scan "a{").to be_false
|
228
|
+
expect(scan "a{b").to be_false
|
229
|
+
end
|
230
|
+
it 'deals with extra braces' do
|
231
|
+
expect(scan "{{{").to eq("{{")
|
232
|
+
expect(scan "{{{{").to eq("{{")
|
233
|
+
expect(scan "{{{{{").to eq("{{")
|
234
|
+
expect(scan "{{{{{{").to eq("{{")
|
235
|
+
end
|
236
|
+
it 'ignores pipes and doubleclosingbrace' do
|
237
|
+
expect(scan "|").to be_false
|
238
|
+
expect(scan "}}").to be_false
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe '.a_doubleclosingbrace' do
|
243
|
+
include ScanShortcutFor(:a_doubleclosingbrace)
|
244
|
+
|
245
|
+
it 'consumes a doubleclosingbrace' do
|
246
|
+
expect(scan "}}").to eq("}}")
|
247
|
+
expect(scan "}}a").to eq("}}")
|
248
|
+
end
|
249
|
+
it 'consumes only one doubleclosingbrace even if there are others around (not greedy)' do
|
250
|
+
expect(scan "}}a}}").to eq("}}")
|
251
|
+
expect(scan "}}a}}a").to eq("}}")
|
252
|
+
end
|
253
|
+
it 'fails when there is stuff before the doubleclosingbrace' do
|
254
|
+
expect(scan "a}}").to be_false
|
255
|
+
expect(scan "a}}b").to be_false
|
256
|
+
end
|
257
|
+
it 'ignores singleclosebrace' do
|
258
|
+
expect(scan "a}").to be_false
|
259
|
+
expect(scan "a}b").to be_false
|
260
|
+
end
|
261
|
+
it 'deals with extra braces' do
|
262
|
+
expect(scan "}}}").to eq("}}")
|
263
|
+
expect(scan "}}}}").to eq("}}")
|
264
|
+
expect(scan "}}}}}").to eq("}}")
|
265
|
+
expect(scan "}}}}}}").to eq("}}")
|
266
|
+
end
|
267
|
+
it 'ignores pipes and doubleopenbrace' do
|
268
|
+
expect(scan "|").to be_false
|
269
|
+
expect(scan "{{").to be_false
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
describe '.a_link' do
|
274
|
+
include ScanShortcutFor(:a_link)
|
275
|
+
|
276
|
+
it 'consumes a normal link' do
|
277
|
+
s = scanner_after("[[foo]]")
|
278
|
+
expect(s.matched).to eq("[[foo]]")
|
279
|
+
expect(s[1]).to eq("foo")
|
280
|
+
expect(s[2]).to be_nil
|
281
|
+
expect(s[3]).to eq("")
|
282
|
+
end
|
283
|
+
it 'consumes only the normal link' do
|
284
|
+
s = scanner_after("[[foo]].")
|
285
|
+
expect(s.matched).to eq("[[foo]]")
|
286
|
+
expect(s[1]).to eq("foo")
|
287
|
+
expect(s[2]).to be_nil
|
288
|
+
expect(s[3]).to eq("")
|
289
|
+
end
|
290
|
+
it 'consumes some extra letters after closing brackets' do
|
291
|
+
s = scanner_after("[[foo]]nx.")
|
292
|
+
expect(s.matched).to eq("[[foo]]nx")
|
293
|
+
expect(s[1]).to eq("foo")
|
294
|
+
expect(s[2]).to be_nil
|
295
|
+
expect(s[3]).to eq("nx")
|
296
|
+
end
|
297
|
+
it 'consumes a link label' do
|
298
|
+
s = scanner_after("[[foo|bar]].")
|
299
|
+
expect(s.matched).to eq("[[foo|bar]]")
|
300
|
+
expect(s[1]).to eq("foo")
|
301
|
+
expect(s[2]).to eq("bar")
|
302
|
+
expect(s[3]).to eq("")
|
303
|
+
end
|
304
|
+
it 'consumes a link label and extra letters' do
|
305
|
+
s = scanner_after("[[foo|bar]]ny.")
|
306
|
+
expect(s.matched).to eq("[[foo|bar]]ny")
|
307
|
+
expect(s[1]).to eq("foo")
|
308
|
+
expect(s[2]).to eq("bar")
|
309
|
+
expect(s[3]).to eq("ny")
|
310
|
+
end
|
311
|
+
it 'consumes an empty link label' do
|
312
|
+
s = scanner_after("[[foo|]].")
|
313
|
+
expect(s.matched).to eq("[[foo|]]")
|
314
|
+
expect(s[1]).to eq("foo")
|
315
|
+
expect(s[2]).to eq("")
|
316
|
+
expect(s[3]).to eq("")
|
317
|
+
end
|
318
|
+
it 'consumes a link with an anchor' do
|
319
|
+
s = scanner_after("[[foo#ro|bar]]ny.")
|
320
|
+
expect(s.matched).to eq("[[foo#ro|bar]]ny")
|
321
|
+
expect(s[1]).to eq("foo#ro")
|
322
|
+
expect(s[2]).to eq("bar")
|
323
|
+
expect(s[3]).to eq("ny")
|
324
|
+
end
|
325
|
+
it 'does not consume unclosed links' do
|
326
|
+
expect(scan "[[a").to be_false
|
327
|
+
end
|
328
|
+
it 'does not consume unclosed links with newlines' do
|
329
|
+
expect(scan "[[a\nb]]").to be_false
|
330
|
+
end
|
331
|
+
it 'consume only to the first pair of brackets even if there are others around' do
|
332
|
+
s = scanner_after("[[a]]b]]c,x")
|
333
|
+
expect(s.matched).to eq("[[a]]b")
|
334
|
+
expect(s[1]).to eq("a")
|
335
|
+
expect(s[2]).to be_nil
|
336
|
+
expect(s[3]).to eq("b")
|
337
|
+
end
|
338
|
+
it 'consumes pipes in the label' do
|
339
|
+
s = scanner_after("[[a|b|c]]d,x")
|
340
|
+
expect(s.matched).to eq("[[a|b|c]]d")
|
341
|
+
expect(s[1]).to eq("a")
|
342
|
+
expect(s[2]).to eq("b|c")
|
343
|
+
expect(s[3]).to eq("d")
|
344
|
+
end
|
345
|
+
it 'consumes single brackets in the label' do
|
346
|
+
s = scanner_after("[[a|b]c]]d,x")
|
347
|
+
expect(s.matched).to eq("[[a|b]c]]d")
|
348
|
+
expect(s[1]).to eq("a")
|
349
|
+
expect(s[2]).to eq("b]c")
|
350
|
+
expect(s[3]).to eq("d")
|
351
|
+
end
|
352
|
+
it 'consumes parens in urls' do
|
353
|
+
s = scanner_after("[[a(b)|c]]d.")
|
354
|
+
expect(s.matched).to eq("[[a(b)|c]]d")
|
355
|
+
expect(s[1]).to eq("a(b)")
|
356
|
+
expect(s[2]).to eq("c")
|
357
|
+
expect(s[3]).to eq("d")
|
358
|
+
end
|
359
|
+
it 'consumes commas in urls' do
|
360
|
+
s = scanner_after("[[a,b|c]]d.")
|
361
|
+
expect(s.matched).to eq("[[a,b|c]]d")
|
362
|
+
expect(s[1]).to eq("a,b")
|
363
|
+
expect(s[2]).to eq("c")
|
364
|
+
expect(s[3]).to eq("d")
|
365
|
+
end
|
366
|
+
it 'consumes spaces in urls' do
|
367
|
+
s = scanner_after("[[ ]]")
|
368
|
+
expect(s.matched).to eq("[[ ]]")
|
369
|
+
expect(s[1]).to eq(" ")
|
370
|
+
expect(s[2]).to be_nil
|
371
|
+
expect(s[3]).to eq("")
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
describe '.until_hash' do
|
376
|
+
it 'prints the part to the first hash, excluding' do
|
377
|
+
expect("abc#def"[subject.until_hash]).to eq("abc")
|
378
|
+
expect("abc#d#ef"[subject.until_hash]).to eq("abc")
|
379
|
+
expect("abc#def#"[subject.until_hash]).to eq("abc")
|
380
|
+
expect("abc#"[subject.until_hash]).to eq("abc")
|
381
|
+
end
|
382
|
+
it 'prints everything if there is no hash' do
|
383
|
+
expect("abc"[subject.until_hash]).to eq("abc")
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
describe '.after_hash' do
|
388
|
+
it 'prints the part after the first hash, excluding' do
|
389
|
+
expect("abc#def"[subject.after_hash]).to eq("def")
|
390
|
+
expect("abc#d#ef"[subject.after_hash]).to eq("d#ef")
|
391
|
+
expect("abc#def#"[subject.after_hash]).to eq("def#")
|
392
|
+
expect("abc#"[subject.after_hash]).to eq("")
|
393
|
+
end
|
394
|
+
it 'returns nil if there is no hash' do
|
395
|
+
expect("abc"[subject.after_hash]).to be_nil
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
describe '.has_parens' do
|
400
|
+
it 'detects if there are matching parens at the end' do
|
401
|
+
expect("abc(def)"[subject.has_parens]).to be_true
|
402
|
+
expect("abc (def)"[subject.has_parens]).to be_true
|
403
|
+
expect("abc (def) "[subject.has_parens]).to be_true
|
404
|
+
expect("abc(def) "[subject.has_parens]).to be_true
|
405
|
+
expect("abc(d(ef)"[subject.has_parens]).to be_true
|
406
|
+
expect("abc(d(e)f)"[subject.has_parens]).to be_true
|
407
|
+
expect("abc(d(ef)"[subject.has_parens]).to be_true
|
408
|
+
expect("abc(d)e(f)"[subject.has_parens]).to be_true
|
409
|
+
expect("abc(def"[subject.has_parens]).to be_false
|
410
|
+
expect("abc)def"[subject.has_parens]).to be_false
|
411
|
+
expect("abc"[subject.has_parens]).to be_false
|
412
|
+
end
|
413
|
+
it 'returns the part without parens as :no_parens' do
|
414
|
+
expect("abc(def)"[subject.has_parens, :no_parens]).to eq("abc")
|
415
|
+
expect("abc (def)"[subject.has_parens, :no_parens]).to eq("abc")
|
416
|
+
expect("abc (def) "[subject.has_parens, :no_parens]).to eq("abc")
|
417
|
+
expect("abc(def) "[subject.has_parens, :no_parens]).to eq("abc")
|
418
|
+
expect("abc(d(ef)"[subject.has_parens, :no_parens]).to eq("abc")
|
419
|
+
expect("abc(d(e)f)"[subject.has_parens, :no_parens]).to eq("abc")
|
420
|
+
expect("abc(d(ef)"[subject.has_parens, :no_parens]).to eq("abc")
|
421
|
+
expect("abc(d)e(f)"[subject.has_parens, :no_parens]).to eq("abc")
|
422
|
+
expect("abc(def"[subject.has_parens, :no_parens]).to be_nil
|
423
|
+
expect("abc)def"[subject.has_parens, :no_parens]).to be_nil
|
424
|
+
expect("abc"[subject.has_parens, :no_parens]).to be_nil
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
describe '.first_comma' do
|
429
|
+
it 'returns the part before the first comma and space, excluding, as :before' do
|
430
|
+
expect("abc, def"[subject.first_comma, :before]).to eq("abc")
|
431
|
+
expect("abc, def, ghi"[subject.first_comma, :before]).to eq("abc")
|
432
|
+
expect("abc def"[subject.first_comma, :before]).to eq("abc def")
|
433
|
+
expect("abc,def"[subject.first_comma, :before]).to eq("abc,def")
|
434
|
+
expect("abc,"[subject.first_comma, :before]).to eq("abc,")
|
435
|
+
expect(",abc"[subject.first_comma, :before]).to eq(",abc")
|
436
|
+
expect(", abc"[subject.first_comma, :before]).to eq("")
|
437
|
+
expect("a, , b"[subject.first_comma, :before]).to eq("a")
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
describe '.first_comma' do
|
442
|
+
it 'returns the part before the matching parens at the end as :before' do
|
443
|
+
expect("abc(def)"[subject.parens, :before]).to eq("abc")
|
444
|
+
# different whitespace behaviour not to loose any valid ", "
|
445
|
+
expect("abc (def)"[subject.parens, :before]).to eq("abc ")
|
446
|
+
expect("abc (def) "[subject.parens, :before]).to eq("abc ")
|
447
|
+
expect("abc(def) "[subject.parens, :before]).to eq("abc")
|
448
|
+
expect("abc(d(ef)"[subject.parens, :before]).to eq("abc")
|
449
|
+
expect("abc(d(e)f)"[subject.parens, :before]).to eq("abc")
|
450
|
+
expect("abc(d(ef)"[subject.parens, :before]).to eq("abc")
|
451
|
+
expect("abc(d)e(f)"[subject.parens, :before]).to eq("abc")
|
452
|
+
expect("abc(def"[subject.parens, :before]).to eq("abc(def")
|
453
|
+
expect("abc)def"[subject.parens, :before]).to eq("abc)def")
|
454
|
+
expect("abc"[subject.parens, :before]).to eq("abc")
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
end
|