lib/index.js
function parseLoopStatement (input) {
  let current = 0
  let char = input[current]

  // parse through keys `each **foo, bar** in x`, which is everything before
  // the word "in"
  const keys = []
  let key = ''
  while (!`${char}${lookahead(3)}`.match(/\s(in|of)\s/)) {
    key += char
    next()

    // if we hit a comma, we're on to the next key
    if (char === ',') {
      keys.push(key.trim())
      key = ''
      next()
    }

    // if we reach the end of the string without getting "in/of", it's an error
    if (typeof char === 'undefined') {
      throw new Error("Loop statement lacking 'in' or 'of' keyword")
    }
  }
  keys.push(key.trim())

  // detect whether it's an in or of
  const loopType = lookahead(2)

  // space before, in/of, space after
  next(4)

  // the rest of the string is evaluated as the array/object to loop
  let expression = ''
  while (current < input.length) {
    expression += char
    next()
  }

  return {keys, expression, loopType}

  // Utility: Move to the next character in the parse
  function next (n = 1) {
    for (let i = 0; i < n; i++) { char = input[++current] }
  }

  // Utility: looks ahead n characters and returns the result
  function lookahead (n) {
    let counter = current
    const target = current + n
    let res = ''
    while (counter < target) {
      res += input[++counter]
    }
    return res
  }
}
function parseLoopStatement (input) {
  let current = 0
  let char = input[current]

  // parse through keys `each **foo, bar** in x`, which is everything before
  // the word "in"
  const keys = []
  let key = ''
  while (!`${char}${lookahead(3)}`.match(/\s(in|of)\s/)) {
    key += char
    next()

    // if we hit a comma, we're on to the next key
    if (char === ',') {
      keys.push(key.trim())
      key = ''
      next()
    }

    // if we reach the end of the string without getting "in/of", it's an error
    if (typeof char === 'undefined') {
      throw new Error("Loop statement lacking 'in' or 'of' keyword")
    }
  }
  keys.push(key.trim())

  // detect whether it's an in or of
  const loopType = lookahead(2)

  // space before, in/of, space after
  next(4)

  // the rest of the string is evaluated as the array/object to loop
  let expression = ''
  while (current < input.length) {
    expression += char
    next()
  }

  return {keys, expression, loopType}

  // Utility: Move to the next character in the parse
  function next (n = 1) {
    for (let i = 0; i < n; i++) { char = input[++current] }
  }

  // Utility: looks ahead n characters and returns the result
  function lookahead (n) {
    let counter = current
    const target = current + n
    let res = ''
    while (counter < target) {
      res += input[++counter]
    }
    return res
  }
}
function parseLoopStatement ( input ) { let current = 0 let char = input [ current ] // parse through keys `each **foo, bar** in x`, which is everything before // the word "in" const keys = [ ] let key = '' while ( ! ` ${ char } ${ lookahead ( 3 ) } ` . match ( / \s(in|of)\s / ) ) { key += char next ( ) // if we hit a comma, we're on to the next key if ( char === ',' ) { keys . push ( key . trim ( ) ) key = '' next ( ) } // if we reach the end of the string without getting "in/of", it's an error if ( typeof char === 'undefined' ) { throw new Error ( "Loop statement lacking 'in' or 'of' keyword" ) } } keys . push ( key . trim ( ) ) // detect whether it's an in or of const loopType = lookahead ( 2 ) // space before, in/of, space after next ( 4 ) // the rest of the string is evaluated as the array/object to loop let expression = '' while ( current < input . length ) { expression += char next ( ) } return { keys , expression , loopType } // Utility: Move to the next character in the parse function next ( n = 1 ) { for ( let i = 0 ; i < n ; i ++ ) { char = input [ ++ current ] } } // Utility: looks ahead n characters and returns the result function lookahead ( n ) { let counter = current const target = current + n let res = '' while ( counter < target ) { res += input [ ++ counter ] } return res } }
Given a "loop" parameter from an "each" tag, parses out the param names and
expression to be looped through using a mini text parser.
Given a loop parameter from an each tag parses out the param names and expression to be looped through using a mini text parser .