예제 #1
0
  private void pushNewTag(String tagName, int startLine, boolean isRemoveId, boolean ignoreBody) {
    Tag tag = new Tag(tagName, startLine);

    tag._component = !isRemoveId;
    tag._removeTag = isRemoveId;

    tag._ignoringBody = ignoreBody;

    _ignoring = tag._ignoringBody;

    tag._mustBalance = true;

    _stack.add(tag);
  }
예제 #2
0
  private void startTag() throws TemplateParseException {
    int cursorStart = _cursor;
    int length = _templateData.length;
    String tagName = null;
    boolean endOfTag = false;
    boolean emptyTag = false;
    int startLine = _line;
    ILocation startLocation = new Location(_resourceLocation, startLine);

    tagBeginEvent(startLine, _cursor);

    advance();

    // Collect the element type

    while (_cursor < length) {
      char ch = _templateData[_cursor];

      if (ch == '/' || ch == '>' || Character.isWhitespace(ch)) {
        tagName = new String(_templateData, cursorStart + 1, _cursor - cursorStart - 1);

        break;
      }

      advance();
    }

    String attributeName = null;
    int attributeNameStart = -1;
    int attributeValueStart = -1;
    int state = WAIT_FOR_ATTRIBUTE_NAME;
    char quoteChar = 0;

    _attributes.clear();

    // Collect each attribute

    while (!endOfTag) {
      if (_cursor >= length) {
        String key =
            (tagName == null)
                ? "TemplateParser.unclosed-unknown-tag"
                : "TemplateParser.unclosed-tag";

        templateParseProblem(
            Tapestry.format(key, tagName, Integer.toString(startLine)),
            startLocation,
            startLine,
            cursorStart);
      }

      char ch = _templateData[_cursor];

      switch (state) {
        case WAIT_FOR_ATTRIBUTE_NAME:

          // Ignore whitespace before the next attribute name, while
          // looking for the end of the current tag.

          if (ch == '/') {
            emptyTag = true;
            advance();
            break;
          }

          if (ch == '>') {
            endOfTag = true;
            break;
          }

          if (Character.isWhitespace(ch)) {
            advance();
            break;
          }

          // Found non-whitespace, assume its the attribute name.
          // Note: could use a check here for non-alpha.

          attributeNameStart = _cursor;
          state = COLLECT_ATTRIBUTE_NAME;
          advance();
          break;

        case COLLECT_ATTRIBUTE_NAME:

          // Looking for end of attribute name.

          if (ch == '=' || ch == '/' || ch == '>' || Character.isWhitespace(ch)) {
            attributeName =
                new String(_templateData, attributeNameStart, _cursor - attributeNameStart);

            state = ADVANCE_PAST_EQUALS;
            break;
          }

          // Part of the attribute name

          advance();
          break;

        case ADVANCE_PAST_EQUALS:

          // Looking for the '=' sign.  May hit the end of the tag, or (for bare attributes),
          // the next attribute name.

          if (ch == '/' || ch == '>') {
            // A bare attribute, which is not interesting to
            // us.

            state = WAIT_FOR_ATTRIBUTE_NAME;
            break;
          }

          if (Character.isWhitespace(ch)) {
            advance();
            break;
          }

          if (ch == '=') {
            state = WAIT_FOR_ATTRIBUTE_VALUE;
            quoteChar = 0;
            attributeValueStart = -1;
            advance();
            break;
          }

          // Otherwise, an HTML style "bare" attribute (such as <select multiple>).
          // We aren't interested in those (we're just looking for the id or jwcid attribute).

          state = WAIT_FOR_ATTRIBUTE_NAME;
          break;

        case WAIT_FOR_ATTRIBUTE_VALUE:
          if (ch == '/' || ch == '>')
            templateParseProblem(
                Tapestry.format(
                    "TemplateParser.missing-attribute-value",
                    tagName,
                    Integer.toString(_line),
                    attributeName),
                getCurrentLocation(),
                _line,
                _cursor);

          // Ignore whitespace between '=' and the attribute value.  Also, look
          // for initial quote.

          if (Character.isWhitespace(ch)) {
            advance();
            break;
          }

          if (ch == '\'' || ch == '"') {
            quoteChar = ch;

            state = COLLECT_QUOTED_VALUE;
            advance();
            attributeValueStart = _cursor;
            attributeBeginEvent(attributeName, _line, attributeValueStart);
            break;
          }

          // Not whitespace or quote, must be start of unquoted attribute.

          state = COLLECT_UNQUOTED_VALUE;
          attributeValueStart = _cursor;
          attributeBeginEvent(attributeName, _line, attributeValueStart);
          break;

        case COLLECT_QUOTED_VALUE:

          // Start collecting the quoted attribute value.  Stop at the matching quote character,
          // unless bare, in which case, stop at the next whitespace.

          if (ch == quoteChar) {
            String attributeValue =
                new String(_templateData, attributeValueStart, _cursor - attributeValueStart);

            attributeEndEvent(_cursor);

            if (_attributes.containsKey(attributeName))
              templateParseProblem(
                  Tapestry.format(
                      "TemplateParser.duplicate-tag-attribute",
                      tagName,
                      Integer.toString(_line),
                      attributeName),
                  getCurrentLocation(),
                  _line,
                  _cursor);

            _attributes.put(attributeName, attributeValue);

            // Advance over the quote.
            advance();
            state = WAIT_FOR_ATTRIBUTE_NAME;
            break;
          }

          advance();
          break;

        case COLLECT_UNQUOTED_VALUE:

          // An unquoted attribute value ends with whitespace
          // or the end of the enclosing tag.

          if (ch == '/' || ch == '>' || Character.isWhitespace(ch)) {
            String attributeValue =
                new String(_templateData, attributeValueStart, _cursor - attributeValueStart);

            attributeEndEvent(_cursor);

            if (_attributes.containsKey(attributeName))
              templateParseProblem(
                  Tapestry.format(
                      "TemplateParser.duplicate-tag-attribute",
                      tagName,
                      Integer.toString(_line),
                      attributeName),
                  getCurrentLocation(),
                  _line,
                  _cursor);

            _attributes.put(attributeName, attributeValue);

            state = WAIT_FOR_ATTRIBUTE_NAME;
            break;
          }

          advance();
          break;
      }
    }

    tagEndEvent(_cursor);

    // Check for invisible localizations

    String localizationKey = findValueCaselessly(LOCALIZATION_KEY_ATTRIBUTE_NAME, _attributes);
    String jwcId = findValueCaselessly(JWCID_ATTRIBUTE_NAME, _attributes);

    if (localizationKey != null && tagName.equalsIgnoreCase("span") && jwcId == null) {
      if (_ignoring)
        templateParseProblem(
            Tapestry.format(
                "TemplateParser.component-may-not-be-ignored",
                tagName,
                Integer.toString(startLine)),
            startLocation,
            startLine,
            cursorStart);

      // If the tag isn't empty, then create a Tag instance to ignore the
      // body of the tag.

      if (!emptyTag) {
        Tag tag = new Tag(tagName, startLine);

        tag._component = false;
        tag._removeTag = true;
        tag._ignoringBody = true;
        tag._mustBalance = true;

        _stack.add(tag);

        // Start ignoring content until the close tag.

        _ignoring = true;
      } else {
        // Cursor is at the closing carat, advance over it and any whitespace.
        advance();
        advanceOverWhitespace();
      }

      // End any open block.

      addTextToken(cursorStart - 1);

      boolean raw = checkBoolean(RAW_ATTRIBUTE_NAME, _attributes);

      Map attributes =
          filter(_attributes, new String[] {LOCALIZATION_KEY_ATTRIBUTE_NAME, RAW_ATTRIBUTE_NAME});

      TemplateToken token =
          _factory.createLocalizationToken(
              tagName, localizationKey, raw, attributes, startLocation);

      _tokens.add(token);

      return;
    }

    if (jwcId != null) {
      processComponentStart(tagName, jwcId, emptyTag, startLine, cursorStart, startLocation);
      return;
    }

    // A static tag (not a tag without a jwcid attribute).
    // We need to record this so that we can match close tags later.

    if (!emptyTag) {
      Tag tag = new Tag(tagName, startLine);
      _stack.add(tag);
    }

    // If there wasn't an active block, then start one.

    if (_blockStart < 0 && !_ignoring) _blockStart = cursorStart;

    advance();
  }