/** Parse a Mediawiki heading of the form "==heading==" and return the resulting HTML output. */
 public String parse(JFlexLexer lexer, String raw, Object... args) throws ParserException {
   if (logger.isTraceEnabled()) {
     logger.trace("heading: " + raw + " (" + lexer.yystate() + ")");
   }
   // the wikiheading tag may match a preceding newline, so strip it
   raw = raw.trim();
   int level = this.generateTagLevel(raw, args);
   String tagText = this.generateTagText(raw, args);
   String tocText = this.buildTocText(lexer, tagText);
   String tagName = this.buildTagName(lexer, tocText);
   if (lexer.getMode() <= JFlexParser.MODE_SLICE) {
     String sectionName = StringEscapeUtils.unescapeHtml4(tocText);
     lexer.getParserOutput().setSectionName(sectionName);
     return raw;
   }
   if (!(lexer instanceof JAMWikiLexer)) {
     throw new IllegalStateException(
         "Cannot parse heading tags except with instances of JAMWikiLexer or in slice/splice mode");
   }
   JAMWikiLexer jamwikiLexer = (JAMWikiLexer) lexer;
   if (jamwikiLexer.paragraphIsOpen()) {
     // close any open paragraph
     jamwikiLexer.popTag("p");
   }
   return this.generateOutput(jamwikiLexer, tagName, tocText, tagText, level, raw, args);
 }