spectacular
Version:
Advanced BDD framework for CoffeeScript and JavaScript
122 lines (95 loc) • 3.55 kB
text/coffeescript
spectacular.dom ||= {}
class spectacular.dom.NodeExpression
spectacular.HasAncestors
spectacular.HasCollection('expressions', 'expression')
constructor: () ->
= document.matchesSelector or
document.mozMatchesSelector or
document.msMatchesSelector or
document.oMatchesSelector or
document.webkitMatchesSelector or
(selector) ->
node = this
nodes = (node.parentNode or document).querySelectorAll(selector)
i = -1
while nodes[++i] && nodes[i] isnt node
i
!!nodes[i]
= []
isTextExpression: -> /^(\/|'|").*(\/|'|")$/gm.test
match: (el) ->
matchesSelector = if el.length?
Array::every.call el, (e) => .call(e, )
else
.call(el, )
matchesSelector and .every (e) -> e.contained el
contained: (el) ->
if ()
el
else
if el?
if el.length?
found = []
for e in el
found.push n for n in e.querySelectorAll()
else
found = el.querySelectorAll()
found.length > 0 and .every (e) -> e.contained found
else
false
handleTextExpression: (el) ->
textContent = if el.length?
Array::map.call(el, (e) -> e.textContent).join ''
else
el.textContent
content = [1..-2]
if .indexOf('/') is 0
new RegExp(content).test textContent
else
textContent is content
class spectacular.dom.DOMExpression
spectacular.HasCollection('expressions', 'expression')
constructor: () ->
= []
()
parse: ->
startingIndent = 0
currentIndent = 0
currentParent = this
current = null
.split('\n').forEach (line, i) =>
invalidIndent = =>
throw new Error "invalid indent on line #{i+1} of '#{@source}'"
return if utils.strip(line).length is 0
indent = line
expr = utils.strip line
exprInst = new spectacular.dom.NodeExpression expr
invalidIndent() if current is null and indent isnt 0
if indent is currentIndent
exprInst.parent = currentParent
currentParent.addExpression exprInst
current = exprInst
else if indent is currentIndent + 1
if current.isTextExpression()
throw new Error "text expressions cannot have children on line #{i+1}"
exprInst.parent = current
current.addExpression exprInst
currentIndent = indent
currentParent = current
current = exprInst
else if indent < currentIndent and Math.round(indent) is indent
dif = currentIndent - indent
currentParent = current.nthAncestor Math.abs(dif)
currentParent.addExpression exprInst
exprInst.parent = currentParent
currentIndent = indent
current = exprInst
else invalidIndent()
getIndent: (line) ->
re = /^(\s+).*/
return 0 unless re.test line
line = line.replace re, '$1'
line.length / 2
match: (el) -> .every (e) -> e.match el
contained: (el) -> .every (e) -> e.contained el
toString: ->