all files / liquidjs/tags/ tablerow.js

100% Statements 52/52
100% Branches 14/14
100% Functions 3/3
100% Lines 51/51
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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85       111×                             13× 13× 13×       13× 13× 13×       13× 13× 13×     13× 13× 13× 13×                  
const Liquid = require('..')
const mapSeries = require('../src/util/promise.js').mapSeries
const lexical = Liquid.lexical
const assert = require('../src/util/assert.js')
const re = new RegExp(`^(${lexical.identifier.source})\\s+in\\s+` +
  `(${lexical.value.source})` +
  `(?:\\s+${lexical.hash.source})*$`)
 
module.exports = function (liquid) {
  liquid.registerTag('tablerow', {
 
    parse: function (tagToken, remainTokens) {
      var match = re.exec(tagToken.args)
      assert(match, `illegal tag: ${tagToken.raw}`)
 
      this.variable = match[1]
      this.collection = match[2]
      this.templates = []
 
      var p
      var stream = liquid.parser.parseStream(remainTokens)
        .on('start', () => (p = this.templates))
        .on('tag:endtablerow', token => stream.stop())
        .on('template', tpl => p.push(tpl))
        .on('end', () => {
          throw new Error(`tag ${tagToken.raw} not closed`)
        })
 
      stream.start()
    },
 
    render: function (scope, hash) {
      var collection = Liquid.evalExp(this.collection, scope) || []
 
      var html = '<table>'
      var offset = hash.offset || 0
      var limit = (hash.limit === undefined) ? collection.length : hash.limit
 
      var cols = hash.cols
      var row
      var col
      if (!cols) throw new Error(`illegal cols: ${cols}`)
 
      // build array of arguments to pass to sequential promises...
      collection = collection.slice(offset, offset + limit)
      var contexts = []
      collection.some((item, i) => {
        var ctx = {}
        ctx[this.variable] = item
        contexts.push(ctx)
      })
 
      return mapSeries(contexts,
        (context, idx) => {
          row = Math.floor(idx / cols) + 1
          col = (idx % cols) + 1
          if (col === 1) {
            if (row !== 1) {
              html += '</tr>'
            }
            html += `<tr class="row${row}">`
          }
 
          html += `<td class="col${col}">`
          scope.push(context)
          return liquid.renderer
            .renderTemplates(this.templates, scope)
            .then((partial) => {
              scope.pop(context)
              html += partial
              html += '</td>'
              return html
            })
        })
        .then(() => {
          if (row > 0) {
            html += '</tr>'
          }
          html += '</table>'
          return html
        })
    }
  })
}