/** * Handle tag <head> * * @param tag */ private void handleHeadTag(ComponentTag tag) { // we found <head> if (tag.isOpen()) { if (foundHead) { throw new MarkupException( new MarkupStream(markup), "Tag <head> is not allowed at this position (do you have multiple <head> tags in your markup?)."); } foundHead = true; if (tag.getId() == null) { tag.setId(HEADER_ID); tag.setAutoComponentTag(true); tag.setModified(true); } } else if (tag.isClose()) { if (foundHeaderItemsTag) { // revert the settings from above ComponentTag headOpenTag = tag.getOpenTag(); // change the id because it is special. See HtmlHeaderResolver headOpenTag.setId(HEADER_ID + "-Ignored"); headOpenTag.setAutoComponentTag(false); headOpenTag.setModified(false); headOpenTag.setFlag(ComponentTag.RENDER_RAW, true); } foundClosingHead = true; } }
/** * Process next header markup fragment. * * @param associatedMarkupStream * @return index or -1 when done */ private int nextHeaderMarkup(final MarkupStream associatedMarkupStream) { // No associated markup => no header section if (associatedMarkupStream == null) { return -1; } // Scan the markup for <wicket:head>. MarkupElement elem = associatedMarkupStream.get(); while (elem != null) { if (elem instanceof WicketTag) { WicketTag tag = (WicketTag) elem; if (tag.isOpen() && tag.isHeadTag()) { if (noMoreWicketHeadTagsAllowed == true) { throw new MarkupException( "<wicket:head> tags are only allowed before <body>, </head>, <wicket:panel> etc. tag"); } return associatedMarkupStream.getCurrentIndex(); } // wicket:head must be before border, panel or extend // @TODO why is that? Why can't it be anywhere? (except inside wicket:fragment) else if (tag.isOpen() && (tag.isPanelTag() || tag.isBorderTag() || tag.isExtendTag())) { noMoreWicketHeadTagsAllowed = true; } } else if (elem instanceof ComponentTag) { ComponentTag tag = (ComponentTag) elem; // wicket:head must be before </head> // @TODO why?? if (tag.isClose() && TagUtils.isHeadTag(tag)) { noMoreWicketHeadTagsAllowed = true; } // wicket:head must be before <body> // @TODO why?? else if (tag.isOpen() && TagUtils.isBodyTag(tag)) { noMoreWicketHeadTagsAllowed = true; } } elem = associatedMarkupStream.next(); } // No (more) wicket:head found return -1; }
@Override protected final MarkupElement onComponentTag(ComponentTag tag) throws ParseException { if (tag.isClose()) { return tag; } final String wicketMessageAttribute = tag.getAttributes().getString(getWicketMessageAttrName()); if ((wicketMessageAttribute != null) && (wicketMessageAttribute.trim().length() > 0)) { // check if this tag is raw markup if (tag.getId() == null) { // if this is a raw tag we need to set the id to something so // that wicket will not merge this as raw markup and instead // pass it on to a resolver tag.setId(WICKET_MESSAGE_CONTAINER_ID); tag.setAutoComponentTag(true); tag.setModified(true); } tag.addBehavior(new AttributeLocalizer(getWicketMessageAttrName())); } return tag; }
@Override protected MarkupElement onComponentTag(final ComponentTag tag) throws ParseException { // We only need ComponentTags if (tag instanceof WicketTag) { return tag; } // Has wicket:enclosure attribute? String enclosureAttr = getAttribute(tag, null); if (enclosureAttr != null) { if (tag.isOpen()) { // Make sure 'wicket:id' and 'id' are consistent String htmlId = tag.getAttribute("id"); if ((tag.getId() != null) && !Strings.isEmpty(htmlId) && !htmlId.equals(tag.getId())) { throw new ParseException( "Make sure that 'id' and 'wicket:id' are the same if both are provided. Tag:" + tag.toString(), tag.getPos()); } // if it doesn't have a wicket-id already, then assign one now. if (Strings.isEmpty(tag.getId())) { if (Strings.isEmpty(htmlId)) { String id = getWicketNamespace() + "_" + INLINE_ENCLOSURE_ID_PREFIX + getRequestUniqueId(); tag.setId(id); } else { tag.setId(htmlId); } tag.setAutoComponentTag(true); tag.setAutoComponentFactory( new ComponentTag.IAutoComponentFactory() { @Override public Component newComponent(MarkupContainer container, ComponentTag tag) { String attributeName = getInlineEnclosureAttributeName(null); String childId = tag.getAttribute(attributeName); return new InlineEnclosure(tag.getId(), childId); } }); tag.setModified(true); } // Put the enclosure on the stack. The most current one will be on top if (enclosures == null) { enclosures = new ArrayDeque<>(); } enclosures.push(tag); } else { throw new ParseException( "Open-close tags don't make sense for InlineEnclosure. Tag:" + tag.toString(), tag.getPos()); } } // Are we within an enclosure? else if ((enclosures != null) && (enclosures.size() > 0)) { // In case the enclosure tag did not provide a child component id, then assign the // first ComponentTag's id found as the controlling child to the enclosure. if (tag.isOpen() && (tag.getId() != null) && !(tag instanceof WicketTag) && !tag.isAutoComponentTag()) { Iterator<ComponentTag> componentTagIterator = enclosures.descendingIterator(); while (componentTagIterator.hasNext()) { ComponentTag lastEnclosure = componentTagIterator.next(); String attr = getAttribute(lastEnclosure, null); if (Strings.isEmpty(attr) == true) { lastEnclosure.getAttributes().put(getInlineEnclosureAttributeName(null), tag.getId()); lastEnclosure.setModified(true); } } } else if (tag.isClose() && tag.closes(enclosures.peek())) { ComponentTag lastEnclosure = enclosures.pop(); String attr = getAttribute(lastEnclosure, null); if (Strings.isEmpty(attr) == true) { throw new ParseException( "Did not find any child for InlineEnclosure. Tag:" + lastEnclosure.toString(), tag.getPos()); } } } return tag; }
/** Scans the given markup and extracts balancing tags. */ private void parseMarkup() { try { // always remember the latest index (size) int size = markup.size(); // Loop through tags MarkupElement elem; while (null != (elem = getNextTag())) { if (elem instanceof HtmlSpecialTag) { elem = new ComponentTag(((HtmlSpecialTag) elem).getXmlTag()); } if (elem instanceof ComponentTag) { ComponentTag tag = (ComponentTag) elem; boolean add = (tag.getId() != null); if (!add && tag.isClose()) { add = ((tag.getOpenTag() != null) && (tag.getOpenTag().getId() != null)); } // Add tag to list? if (add || /*tag.isModified() ||*/ (markup.size() != size)) { // Add text from last position to the current tag position CharSequence text = xmlParser.getInputFromPositionMarker(tag.getPos()); if (text.length() > 0) { text = handleRawText(text.toString()); // Make sure you add it at the correct location. // IMarkupFilters might have added elements as well. markup.addMarkupElement(size, new RawMarkup(text)); } xmlParser.setPositionMarker(); if (add) { // Add to the markup unless the tag has been flagged as // to be removed from the markup. (e.g. <wicket:remove> if (tag.isIgnore() == false) { markup.addMarkupElement(tag); } } /*else if (tag.isModified()) { markup.addMarkupElement(new RawMarkup(tag.toCharSequence())); }*/ else { xmlParser.setPositionMarker(tag.getPos()); } } // always remember the latest index (size) size = markup.size(); } } } catch (final ParseException ex) { // Add remaining input string final CharSequence text = xmlParser.getInputFromPositionMarker(-1); if (text.length() > 0) { markup.addMarkupElement(new RawMarkup(text)); } // markup.getMarkupResourceStream().setEncoding(xmlParser.getEncoding()); markup.getMarkupResourceStream().setDoctype(xmlParser.getDoctype()); final MarkupStream markupStream = new MarkupStream(markup); markupStream.setCurrentIndex(markup.size() - 1); throw new MarkupException(markupStream, ex.getMessage(), ex); } // Add tail? CharSequence text = xmlParser.getInputFromPositionMarker(-1); if (text.length() > 0) { text = handleRawText(text.toString()); // Make sure you add it at the correct location. // IMarkupFilters might have added elements as well. markup.addMarkupElement(new RawMarkup(text)); } postProcess(markup); // Make all tags immutable and the list of elements unmodifiable markup.makeImmutable(); }