all files / liquidjs/src/ tokenizer.js

100% Statements 52/52
100% Branches 20/20
100% Functions 4/4
100% Lines 52/52
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 86 87 88 89 90 91 92 93 94 95 96 97   286×   285×   285× 285× 285× 285× 285× 285×   285×   518× 159× 159×           518×   333×   333× 333×   326× 326×     326× 326×   326×     185× 185×   511×       278× 53× 53×           278×   518×                   518× 518× 518× 518×       307× 307×   307×   307× 307× 307×      
const lexical = require('./lexical.js')
const TokenizationError = require('./util/error.js').TokenizationError
const _ = require('./util/underscore.js')
const assert = require('../src/util/assert.js')
 
function parse (html, filepath, options) {
  assert(_.isString(html), 'illegal input type')
 
  html = whiteSpaceCtrl(html, options)
 
  var tokens = []
  var syntax = /({%-?([\s\S]*?)-?%})|({{-?([\s\S]*?)-?}})/g
  var result, htmlFragment, token
  var lastMatchEnd = 0
  var lastMatchBegin = -1
  var parsedLinesCount = 0
 
  while ((result = syntax.exec(html)) !== null) {
    // passed html fragments
    if (result.index > lastMatchEnd) {
      htmlFragment = html.slice(lastMatchEnd, result.index)
      tokens.push({
        type: 'html',
        raw: htmlFragment,
        value: htmlFragment
      })
    }
    if (result[1]) {
      // tag appeared
      token = factory('tag', 1, result)
 
      var match = token.value.match(lexical.tagLine)
      if (!match) {
        throw new TokenizationError(`illegal tag syntax`, token)
      }
      token.name = match[1]
      token.args = match[2]
 
      // get last line indentation
      var lineStart = (htmlFragment || '').split('\n')
      token.indent = lineStart[lineStart.length - 1].length
 
      tokens.push(token)
    } else {
      // output
      token = factory('output', 3, result)
      tokens.push(token)
    }
    lastMatchEnd = syntax.lastIndex
  }
 
  // remaining html
  if (html.length > lastMatchEnd) {
    htmlFragment = html.slice(lastMatchEnd, html.length)
    tokens.push({
      type: 'html',
      raw: htmlFragment,
      value: htmlFragment
    })
  }
  return tokens
 
  function factory (type, offset, match) {
    return {
      type: type,
      raw: match[offset],
      value: match[offset + 1].trim(),
      line: getLineNum(match),
      input: html,
      file: filepath
    }
  }
 
  function getLineNum (match) {
    var lines = match.input.slice(lastMatchBegin + 1, match.index).split('\n')
    parsedLinesCount += lines.length - 1
    lastMatchBegin = match.index
    return parsedLinesCount + 1
  }
}
 
function whiteSpaceCtrl (html, options) {
  options = options || {}
  if (options.trim_left) {
    html = html.replace(/({[{%])-?/g, '$1-')
  }
  if (options.trim_right) {
    html = html.replace(/-?([%}]})/g, '-$1')
  }
  var rLeft = options.greedy ? /\s+({[{%]-)/g : /[\t\r ]*({[{%]-)/g
  var rRight = options.greedy ? /(-[%}]})\s+/g : /(-[%}]})[\t\r ]*\n?/g
  return html.replace(rLeft, '$1').replace(rRight, '$1')
}
 
exports.parse = parse
exports.whiteSpaceCtrl = whiteSpaceCtrl