all files / liquidjs/src/ render.js

100% Statements 42/42
100% Branches 16/16
100% Functions 6/6
100% Lines 41/41
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69       363×   362× 362× 536× 510×   26×   19×   336×   536× 174× 153× 362× 210× 210× 205×   152×           174×   169×   168×       239× 238× 119×         116× 116×     202× 96×      
const Syntax = require('./syntax.js')
const Promise = require('any-promise')
const mapSeries = require('./util/promise.js').mapSeries
const RenderBreakError = require('./util/error.js').RenderBreakError
const RenderError = require('./util/error.js').RenderError
const assert = require('./util/assert.js')
 
var render = {
 
  renderTemplates: function (templates, scope) {
    assert(scope, 'unable to evalTemplates: scope undefined')
 
    var html = ''
    return mapSeries(templates, (tpl) => {
      return renderTemplate.call(this, tpl)
        .then(partial => (html += partial))
        .catch(e => {
          if (e instanceof RenderBreakError) {
            e.resolvedHTML = html
            throw e
          }
          throw new RenderError(e, tpl)
        })
    }).then(() => html)
 
    function renderTemplate (template) {
      if (template.type === 'tag') {
        return this.renderTag(template, scope)
          .then(partial => partial === undefined ? '' : partial)
      } else if (template.type === 'output') {
        return Promise.resolve()
          .then(() => this.evalOutput(template, scope))
          .then(partial => partial === undefined ? '' : stringify(partial))
      } else { // template.type === 'html'
        return Promise.resolve(template.value)
      }
    }
  },
 
  renderTag: function (template, scope) {
    if (template.name === 'continue') {
      return Promise.reject(new RenderBreakError('continue'))
    }
    if (template.name === 'break') {
      return Promise.reject(new RenderBreakError('break'))
    }
    return template.render(scope)
  },
 
  evalOutput: function (template, scope) {
    assert(scope, 'unable to evalOutput: scope undefined')
    return template.filters.reduce(
      (prev, filter) => filter.render(prev, scope),
      Syntax.evalExp(template.initial, scope))
  }
}
 
function factory () {
  var instance = Object.create(render)
  return instance
}
 
function stringify (val) {
  if (typeof val === 'string') return val
  return JSON.stringify(val)
}
 
module.exports = factory