rails_blocks 0.5.4.pre.alpha.pre.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.
- checksums.yaml +15 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.travis.yml +10 -0
- data/Gemfile +10 -0
- data/Guardfile +43 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +12 -0
- data/app/assets/javascripts/block.coffee +98 -0
- data/app/assets/javascripts/jblocks.coffee +95 -0
- data/app/assets/javascripts/jquery_bem.coffee +4 -0
- data/app/assets/javascripts/jquery_bem_copy.coffee +486 -0
- data/app/assets/javascripts/main.coffee +10 -0
- data/app/assets/javascripts/rails_blocks.js +5 -0
- data/app/assets/stylesheets/rails_blocks.sass +94 -0
- data/app/helpers/block_helper.rb +122 -0
- data/app/views/rails_blocks/element.slim +2 -0
- data/coffeelint.json +12 -0
- data/config/spring.rb +1 -0
- data/config.ru +7 -0
- data/lib/rails_blocks/blocks/block.rb +28 -0
- data/lib/rails_blocks/blocks/element.rb +6 -0
- data/lib/rails_blocks/blocks/renderer.rb +13 -0
- data/lib/rails_blocks/configuration.rb +27 -0
- data/lib/rails_blocks/engine.rb +29 -0
- data/lib/rails_blocks/exceptions.rb +4 -0
- data/lib/rails_blocks/initializers/rails_blocks.rb +0 -0
- data/lib/rails_blocks/levels.rb +7 -0
- data/lib/rails_blocks/names.rb +60 -0
- data/lib/rails_blocks/path.rb +108 -0
- data/lib/rails_blocks/version.rb +3 -0
- data/lib/rails_blocks.rb +24 -0
- data/lib/tasks/rails_blocks.rake +8 -0
- data/rails_blocks.gemspec +39 -0
- data/spec/helpers/block_helper_spec.rb +58 -0
- data/spec/internal/app/blocks/app/block3/_mod1.slim +0 -0
- data/spec/internal/app/blocks/app/block3/_mod2_value2.slim +0 -0
- data/spec/internal/app/blocks/app/block3/block3.slim +0 -0
- data/spec/internal/app/blocks/common/block1/_mod1.slim +0 -0
- data/spec/internal/app/blocks/common/block1/_mod2_value2.slim +0 -0
- data/spec/internal/app/blocks/common/block1/block1.slim +2 -0
- data/spec/internal/app/blocks/common/block2/__elem1.slim +0 -0
- data/spec/internal/app/blocks/common/block2/__elem1_mod1.slim +0 -0
- data/spec/internal/app/blocks/common/block2/__elem1_mod2_val2.slim +0 -0
- data/spec/internal/app/blocks/common/block2/block2.slim +0 -0
- data/spec/internal/app/blocks/common/block3/_mod1.slim +0 -0
- data/spec/internal/app/blocks/common/block3/_mod2_value2.slim +0 -0
- data/spec/internal/app/blocks/common/block3/block3.slim +0 -0
- data/spec/internal/app/controllers/admin/admin_test_controller.rb +2 -0
- data/spec/internal/app/controllers/admin_controller.rb +2 -0
- data/spec/internal/app/controllers/application_controller.rb +2 -0
- data/spec/internal/config/database.yml +3 -0
- data/spec/internal/config/initializers/rails_blocks.rb +7 -0
- data/spec/internal/config/routes.rb +3 -0
- data/spec/internal/db/schema.rb +3 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/internal/log/test.log +8 -0
- data/spec/internal/public/favicon.ico +0 -0
- data/spec/rails_blocks/blocks/block_spec.rb +11 -0
- data/spec/rails_blocks/configuration_spec.rb +29 -0
- data/spec/rails_blocks/names_spec.rb +66 -0
- data/spec/rails_blocks/path_spec.rb +70 -0
- data/spec/rails_blocks_spec.rb +104 -0
- data/spec/spec_helper.rb +112 -0
- metadata +368 -0
@@ -0,0 +1,486 @@
|
|
1
|
+
### @required jQuery ###
|
2
|
+
|
3
|
+
(($) ->
|
4
|
+
|
5
|
+
###*
|
6
|
+
# Base BEM class.
|
7
|
+
# @constructor
|
8
|
+
###
|
9
|
+
|
10
|
+
BEM = (config) ->
|
11
|
+
|
12
|
+
###*
|
13
|
+
# Default configuration.
|
14
|
+
# @type {Object}
|
15
|
+
###
|
16
|
+
|
17
|
+
@config = config or {}
|
18
|
+
@blockClassRe = @buildBlockClassRe()
|
19
|
+
@elemClassRe = @buildElemClassRe()
|
20
|
+
@modClassRe = @buildModClassRe()
|
21
|
+
return
|
22
|
+
|
23
|
+
###*
|
24
|
+
# Get parent block of element.
|
25
|
+
# @public
|
26
|
+
#
|
27
|
+
# @param {Object} $this
|
28
|
+
# @return {Object}
|
29
|
+
###
|
30
|
+
|
31
|
+
BEM::getBlock = ($this) ->
|
32
|
+
blockClass = @getBlockClass($this)
|
33
|
+
block = $this.closest('.' + blockClass)
|
34
|
+
block.selector = blockClass
|
35
|
+
block
|
36
|
+
|
37
|
+
###*
|
38
|
+
# Switch block context.
|
39
|
+
# @public
|
40
|
+
#
|
41
|
+
# @param {Object} $this
|
42
|
+
# @param {String} block
|
43
|
+
# @param {String} [elem]
|
44
|
+
# @return {Object}
|
45
|
+
###
|
46
|
+
|
47
|
+
BEM::switchBlock = ($this, block, elem) ->
|
48
|
+
`var elem`
|
49
|
+
elem = elem or null
|
50
|
+
if elem then ($this.selector = @buildSelector(
|
51
|
+
block: block
|
52
|
+
elem: elem)) else ($this.selector = @buildSelector(block: block))
|
53
|
+
$this
|
54
|
+
|
55
|
+
###*
|
56
|
+
# Find element in block.
|
57
|
+
# @public
|
58
|
+
#
|
59
|
+
# @param {Object} $this DOM element
|
60
|
+
# @param {String} elemKey Element name
|
61
|
+
# @return {Object}
|
62
|
+
###
|
63
|
+
|
64
|
+
BEM::findElem = ($this, elemKey) ->
|
65
|
+
blockClass = @getBlockClass($this)
|
66
|
+
elemName = @buildElemClass(blockClass, elemKey)
|
67
|
+
elem = $this.find('.' + elemName)
|
68
|
+
elem
|
69
|
+
|
70
|
+
###*
|
71
|
+
# Get value of modifier.
|
72
|
+
# @public
|
73
|
+
#
|
74
|
+
# @param {Object} $this
|
75
|
+
# @param {String} modKey
|
76
|
+
# @return {String}
|
77
|
+
###
|
78
|
+
|
79
|
+
BEM::getMod = ($this, modKey) ->
|
80
|
+
mods = @extractMods($this.first())
|
81
|
+
if mods[modKey] != undefined
|
82
|
+
return mods[modKey]
|
83
|
+
null
|
84
|
+
|
85
|
+
###*
|
86
|
+
# Check modifier of element.
|
87
|
+
# @public
|
88
|
+
#
|
89
|
+
# @param {Object} $this
|
90
|
+
# @param {String} modKey
|
91
|
+
# @param {String} [modVal]
|
92
|
+
# @return {Boolean}
|
93
|
+
###
|
94
|
+
|
95
|
+
BEM::hasMod = ($this, modKey, modVal) ->
|
96
|
+
mods = @extractMods($this.first())
|
97
|
+
if modVal
|
98
|
+
if mods[modKey] == modVal
|
99
|
+
return true
|
100
|
+
else
|
101
|
+
if mods[modKey]
|
102
|
+
return true
|
103
|
+
false
|
104
|
+
|
105
|
+
###*
|
106
|
+
# Set modifier on element.
|
107
|
+
# @public
|
108
|
+
#
|
109
|
+
# @param {Object} $this
|
110
|
+
# @param {String} modKey
|
111
|
+
# @param {String} [modVal]
|
112
|
+
# @param {Object}
|
113
|
+
###
|
114
|
+
|
115
|
+
BEM::setMod = ($this, modKey, modVal) ->
|
116
|
+
self = this
|
117
|
+
selector = $this.selector
|
118
|
+
$this.each ->
|
119
|
+
current = $(this)
|
120
|
+
current.selector = selector
|
121
|
+
mods = self.extractMods(current)
|
122
|
+
baseName = self.getBaseClass(current)
|
123
|
+
if mods[modKey] != undefined
|
124
|
+
oldModName = self.buildModClass(baseName, modKey, mods[modKey])
|
125
|
+
current.removeClass oldModName
|
126
|
+
if modVal != false
|
127
|
+
newModName = self.buildModClass(baseName, modKey, modVal)
|
128
|
+
current.addClass(newModName).trigger 'setmod', [
|
129
|
+
modKey
|
130
|
+
modVal
|
131
|
+
]
|
132
|
+
return
|
133
|
+
$this
|
134
|
+
|
135
|
+
###*
|
136
|
+
# Delete modifier on element.
|
137
|
+
# @public
|
138
|
+
#
|
139
|
+
# @param {Object} $this
|
140
|
+
# @param {String} modKey
|
141
|
+
# @param {String} [modVal]
|
142
|
+
# @param {Object}
|
143
|
+
###
|
144
|
+
|
145
|
+
BEM::delMod = ($this, modKey, modVal) ->
|
146
|
+
self = this
|
147
|
+
selector = $this.selector
|
148
|
+
$this.each ->
|
149
|
+
`var modName`
|
150
|
+
current = $(this)
|
151
|
+
current.selector = selector
|
152
|
+
mods = self.extractMods(current)
|
153
|
+
baseName = self.getBaseClass(current)
|
154
|
+
if modVal
|
155
|
+
if mods[modKey] == modVal
|
156
|
+
modName = self.buildModClass(baseName, modKey, mods[modKey])
|
157
|
+
else
|
158
|
+
modName = self.buildModClass(baseName, modKey, mods[modKey])
|
159
|
+
current.removeClass(modName).trigger 'delmod', [
|
160
|
+
modKey
|
161
|
+
modVal
|
162
|
+
]
|
163
|
+
return
|
164
|
+
$this
|
165
|
+
|
166
|
+
###*
|
167
|
+
# Filtering elements by modifier.
|
168
|
+
# @public
|
169
|
+
#
|
170
|
+
# @param {Object} $this
|
171
|
+
# @param {String} modKey
|
172
|
+
# @param {String} [modVal]
|
173
|
+
# @param {Boolean} [inverse]
|
174
|
+
# @return {Object}
|
175
|
+
###
|
176
|
+
|
177
|
+
BEM::byMod = ($this, modKey, modVal, inverse) ->
|
178
|
+
`var inverse`
|
179
|
+
`var modVal`
|
180
|
+
self = this
|
181
|
+
modVal = modVal or null
|
182
|
+
inverse = inverse or false
|
183
|
+
selector = $this.selector
|
184
|
+
result = $()
|
185
|
+
$this.each ->
|
186
|
+
`var modName`
|
187
|
+
current = $(this)
|
188
|
+
current.selector = selector
|
189
|
+
mods = self.extractMods(current)
|
190
|
+
baseName = self.getBaseClass(current)
|
191
|
+
if modVal
|
192
|
+
if mods[modKey] == modVal
|
193
|
+
modName = self.buildModClass(baseName, modKey, mods[modKey])
|
194
|
+
else
|
195
|
+
if mods[modKey] != undefined
|
196
|
+
modName = self.buildModClass(baseName, modKey, mods[modKey])
|
197
|
+
result = result.add(if inverse then current.not('.' + modName) else current.filter('.' + modName))
|
198
|
+
return
|
199
|
+
result.selector = selector
|
200
|
+
result
|
201
|
+
|
202
|
+
###*
|
203
|
+
# Get block names from element.
|
204
|
+
# @protected
|
205
|
+
#
|
206
|
+
# @param {Object|String} $this
|
207
|
+
# @return {Object}
|
208
|
+
###
|
209
|
+
|
210
|
+
BEM::extractBlocks = ($this) ->
|
211
|
+
self = this
|
212
|
+
result = []
|
213
|
+
selectors = @getClasses($this)
|
214
|
+
$.each selectors, (i, sel) ->
|
215
|
+
type = self.getClassType(sel)
|
216
|
+
if type == 'block'
|
217
|
+
result.push sel
|
218
|
+
else if type == 'elem'
|
219
|
+
elem = sel.split(self.config.elemPrefix)
|
220
|
+
result.push elem[0]
|
221
|
+
return
|
222
|
+
result
|
223
|
+
|
224
|
+
###*
|
225
|
+
# Get element names from element.
|
226
|
+
# @protected
|
227
|
+
#
|
228
|
+
# @param {Object} $this
|
229
|
+
# @return {Object}
|
230
|
+
###
|
231
|
+
|
232
|
+
BEM::extractElems = ($this) ->
|
233
|
+
self = this
|
234
|
+
result = []
|
235
|
+
$.each self.getClasses($this), (i, className) ->
|
236
|
+
if self.getClassType(className) == 'elem'
|
237
|
+
elemName = className.split(self.config.elemPrefix)
|
238
|
+
result.push elemName[1]
|
239
|
+
return
|
240
|
+
result
|
241
|
+
|
242
|
+
###*
|
243
|
+
# Get modifiers from element.
|
244
|
+
# @protected
|
245
|
+
#
|
246
|
+
# @param {Object} $this
|
247
|
+
# @return {Object}
|
248
|
+
###
|
249
|
+
|
250
|
+
BEM::extractMods = ($this) ->
|
251
|
+
self = this
|
252
|
+
result = {}
|
253
|
+
$this.each ->
|
254
|
+
`var $this`
|
255
|
+
$this = $(this)
|
256
|
+
$.each self.getClasses($this), (i, className) ->
|
257
|
+
`var modVal`
|
258
|
+
if self.getClassType(className) == 'mod'
|
259
|
+
re = self.buildModClassRe().exec(className)
|
260
|
+
modName = re[1].split(self.config.modDlmtr)
|
261
|
+
if modName[1] != undefined and modName[1] != false
|
262
|
+
modVal = modName[1]
|
263
|
+
else
|
264
|
+
modVal = true
|
265
|
+
result[modName[0]] = modVal
|
266
|
+
return
|
267
|
+
return
|
268
|
+
result
|
269
|
+
|
270
|
+
###*
|
271
|
+
# Get classes names from element.
|
272
|
+
# @protected
|
273
|
+
#
|
274
|
+
# @param {Object} $this
|
275
|
+
# @return {Object}
|
276
|
+
###
|
277
|
+
|
278
|
+
BEM::getClasses = ($this) ->
|
279
|
+
classes = undefined
|
280
|
+
result = []
|
281
|
+
if typeof $this == 'object'
|
282
|
+
if $this.selector.indexOf('.') == 0
|
283
|
+
classes = $this.selector.split('.')
|
284
|
+
else if $this.attr('class') != undefined
|
285
|
+
classes = $this.attr('class').split(' ')
|
286
|
+
else
|
287
|
+
return null
|
288
|
+
else
|
289
|
+
classes = $this.split('.')
|
290
|
+
$.each classes, (i, className) ->
|
291
|
+
if className != ''
|
292
|
+
result.push $.trim(className)
|
293
|
+
return
|
294
|
+
result
|
295
|
+
|
296
|
+
###*
|
297
|
+
# Build regexp for blocks.
|
298
|
+
# @protected
|
299
|
+
#
|
300
|
+
# @return {RegExp}
|
301
|
+
###
|
302
|
+
|
303
|
+
BEM::buildBlockClassRe = ->
|
304
|
+
new RegExp('^(' + @config.namePattern + ')$')
|
305
|
+
|
306
|
+
###*
|
307
|
+
# Build regexp for elements.
|
308
|
+
# @protected
|
309
|
+
#
|
310
|
+
# @return {RegExp}
|
311
|
+
###
|
312
|
+
|
313
|
+
BEM::buildElemClassRe = ->
|
314
|
+
new RegExp('^' + @config.namePattern + @config.elemPrefix + '(' + @config.namePattern + ')$')
|
315
|
+
|
316
|
+
###*
|
317
|
+
# Build regexp for modifiers.
|
318
|
+
# @protected
|
319
|
+
#
|
320
|
+
# @return {RegExp}
|
321
|
+
###
|
322
|
+
|
323
|
+
BEM::buildModClassRe = ->
|
324
|
+
new RegExp('^(?:' + @config.namePattern + '|' + @config.namePattern + @config.elemPrefix + @config.namePattern + ')' + @config.modPrefix + '(' + @config.namePattern + '((' + @config.modDlmtr + @config.namePattern + ')$|$))')
|
325
|
+
|
326
|
+
###*
|
327
|
+
# Build class name for block.
|
328
|
+
# @protected
|
329
|
+
#
|
330
|
+
# @param {String} blockName
|
331
|
+
# @return {String}
|
332
|
+
###
|
333
|
+
|
334
|
+
BEM::buildBlockClass = (blockName) ->
|
335
|
+
@config.blockPrefix + blockName
|
336
|
+
|
337
|
+
###*
|
338
|
+
# Build class name for element.
|
339
|
+
# @protected
|
340
|
+
#
|
341
|
+
# @param {String} blockName
|
342
|
+
# @param {String} elemKey
|
343
|
+
# @return {String}
|
344
|
+
###
|
345
|
+
|
346
|
+
BEM::buildElemClass = (blockName, elemKey) ->
|
347
|
+
blockName + @config.elemPrefix + elemKey
|
348
|
+
|
349
|
+
###*
|
350
|
+
# Build class name for modifier.
|
351
|
+
# @protected
|
352
|
+
#
|
353
|
+
# @param {String} blockName
|
354
|
+
# @param {String} modKey
|
355
|
+
# @param {String} modVal
|
356
|
+
# @return {String}
|
357
|
+
###
|
358
|
+
|
359
|
+
BEM::buildModClass = (baseClass, modKey, modVal) ->
|
360
|
+
if modVal != undefined and modVal != true
|
361
|
+
baseClass + @config.modPrefix + modKey + @config.modDlmtr + modVal
|
362
|
+
else
|
363
|
+
baseClass + @config.modPrefix + modKey
|
364
|
+
|
365
|
+
###*
|
366
|
+
# Build selector from object or string.
|
367
|
+
# @private
|
368
|
+
#
|
369
|
+
# @param {String|Object}
|
370
|
+
# @param {String}
|
371
|
+
# @return {String}
|
372
|
+
###
|
373
|
+
|
374
|
+
BEM::buildSelector = (selector, prefix) ->
|
375
|
+
`var prefix`
|
376
|
+
if prefix != ''
|
377
|
+
prefix = prefix or '.'
|
378
|
+
if typeof selector == 'object'
|
379
|
+
if selector.block != undefined
|
380
|
+
buildSelector = @buildBlockClass(selector.block)
|
381
|
+
if selector.elem != undefined
|
382
|
+
buildSelector = @buildElemClass(buildSelector, selector.elem)
|
383
|
+
if selector.mod != undefined
|
384
|
+
mod = selector.mod.split(':')
|
385
|
+
buildSelector = @buildModClass(buildSelector, mod[0], mod[1])
|
386
|
+
if buildSelector != undefined then prefix + buildSelector else prefix + selector
|
387
|
+
|
388
|
+
###*
|
389
|
+
# Build class name for block.
|
390
|
+
# @protected
|
391
|
+
#
|
392
|
+
# @param {Object|String} $this
|
393
|
+
# @param {Number} [index]
|
394
|
+
# @return {String}
|
395
|
+
###
|
396
|
+
|
397
|
+
BEM::getBlockClass = ($this, index) ->
|
398
|
+
`var index`
|
399
|
+
blockClasses = @extractBlocks($this)
|
400
|
+
index = index or 0
|
401
|
+
if index <= blockClasses.length - 1 then blockClasses[index] else null
|
402
|
+
|
403
|
+
###*
|
404
|
+
# Get base class from element.
|
405
|
+
# @protected
|
406
|
+
#
|
407
|
+
# @param {Object} $this
|
408
|
+
# @return {String}
|
409
|
+
###
|
410
|
+
|
411
|
+
BEM::getBaseClass = ($this) ->
|
412
|
+
self = this
|
413
|
+
baseClass = null
|
414
|
+
selectors = @getClasses($this)
|
415
|
+
$.each selectors, (i, sel) ->
|
416
|
+
classType = self.getClassType(sel)
|
417
|
+
if classType and classType != 'mod'
|
418
|
+
baseClass = sel
|
419
|
+
return
|
420
|
+
baseClass
|
421
|
+
|
422
|
+
###*
|
423
|
+
# Get class type.
|
424
|
+
# @protected
|
425
|
+
#
|
426
|
+
# @param {String} className
|
427
|
+
# @return {String}
|
428
|
+
###
|
429
|
+
|
430
|
+
BEM::getClassType = (className) ->
|
431
|
+
if @modClassRe.test(className)
|
432
|
+
return 'mod'
|
433
|
+
else if @elemClassRe.test(className)
|
434
|
+
return 'elem'
|
435
|
+
else if @blockClassRe.test(className)
|
436
|
+
return 'block'
|
437
|
+
null
|
438
|
+
|
439
|
+
###*
|
440
|
+
# Create BEM instance.
|
441
|
+
###
|
442
|
+
|
443
|
+
$.BEM = new BEM(
|
444
|
+
namePattern: '[a-zA-Z0-9-]+'
|
445
|
+
blockPrefix: 'b-'
|
446
|
+
elemPrefix: '__'
|
447
|
+
modPrefix: '--'
|
448
|
+
modDlmtr: '_')
|
449
|
+
|
450
|
+
###*
|
451
|
+
# Extend jQuery object.
|
452
|
+
###
|
453
|
+
|
454
|
+
$.fn.extend
|
455
|
+
block: ->
|
456
|
+
$.BEM.getBlock this
|
457
|
+
elem: (elemKey) ->
|
458
|
+
$.BEM.findElem this, elemKey
|
459
|
+
ctx: (block, elem) ->
|
460
|
+
$.BEM.switchBlock this, block, elem
|
461
|
+
mod: (modKey, modVal) ->
|
462
|
+
if typeof modVal == 'undefined'
|
463
|
+
modVal = null
|
464
|
+
if modVal == false
|
465
|
+
return $.BEM.delMod(this, modKey)
|
466
|
+
if modVal != null
|
467
|
+
$.BEM.setMod(this, modKey, modVal)
|
468
|
+
else
|
469
|
+
$.BEM.getMod(this, modKey)
|
470
|
+
setMod: (modKey, modVal) ->
|
471
|
+
$.BEM.setMod this, modKey, modVal
|
472
|
+
delMod: (modKey, modVal) ->
|
473
|
+
$.BEM.delMod this, modKey, modVal
|
474
|
+
hasMod: (modKey, modVal) ->
|
475
|
+
$.BEM.hasMod this, modKey, modVal
|
476
|
+
byMod: (modKey, modVal) ->
|
477
|
+
$.BEM.byMod this, modKey, modVal
|
478
|
+
byNotMod: (modKey, modVal) ->
|
479
|
+
$.BEM.byMod this, modKey, modVal, 'inverse'
|
480
|
+
toggleMod: (modKey, modVal1, modVal2) ->
|
481
|
+
if @hasMod(modKey, modVal1)
|
482
|
+
@delMod(modKey, modVal1).setMod modKey, modVal2
|
483
|
+
else
|
484
|
+
@delMod(modKey, modVal2).setMod modKey, modVal1
|
485
|
+
return
|
486
|
+
) jQuery
|
@@ -0,0 +1,10 @@
|
|
1
|
+
$ ->
|
2
|
+
# $.extend $,
|
3
|
+
# RB:
|
4
|
+
# blocks: {}
|
5
|
+
# decl: (name, options) ->
|
6
|
+
# block = @createBlockDeclaration(name, options)
|
7
|
+
# if(options['init'] != undefined)
|
8
|
+
# options['init'].call(block)
|
9
|
+
# createBlockDeclaration: (name, options) ->
|
10
|
+
# return new Block name, options
|
@@ -0,0 +1,94 @@
|
|
1
|
+
$bemBlockPrefix: 'b-'
|
2
|
+
$bemElementSeparator: '__'
|
3
|
+
$bemModifierSeparator: '--'
|
4
|
+
|
5
|
+
@function b-class($block)
|
6
|
+
@return ".#{$bemBlockPrefix+$block}"
|
7
|
+
|
8
|
+
@function selectorToString($selector)
|
9
|
+
$selector: inspect($selector) //cast to string
|
10
|
+
$selector: str-slice($selector, 2, -2) //remove bracket
|
11
|
+
@return $selector
|
12
|
+
|
13
|
+
@function containsModifier($selector)
|
14
|
+
$selector: selectorToString($selector)
|
15
|
+
@if str-index($selector, $bemModifierSeparator)
|
16
|
+
@return true
|
17
|
+
@else
|
18
|
+
@return false
|
19
|
+
|
20
|
+
@function containsPseudo($selector)
|
21
|
+
$selector: selectorToString($selector)
|
22
|
+
@if str-index($selector, ':')
|
23
|
+
@return true
|
24
|
+
@else
|
25
|
+
@return false
|
26
|
+
|
27
|
+
@function containsElement($selector)
|
28
|
+
$selector: selectorToString($selector)
|
29
|
+
@if str-index($selector, $bemElementSeparator)
|
30
|
+
@return true
|
31
|
+
@else
|
32
|
+
@return false
|
33
|
+
|
34
|
+
@function getBlock($selector)
|
35
|
+
$selector: selectorToString($selector)
|
36
|
+
$elementStart: str-index($selector, $bemElementSeparator)
|
37
|
+
$modifierStart: str-index($selector, $bemModifierSeparator)
|
38
|
+
$pseudoStart: str-index($selector, ':')
|
39
|
+
$start: if($elementStart, $elementStart - 1, if($modifierStart, $modifierStart - 1, $pseudoStart - 1))
|
40
|
+
@return str-slice($selector, 0, $start)
|
41
|
+
|
42
|
+
=b($block)
|
43
|
+
.#{$bemBlockPrefix+$block}
|
44
|
+
@content
|
45
|
+
|
46
|
+
=plus_b
|
47
|
+
@at-root
|
48
|
+
$block: &
|
49
|
+
#{$block} + #{$block}
|
50
|
+
@content
|
51
|
+
|
52
|
+
=hover_b
|
53
|
+
@at-root
|
54
|
+
$block: &
|
55
|
+
#{$block}:hover
|
56
|
+
@content
|
57
|
+
|
58
|
+
=e($element)
|
59
|
+
$selector: &
|
60
|
+
@at-root
|
61
|
+
@if containsModifier($selector) or containsPseudo($selector)
|
62
|
+
$block: getBlock($selector)
|
63
|
+
#{$selector}
|
64
|
+
#{$block+$bemElementSeparator+$element}
|
65
|
+
@content
|
66
|
+
@else
|
67
|
+
#{$selector+$bemElementSeparator+$element}
|
68
|
+
@content
|
69
|
+
|
70
|
+
=es($elements...)
|
71
|
+
@each $element in $elements
|
72
|
+
+e($element)
|
73
|
+
@content
|
74
|
+
|
75
|
+
=m($modifier)
|
76
|
+
@at-root
|
77
|
+
#{&}#{$bemModifierSeparator+$modifier}
|
78
|
+
@content
|
79
|
+
|
80
|
+
=icons-m($modifiers, $width, $height)
|
81
|
+
@for $i from 1 through length($modifiers)
|
82
|
+
+m(nth($modifiers, $i))
|
83
|
+
background-position: -($i - 1) * $width (0)
|
84
|
+
&:hover
|
85
|
+
background-position: -($i - 1)*$width (-$height)
|
86
|
+
&:active
|
87
|
+
background-position: -($i - 1) * $width (-2 * $height)
|
88
|
+
|
89
|
+
@function block-image-url($level, $image)
|
90
|
+
$selector: &
|
91
|
+
$selector: selectorToString($selector)
|
92
|
+
$block: if(containsModifier($selector) or containsPseudo($selector) or containsElement($selector), getBlock($selector), selectorToString($selector))
|
93
|
+
$block: str-slice($block, str-length($bemBlockPrefix) + 1)
|
94
|
+
@return image-url("#{$level}/#{$block}/images/#{$image}")
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'rails_blocks/names'
|
2
|
+
require 'rails_blocks/path'
|
3
|
+
|
4
|
+
module BlockHelper
|
5
|
+
include RailsBlocks::Path
|
6
|
+
include RailsBlocks::Names
|
7
|
+
|
8
|
+
BEM_KEYS = [:tag, :class, :attrs, :mods, :mix, :data, :levels, :content]
|
9
|
+
|
10
|
+
def bem_page(options, &block)
|
11
|
+
@page_options = options
|
12
|
+
block_given? ? capture(&block) : ''
|
13
|
+
end
|
14
|
+
|
15
|
+
def page_options
|
16
|
+
defaults = {
|
17
|
+
levels: RailsBlocks.config.levels
|
18
|
+
}
|
19
|
+
defaults.merge @page_options || {}
|
20
|
+
end
|
21
|
+
|
22
|
+
#TODO бога ради, отрефактори это дерьмо
|
23
|
+
def b(b_name, options = {}, &block)
|
24
|
+
parent_block = context_block
|
25
|
+
push_context_block b_name
|
26
|
+
options = page_options.merge options
|
27
|
+
options[:parent_block] = parent_block if parent_block
|
28
|
+
template = block_template b_name, options
|
29
|
+
classes = block_classes b_name, options
|
30
|
+
|
31
|
+
result = element(classes, template, options, &block)
|
32
|
+
pop_context_block
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
def b_classes(b_name, options = {})
|
37
|
+
parent_block = context_block
|
38
|
+
push_context_block b_name
|
39
|
+
options = page_options.merge options
|
40
|
+
options[:parent_block] = parent_block if parent_block
|
41
|
+
classes = block_classes b_name, options
|
42
|
+
pop_context_block
|
43
|
+
classes
|
44
|
+
end
|
45
|
+
|
46
|
+
def b_context(b_name, &block)
|
47
|
+
push_context_block b_name
|
48
|
+
result = capture(&block)
|
49
|
+
pop_context_block
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
53
|
+
def e(e_name, options = {}, &block)
|
54
|
+
parent_block = options[:b] || context_block
|
55
|
+
raise RailsBlocks::NoBlockContextError unless parent_block
|
56
|
+
options = page_options.merge options
|
57
|
+
options[:parent_block] = parent_block
|
58
|
+
template = element_template parent_block, e_name, options
|
59
|
+
classes = element_classes(parent_block, e_name, options)
|
60
|
+
element(classes, template, options, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
def e_classes(e_name, options = {})
|
64
|
+
parent_block = options[:b] || context_block
|
65
|
+
raise RailsBlocks::NoBlockContextError unless parent_block
|
66
|
+
options = page_options.merge options
|
67
|
+
options[:parent_block] = parent_block
|
68
|
+
element_classes(parent_block, e_name, options).join(' ')
|
69
|
+
end
|
70
|
+
|
71
|
+
def element(classes, template, options, &block)
|
72
|
+
content = block ? capture(&block) : options[:content]
|
73
|
+
@attrs = {class: classes.join(' ')}
|
74
|
+
@attrs.merge! options[:attrs] if options[:attrs]
|
75
|
+
@attrs["data-bem"] = options[:data].to_json if options[:data]
|
76
|
+
@attrs[:tag] = options[:tag] || 'div'
|
77
|
+
|
78
|
+
template.nil? ? empty(content) : render(file: template, locals: {content: content, options: options})
|
79
|
+
end
|
80
|
+
|
81
|
+
#убрать после тестов производительности
|
82
|
+
# def empty(content)
|
83
|
+
# atrrs = @attrs.except(:tag).map do |key, value|
|
84
|
+
# key.to_s + '=\'' + value.to_s + "'"
|
85
|
+
# end
|
86
|
+
# "<#{@attrs[:tag]} #{atrrs.join(' ')}>#{content}</#{@attrs[:tag]}>".html_safe
|
87
|
+
# end
|
88
|
+
|
89
|
+
def empty(content)
|
90
|
+
content_tag bem_tag, content, bem_attrs_without_tag
|
91
|
+
end
|
92
|
+
|
93
|
+
def bem_tag
|
94
|
+
@attrs[:tag]
|
95
|
+
end
|
96
|
+
|
97
|
+
def bem_attrs
|
98
|
+
@attrs
|
99
|
+
end
|
100
|
+
|
101
|
+
def bem_attrs_without_tag
|
102
|
+
@attrs.except :tag
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def blocks_stack
|
108
|
+
@blocks_stack = @blocks_stack || []
|
109
|
+
end
|
110
|
+
|
111
|
+
def context_block
|
112
|
+
blocks_stack.last
|
113
|
+
end
|
114
|
+
|
115
|
+
def push_context_block(b_name)
|
116
|
+
blocks_stack.push b_name
|
117
|
+
end
|
118
|
+
|
119
|
+
def pop_context_block
|
120
|
+
blocks_stack.pop
|
121
|
+
end
|
122
|
+
end
|