1 package org.plog4u.wiki.filter;
3 import java.io.IOException;
5 import java.util.ArrayList;
6 import java.util.NoSuchElementException;
7 import java.util.Stack;
8 import java.util.StringTokenizer;
10 //import org.apache.commons.logging.Log;
11 //import org.apache.commons.logging.LogFactory;
12 import org.plog4u.wiki.filter.WikipediaFilter.InvalidInputException;
13 import org.plog4u.wiki.filter.tags.AbstractTag;
14 import org.plog4u.wiki.filter.tags.CloseTagToken;
15 import org.plog4u.wiki.filter.tags.ListToken;
16 import org.plog4u.wiki.filter.tags.OpenTagToken;
17 import org.plog4u.wiki.filter.tags.SpecialTagToken;
18 import org.radeox.api.engine.ImageRenderEngine;
19 import org.radeox.api.engine.IncludeRenderEngine;
20 import org.radeox.api.engine.RenderEngine;
21 import org.radeox.api.engine.WikiRenderEngine;
22 import org.radeox.filter.context.FilterContext;
23 import org.radeox.filter.interwiki.InterWiki;
24 import org.radeox.macro.Macro;
25 import org.radeox.macro.MacroRepository;
26 import org.radeox.macro.parameter.MacroParameter;
27 import org.radeox.util.Encoder;
28 import org.radeox.util.StringBufferWriter;
31 * A parser for the WikipediaFilter
33 * @see org.plog4u.wiki.filter.WikipediaFilter
35 public class WikipediaParser {
36 // private static Log log = LogFactory.getLog(WikipediaFilter.class);
38 MacroRepository fMacros;
40 private FilterContext fContext;
42 private RenderEngine fWikiEngine;
44 // TODO check, if this counter is correct in recursions:
45 private int fImageCounter;
50 // private Snip fSnip;
52 * If the snip contains headings for a "table of content" this buffer temporarily contains the start of the snip and the
53 * "table of content"
55 private StringBuffer fResultBufferHeader = null;
58 * The buffer for the resulting HTML rendering from the current snip.
60 private StringBuffer fResultBuffer;
63 * The wiki syntax string which should be parsed
65 private char[] fSource;
68 * The corresponding String for the character source array
70 private final String fStringSource;
73 * The current scanned character
75 private char fCurrentCharacter;
78 * The current offset in the character source array
80 private int fCurrentPosition;
83 * The current recursion level for this parser
85 private int fRecursionLevel;
87 private Stack fTokenStack;
89 // private Stack fTableStack;
91 private boolean fWhiteStart = false;
93 private int fWhiteStartPosition = 0;
95 // private TeXParser fTeXParser;
96 // private TeXParser fTeXImageParser;
99 * "table of content"
102 private ArrayList fTableOfContent = null;
104 // private String fSrcPath;
105 // private String fBinPath;
106 public WikipediaParser(MacroRepository macros, String stringSource, StringBuffer result, FilterContext context, int recursionLevel) {
108 fWikiEngine = context.getRenderContext().getRenderEngine();
111 // SnipMacroParameter params = (SnipMacroParameter)
112 // fContext.getMacroParameter();
113 // fSnip = params.getSnipRenderContext().getSnip();
114 // } catch (ClassCastException e) {
115 // e.printStackTrace();
118 fResultBuffer = result;
119 fStringSource = stringSource;
120 setSource(stringSource.toCharArray());
121 fRecursionLevel = recursionLevel;
122 fTokenStack = new Stack();
123 // fTableStack = new Stack();
124 // fTeXParser = new TeXParser("", "m:");
125 // fTeXImageParser = new TeXParser("", "");
128 // fSrcPath = (String) fContext.getRenderContext().get("srcpath");
129 // if (fSrcPath==null) {
132 // fBinPath = (String) fContext.getRenderContext().get("binpath");
133 // if (fBinPath==null) {
139 * Check until a new-line was found, if there are only whitespace characters before the given endposition.
141 * @param startPosition
143 * @return -1 if no whitespace line is found from the end (i.e. endPosition); otherwise the offset directly after where the
146 private int checkWhitespaces(int startPosition, int endPosition) {
148 while (endPosition >= startPosition) {
149 if ((tempChar = fSource[endPosition--]) == '\n') {
150 return endPosition + 2;
152 if (tempChar != ' ' && tempChar != '\t' && tempChar != '\r') {
156 if (endPosition < startPosition && endPosition >= 0) {
157 if ((tempChar = fSource[endPosition]) != '\n') {
160 } else if (endPosition == (-1) && startPosition == 0) {
161 // special case at the start of a string
164 return startPosition;
168 * copy the content in the resulting buffer and escape special html characters (< > " & ')
170 private void copyWhite(boolean whiteStart, final int whiteStartPosition, final int diff) {
172 final int len = fCurrentPosition - diff;
173 int currentIndex = whiteStartPosition;
174 int lastIndex = currentIndex;
175 while (currentIndex < len) {
176 switch (fSource[currentIndex++]) {
177 case '<': // special html escape character
178 if (lastIndex < (currentIndex - 1)) {
179 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
180 lastIndex = currentIndex;
184 fResultBuffer.append("<");
186 case '>': // special html escape character
187 if (lastIndex < (currentIndex - 1)) {
188 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
189 lastIndex = currentIndex;
193 fResultBuffer.append(">");
195 case '&': // special html escape character
196 if (lastIndex < (currentIndex - 1)) {
197 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
198 lastIndex = currentIndex;
202 fResultBuffer.append("&");
204 case '\'': // special html escape character
205 if (lastIndex < (currentIndex - 1)) {
206 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
207 lastIndex = currentIndex;
211 fResultBuffer.append("'");
213 case '\"': // special html escape character
214 if (lastIndex < (currentIndex - 1)) {
215 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
216 lastIndex = currentIndex;
220 fResultBuffer.append(""");
224 if (lastIndex < (currentIndex)) {
225 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex);
232 * copy the text in the resulting buffer and escape special html characters (< > " & ')
234 private void copyWhite(String text) {
235 final int len = text.length();
236 int currentIndex = 0;
237 int lastIndex = currentIndex;
238 while (currentIndex < len) {
239 switch (text.charAt(currentIndex++)) {
240 case '<': // special html escape character
241 if (lastIndex < (currentIndex - 1)) {
242 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
243 lastIndex = currentIndex;
245 fResultBuffer.append("<");
247 case '>': // special html escape character
248 if (lastIndex < (currentIndex - 1)) {
249 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
250 lastIndex = currentIndex;
254 fResultBuffer.append(">");
256 case '&': // special html escape character
257 if (lastIndex < (currentIndex - 1)) {
258 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
259 lastIndex = currentIndex;
263 fResultBuffer.append("&");
265 case '\'': // special html escape character
266 if (lastIndex < (currentIndex - 1)) {
267 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
268 lastIndex = currentIndex;
272 fResultBuffer.append("'");
274 case '\"': // special html escape character
275 if (lastIndex < (currentIndex - 1)) {
276 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
277 lastIndex = currentIndex;
281 fResultBuffer.append(""");
285 if (lastIndex < (currentIndex)) {
286 fResultBuffer.append(text.substring(lastIndex, currentIndex));
291 * Copy the text in the resulting buffer and escape special html characters (< > " & ') Additionally every
292 * newline will be replaced by <br/>
294 private void copyNowikiNewLine(String text) {
295 final int len = text.length();
296 int currentIndex = 0;
297 int lastIndex = currentIndex;
298 while (currentIndex < len) {
299 switch (text.charAt(currentIndex++)) {
301 if (lastIndex < (currentIndex - 1)) {
302 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
303 lastIndex = currentIndex;
307 fResultBuffer.append("<br/>");
309 case '<': // special html escape character
310 if (lastIndex < (currentIndex - 1)) {
311 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
312 lastIndex = currentIndex;
316 fResultBuffer.append("<");
318 case '>': // special html escape character
319 if (lastIndex < (currentIndex - 1)) {
320 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
321 lastIndex = currentIndex;
325 fResultBuffer.append(">");
327 // case '&': // special html escape character
328 // if (lastIndex < (currentIndex - 1)) {
329 // fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
330 // lastIndex = currentIndex;
334 // fResultBuffer.append("&");
336 case '\'': // special html escape character
337 if (lastIndex < (currentIndex - 1)) {
338 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
339 lastIndex = currentIndex;
343 fResultBuffer.append("'");
345 case '\"': // special html escape character
346 if (lastIndex < (currentIndex - 1)) {
347 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
348 lastIndex = currentIndex;
352 fResultBuffer.append(""");
356 if (lastIndex < (currentIndex)) {
357 fResultBuffer.append(text.substring(lastIndex, currentIndex));
362 * Render the HTML token which are defined in the OPEN_TAGS and CLOSE_TAGS map
366 public int getHTMLToken() {
367 int currentHtmlPosition = fCurrentPosition;
371 if (getNextChar('/')) {
373 currentHtmlPosition++;
375 int r = readUntilCharOrEOL('>');
377 return WikipediaFilter.TokenNotFound;
379 String closeTagString = new String(fSource, currentHtmlPosition, fCurrentPosition - currentHtmlPosition - 1).toLowerCase();
380 // System.out.println(closeTagString);
381 StringTokenizer tagTokenizer = new StringTokenizer(closeTagString);
384 tokenString = tagTokenizer.nextToken();
385 CloseTagToken token = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tokenString);
387 return WikipediaFilter.TokenNotFound;
389 Object topToken = fTokenStack.peek();
390 if (topToken instanceof OpenTagToken && ((OpenTagToken) topToken).getTagName() == token.getTagName()) {
392 // if (token.getTagName().equals("table")) {
393 // fTableStack.pop();
395 copyWhite(fWhiteStart, fWhiteStartPosition, 3 + tokenString.length());
397 fResultBuffer.append(token.getCloseTag());
398 return WikipediaFilter.TokenIgnore;
401 unexpectedTag(token.getTagName());
402 return WikipediaFilter.TokenIgnore;
403 } catch (NoSuchElementException e) {
404 return WikipediaFilter.TokenNotFound;
410 int tagNameStart = fCurrentPosition;
412 while (Character.isJavaIdentifierStart(fSource[fCurrentPosition])) {
417 tokenString = new String(fSource, tagNameStart, fCurrentPosition - tagNameStart); //tagTokenizer.nextToken();
419 OpenTagToken token = (OpenTagToken) WikipediaFilter.OPEN_TAGS.get(tokenString);
421 return WikipediaFilter.TokenNotFound;
423 copyWhite(fWhiteStart, fWhiteStartPosition, (fCurrentPosition - tagNameStart) + 1);
425 if (token instanceof SpecialTagToken) {
426 // for <br> <br/> <br /> <hr> <hr/>
428 while (Character.isWhitespace(fSource[fCurrentPosition])) {
431 if (fSource[fCurrentPosition] == '/') {
434 if (fSource[fCurrentPosition] == '>') {
436 fWhiteStartPosition = fCurrentPosition;
437 // insert the special tag :
438 fResultBuffer.append(token.getOpenTag());
439 return WikipediaFilter.TokenIgnore;
442 } else if (token instanceof OpenTagToken) {
443 fResultBuffer.append("<");
444 fResultBuffer.append(token.getTagName());
445 fTokenStack.push(token);
446 fCurrentPosition = token.scan(fResultBuffer, fSource, fCurrentPosition - 1);
447 fResultBuffer.append(">");
448 return WikipediaFilter.TokenIgnore;
450 return WikipediaFilter.TokenNotFound;
451 } catch (NoSuchElementException e) {
452 return WikipediaFilter.TokenNotFound;
456 } catch (IndexOutOfBoundsException e) {
459 fCurrentPosition = currentHtmlPosition;
460 return WikipediaFilter.TokenNotFound;
463 public final boolean getNextChar(char testedChar) {
464 int temp = fCurrentPosition;
466 fCurrentCharacter = fSource[fCurrentPosition++];
467 if (fCurrentCharacter != testedChar) {
468 fCurrentPosition = temp;
473 } catch (IndexOutOfBoundsException e) {
474 fCurrentPosition = temp;
479 public final int getNextChar(char testedChar1, char testedChar2) {
480 int temp = fCurrentPosition;
483 fCurrentCharacter = fSource[fCurrentPosition++];
484 if (fCurrentCharacter == testedChar1)
486 else if (fCurrentCharacter == testedChar2)
489 fCurrentPosition = temp;
493 } catch (IndexOutOfBoundsException e) {
494 fCurrentPosition = temp;
499 public final boolean getNextCharAsDigit() {
500 int temp = fCurrentPosition;
502 fCurrentCharacter = fSource[fCurrentPosition++];
503 if (!Character.isDigit(fCurrentCharacter)) {
504 fCurrentPosition = temp;
508 } catch (IndexOutOfBoundsException e) {
509 fCurrentPosition = temp;
514 public final boolean getNextCharAsDigit(int radix) {
516 int temp = fCurrentPosition;
518 fCurrentCharacter = fSource[fCurrentPosition++];
520 if (Character.digit(fCurrentCharacter, radix) == -1) {
521 fCurrentPosition = temp;
525 } catch (IndexOutOfBoundsException e) {
526 fCurrentPosition = temp;
531 public final int getNumberOfChar(char testedChar) {
534 while ((fCurrentCharacter = fSource[fCurrentPosition++]) == testedChar) {
537 } catch (IndexOutOfBoundsException e) {
544 public final char[] getListChars() {
546 int startPosition = fCurrentPosition - 1;
549 fCurrentCharacter = fSource[fCurrentPosition++];
550 if (fCurrentCharacter != '*' && fCurrentCharacter != '#') {
554 } catch (IndexOutOfBoundsException e) {
558 char[] result = new char[fCurrentPosition - startPosition];
559 System.arraycopy(fSource, startPosition, result, 0, fCurrentPosition - startPosition);
563 public boolean getNextCharAsWikiPluginIdentifierPart() {
564 int temp = fCurrentPosition;
566 fCurrentCharacter = fSource[fCurrentPosition++];
568 if (!WikipediaFilter.isWikiPluginIdentifierPart(fCurrentCharacter)) {
569 fCurrentPosition = temp;
573 } catch (IndexOutOfBoundsException e) {
574 fCurrentPosition = temp;
579 private void stopList() {
580 while (!fTokenStack.isEmpty()) {
581 AbstractTag tok = (AbstractTag) fTokenStack.peek();
582 if (tok.equals(WikipediaFilter.LIST_UL_START)) {
584 fResultBuffer.append("</li></ul>");
585 } else if (tok.equals(WikipediaFilter.LIST_OL_START)) {
587 fResultBuffer.append("</li></ol>");
588 } else if (tok == WikipediaFilter.BOLD) {
590 fResultBuffer.append("</b>");
591 } else if (tok == WikipediaFilter.ITALIC) {
593 fResultBuffer.append("</i>");
594 } else if (tok == WikipediaFilter.STRONG) {
596 fResultBuffer.append("</strong>");
597 } else if (tok == WikipediaFilter.EM) {
599 fResultBuffer.append("</em>");
600 } else if (tok == WikipediaFilter.STRIKETHROUGH) {
602 fResultBuffer.append("</strike>");
609 protected int getNextToken() throws InvalidInputException {
610 boolean startOfIndent = false;
611 fWhiteStartPosition = 0;
615 // fStartPosition = fCurrentPosition;
616 fCurrentCharacter = fSource[fCurrentPosition++];
618 // ---------Identify the next token-------------
619 switch (fCurrentCharacter) {
622 int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 2);
623 if (tempPosition >= 0) {
624 copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - (++tempPosition));
627 fResultBuffer.append("<p/>");
632 int fStartPrePosition = fCurrentPosition;
633 boolean preSection = false;
635 while (fSource[fCurrentPosition++] == ' ') {
636 fCurrentCharacter = fSource[fCurrentPosition++];
637 while (fCurrentCharacter != '\n') {
638 if (!Character.isWhitespace(fCurrentCharacter)) {
639 // preformatted section starts here
642 fCurrentCharacter = fSource[fCurrentPosition++];
646 } catch (IndexOutOfBoundsException e) {
649 if (preSection && fRecursionLevel == 1) {
651 copyWhite(fWhiteStart, fStartPrePosition, fCurrentPosition - fStartPrePosition);
653 fResultBuffer.append("<pre>");
654 // copyWhite(fWhiteStart, fStartPrePosition, 1);
655 preString = new String(fSource, fStartPrePosition, fCurrentPosition - fStartPrePosition - 1) + '\n';
656 fResultBuffer.append(WikipediaFilter.filterParser(preString, fContext, fMacros, fRecursionLevel));
657 // preString = new String(fSource, fStartPrePosition, fCurrentPosition - fStartPrePosition - 1)+'\n';
659 // int lastIndex = 0;
660 // while (preIndex>=0) {
661 // preIndex = preString.indexOf('\n', lastIndex);
662 // if (preIndex>=0) {
663 // fResultBuffer.append(WikipediaFilter.filterParser(preString.substring(lastIndex,preIndex), fContext,
664 // fCachedPage, fMacros, fRecursionLevel));
665 // fResultBuffer.append('\n');
666 // lastIndex = ++preIndex;
669 fResultBuffer.append("</pre>");
673 fCurrentPosition = fStartPrePosition;
677 if (isStartOfLine()) {
678 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
681 int levelHeader = getNumberOfChar(':') + 1;
682 int startHeadPosition = fCurrentPosition;
683 if (readUntilEOL()) {
684 String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition);
685 for (int i = 0; i < levelHeader; i++) {
686 fResultBuffer.append("<dl><dd>");
688 fResultBuffer.append(head);
689 for (int i = 0; i < levelHeader; i++) {
690 fResultBuffer.append("</dd></dl>");
699 if (isStartOfLine() && getNextChar(' ')) {
700 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
703 int startHeadPosition = fCurrentPosition;
704 if (readUntilEOL()) {
705 // TODO not correct - improve this
706 String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition);
707 int index = head.indexOf(": ");
709 fResultBuffer.append("<dl><dt>");
710 fResultBuffer.append(head.substring(0, index));
711 fResultBuffer.append("</dt><dd>");
712 fResultBuffer.append(head.substring(index + 2));
713 fResultBuffer.append("</dd></dl>");
715 fResultBuffer.append("<dl><dt>");
716 fResultBuffer.append(head);
717 fResultBuffer.append("</dt></dl>");
726 int startLinkPosition = fCurrentPosition;
727 if (getNextChar('[')) { // wikipedia link style
728 startLinkPosition = fCurrentPosition;
729 copyWhite(fWhiteStart, fWhiteStartPosition, 2);
731 if (readUntilString("]]")) {
732 String name = new String(fSource, startLinkPosition, fCurrentPosition - startLinkPosition - 2);
733 // test for suffix string
734 int temp = fCurrentPosition;
735 StringBuffer suffixBuffer = new StringBuffer();
738 fCurrentCharacter = fSource[fCurrentPosition++];
739 if (!Character.isLetterOrDigit(fCurrentCharacter)) {
743 suffixBuffer.append(fCurrentCharacter);
745 handleWikipediaLink(name, suffixBuffer.toString());
747 } catch (IndexOutOfBoundsException e) {
748 fCurrentPosition = temp;
751 handleWikipediaLink(name, "");
756 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
759 if (readUntilChar(']')) {
760 String name = new String(fSource, startLinkPosition, fCurrentPosition - startLinkPosition - 1);
761 handleSnipLink(name);
766 case '*': // <ul> list
767 case '#': // <ol> list
768 if (isStartOfLine()) {
769 char[] listChars = getListChars();
770 int tempStarPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - listChars.length);
771 if (tempStarPosition >= 0) {
772 appendList(listChars);
778 if (getNextChar('\'')) {
779 if (getNextChar('\'')) {
780 copyWhite(fWhiteStart, fWhiteStartPosition, 3);
782 return WikipediaFilter.TokenSTRONG;
784 copyWhite(fWhiteStart, fWhiteStartPosition, 2);
786 return WikipediaFilter.TokenEM;
790 int tempCurrPosition = fCurrentPosition;
792 if (fSource[tempCurrPosition++] == '-' && fSource[tempCurrPosition++] == '-' && fSource[tempCurrPosition++] == '-') {
793 if (fSource[tempCurrPosition] == '\n') {
794 fCurrentPosition = tempCurrPosition;
795 fResultBuffer.append("<hr/>");
798 } else if (fSource[tempCurrPosition++] == '\r' && fSource[tempCurrPosition++] == '\n') {
799 fCurrentPosition = tempCurrPosition - 1;
800 fResultBuffer.append("<hr/>");
805 } catch (IndexOutOfBoundsException e) {
809 case 'h': // http(s)://
810 int urlStartPosition = fCurrentPosition;
811 boolean foundUrl = false;
814 String urlString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 3);
815 if (urlString.equals("http")) {
816 fCurrentPosition += 3;
817 fCurrentCharacter = fSource[fCurrentPosition++];
818 if (fCurrentCharacter == 's') { // optional
819 fCurrentCharacter = fSource[fCurrentPosition++];
823 if (fCurrentCharacter == ':' && fSource[fCurrentPosition++] == '/' && fSource[fCurrentPosition++] == '/') {
824 copyWhite(fWhiteStart, fWhiteStartPosition, diff);
827 while (WikipediaFilter.isUrlIdentifierPart(fSource[fCurrentPosition++])) {
831 } catch (IndexOutOfBoundsException e) {
834 fCurrentPosition = urlStartPosition;
838 String urlString = new String(fSource, urlStartPosition - 1, fCurrentPosition - urlStartPosition);
840 WikipediaFilter.createExternalLink(fResultBuffer, fWikiEngine, urlString);
845 // case '@': // images @xml@ -> /static/rss-small.png
846 // copyWhite(fWhiteStart, fWhiteStartPosition, 1);
847 // fWhiteStart = false;
848 // int atStart = fCurrentPosition;
849 // if (readUntilChar('@')) {
850 // String imageTag = new String(fSource, atStart, fCurrentPosition - atStart - 1);
851 // if (imageTag != null) {
852 // if (WikipediaFilter.createStaticImage(imageTag, fResultBuffer)) {
857 // fCurrentPosition = atStart;
860 int ampersandStart = fCurrentPosition - 1;
861 if (getNextChar('#')) {
863 StringBuffer num = new StringBuffer(5);
864 char ch = fSource[fCurrentPosition++];
865 while (Character.isDigit(ch)) {
867 ch = fSource[fCurrentPosition++];
869 if (num.length() > 0 && ch == ';') {
870 Integer i = Integer.valueOf(num.toString());
871 if (i.intValue() < 65536) {
872 copyWhite(fWhiteStart, fWhiteStartPosition, 3 + num.length());
874 fResultBuffer.append(fSource, ampersandStart, fCurrentPosition - ampersandStart);
878 } catch (IndexOutOfBoundsException e) {
880 } catch (NumberFormatException e) {
885 StringBuffer entity = new StringBuffer(10);
886 char ch = fSource[fCurrentPosition++];
887 while (Character.isLetterOrDigit(ch)) {
889 ch = fSource[fCurrentPosition++];
891 if (entity.length() > 0 && ch == ';') {
892 if (WikipediaFilter.ENTITY_SET.contains(entity.toString())) {
893 copyWhite(fWhiteStart, fWhiteStartPosition, 2 + entity.length());
895 fResultBuffer.append(fSource, ampersandStart, fCurrentPosition - ampersandStart);
899 } catch (IndexOutOfBoundsException e) {
901 } catch (NumberFormatException e) {
908 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
910 int startMacroPosition = fCurrentPosition;
911 if (getNextChar('|') && handleWikipediaTable()) { // Wikipedia
916 if (readUntilChar('}')) {
917 String macroStartTag;
919 macroStartTag = new String(fSource, startMacroPosition, fCurrentPosition - startMacroPosition - 1);
920 if (macroStartTag != null) {
921 createMacro(startMacroPosition, macroStartTag);
928 int htmlStartPosition = fCurrentPosition;
930 switch (fStringSource.charAt(fCurrentPosition)) {
931 case '!': // <!-- html comment -->
932 String htmlCommentString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 3);
934 if (htmlCommentString.equals("<!--")) {
935 fCurrentPosition += 3;
936 if (readUntilString("-->")) {
937 String htmlCommentContent = new String(fSource, htmlStartPosition + 3, fCurrentPosition - htmlStartPosition - 6);
938 if (htmlCommentContent != null) {
939 copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - htmlStartPosition + 1);
941 // insert html comment for visual checks
944 * fResultBuffer.append(" <!--"); copyWhite(htmlCommentContent); fResultBuffer.append("--> ");
952 String nowikiString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 7);
954 if (nowikiString.equals("<nowiki>")) {
955 fCurrentPosition += 7;
956 if (readUntilString("</nowiki>")) {
957 String nowikiContent = new String(fSource, htmlStartPosition + 7, fCurrentPosition - htmlStartPosition - 16);
958 if (nowikiContent != null) {
959 copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - htmlStartPosition + 1);
961 copyNowikiNewLine(nowikiContent);
968 } catch (IndexOutOfBoundsException e) {
971 startOfIndent = false;
972 fCurrentPosition = htmlStartPosition;
973 // detect special html tags
974 int htmlToken = getHTMLToken();
975 if (htmlToken == WikipediaFilter.TokenIgnore) {
977 // } else if (htmlToken > TokenIgnore) {
980 fCurrentPosition = htmlStartPosition;
982 case '=': // wikipedia header ?
983 if (isStartOfLine()) {
984 int levelHeader = getNumberOfChar('=') + 1;
985 // int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - levelHeader);
986 // if (tempPosition >= 0) {
987 copyWhite(fWhiteStart, fWhiteStartPosition, levelHeader);
989 int startHeadPosition = fCurrentPosition;
990 // int initialOffset = levelHeader;
991 if (levelHeader > 6) {
995 if (readUntilString(WikipediaFilter.HEADER_STRINGS[levelHeader])) {
996 String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition - (1 + levelHeader));
998 handleHead(head, levelHeader);
1007 fWhiteStartPosition = fCurrentPosition - 1;
1010 startOfIndent = false;
1012 // -----------------end switch while try--------------------
1013 } catch (IndexOutOfBoundsException e) {
1014 // end of scanner text
1016 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
1018 return WikipediaFilter.TokenEOF;
1024 private boolean isStartOfLine() {
1025 boolean isListStart = false;
1026 if (fCurrentPosition >= 2) {
1027 char beforeChar = fSource[fCurrentPosition - 2];
1028 if (beforeChar == '\n' || beforeChar == '\r') {
1032 if (fCurrentPosition == 1) {
1043 private void appendList(char[] listChars) {
1045 int levelStar = listChars.length;
1046 copyWhite(fWhiteStart, fWhiteStartPosition, levelStar);
1047 fWhiteStart = false;
1048 AbstractTag tok = (AbstractTag) fTokenStack.peek();
1050 if (tok instanceof ListToken) {
1051 ListToken listToken = (ListToken) tok;
1052 topLevel = listToken.getLevel();
1054 if (levelStar > topLevel) {
1055 while (levelStar > topLevel) {
1056 if (listChars[topLevel] == '*') {
1057 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, ++topLevel));
1058 fResultBuffer.append("<ul><li>");
1060 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, ++topLevel));
1061 fResultBuffer.append("<ol><li>");
1064 } else if (levelStar < topLevel) {
1065 while (levelStar < topLevel) {
1066 tok = (AbstractTag) fTokenStack.peek();
1067 if (tok instanceof ListToken) {
1069 listToken = (ListToken) tok;
1070 if (listToken.getToken() == WikipediaFilter.TokenLIST_UL_START) {
1071 fResultBuffer.append("</li></ul></li><li>");
1073 fResultBuffer.append("</li></ol></li><li>");
1082 if (listToken.getToken() == WikipediaFilter.TokenLIST_UL_START && listChars[topLevel] == '#') {
1084 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel));
1085 fResultBuffer.append("</li></ul><ol><li>");
1086 } else if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START && listChars[topLevel] == '*') {
1088 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, topLevel));
1089 fResultBuffer.append("</li></ol><ul><li>");
1091 fResultBuffer.append("</li><li>");
1095 while (levelStar > topLevel) {
1096 if (listChars[topLevel] == '*') {
1097 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, ++topLevel));
1098 fResultBuffer.append("\n<ul><li>");
1100 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, ++topLevel));
1101 fResultBuffer.append("\n<ol><li>");
1107 private void createMacro(int startMacroPosition, String macroStartTag) {
1108 String command = "";
1111 String parameterString = null;
1112 String macroBodyString = "";
1115 if ((index0 = macroStartTag.indexOf(':')) >= 0) {
1116 command = macroStartTag.substring(0, index0);
1117 parameterString = macroStartTag.substring(index0 + 1, macroStartTag.length());
1119 command = macroStartTag;
1121 Macro macro = (Macro) fMacros.get(command);
1123 String completeMacroSubString;
1125 if ((macro != null) && (macro instanceof IBodyTagSupportMacro)) {
1126 endTag = '{' + command + '}';
1127 index0 = fStringSource.indexOf(endTag, fCurrentPosition);
1130 macroBodyString = fStringSource.substring(fCurrentPosition, index0);
1131 completeMacroSubString = new String(fSource, startMacroPosition - 1, index0 + endTag.length() - startMacroPosition + 1);
1132 fCurrentPosition = startMacroPosition + completeMacroSubString.length() - 1;
1134 completeMacroSubString = new String(fSource, startMacroPosition - 1, macroStartTag.length() + 2);
1137 completeMacroSubString = new String(fSource, startMacroPosition - 1, macroStartTag.length() + 2);
1140 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
1142 handleMacro(completeMacroSubString, command, parameterString, macroBodyString);
1145 // private void createExternalLink(String urlString) {
1147 // // Does our engine know images?
1148 // if (fWikiEngine instanceof ImageRenderEngine) {
1149 // fResult.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
1151 // fResult.append("<span class=\"nobr\">");
1152 // fResult.append("<a href=\"");
1153 // fResult.append(Encoder.escape(urlString));
1154 // fResult.append("\">");
1155 // fResult.append(Encoder.toEntity(urlString.charAt(0)) +
1156 // urlString.substring(1));
1157 // fResult.append("</a></span>");
1160 // private void handleTeXMath(String mathContent, boolean inlineExpression)
1162 // // TODO clean this up
1163 // Map map = Application.get().getParameters();
1164 // HttpServletRequest request = (HttpServletRequest) map.get("request");
1165 // MathSniffer sniffy = MathSniffer.getBrowserDetection(request);
1167 // if (fCacheStaticBlockActive) {
1168 // fCachedPage.addHTML(fResultBuffer.substring(fCacheStaticBlockStartPosition,
1169 // fResultBuffer.length()));
1170 // fCacheStaticBlockActive = false;
1172 // // if (inlineExpression) {
1173 // // fASMCompiler.compileMath(mathContent, "true");
1175 // // fASMCompiler.compileMath(mathContent, "false");
1177 // if (fCachedPage == WikipediaFilter.DUMMY_CACHED_PAGE) {
1178 // switch (sniffy.getBrowserId()) {
1179 // case MathSniffer.XMLID :
1180 // case MathSniffer.MATHPLAYERID :
1181 // if (inlineExpression) {
1182 // fResultBuffer.append("<m:math><m:mstyle mathcolor=\"Black\"
1183 // displaystyle=\"true\">");
1184 // fTeXParser.initialize(mathContent);
1185 // fTeXParser.parse2MML(fResultBuffer);
1186 // fResultBuffer.append("</m:mstyle></m:math>");
1188 // fResultBuffer.append("<dl><dd><m:math><m:mstyle mathcolor=\"Black\"
1189 // displaystyle=\"true\">");
1190 // fTeXParser.initialize(mathContent);
1191 // fTeXParser.parse2MML(fResultBuffer);
1192 // fResultBuffer.append("</m:mstyle></m:math></dd></dl>");
1195 // case MathSniffer.CSSID :
1196 // if (inlineExpression) {
1197 // fResultBuffer.append("<m>");
1198 // fTeXParser.initialize(mathContent);
1199 // fTeXParser.parse2CSS(fResultBuffer, true);
1200 // fResultBuffer.append("</m>");
1202 // fResultBuffer.append("<e>");
1203 // fTeXParser.initialize(mathContent);
1204 // fTeXParser.parse2CSS(fResultBuffer, true);
1205 // fResultBuffer.append("</e>");
1209 // copyWhite(mathContent);
1212 // String[] mathStrings = new String[3];
1213 // StringBuffer mathBuffer = new StringBuffer();
1214 // if (inlineExpression) {
1216 // mathBuffer.append("<m:math><m:mstyle mathcolor=\"Black\"
1217 // displaystyle=\"true\">");
1219 // fTeXParser.initialize(mathContent);
1220 // fTeXParser.parse2MML(mathBuffer);
1221 // mathBuffer.append("</m:mstyle></m:math>");
1223 // mathBuffer.append("<dl><dd><m:math><m:mstyle mathcolor=\"Black\"
1224 // displaystyle=\"true\">");
1225 // fTeXParser.initialize(mathContent);
1226 // fTeXParser.parse2MML(mathBuffer);
1227 // mathBuffer.append("</m:mstyle></m:math></dd></dl>");
1229 // mathStrings[0] = mathBuffer.toString();
1230 // mathBuffer.setLength(0);
1231 // // if (inlineExpression) {
1233 // // mathBuffer.append("<m>");
1234 // // fTeXParser.initialize(mathContent);
1235 // // fTeXParser.parse2CSS(mathBuffer, true);
1236 // // mathBuffer.append("</m>");
1238 // // // css block mode
1239 // // mathBuffer.append("<e>");
1240 // // fTeXParser.initialize(mathContent);
1241 // // fTeXParser.parse2CSS(mathBuffer, true);
1242 // // mathBuffer.append("</e>");
1245 // String encodedMathContent = Encoder.escape(mathContent);
1246 // StringBuffer mathmlBuffer = new StringBuffer();
1247 // String shortImageName = "____tex_" + (fImageCounter++);
1248 // String longImageName = shortImageName + ".gif";
1249 // mathmlBuffer.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
1250 // if (inlineExpression) {
1251 // mathmlBuffer.append("<math><mstyle mathcolor=\"Black\"
1252 // displaystyle=\"true\">");
1253 // fTeXImageParser.initialize(mathContent);
1254 // fTeXImageParser.parse2MML(mathmlBuffer);
1255 // mathmlBuffer.append("</mstyle></math>");
1257 // mathmlBuffer.append("<math><mstyle mathcolor=\"Black\"
1258 // displaystyle=\"true\">");
1259 // fTeXImageParser.initialize(mathContent);
1260 // fTeXImageParser.parse2MML(mathmlBuffer);
1261 // mathmlBuffer.append("</mstyle></math>");
1264 // String snipname = fSnip.getName();
1265 // String SnipSnapSpacePath =
1266 // Application.get().getConfiguration().getFilePath().getAbsolutePath();
1267 // // Remove old image
1268 // fSnip.getAttachments().removeAttachment(longImageName + ".gif");
1270 // String directoryName = SnipSnapSpacePath + "/" + snipname;
1271 // File directory = new File(directoryName);
1272 // if (!directory.exists()) {
1273 // directory.mkdirs();
1275 // String gifFilename = directoryName + "/" + longImageName;
1276 // // File file = new File();
1277 // // Get the number of bytes in the file
1278 // // long length = file.length();
1279 // MathMLToGIFConverter conv = new MathMLToGIFConverter();
1281 // // "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><math
1283 // mode=\"display\"><mrow><munderover><mo>∫</mo><mn>1</mn><mi>x</mi></munderover><mfrac><mi>dt</mi><mi>t</mi></mfrac></mrow></math>";
1285 // File imageFile = conv.convert(mathmlBuffer.toString(), gifFilename);
1286 // if (imageFile != null) {
1287 // Attachment attachment =
1288 // new Attachment(longImageName, "image/gif", imageFile.length(), new
1289 // Date(), snipname + "/" + longImageName, true);
1290 // // fSnip.getAttachments().addAttachment(longImageName, "image/gif",
1291 // imageFile.length(), snipname + "/" + longImageName,
1293 // fSnip.getAttachments().addAttachment(attachment);
1294 // StringWriter writer = new StringWriter();
1296 // SnipLink.appendImage(writer, fSnip, shortImageName, encodedMathContent,
1299 // mathBuffer = writer.getBuffer();
1300 // mathStrings[1] = mathBuffer.toString();
1302 // mathStrings[1] = encodedMathContent;
1304 // } catch (IOException e) {
1305 // // TODO Auto-generated catch block
1306 // e.printStackTrace();
1307 // mathStrings[1] = encodedMathContent;
1309 // mathBuffer.setLength(0);
1310 // WikipediaFilter.copyWhite(mathBuffer, mathContent);
1311 // mathStrings[2] = mathBuffer.toString();
1312 // fCachedPage.addMath(mathStrings);
1314 // if (!fCacheStaticBlockActive) {
1315 // fCacheStaticBlockActive = true;
1316 // fCacheStaticBlockStartPosition = fResultBuffer.length();
1319 private void handleSnipLink(String name) {
1321 int index = name.indexOf("http://");
1322 // Configuration probably wrote [http://radeox.org] instead of
1323 // http://radeox.org
1325 // WikipediaFilter.createExternalLink(fResultBuffer,
1326 // fWikiEngine, name.substring(index));
1327 String urlString = name.substring(index);
1328 // Wikipedia like style:
1329 int pipeIndex = urlString.indexOf(' ');
1331 if (pipeIndex != (-1)) {
1332 alias = urlString.substring(pipeIndex + 1);
1333 urlString = urlString.substring(0, pipeIndex);
1338 if (fWikiEngine instanceof ImageRenderEngine) {
1339 fResultBuffer.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
1341 fResultBuffer.append("<span class=\"nobr\">");
1342 fResultBuffer.append("<a href=\"");
1343 fResultBuffer.append(Encoder.escape(urlString));
1344 fResultBuffer.append("\">");
1345 fResultBuffer.append(Encoder.toEntity(alias.charAt(0)) + alias.substring(1));
1346 fResultBuffer.append("</a></span>");
1349 // // trim the name and unescape it
1350 // name = Encoder.unescape(name.trim());
1351 // // Is there an alias like [alias|link] ?
1352 // int pipeIndex = name.indexOf('|');
1353 // String alias = "";
1354 // if (-1 != pipeIndex) {
1355 // alias = name.substring(0, pipeIndex);
1356 // name = name.substring(pipeIndex + 1);
1359 // int hashIndex = name.lastIndexOf('#');
1361 // String hash = "";
1362 // if (-1 != hashIndex && hashIndex != name.length() - 1) {
1363 // hash = name.substring(hashIndex + 1);
1364 // name = name.substring(0, hashIndex);
1367 // int colonIndex = name.indexOf(':');
1369 // if (-1 != colonIndex) {
1370 // // for now throw away the fType information
1371 // name = name.substring(colonIndex + 1);
1374 // int atIndex = name.lastIndexOf('@');
1375 // // InterWiki link ?
1376 // if (-1 != atIndex) {
1377 // String extSpace = name.substring(atIndex + 1);
1378 // // known extarnal space ?
1379 // InterWiki interWiki = InterWiki.getInstance();
1380 // if (interWiki.contains(extSpace)) {
1381 // name = name.substring(0, atIndex);
1382 // Writer writer = new StringBufferWriter(fResultBuffer);
1384 // if (-1 != hashIndex) {
1385 // interWiki.expand(writer, extSpace, name, hash);
1387 // interWiki.expand(writer, extSpace, name, "");
1389 // } catch (IOException e) {
1390 // log.debug("InterWiki " + extSpace + " not found.");
1393 // fResultBuffer.append("[<span class=\"error\">");
1394 // fResultBuffer.append(name);
1395 // fResultBuffer.append("?</span>]");
1399 // if (fWikiEngine != null && fWikiEngine instanceof WikiRenderEngine) {
1400 // if (fCacheStaticBlockActive) {
1401 // fCachedPage.addHTML(fResultBuffer.substring(fCacheStaticBlockStartPosition, fResultBuffer.length()));
1402 // fCacheStaticBlockActive = false;
1404 // fCachedPage.addSnipLink(name);
1405 // if (fCachedPage == WikipediaFilter.DUMMY_CACHED_PAGE) {
1406 // if (((WikiRenderEngine) fWikiEngine).exists(name)) {
1407 // String view = name;
1408 // if (-1 != pipeIndex) {
1411 // // Do not add hash if an alias was given
1412 // if (-1 != hashIndex) {
1413 // ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view, hash);
1415 // ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view);
1417 // } else if (((WikiRenderEngine) fWikiEngine).showCreate()) {
1418 // ((WikiRenderEngine) fWikiEngine).appendCreateLink(fResultBuffer, name, name);
1419 // // links with "create" are not cacheable because
1420 // // a missing wiki could be created
1421 // fContext.getRenderContext().setCacheable(false);
1423 // // cannot display/create wiki, so just display
1425 // fResultBuffer.append(name);
1428 // if (!fCacheStaticBlockActive) {
1429 // fCacheStaticBlockActive = true;
1430 // fCacheStaticBlockStartPosition = fResultBuffer.length();
1433 // // cannot display/create wiki, so just display the text
1434 // fResultBuffer.append(name);
1441 private boolean handleWikipediaTable() {
1453 int temp = fCurrentPosition;
1454 int sequenceStart = 0;
1455 char lastChar = ' ';
1456 int sequenceLength = 0;
1457 int thStartPosition = 0;
1458 Stack wpTokenStack = new Stack();
1460 // add table attributes:
1461 fResultBuffer.append("<table ");
1462 sequenceStart = fCurrentPosition;
1463 fCurrentCharacter = fSource[fCurrentPosition++];
1464 while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
1466 fCurrentCharacter = fSource[fCurrentPosition++];
1468 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
1469 fCurrentCharacter = fSource[fCurrentPosition++];
1471 if (sequenceLength > 0) {
1472 fResultBuffer.append(fSource, sequenceStart + 1, sequenceLength - 1);
1474 fResultBuffer.append(">");
1475 wpTokenStack.push(WikipediaFilter.HTML_TABLE_OPEN);
1477 fResultBuffer.append("<tr>\n");
1478 wpTokenStack.push(WikipediaFilter.HTML_TR_OPEN);
1479 String attributes = null;
1480 // parse rest of table
1482 sequenceStart = fCurrentPosition;
1483 fCurrentCharacter = fSource[fCurrentPosition++];
1484 if (fCurrentCharacter == '{' && fSource[fCurrentPosition] == '|') { // nested table
1485 handleWikipediaTable();
1486 } else if (fCurrentCharacter == '!') {
1488 reduceTableCellStack(fResultBuffer, wpTokenStack);
1489 fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1490 sequenceStart = fCurrentPosition;
1491 // add header row cells
1494 fCurrentCharacter = fSource[fCurrentPosition++];
1495 if (fCurrentCharacter == '|' || fCurrentCharacter == '\n') {
1496 if (fSource[fCurrentPosition] == '|' || fCurrentCharacter == '\n') {
1497 reduceTableCellStack(fResultBuffer, wpTokenStack);
1498 if (attributes == null) {
1499 fResultBuffer.append("<th>");
1501 fResultBuffer.append("<th ");
1502 fResultBuffer.append(attributes);
1503 fResultBuffer.append(">");
1505 wpTokenStack.push(WikipediaFilter.HTML_TH_OPEN);
1506 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1507 - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1509 sequenceStart = fCurrentPosition;
1512 attributes = new String(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1513 sequenceStart = fCurrentPosition;
1516 if (fCurrentCharacter == '\n') {
1521 } else if (fCurrentCharacter == '|') {
1522 reduceTableCellStack(fResultBuffer, wpTokenStack);
1523 fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1525 sequenceStart = fCurrentPosition;
1526 fCurrentCharacter = fSource[fCurrentPosition++];
1527 switch (fCurrentCharacter) {
1528 case '+': // caption
1530 reduceTableRowStack(WikipediaFilter.HTML_TABLE_OPEN, fResultBuffer, wpTokenStack);
1531 fResultBuffer.append("<caption>\n");
1532 wpTokenStack.push(WikipediaFilter.HTML_CAPTION_OPEN);
1533 // read until end of line
1534 while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
1535 fCurrentCharacter = fSource[fCurrentPosition++];
1537 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
1538 fCurrentCharacter = fSource[fCurrentPosition++];
1540 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition - sequenceStart
1541 - 1), fContext, fMacros, fRecursionLevel));
1543 case '-': // new row
1545 reduceTableRowStack(WikipediaFilter.HTML_TR_OPEN, fResultBuffer, wpTokenStack);
1547 // read until end of line
1548 while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
1549 fCurrentCharacter = fSource[fCurrentPosition++];
1551 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
1552 fCurrentCharacter = fSource[fCurrentPosition++];
1554 // TODO handle row attributes
1555 fResultBuffer.append("<tr ");
1556 wpTokenStack.push(WikipediaFilter.HTML_TR_OPEN);
1557 fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1558 fResultBuffer.append(">\n");
1559 // fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1560 // - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1562 case '}': // end of table
1563 clearTableStack(fResultBuffer, wpTokenStack);
1564 // System.out.println(fResultBuffer.toString());
1570 fCurrentCharacter = fSource[fCurrentPosition++];
1571 if (fCurrentCharacter == '|' || fCurrentCharacter == '\n') {
1572 if (fSource[fCurrentPosition] == '|' || fCurrentCharacter == '\n') {
1573 reduceTableCellStack(fResultBuffer, wpTokenStack);
1574 if (attributes == null) {
1575 fResultBuffer.append("<td>");
1577 fResultBuffer.append("<td ");
1578 fResultBuffer.append(attributes);
1579 fResultBuffer.append(">");
1581 wpTokenStack.push(WikipediaFilter.HTML_TD_OPEN);
1582 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1583 - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1584 // TODO reduce fTokenStack to <tr> element
1586 // fResultBuffer.append("</td>");
1587 // fTokenStack.pop();
1589 sequenceStart = fCurrentPosition;
1592 attributes = new String(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1594 sequenceStart = fCurrentPosition;
1597 if (fCurrentCharacter == '\n') {
1603 } else if (wpTokenStack.peek() == WikipediaFilter.HTML_TD_OPEN) {
1604 // continue a table cell in the next line
1606 if (fCurrentCharacter == '\n') {
1607 char ch0 = fSource[fCurrentPosition];
1608 char ch1 = fSource[fCurrentPosition + 1];
1609 if (ch0 == '|' || ch0 == '!' || (ch0 == '{' && ch1 == '|')) {
1610 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1611 - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1612 sequenceStart = fCurrentPosition;
1617 fCurrentCharacter = fSource[fCurrentPosition++];
1621 } catch (IndexOutOfBoundsException e) {
1622 if (sequenceStart + 1 < fCurrentPosition && fSource[sequenceStart + 1] == '}') {
1623 // TODO reduce fTokenStack to <tr> element if necessary
1624 // fResultBuffer.append("</tr></table>\n");
1625 // wpTokenStack.pop(); // tr
1626 // wpTokenStack.pop();// table
1627 // System.out.println(fResultBuffer.toString());
1628 clearTableStack(fResultBuffer, wpTokenStack);
1632 fCurrentPosition = temp - 1;
1633 // System.out.print(fResultBuffer.toString());
1635 } // private boolean handleWikipediaTable() {
1637 private void clearTableStack(StringBuffer buffer, Stack stack) {
1638 CloseTagToken closeTag;
1640 while (!stack.isEmpty()) {
1641 tag = (AbstractTag) stack.pop();
1642 closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
1643 buffer.append(closeTag.getCloseTag());
1647 private void reduceTableRowStack(AbstractTag stopTag, StringBuffer buffer, Stack stack) {
1648 CloseTagToken closeTag;
1650 while (!stack.isEmpty()) {
1651 tag = (AbstractTag) stack.peek();
1652 if (tag == WikipediaFilter.HTML_TABLE_OPEN) {
1656 closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
1657 buffer.append(closeTag.getCloseTag());
1658 if (tag == WikipediaFilter.HTML_TR_OPEN || tag == WikipediaFilter.HTML_CAPTION_OPEN) {
1664 private void reduceTableCellStack(StringBuffer buffer, Stack stack) {
1665 CloseTagToken closeTag;
1667 while (!stack.isEmpty()) {
1668 tag = (AbstractTag) stack.peek();
1669 if (tag != WikipediaFilter.HTML_TH_OPEN && tag != WikipediaFilter.HTML_TD_OPEN) {
1673 closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
1674 buffer.append(closeTag.getCloseTag());
1675 if (tag == WikipediaFilter.HTML_TR_OPEN || tag == WikipediaFilter.HTML_CAPTION_OPEN || tag == WikipediaFilter.HTML_TH_OPEN
1676 || tag == WikipediaFilter.HTML_TD_OPEN) {
1694 // int temp = fCurrentPosition;
1695 // // StringBuffer suffixBuffer = new StringBuffer();
1696 // Table table = new Table(fContext.getRenderContext());
1697 // // char currentChar = ' ';
1698 // char lastChar = ' ';
1699 // // int startPosition = 0;
1700 // // int currentPosition = 0;
1701 // StringBuffer buffer = new StringBuffer();
1702 // int thStartPosition = 0;
1704 // try { // read first line
1705 // fCurrentCharacter = fSource[fCurrentPosition++];
1706 // // TODO improve this for different table attributes
1707 // while (fCurrentCharacter != '\n' ) {
1708 // fCurrentCharacter = fSource[fCurrentPosition++];
1709 // // System.out.println(fCurrentCharacter);
1712 // lastChar = fCurrentCharacter;
1713 // fCurrentCharacter = fSource[fCurrentPosition++];
1716 // switch (fCurrentCharacter) {
1717 // // case '{' : // start of nested table ?
1718 // // if (getNextChar('|') && handleWikipediaTable()) { // Wikipedia table
1724 // if (lastChar == '\n') {
1725 // table.addCell(buffer.toString());
1726 // // System.out.println(buffer.toString());
1727 // buffer.setLength(0);
1728 // thStartPosition = fCurrentPosition;
1730 // lastChar = fCurrentCharacter;
1731 // fCurrentCharacter = fSource[fCurrentPosition++];
1732 // if (fCurrentCharacter == '|') {
1735 // if (fCurrentCharacter == '\n') {
1737 // fCurrentPosition = thStartPosition;
1742 // buffer.append(fCurrentCharacter);
1746 // if (lastChar == '\n') {
1747 // if (getNextChar('}')) { // Wikipedia table end reached
1748 // table.addCell(buffer.toString());
1749 // StringWriter writer = new StringWriter();
1751 // table.appendTo(writer);
1752 // fResultBuffer.append(writer.getBuffer());
1753 // } catch (IOException e1) {
1754 // // TODO Auto-generated catch block
1755 // e1.printStackTrace();
1759 // } else if (getNextChar('-')) {
1760 // table.addCell(buffer.toString());
1761 // buffer.setLength(0);
1764 // lastChar = fCurrentCharacter;
1765 // fCurrentCharacter = fSource[fCurrentPosition++];
1766 // if (fCurrentCharacter == '|' || fCurrentCharacter == '!') {
1772 // if (buffer.length()>0) {
1773 // table.addCell(buffer.toString());
1774 // buffer.setLength(0);
1777 // } else if (getNextChar('|')) {
1778 // table.addCell(buffer.toString());
1779 // // System.out.println(buffer.toString());
1780 // buffer.setLength(0);
1782 // buffer.append(fCurrentCharacter);
1786 // buffer.append(fCurrentCharacter);
1788 // lastChar = fCurrentCharacter;
1789 // fCurrentCharacter = fSource[fCurrentPosition++];
1792 // } catch (IndexOutOfBoundsException e) {
1795 // fCurrentPosition = temp - 1;
1798 private void handleWikipediaLink(String linkText, String suffix) {
1799 String name = linkText;
1801 int index = name.indexOf("http://");
1802 // Configuration probably wrote [http://radeox.org] instead of
1803 // http://radeox.org
1805 WikipediaFilter.createExternalLink(fResultBuffer, fWikiEngine, name.substring(index));
1807 // fResult.append("<div class=\"error\">Do not surround URLs
1808 // with [...].</div>");
1810 // trim the name and unescape it
1811 name = Encoder.unescape(name.trim());
1812 // Is there an alias like [alias|link] ?
1813 int pipeIndex = name.indexOf('|');
1815 if (-1 != pipeIndex) {
1816 alias = name.substring(pipeIndex + 1);
1817 name = name.substring(0, pipeIndex);
1820 int hashIndex = name.lastIndexOf('#');
1823 if (-1 != hashIndex && hashIndex != name.length() - 1) {
1824 hash = name.substring(hashIndex + 1);
1825 name = name.substring(0, hashIndex);
1828 // int colonIndex = name.indexOf(':');
1830 // if (-1 != colonIndex) {
1831 // // for now throw away the fType information
1832 // name = name.substring(colonIndex + 1);
1835 int atIndex = name.lastIndexOf('@');
1837 if (-1 != atIndex) {
1838 String extSpace = name.substring(atIndex + 1);
1839 // known extarnal space ?
1840 InterWiki interWiki = InterWiki.getInstance();
1841 if (interWiki.contains(extSpace)) {
1842 name = name.substring(0, atIndex);
1843 Writer writer = new StringBufferWriter(fResultBuffer);
1845 if (-1 != hashIndex) {
1846 interWiki.expand(writer, extSpace, name, hash);
1848 interWiki.expand(writer, extSpace, name, "");
1850 } catch (IOException e) {
1851 // log.debug("InterWiki " + extSpace + " not found.");
1854 fResultBuffer.append("[<span class=\"error\">");
1855 fResultBuffer.append(name);
1856 fResultBuffer.append("?</span>]");
1860 if (name.startsWith("Image:") && (fWikiEngine instanceof ImageRenderEngine)) {
1861 // server part of rendering images
1862 ImageRenderEngine imageEngine = (ImageRenderEngine) fWikiEngine;
1863 // fResultBuffer.append("<img src=\"space/1/2004-11-21/5/");
1864 fResultBuffer.append("<img src=\"");
1865 fResultBuffer.append(FilterUtil.createServerImage(null, name.substring(6), null));
1866 fResultBuffer.append("\">");
1867 } else if (fWikiEngine != null && fWikiEngine instanceof WikiRenderEngine) {
1868 if (((WikiRenderEngine) fWikiEngine).exists(name)) {
1869 String view = name + suffix;
1870 if (-1 != pipeIndex) {
1871 view = alias + suffix;
1873 if (name.startsWith("Image:")) {
1874 fResultBuffer.append("<img src=\"");
1876 fResultBuffer.append(FilterUtil.createHTMLLink(null, name, null));
1877 fResultBuffer.append("\">");
1879 // Do not add hash if an alias was given
1880 if (-1 != hashIndex) {
1881 ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view, hash);
1883 ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view);
1886 } else if (((WikiRenderEngine) fWikiEngine).showCreate()) {
1887 ((WikiRenderEngine) fWikiEngine).appendCreateLink(fResultBuffer, name, name + suffix);
1888 // links with "create" are not cacheable because
1889 // a missing wiki could be created
1890 fContext.getRenderContext().setCacheable(false);
1892 // cannot display/create wiki, so just display
1894 fResultBuffer.append(name);
1897 // cannot display/create wiki, so just display the text
1898 fResultBuffer.append(name);
1905 public String createAnchor(String head) {
1906 StringBuffer result = new StringBuffer(head.length() + 1);
1909 // reduce Anchorstring
1910 for (int i = 0; i < head.length(); i++) {
1911 ch = head.charAt(i);
1912 if ('a' <= ch && 'z' >= ch) {
1914 } else if ('A' <= ch && 'Z' >= ch) {
1916 } else if ('0' <= ch && '9' >= ch) {
1921 // result.append('_');
1923 // case '<' : // special html escape character
1924 // fResult.append(Encoder.toEntity('<'));
1926 // case '>' : // special html escape character
1927 // fResult.append(Encoder.toEntity('>'));
1929 // case '&' : // special html escape character
1930 // fResult.append(Encoder.toEntity('&'));
1932 // case '\'' : // special html escape character
1933 // fResult.append(Encoder.toEntity('\''));
1935 // case '\"' : // special html escape character
1936 // fResult.append(Encoder.toEntity('\"'));
1939 // result.append(ch);
1942 return result.toString();
1945 public static StringBuffer appendLink(StringBuffer buffer, String name, String view, String target) {
1946 return appendLinkWithRoot(buffer, null, name + "#" + target, view);
1950 * Create a link with a root and a special view. The name will not be url encoded!
1952 public static StringBuffer appendLinkWithRoot(StringBuffer buffer, String root, String name, String view) {
1953 buffer.append("<a href=\"");
1955 buffer.append(root);
1958 buffer.append(name);
1959 buffer.append("\">");
1960 buffer.append(Encoder.escape(view));
1961 buffer.append("</a>");
1966 * add an entry to the "table of content" TODO refactor this to a class
1973 private void addToTableOfContent(ArrayList toc, String head, String anchor, int headLevel) {
1975 if (level == headLevel) {
1976 String snipName = "";
1977 // if (fSnip != null) {
1978 // snipName = fSnip.getName();
1981 StringBuffer link = new StringBuffer(snipName.length() + 40 + head.length() + anchor.length());
1982 link.append("<li>");
1983 //TODO create link for table of content
1984 appendLink(link, snipName, head, anchor);
1985 link.append("</li>");
1986 toc.add(link.toString());
1988 if (toc.size() > 0) {
1989 if (toc.get(toc.size() - 1) instanceof ArrayList) {
1990 addToTableOfContent((ArrayList) toc.get(toc.size() - 1), head, anchor, --headLevel);
1994 ArrayList list = new ArrayList();
1996 addToTableOfContent(list, head, anchor, --headLevel);
2001 * handle head for table of content
2006 private void handleHead(String head, int headLevel) {
2008 String anchor = createAnchor(head.trim());
2010 if (fTableOfContent == null) {
2011 // create new table of content
2012 fTableOfContent = new ArrayList();
2013 // copy fResult and new initialization:
2015 fResultBufferHeader = fResultBuffer;
2016 fResultBuffer = new StringBuffer(fResultBuffer.capacity());
2018 addToTableOfContent(fTableOfContent, head, anchor, headLevel);
2020 fResultBuffer.append("<h");
2021 fResultBuffer.append(headLevel);
2022 fResultBuffer.append("><a name=\"");
2023 fResultBuffer.append(anchor);
2024 fResultBuffer.append("\">");
2025 fResultBuffer.append(head);
2026 fResultBuffer.append("</a></h");
2027 fResultBuffer.append(headLevel);
2028 fResultBuffer.append(">");
2029 // if (headLevel <= 2) {
2030 // fResultBuffer.append("<hr/>");
2035 private boolean getList(char listChar, String openTag, String closeTag) {
2036 int currentPosition = fCurrentPosition;
2037 int level = getNumberOfChar(listChar) + 1;
2038 if (getNextChar('.') && getNextChar(' ')) {
2039 int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 3 - level);
2040 if (tempPosition >= 0) {
2041 copyWhite(fWhiteStart, fWhiteStartPosition, 2 + level);
2042 fWhiteStart = false;
2043 AbstractTag tok = (AbstractTag) fTokenStack.peek();
2044 if (tok instanceof ListToken) {
2045 ListToken listToken = (ListToken) tok;
2046 int topLevel = listToken.getLevel();
2047 if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START) {
2048 if (level > topLevel) {
2049 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel + 1));
2050 fResultBuffer.append(openTag + "<li>");
2051 } else if (level < topLevel) {
2053 fResultBuffer.append("</li>" + closeTag + "</li><li>");
2055 fResultBuffer.append("</li><li>");
2058 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, level));
2059 fResultBuffer.append(openTag + "<li>");
2062 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, 1));
2063 fResultBuffer.append("\n" + openTag + "<li>");
2068 fCurrentPosition = currentPosition;
2073 * read until the string is found
2078 private final boolean readUntilString(String testedString) {
2079 int temp = fCurrentPosition;
2080 int index = fStringSource.indexOf(testedString, fCurrentPosition);
2081 if (index != (-1)) {
2082 fCurrentPosition = index + testedString.length();
2089 * read until character is found
2094 private final boolean readUntilChar(char testedChar) {
2095 int temp = fCurrentPosition;
2097 while ((fCurrentCharacter = fSource[fCurrentPosition++]) != testedChar) {
2100 } catch (IndexOutOfBoundsException e) {
2101 fCurrentPosition = temp;
2107 * read until character is found or end-of-line is reached
2110 * @return -1 - for IndexOutOfBoundsException; 0 - for LF found; 1 - for testedChar found
2112 private final int readUntilCharOrEOL(char testedChar) {
2113 int temp = fCurrentPosition;
2115 while ((fCurrentCharacter = fSource[fCurrentPosition++]) != testedChar) {
2116 // if (fCurrentCharacter == '\n') {
2121 } catch (IndexOutOfBoundsException e) {
2122 fCurrentPosition = temp;
2128 * read until character is found or end-of-line is reached
2131 * @return -1 - for IndexOutOfBoundsException; 0 - for LF found; 1 - for testedChar found
2133 private final boolean readUntilEOL() {
2134 int temp = fCurrentPosition;
2137 fCurrentCharacter = fSource[fCurrentPosition++];
2138 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
2142 } catch (IndexOutOfBoundsException e) {
2149 * Returns the view of the wiki name that is shown to the fUser. Overwrite to support other views for example transform
2150 * "WikiLinking" to "Wiki Linking". Does nothing by default.
2152 * @return view The view of the wiki name
2154 // protected String getWikiView(String name) {
2157 private void handleMacro(String completeMacroSubString, String command, String unsplittedMacroParameters, String group3) {
2158 if (command != null) {
2159 // {$peng} are variables not macros.
2160 if (!command.startsWith("$")) {
2161 MacroParameter mParams = fContext.getMacroParameter();
2163 if (group3 != null) {
2164 mParams.setContent(group3);
2165 mParams.setContentStart(0);
2166 mParams.setContentEnd(group3.length());
2168 if (unsplittedMacroParameters != null && unsplittedMacroParameters.length() > 1) {
2169 // mParams.setParams(parseParameters(unsplittedMacroParameters));
2170 mParams.setParams(unsplittedMacroParameters);
2172 mParams.setStart(0);
2173 mParams.setEnd(completeMacroSubString.length());
2175 // @DANGER: recursive calls may replace macros in included
2178 if (fMacros.containsKey(command)) {
2179 Macro macro = (Macro) fMacros.get(command);
2181 // recursively filter macros within macros
2182 if (null != mParams.getContent() && !(macro instanceof INoParserBodyFilterMacro)) {
2183 mParams.setContent(WikipediaFilter.filterParser(mParams.getContent(), fContext, fMacros, fRecursionLevel));
2185 StringBufferWriter writer = new StringBufferWriter(new StringBuffer(256));
2186 macro.execute(writer, mParams);
2187 StringBuffer buffer = writer.getBuffer();
2188 if (macro instanceof IRenderResultMacro) {
2189 fResultBuffer.append(WikipediaFilter.filterParser(buffer.toString(), fContext, fMacros, fRecursionLevel));
2191 fResultBuffer.append(buffer);
2194 } else if (command.startsWith("!")) {
2196 RenderEngine engine = fContext.getRenderContext().getRenderEngine();
2197 if (engine instanceof IncludeRenderEngine) {
2198 String include = ((IncludeRenderEngine) engine).include(command.substring(1));
2199 if (null != include) {
2200 // Filter paramFilter = new
2201 // ParamFilter(mParams);
2202 // included = paramFilter.filter(included,
2204 // fResult.append(include);
2206 fResultBuffer.append(WikipediaFilter.filterParser(include, fContext, fMacros, fRecursionLevel));
2209 fResultBuffer.append(command.substring(1) + " not found.");
2215 // fResult.append(group0);
2216 copyWhite(completeMacroSubString);
2219 } catch (IllegalArgumentException e) {
2221 fResultBuffer.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
2223 e.printStackTrace();
2225 } catch (Throwable e) {
2226 // log.warn("MacroFilter: unable to format macro: " + command, e);
2227 fResultBuffer.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
2228 e.printStackTrace();
2232 fResultBuffer.append("<");
2233 fResultBuffer.append(command.substring(1));
2234 fResultBuffer.append(">");
2237 // fResult.append(group0);
2238 copyWhite(completeMacroSubString);
2242 public void parse() {
2243 int token = WikipediaFilter.TokenSTART;
2244 fTokenStack.add(WikipediaFilter.START);
2245 // fListStack.add(START);
2247 while ((token = getNextToken()) != WikipediaFilter.TokenEOF) {
2249 case WikipediaFilter.TokenBOLD:
2250 if (fTokenStack.peek() == WikipediaFilter.BOLD) {
2252 fResultBuffer.append("</b>");
2254 fTokenStack.push(WikipediaFilter.BOLD);
2255 fResultBuffer.append("<b>");
2258 case WikipediaFilter.TokenITALIC:
2259 if (fTokenStack.peek() == WikipediaFilter.ITALIC) {
2261 fResultBuffer.append("</i>");
2263 fTokenStack.push(WikipediaFilter.ITALIC);
2264 fResultBuffer.append("<i>");
2267 case WikipediaFilter.TokenSTRONG:
2268 if (fTokenStack.peek() == WikipediaFilter.STRONG) {
2270 fResultBuffer.append("</strong>");
2272 fTokenStack.push(WikipediaFilter.STRONG);
2273 fResultBuffer.append("<strong>");
2276 case WikipediaFilter.TokenEM:
2277 if (fTokenStack.peek() == WikipediaFilter.EM) {
2279 fResultBuffer.append("</em>");
2281 fTokenStack.push(WikipediaFilter.EM);
2282 fResultBuffer.append("<em>");
2285 case WikipediaFilter.TokenSTRIKETHROUGH:
2286 if (fTokenStack.peek() == WikipediaFilter.STRIKETHROUGH) {
2288 fResultBuffer.append("</strike>");
2290 fTokenStack.push(WikipediaFilter.STRIKETHROUGH);
2291 fResultBuffer.append("<strike>");
2294 // case TokenLIST_UL_START :
2295 // if (fTokenStack.peek().equals(LIST_UL_START)) {
2296 // fResult.append("</li>\n<li>");
2298 // fTokenStack.push(LIST_UL_START);
2299 // fResult.append("\n<ul class=\"star\">\n<li>");
2302 // case TokenLIST_UL_END :
2303 // fTokenStack.pop();
2304 // fResult.append("</li>\n</ul>\n");
2306 // case TokenLIST_OL_START :
2307 // if (fTokenStack.peek().equals(LIST_OL_START)) {
2308 // fResult.append("</li>\n<li>");
2310 // fTokenStack.push(LIST_OL_START);
2311 // fResult.append("\n<ol>\n<li>");
2314 // case TokenLIST_OL_END :
2315 // fTokenStack.pop();
2316 // fResult.append("</li>\n</ol>\n");
2320 } catch (InvalidInputException e) {
2323 // clear rest of stack if necessary (case of error in syntax!?)
2325 while ((tok = (AbstractTag) fTokenStack.pop()) != WikipediaFilter.START) {
2326 if (tok instanceof OpenTagToken) {
2328 CloseTagToken closeToken = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tok.getTagName());
2329 if (closeToken == null) {
2330 // here is something wrong ???
2331 fResultBuffer.append("</" + (tok.getTagName()) + ">");
2333 fResultBuffer.append(closeToken.getCloseTag());
2335 } else if (tok == WikipediaFilter.BOLD) {
2336 fResultBuffer.append("</b>");
2337 } else if (tok == WikipediaFilter.ITALIC) {
2338 fResultBuffer.append("</i>");
2339 } else if (tok == WikipediaFilter.STRONG) {
2340 fResultBuffer.append("</strong>");
2341 } else if (tok == WikipediaFilter.EM) {
2342 fResultBuffer.append("</em>");
2343 } else if (tok == WikipediaFilter.STRIKETHROUGH) {
2344 fResultBuffer.append("</strike>");
2345 } else if (tok.equals(WikipediaFilter.LIST_UL_START)) {
2346 fResultBuffer.append("</li>\n</ul>\n");
2347 } else if (tok.equals(WikipediaFilter.LIST_OL_START)) {
2348 fResultBuffer.append("</li>\n</ol>\n");
2352 if (fResultBufferHeader != null) {
2353 int tocStart = fResultBufferHeader.length();
2354 if (isToC(fTableOfContent) > 3) {
2355 fResultBufferHeader.append("<table id=\"toc\" border=\"0\"><tr><th>Table of contents</th></tr><tr><td>");
2356 fResultBufferHeader.append("<ol>");
2357 createToC(fTableOfContent);
2358 fResultBufferHeader.append("</ol>");
2359 fResultBufferHeader.append("</td></tr></table><hr/>");
2362 fResultBufferHeader.append(fResultBuffer);
2363 fResultBuffer = fResultBufferHeader;
2364 fResultBufferHeader = null;
2365 fTableOfContent = null;
2370 * count the number of wiki headers in this document
2375 private int isToC(ArrayList toc) {
2377 if (toc.size() == 1 && (toc.get(0) instanceof ArrayList)) {
2378 return isToC((ArrayList) toc.get(0));
2381 for (int i = 0; i < toc.size(); i++) {
2382 if (toc.get(i) instanceof ArrayList) {
2383 result += isToC((ArrayList) toc.get(i));
2391 private void createToC(ArrayList toc) {
2392 if (toc.size() == 1 && (toc.get(0) instanceof ArrayList)) {
2393 createToC((ArrayList) toc.get(0));
2396 for (int i = 0; i < toc.size(); i++) {
2397 if (toc.get(i) instanceof ArrayList) {
2398 fResultBufferHeader.append("<ol>");
2399 createToC((ArrayList) toc.get(i));
2400 fResultBufferHeader.append("</ol>");
2402 fResultBufferHeader.append(toc.get(i));
2407 // public int readUntil(String testString) throws InvalidInputException {
2408 // startPosition = currentPosition;
2409 // int tempPosition;
2413 // currentCharacter = source[currentPosition++];
2414 // if (currentCharacter == testString.charAt(0)) {
2415 // tempPosition = currentPosition;
2417 // for (int i = 1; i < testString.length(); i++) {
2418 // currentCharacter = source[currentPosition++];
2419 // if (currentCharacter != testString.charAt(i)) {
2421 // currentPosition = tempPosition;
2426 // return TokenBODY;
2430 // } catch (IndexOutOfBoundsException e) {
2431 // // end of scanner text
2436 public int scanIdentifierOrKeyword(boolean isVariable) throws InvalidInputException {
2437 while (getNextCharAsWikiPluginIdentifierPart()) {
2440 return WikipediaFilter.TokenIdentifier;
2443 private final void setSource(char[] source) {
2444 //the source-buffer is set to sourceString
2445 if (source == null) {
2446 this.fSource = new char[0];
2448 this.fSource = source;
2450 // this.fEOFPosition = this.fSource.length;
2451 // fStartPosition = -1;
2454 private void unexpectedTag(String tag) {
2455 fResultBuffer.append("<div class=\"error\">Unexpected end for tag: <" + tag + "></div>");
2459 * @return Returns the context.
2461 public FilterContext getContext() {
2467 * The context to set.
2469 public void setContext(FilterContext context) {
2474 * @return Returns the wikiEngine.
2476 public RenderEngine getWikiEngine() {
2482 * The wikiEngine to set.
2484 public void setWikiEngine(RenderEngine wikiEngine) {
2485 fWikiEngine = wikiEngine;