liquid-node
Version:
Node.js port of Tobias Lütke's Liquid template engine.
82 lines (65 loc) • 2.41 kB
text/coffeescript
Liquid = require "../liquid"
{ _ } = require "underscore"
Q = require "q"
# Container for liquid nodes which conveniently wraps decision making logic
#
# Example:
#
# c = Condition.new('1', '==', '1')
# c.evaluate #=> true
#
module.exports = class Condition
@operators =
'==': (cond, left, right) -> cond.equalVariables(left, right)
'is': (cond, left, right) -> cond.equalVariables(left, right)
'!=': (cond, left, right) -> !cond.equalVariables(left, right)
'<>': (cond, left, right) -> !cond.equalVariables(left, right)
'isnt': (cond, left, right) -> cond.equalVariables(left, right)
'<': (cond, left, right) -> left < right
'>': (cond, left, right) -> left > right
'<=': (cond, left, right) -> left <= right
'>=': (cond, left, right) -> left >= right
'contains': (cond, left, right) -> left?.indexOf?(right) >= 0
constructor: (@left, @operator, @right) ->
@childRelation = null
@childCondition = null
evaluate: (context) ->
context or= new Liquid.Context()
result = @interpretCondition(@left, @right, @operator, context)
switch @childRelation
when "or"
Q.when(result).then (result) =>
result or @childCondition.evaluate(context)
when "and"
Q.when(result).then (result) =>
result and @childCondition.evaluate(context)
else
result
or: (@childCondition) ->
@childRelation = "or"
and: (@childCondition) ->
@childRelation = "and"
# Returns parameter
attach: (attachment) ->
@attachment = attachment
attachment
else: ->
false
inspect: ->
operands = _([@left, @operator, @right]).compact().join('#')
"<Condition [#{operands}], attachment: #{@attachment}>"
# private API
equalVariables: (left, right) ->
# TODO: symbol stuff?
left == right
interpretCondition: (left, right, op, context) ->
# If the operator is empty this means that the decision statement is just
# a single variable. We can just poll this variable from the context and
# return this as the result.
return context.get(left) unless op?
operation = Condition.operators[op]
throw new Error("Unknown operator #{op}") unless operation?
left = context.get(left)
right = context.get(right)
Q.spread [left, right], (left, right) =>
operation @, left, right