all files / liquidjs/tags/ layout.js

100% Statements 40/40
100% Branches 14/14
100% Functions 5/5
100% Lines 40/40
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               132×   16× 16× 15×     16× 16× 15×     16×     15× 15×     14× 14×   14×   14×       14× 14× 14×       13× 13×         132×   32× 32×   32× 32× 31× 20×     32×     30× 30×           30× 14× 14×   16×          
const Liquid = require('..')
const lexical = Liquid.lexical
const assert = require('../src/util/assert.js')
const staticFileRE = /\S+/
 
/*
 * blockMode:
 * * "store": store rendered html into blocks
 * * "output": output rendered html
 */
 
module.exports = function (liquid) {
  liquid.registerTag('layout', {
    parse: function (token, remainTokens) {
      var match = staticFileRE.exec(token.args)
      if (match) {
        this.staticLayout = match[0]
      }
 
      match = lexical.value.exec(token.args)
      if (match) {
        this.layout = match[0]
      }
 
      this.tpls = liquid.parser.parse(remainTokens)
    },
    render: function (scope, hash) {
      var layout = scope.opts.dynamicPartials ? Liquid.evalValue(this.layout, scope) : this.staticLayout
      assert(layout, `cannot apply layout with empty filename`)
 
      // render the remaining tokens immediately
      scope.opts.blockMode = 'store'
      return liquid.renderer.renderTemplates(this.tpls, scope)
        .then(html => {
          if (scope.opts.blocks[''] === undefined) {
            scope.opts.blocks[''] = html
          }
          return liquid.getTemplate(layout, scope.opts.root)
        })
        .then(templates => {
          // push the hash
          scope.push(hash)
          scope.opts.blockMode = 'output'
          return liquid.renderer.renderTemplates(templates, scope)
        })
        // pop the hash
        .then(partial => {
          scope.pop()
          return partial
        })
    }
  })
 
  liquid.registerTag('block', {
    parse: function (token, remainTokens) {
      var match = /\w+/.exec(token.args)
      this.block = match ? match[0] : ''
 
      this.tpls = []
      var stream = liquid.parser.parseStream(remainTokens)
        .on('tag:endblock', () => stream.stop())
        .on('template', tpl => this.tpls.push(tpl))
        .on('end', () => {
          throw new Error(`tag ${token.raw} not closed`)
        })
      stream.start()
    },
    render: function (scope) {
      return Promise.resolve(scope.opts.blocks[this.block])
        .then(html => html === undefined
          // render default block
          ? liquid.renderer.renderTemplates(this.tpls, scope)
          // use child-defined block
          : html)
        .then(html => {
          if (scope.opts.blockMode === 'store') {
            scope.opts.blocks[this.block] = html
            return ''
          }
          return html
        })
    }
  })
}