function scan()

in web/1.0.0/hogan.js [188:296]


  function scan(text) {
    var len = text.length,
        IN_TEXT = 0,
        IN_TAG_TYPE = 1,
        IN_TAG = 2,
        state = IN_TEXT,
        tagType = null,
        buf = '',
        tokens = [],
        seenTag = false,
        i = 0,
        lineStart = 0,
        otag = '{{',
        ctag = '}}';

    function addBuf() {
      if (buf.length > 0) {
        tokens.push(new String(buf));
        buf = '';
      }
    }

    function lineIsWhitespace() {
      var isAllWhitespace = true;
      for (var j = lineStart; j < tokens.length; j++) {
        isAllWhitespace =
          (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
           (!tokens[j].tag && tokens[j].match(rIsWhitespace) == null);
        if (!isAllWhitespace) {
          return false;
        }
      }

      return isAllWhitespace;
    }

    function filterLine(haveSeenTag, noNewLine) {
      addBuf();
      if (haveSeenTag && lineIsWhitespace()) {
        for (var j = lineStart; j < tokens.length; j++) {
          if (!tokens[j].tag) {
            tokens.splice(j, 1);
          }
        }
      } else if (!noNewLine) {
        tokens.push({tag:'\n'})
      }

      seenTag = false;
      lineStart = tokens.length;
    }

    function changeDelimiters(text, index) {
      var close = '=' + ctag;
      var closeIndex = text.indexOf(close, index);
      var delimiters = trim(text.substring(text.indexOf('=', index) + 1,
                                           closeIndex)).split(' ');
      otag = delimiters[0];
      ctag = delimiters[1];
      return closeIndex + close.length - 1;
    }

    for (i = 0; i < len; i++) {
      if (state == IN_TEXT) {
        if (tagChange(otag, text, i)) {
          --i;
          addBuf();
          state = IN_TAG_TYPE;
        } else {
          if (text[i] == '\n') {
            filterLine(seenTag);
          } else {
            buf += text[i];
          }
        }
      } else if (state == IN_TAG_TYPE) {
        i += otag.length - 1;
        var tag = tagTypes[text[i + 1]];
        tagType = tag ? text[i + 1] : '_v';
        seenTag = i;
        if (tagType == '=') {
          i = changeDelimiters(text, i);
          state = IN_TEXT;
        } else {
          if (tag) {
            i++;
          }
          state = IN_TAG;
        }
      } else {
        if (tagChange(ctag, text, i)) {
          i += ctag.length - 1;
          tokens.push({tag: tagType, n: trim(buf),
                       i: (tagType == '/') ? seenTag - 1 : i + 1});
          buf = '';
          state = IN_TEXT;
          if (tagType == '{') {
            i++;
          }
        } else {
          buf += text[i];
        }
      }
    }

    filterLine(seenTag, true);

    return tokens;
  }