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);
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 // SnipSnap / Radeox Macro Syntax
917 // if (readUntilChar('}')) {
918 // String macroStartTag;
920 // macroStartTag = new String(fSource, startMacroPosition, fCurrentPosition - startMacroPosition - 1);
921 // if (macroStartTag != null) {
922 // createMacro(startMacroPosition, macroStartTag);
929 int htmlStartPosition = fCurrentPosition;
931 switch (fStringSource.charAt(fCurrentPosition)) {
932 case '!': // <!-- html comment -->
933 String htmlCommentString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 3);
935 if (htmlCommentString.equals("<!--")) {
936 fCurrentPosition += 3;
937 if (readUntilString("-->")) {
938 String htmlCommentContent = new String(fSource, htmlStartPosition + 3, fCurrentPosition - htmlStartPosition - 6);
939 if (htmlCommentContent != null) {
940 copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - htmlStartPosition + 1);
942 // insert html comment for visual checks
945 * fResultBuffer.append(" <!--"); copyWhite(htmlCommentContent); fResultBuffer.append("--> ");
953 String nowikiString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 7);
955 if (nowikiString.equals("<nowiki>")) {
956 fCurrentPosition += 7;
957 if (readUntilString("</nowiki>")) {
958 String nowikiContent = new String(fSource, htmlStartPosition + 7, fCurrentPosition - htmlStartPosition - 16);
959 if (nowikiContent != null) {
960 copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - htmlStartPosition + 1);
962 copyNowikiNewLine(nowikiContent);
969 } catch (IndexOutOfBoundsException e) {
972 startOfIndent = false;
973 fCurrentPosition = htmlStartPosition;
974 // detect special html tags
975 int htmlToken = getHTMLToken();
976 if (htmlToken == WikipediaFilter.TokenIgnore) {
978 // } else if (htmlToken > TokenIgnore) {
981 fCurrentPosition = htmlStartPosition;
983 case '=': // wikipedia header ?
984 if (isStartOfLine()) {
985 int levelHeader = getNumberOfChar('=') + 1;
986 // int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - levelHeader);
987 // if (tempPosition >= 0) {
988 copyWhite(fWhiteStart, fWhiteStartPosition, levelHeader);
990 int startHeadPosition = fCurrentPosition;
991 // int initialOffset = levelHeader;
992 if (levelHeader > 6) {
996 if (readUntilString(WikipediaFilter.HEADER_STRINGS[levelHeader])) {
997 String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition - (1 + levelHeader));
999 handleHead(head, levelHeader);
1008 fWhiteStartPosition = fCurrentPosition - 1;
1011 startOfIndent = false;
1013 // -----------------end switch while try--------------------
1014 } catch (IndexOutOfBoundsException e) {
1015 // end of scanner text
1017 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
1019 return WikipediaFilter.TokenEOF;
1025 private boolean isStartOfLine() {
1026 boolean isListStart = false;
1027 if (fCurrentPosition >= 2) {
1028 char beforeChar = fSource[fCurrentPosition - 2];
1029 if (beforeChar == '\n' || beforeChar == '\r') {
1033 if (fCurrentPosition == 1) {
1044 private void appendList(char[] listChars) {
1046 int levelStar = listChars.length;
1047 copyWhite(fWhiteStart, fWhiteStartPosition, levelStar);
1048 fWhiteStart = false;
1049 AbstractTag tok = (AbstractTag) fTokenStack.peek();
1051 if (tok instanceof ListToken) {
1052 ListToken listToken = (ListToken) tok;
1053 topLevel = listToken.getLevel();
1055 if (levelStar > topLevel) {
1056 while (levelStar > topLevel) {
1057 if (listChars[topLevel] == '*') {
1058 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, ++topLevel));
1059 fResultBuffer.append("<ul><li>");
1061 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, ++topLevel));
1062 fResultBuffer.append("<ol><li>");
1065 } else if (levelStar < topLevel) {
1066 while (levelStar < topLevel) {
1067 tok = (AbstractTag) fTokenStack.peek();
1068 if (tok instanceof ListToken) {
1070 listToken = (ListToken) tok;
1071 if (listToken.getToken() == WikipediaFilter.TokenLIST_UL_START) {
1072 fResultBuffer.append("</li></ul></li><li>");
1074 fResultBuffer.append("</li></ol></li><li>");
1083 if (listToken.getToken() == WikipediaFilter.TokenLIST_UL_START && listChars[topLevel] == '#') {
1085 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel));
1086 fResultBuffer.append("</li></ul><ol><li>");
1087 } else if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START && listChars[topLevel] == '*') {
1089 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, topLevel));
1090 fResultBuffer.append("</li></ol><ul><li>");
1092 fResultBuffer.append("</li><li>");
1096 while (levelStar > topLevel) {
1097 if (listChars[topLevel] == '*') {
1098 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, ++topLevel));
1099 fResultBuffer.append("\n<ul><li>");
1101 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, ++topLevel));
1102 fResultBuffer.append("\n<ol><li>");
1108 private void createMacro(int startMacroPosition, String macroStartTag) {
1109 String command = "";
1112 String parameterString = null;
1113 String macroBodyString = "";
1116 if ((index0 = macroStartTag.indexOf(':')) >= 0) {
1117 command = macroStartTag.substring(0, index0);
1118 parameterString = macroStartTag.substring(index0 + 1, macroStartTag.length());
1120 command = macroStartTag;
1122 Macro macro = (Macro) fMacros.get(command);
1124 String completeMacroSubString;
1126 if ((macro != null) && (macro instanceof IBodyTagSupportMacro)) {
1127 endTag = '{' + command + '}';
1128 index0 = fStringSource.indexOf(endTag, fCurrentPosition);
1131 macroBodyString = fStringSource.substring(fCurrentPosition, index0);
1132 completeMacroSubString = new String(fSource, startMacroPosition - 1, index0 + endTag.length() - startMacroPosition + 1);
1133 fCurrentPosition = startMacroPosition + completeMacroSubString.length() - 1;
1135 completeMacroSubString = new String(fSource, startMacroPosition - 1, macroStartTag.length() + 2);
1138 completeMacroSubString = new String(fSource, startMacroPosition - 1, macroStartTag.length() + 2);
1141 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
1143 handleMacro(completeMacroSubString, command, parameterString, macroBodyString);
1146 // private void createExternalLink(String urlString) {
1148 // // Does our engine know images?
1149 // if (fWikiEngine instanceof ImageRenderEngine) {
1150 // fResult.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
1152 // fResult.append("<span class=\"nobr\">");
1153 // fResult.append("<a href=\"");
1154 // fResult.append(Encoder.escape(urlString));
1155 // fResult.append("\">");
1156 // fResult.append(Encoder.toEntity(urlString.charAt(0)) +
1157 // urlString.substring(1));
1158 // fResult.append("</a></span>");
1161 // private void handleTeXMath(String mathContent, boolean inlineExpression)
1163 // // TODO clean this up
1164 // Map map = Application.get().getParameters();
1165 // HttpServletRequest request = (HttpServletRequest) map.get("request");
1166 // MathSniffer sniffy = MathSniffer.getBrowserDetection(request);
1168 // if (fCacheStaticBlockActive) {
1169 // fCachedPage.addHTML(fResultBuffer.substring(fCacheStaticBlockStartPosition,
1170 // fResultBuffer.length()));
1171 // fCacheStaticBlockActive = false;
1173 // // if (inlineExpression) {
1174 // // fASMCompiler.compileMath(mathContent, "true");
1176 // // fASMCompiler.compileMath(mathContent, "false");
1178 // if (fCachedPage == WikipediaFilter.DUMMY_CACHED_PAGE) {
1179 // switch (sniffy.getBrowserId()) {
1180 // case MathSniffer.XMLID :
1181 // case MathSniffer.MATHPLAYERID :
1182 // if (inlineExpression) {
1183 // fResultBuffer.append("<m:math><m:mstyle mathcolor=\"Black\"
1184 // displaystyle=\"true\">");
1185 // fTeXParser.initialize(mathContent);
1186 // fTeXParser.parse2MML(fResultBuffer);
1187 // fResultBuffer.append("</m:mstyle></m:math>");
1189 // fResultBuffer.append("<dl><dd><m:math><m:mstyle mathcolor=\"Black\"
1190 // displaystyle=\"true\">");
1191 // fTeXParser.initialize(mathContent);
1192 // fTeXParser.parse2MML(fResultBuffer);
1193 // fResultBuffer.append("</m:mstyle></m:math></dd></dl>");
1196 // case MathSniffer.CSSID :
1197 // if (inlineExpression) {
1198 // fResultBuffer.append("<m>");
1199 // fTeXParser.initialize(mathContent);
1200 // fTeXParser.parse2CSS(fResultBuffer, true);
1201 // fResultBuffer.append("</m>");
1203 // fResultBuffer.append("<e>");
1204 // fTeXParser.initialize(mathContent);
1205 // fTeXParser.parse2CSS(fResultBuffer, true);
1206 // fResultBuffer.append("</e>");
1210 // copyWhite(mathContent);
1213 // String[] mathStrings = new String[3];
1214 // StringBuffer mathBuffer = new StringBuffer();
1215 // if (inlineExpression) {
1217 // mathBuffer.append("<m:math><m:mstyle mathcolor=\"Black\"
1218 // displaystyle=\"true\">");
1220 // fTeXParser.initialize(mathContent);
1221 // fTeXParser.parse2MML(mathBuffer);
1222 // mathBuffer.append("</m:mstyle></m:math>");
1224 // mathBuffer.append("<dl><dd><m:math><m:mstyle mathcolor=\"Black\"
1225 // displaystyle=\"true\">");
1226 // fTeXParser.initialize(mathContent);
1227 // fTeXParser.parse2MML(mathBuffer);
1228 // mathBuffer.append("</m:mstyle></m:math></dd></dl>");
1230 // mathStrings[0] = mathBuffer.toString();
1231 // mathBuffer.setLength(0);
1232 // // if (inlineExpression) {
1234 // // mathBuffer.append("<m>");
1235 // // fTeXParser.initialize(mathContent);
1236 // // fTeXParser.parse2CSS(mathBuffer, true);
1237 // // mathBuffer.append("</m>");
1239 // // // css block mode
1240 // // mathBuffer.append("<e>");
1241 // // fTeXParser.initialize(mathContent);
1242 // // fTeXParser.parse2CSS(mathBuffer, true);
1243 // // mathBuffer.append("</e>");
1246 // String encodedMathContent = Encoder.escape(mathContent);
1247 // StringBuffer mathmlBuffer = new StringBuffer();
1248 // String shortImageName = "____tex_" + (fImageCounter++);
1249 // String longImageName = shortImageName + ".gif";
1250 // mathmlBuffer.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
1251 // if (inlineExpression) {
1252 // mathmlBuffer.append("<math><mstyle mathcolor=\"Black\"
1253 // displaystyle=\"true\">");
1254 // fTeXImageParser.initialize(mathContent);
1255 // fTeXImageParser.parse2MML(mathmlBuffer);
1256 // mathmlBuffer.append("</mstyle></math>");
1258 // mathmlBuffer.append("<math><mstyle mathcolor=\"Black\"
1259 // displaystyle=\"true\">");
1260 // fTeXImageParser.initialize(mathContent);
1261 // fTeXImageParser.parse2MML(mathmlBuffer);
1262 // mathmlBuffer.append("</mstyle></math>");
1265 // String snipname = fSnip.getName();
1266 // String SnipSnapSpacePath =
1267 // Application.get().getConfiguration().getFilePath().getAbsolutePath();
1268 // // Remove old image
1269 // fSnip.getAttachments().removeAttachment(longImageName + ".gif");
1271 // String directoryName = SnipSnapSpacePath + "/" + snipname;
1272 // File directory = new File(directoryName);
1273 // if (!directory.exists()) {
1274 // directory.mkdirs();
1276 // String gifFilename = directoryName + "/" + longImageName;
1277 // // File file = new File();
1278 // // Get the number of bytes in the file
1279 // // long length = file.length();
1280 // MathMLToGIFConverter conv = new MathMLToGIFConverter();
1282 // // "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><math
1284 // mode=\"display\"><mrow><munderover><mo>∫</mo><mn>1</mn><mi>x</mi></munderover><mfrac><mi>dt</mi><mi>t</mi></mfrac></mrow></math>";
1286 // File imageFile = conv.convert(mathmlBuffer.toString(), gifFilename);
1287 // if (imageFile != null) {
1288 // Attachment attachment =
1289 // new Attachment(longImageName, "image/gif", imageFile.length(), new
1290 // Date(), snipname + "/" + longImageName, true);
1291 // // fSnip.getAttachments().addAttachment(longImageName, "image/gif",
1292 // imageFile.length(), snipname + "/" + longImageName,
1294 // fSnip.getAttachments().addAttachment(attachment);
1295 // StringWriter writer = new StringWriter();
1297 // SnipLink.appendImage(writer, fSnip, shortImageName, encodedMathContent,
1300 // mathBuffer = writer.getBuffer();
1301 // mathStrings[1] = mathBuffer.toString();
1303 // mathStrings[1] = encodedMathContent;
1305 // } catch (IOException e) {
1306 // // TODO Auto-generated catch block
1307 // e.printStackTrace();
1308 // mathStrings[1] = encodedMathContent;
1310 // mathBuffer.setLength(0);
1311 // WikipediaFilter.copyWhite(mathBuffer, mathContent);
1312 // mathStrings[2] = mathBuffer.toString();
1313 // fCachedPage.addMath(mathStrings);
1315 // if (!fCacheStaticBlockActive) {
1316 // fCacheStaticBlockActive = true;
1317 // fCacheStaticBlockStartPosition = fResultBuffer.length();
1320 private void handleSnipLink(String name) {
1322 int index = name.indexOf("http://");
1323 // Configuration probably wrote [http://radeox.org] instead of
1324 // http://radeox.org
1326 // WikipediaFilter.createExternalLink(fResultBuffer,
1327 // fWikiEngine, name.substring(index));
1328 String urlString = name.substring(index);
1329 // Wikipedia like style:
1330 int pipeIndex = urlString.indexOf(' ');
1332 if (pipeIndex != (-1)) {
1333 alias = urlString.substring(pipeIndex + 1);
1334 urlString = urlString.substring(0, pipeIndex);
1339 if (fWikiEngine instanceof ImageRenderEngine) {
1340 fResultBuffer.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
1342 fResultBuffer.append("<span class=\"nobr\">");
1343 fResultBuffer.append("<a href=\"");
1344 fResultBuffer.append(Encoder.escape(urlString));
1345 fResultBuffer.append("\">");
1346 fResultBuffer.append(Encoder.toEntity(alias.charAt(0)) + alias.substring(1));
1347 fResultBuffer.append("</a></span>");
1350 // // trim the name and unescape it
1351 // name = Encoder.unescape(name.trim());
1352 // // Is there an alias like [alias|link] ?
1353 // int pipeIndex = name.indexOf('|');
1354 // String alias = "";
1355 // if (-1 != pipeIndex) {
1356 // alias = name.substring(0, pipeIndex);
1357 // name = name.substring(pipeIndex + 1);
1360 // int hashIndex = name.lastIndexOf('#');
1362 // String hash = "";
1363 // if (-1 != hashIndex && hashIndex != name.length() - 1) {
1364 // hash = name.substring(hashIndex + 1);
1365 // name = name.substring(0, hashIndex);
1368 // int colonIndex = name.indexOf(':');
1370 // if (-1 != colonIndex) {
1371 // // for now throw away the fType information
1372 // name = name.substring(colonIndex + 1);
1375 // int atIndex = name.lastIndexOf('@');
1376 // // InterWiki link ?
1377 // if (-1 != atIndex) {
1378 // String extSpace = name.substring(atIndex + 1);
1379 // // known extarnal space ?
1380 // InterWiki interWiki = InterWiki.getInstance();
1381 // if (interWiki.contains(extSpace)) {
1382 // name = name.substring(0, atIndex);
1383 // Writer writer = new StringBufferWriter(fResultBuffer);
1385 // if (-1 != hashIndex) {
1386 // interWiki.expand(writer, extSpace, name, hash);
1388 // interWiki.expand(writer, extSpace, name, "");
1390 // } catch (IOException e) {
1391 // log.debug("InterWiki " + extSpace + " not found.");
1394 // fResultBuffer.append("[<span class=\"error\">");
1395 // fResultBuffer.append(name);
1396 // fResultBuffer.append("?</span>]");
1400 // if (fWikiEngine != null && fWikiEngine instanceof WikiRenderEngine) {
1401 // if (fCacheStaticBlockActive) {
1402 // fCachedPage.addHTML(fResultBuffer.substring(fCacheStaticBlockStartPosition, fResultBuffer.length()));
1403 // fCacheStaticBlockActive = false;
1405 // fCachedPage.addSnipLink(name);
1406 // if (fCachedPage == WikipediaFilter.DUMMY_CACHED_PAGE) {
1407 // if (((WikiRenderEngine) fWikiEngine).exists(name)) {
1408 // String view = name;
1409 // if (-1 != pipeIndex) {
1412 // // Do not add hash if an alias was given
1413 // if (-1 != hashIndex) {
1414 // ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view, hash);
1416 // ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view);
1418 // } else if (((WikiRenderEngine) fWikiEngine).showCreate()) {
1419 // ((WikiRenderEngine) fWikiEngine).appendCreateLink(fResultBuffer, name, name);
1420 // // links with "create" are not cacheable because
1421 // // a missing wiki could be created
1422 // fContext.getRenderContext().setCacheable(false);
1424 // // cannot display/create wiki, so just display
1426 // fResultBuffer.append(name);
1429 // if (!fCacheStaticBlockActive) {
1430 // fCacheStaticBlockActive = true;
1431 // fCacheStaticBlockStartPosition = fResultBuffer.length();
1434 // // cannot display/create wiki, so just display the text
1435 // fResultBuffer.append(name);
1442 private boolean handleWikipediaTable() {
1454 int temp = fCurrentPosition;
1455 int sequenceStart = 0;
1456 char lastChar = ' ';
1457 int sequenceLength = 0;
1458 int thStartPosition = 0;
1459 Stack wpTokenStack = new Stack();
1461 // add table attributes:
1462 fResultBuffer.append("<table ");
1463 sequenceStart = fCurrentPosition;
1464 fCurrentCharacter = fSource[fCurrentPosition++];
1465 while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
1467 fCurrentCharacter = fSource[fCurrentPosition++];
1469 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
1470 fCurrentCharacter = fSource[fCurrentPosition++];
1472 if (sequenceLength > 0) {
1473 fResultBuffer.append(fSource, sequenceStart + 1, sequenceLength - 1);
1475 fResultBuffer.append(">");
1476 wpTokenStack.push(WikipediaFilter.HTML_TABLE_OPEN);
1478 fResultBuffer.append("<tr>\n");
1479 wpTokenStack.push(WikipediaFilter.HTML_TR_OPEN);
1480 String attributes = null;
1481 // parse rest of table
1483 sequenceStart = fCurrentPosition;
1484 fCurrentCharacter = fSource[fCurrentPosition++];
1485 if (fCurrentCharacter == '{' && fSource[fCurrentPosition] == '|') { // nested table
1486 handleWikipediaTable();
1487 } else if (fCurrentCharacter == '!') {
1489 reduceTableCellStack(fResultBuffer, wpTokenStack);
1490 fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1491 sequenceStart = fCurrentPosition;
1492 // add header row cells
1495 fCurrentCharacter = fSource[fCurrentPosition++];
1496 if (fCurrentCharacter == '|' || fCurrentCharacter == '\n') {
1497 if (fSource[fCurrentPosition] == '|' || fCurrentCharacter == '\n') {
1498 reduceTableCellStack(fResultBuffer, wpTokenStack);
1499 if (attributes == null) {
1500 fResultBuffer.append("<th>");
1502 fResultBuffer.append("<th ");
1503 fResultBuffer.append(attributes);
1504 fResultBuffer.append(">");
1506 wpTokenStack.push(WikipediaFilter.HTML_TH_OPEN);
1507 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1508 - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1510 sequenceStart = fCurrentPosition;
1513 attributes = new String(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1514 sequenceStart = fCurrentPosition;
1517 if (fCurrentCharacter == '\n') {
1522 } else if (fCurrentCharacter == '|') {
1523 reduceTableCellStack(fResultBuffer, wpTokenStack);
1524 fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1526 sequenceStart = fCurrentPosition;
1527 fCurrentCharacter = fSource[fCurrentPosition++];
1528 switch (fCurrentCharacter) {
1529 case '+': // caption
1531 reduceTableRowStack(WikipediaFilter.HTML_TABLE_OPEN, fResultBuffer, wpTokenStack);
1532 fResultBuffer.append("<caption>\n");
1533 wpTokenStack.push(WikipediaFilter.HTML_CAPTION_OPEN);
1534 // read until end of line
1535 while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
1536 fCurrentCharacter = fSource[fCurrentPosition++];
1538 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
1539 fCurrentCharacter = fSource[fCurrentPosition++];
1541 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition - sequenceStart
1542 - 1), fContext, fMacros, fRecursionLevel));
1544 case '-': // new row
1546 reduceTableRowStack(WikipediaFilter.HTML_TR_OPEN, fResultBuffer, wpTokenStack);
1548 // read until end of line
1549 while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
1550 fCurrentCharacter = fSource[fCurrentPosition++];
1552 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
1553 fCurrentCharacter = fSource[fCurrentPosition++];
1555 // TODO handle row attributes
1556 fResultBuffer.append("<tr ");
1557 wpTokenStack.push(WikipediaFilter.HTML_TR_OPEN);
1558 fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1559 fResultBuffer.append(">\n");
1560 // fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1561 // - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1563 case '}': // end of table
1564 clearTableStack(fResultBuffer, wpTokenStack);
1565 // System.out.println(fResultBuffer.toString());
1571 fCurrentCharacter = fSource[fCurrentPosition++];
1572 if (fCurrentCharacter == '|' || fCurrentCharacter == '\n') {
1573 if (fSource[fCurrentPosition] == '|' || fCurrentCharacter == '\n') {
1574 reduceTableCellStack(fResultBuffer, wpTokenStack);
1575 if (attributes == null) {
1576 fResultBuffer.append("<td>");
1578 fResultBuffer.append("<td ");
1579 fResultBuffer.append(attributes);
1580 fResultBuffer.append(">");
1582 wpTokenStack.push(WikipediaFilter.HTML_TD_OPEN);
1583 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1584 - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1585 // TODO reduce fTokenStack to <tr> element
1587 // fResultBuffer.append("</td>");
1588 // fTokenStack.pop();
1590 sequenceStart = fCurrentPosition;
1593 attributes = new String(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1595 sequenceStart = fCurrentPosition;
1598 if (fCurrentCharacter == '\n') {
1604 } else if (wpTokenStack.peek() == WikipediaFilter.HTML_TD_OPEN) {
1605 // continue a table cell in the next line
1607 if (fCurrentCharacter == '\n') {
1608 char ch0 = fSource[fCurrentPosition];
1609 char ch1 = fSource[fCurrentPosition + 1];
1610 if (ch0 == '|' || ch0 == '!' || (ch0 == '{' && ch1 == '|')) {
1611 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1612 - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1613 sequenceStart = fCurrentPosition;
1618 fCurrentCharacter = fSource[fCurrentPosition++];
1622 } catch (IndexOutOfBoundsException e) {
1623 if (sequenceStart + 1 < fCurrentPosition && fSource[sequenceStart + 1] == '}') {
1624 // TODO reduce fTokenStack to <tr> element if necessary
1625 // fResultBuffer.append("</tr></table>\n");
1626 // wpTokenStack.pop(); // tr
1627 // wpTokenStack.pop();// table
1628 // System.out.println(fResultBuffer.toString());
1629 clearTableStack(fResultBuffer, wpTokenStack);
1633 fCurrentPosition = temp - 1;
1634 // System.out.print(fResultBuffer.toString());
1636 } // private boolean handleWikipediaTable() {
1638 private void clearTableStack(StringBuffer buffer, Stack stack) {
1639 CloseTagToken closeTag;
1641 while (!stack.isEmpty()) {
1642 tag = (AbstractTag) stack.pop();
1643 closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
1644 buffer.append(closeTag.getCloseTag());
1648 private void reduceTableRowStack(AbstractTag stopTag, StringBuffer buffer, Stack stack) {
1649 CloseTagToken closeTag;
1651 while (!stack.isEmpty()) {
1652 tag = (AbstractTag) stack.peek();
1653 if (tag == WikipediaFilter.HTML_TABLE_OPEN) {
1657 closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
1658 buffer.append(closeTag.getCloseTag());
1659 if (tag == WikipediaFilter.HTML_TR_OPEN || tag == WikipediaFilter.HTML_CAPTION_OPEN) {
1665 private void reduceTableCellStack(StringBuffer buffer, Stack stack) {
1666 CloseTagToken closeTag;
1668 while (!stack.isEmpty()) {
1669 tag = (AbstractTag) stack.peek();
1670 if (tag != WikipediaFilter.HTML_TH_OPEN && tag != WikipediaFilter.HTML_TD_OPEN) {
1674 closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
1675 buffer.append(closeTag.getCloseTag());
1676 if (tag == WikipediaFilter.HTML_TR_OPEN || tag == WikipediaFilter.HTML_CAPTION_OPEN || tag == WikipediaFilter.HTML_TH_OPEN
1677 || tag == WikipediaFilter.HTML_TD_OPEN) {
1695 // int temp = fCurrentPosition;
1696 // // StringBuffer suffixBuffer = new StringBuffer();
1697 // Table table = new Table(fContext.getRenderContext());
1698 // // char currentChar = ' ';
1699 // char lastChar = ' ';
1700 // // int startPosition = 0;
1701 // // int currentPosition = 0;
1702 // StringBuffer buffer = new StringBuffer();
1703 // int thStartPosition = 0;
1705 // try { // read first line
1706 // fCurrentCharacter = fSource[fCurrentPosition++];
1707 // // TODO improve this for different table attributes
1708 // while (fCurrentCharacter != '\n' ) {
1709 // fCurrentCharacter = fSource[fCurrentPosition++];
1710 // // System.out.println(fCurrentCharacter);
1713 // lastChar = fCurrentCharacter;
1714 // fCurrentCharacter = fSource[fCurrentPosition++];
1717 // switch (fCurrentCharacter) {
1718 // // case '{' : // start of nested table ?
1719 // // if (getNextChar('|') && handleWikipediaTable()) { // Wikipedia table
1725 // if (lastChar == '\n') {
1726 // table.addCell(buffer.toString());
1727 // // System.out.println(buffer.toString());
1728 // buffer.setLength(0);
1729 // thStartPosition = fCurrentPosition;
1731 // lastChar = fCurrentCharacter;
1732 // fCurrentCharacter = fSource[fCurrentPosition++];
1733 // if (fCurrentCharacter == '|') {
1736 // if (fCurrentCharacter == '\n') {
1738 // fCurrentPosition = thStartPosition;
1743 // buffer.append(fCurrentCharacter);
1747 // if (lastChar == '\n') {
1748 // if (getNextChar('}')) { // Wikipedia table end reached
1749 // table.addCell(buffer.toString());
1750 // StringWriter writer = new StringWriter();
1752 // table.appendTo(writer);
1753 // fResultBuffer.append(writer.getBuffer());
1754 // } catch (IOException e1) {
1755 // // TODO Auto-generated catch block
1756 // e1.printStackTrace();
1760 // } else if (getNextChar('-')) {
1761 // table.addCell(buffer.toString());
1762 // buffer.setLength(0);
1765 // lastChar = fCurrentCharacter;
1766 // fCurrentCharacter = fSource[fCurrentPosition++];
1767 // if (fCurrentCharacter == '|' || fCurrentCharacter == '!') {
1773 // if (buffer.length()>0) {
1774 // table.addCell(buffer.toString());
1775 // buffer.setLength(0);
1778 // } else if (getNextChar('|')) {
1779 // table.addCell(buffer.toString());
1780 // // System.out.println(buffer.toString());
1781 // buffer.setLength(0);
1783 // buffer.append(fCurrentCharacter);
1787 // buffer.append(fCurrentCharacter);
1789 // lastChar = fCurrentCharacter;
1790 // fCurrentCharacter = fSource[fCurrentPosition++];
1793 // } catch (IndexOutOfBoundsException e) {
1796 // fCurrentPosition = temp - 1;
1799 private void handleWikipediaLink(String linkText, String suffix) {
1800 String name = linkText;
1802 int index = name.indexOf("http://");
1803 // Configuration probably wrote [http://radeox.org] instead of
1804 // http://radeox.org
1806 WikipediaFilter.createExternalLink(fResultBuffer, fWikiEngine, name.substring(index));
1808 // fResult.append("<div class=\"error\">Do not surround URLs
1809 // with [...].</div>");
1811 // trim the name and unescape it
1812 name = Encoder.unescape(name.trim());
1813 // Is there an alias like [alias|link] ?
1814 int pipeIndex = name.indexOf('|');
1816 if (-1 != pipeIndex) {
1817 alias = name.substring(pipeIndex + 1);
1818 name = name.substring(0, pipeIndex);
1821 int hashIndex = name.lastIndexOf('#');
1824 if (-1 != hashIndex && hashIndex != name.length() - 1) {
1825 hash = name.substring(hashIndex + 1);
1826 name = name.substring(0, hashIndex);
1829 // int colonIndex = name.indexOf(':');
1831 // if (-1 != colonIndex) {
1832 // // for now throw away the fType information
1833 // name = name.substring(colonIndex + 1);
1836 int atIndex = name.lastIndexOf('@');
1838 if (-1 != atIndex) {
1839 String extSpace = name.substring(atIndex + 1);
1840 // known extarnal space ?
1841 InterWiki interWiki = InterWiki.getInstance();
1842 if (interWiki.contains(extSpace)) {
1843 name = name.substring(0, atIndex);
1844 Writer writer = new StringBufferWriter(fResultBuffer);
1846 if (-1 != hashIndex) {
1847 interWiki.expand(writer, extSpace, name, hash);
1849 interWiki.expand(writer, extSpace, name, "");
1851 } catch (IOException e) {
1852 // log.debug("InterWiki " + extSpace + " not found.");
1855 fResultBuffer.append("[<span class=\"error\">");
1856 fResultBuffer.append(name);
1857 fResultBuffer.append("?</span>]");
1861 if (name.startsWith("Image:") && (fWikiEngine instanceof ImageRenderEngine)) {
1862 // server part of rendering images
1863 ImageRenderEngine imageEngine = (ImageRenderEngine) fWikiEngine;
1864 // fResultBuffer.append("<img src=\"space/1/2004-11-21/5/");
1865 fResultBuffer.append("<img src=\"");
1866 fResultBuffer.append(FilterUtil.createServerImage(null, name.substring(6), null));
1867 fResultBuffer.append("\">");
1868 } else if (fWikiEngine != null && fWikiEngine instanceof WikiRenderEngine) {
1869 if (((WikiRenderEngine) fWikiEngine).exists(name)) {
1870 String view = name + suffix;
1871 if (-1 != pipeIndex) {
1872 view = alias + suffix;
1874 if (name.startsWith("Image:")) {
1875 fResultBuffer.append("<img src=\"");
1877 fResultBuffer.append(FilterUtil.createHTMLLink(null, name, null));
1878 fResultBuffer.append("\">");
1880 // Do not add hash if an alias was given
1881 if (-1 != hashIndex) {
1882 ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view, hash);
1884 ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view);
1887 } else if (((WikiRenderEngine) fWikiEngine).showCreate()) {
1888 ((WikiRenderEngine) fWikiEngine).appendCreateLink(fResultBuffer, name, name + suffix);
1889 // links with "create" are not cacheable because
1890 // a missing wiki could be created
1891 fContext.getRenderContext().setCacheable(false);
1893 // cannot display/create wiki, so just display
1895 fResultBuffer.append(name);
1898 // cannot display/create wiki, so just display the text
1899 fResultBuffer.append(name);
1906 public String createAnchor(String head) {
1907 StringBuffer result = new StringBuffer(head.length() + 1);
1910 // reduce Anchorstring
1911 for (int i = 0; i < head.length(); i++) {
1912 ch = head.charAt(i);
1913 if ('a' <= ch && 'z' >= ch) {
1915 } else if ('A' <= ch && 'Z' >= ch) {
1917 } else if ('0' <= ch && '9' >= ch) {
1922 // result.append('_');
1924 // case '<' : // special html escape character
1925 // fResult.append(Encoder.toEntity('<'));
1927 // case '>' : // special html escape character
1928 // fResult.append(Encoder.toEntity('>'));
1930 // case '&' : // special html escape character
1931 // fResult.append(Encoder.toEntity('&'));
1933 // case '\'' : // special html escape character
1934 // fResult.append(Encoder.toEntity('\''));
1936 // case '\"' : // special html escape character
1937 // fResult.append(Encoder.toEntity('\"'));
1940 // result.append(ch);
1943 return result.toString();
1946 public static StringBuffer appendLink(StringBuffer buffer, String name, String view, String target) {
1947 return appendLinkWithRoot(buffer, null, name + "#" + target, view);
1951 * Create a link with a root and a special view. The name will not be url encoded!
1953 public static StringBuffer appendLinkWithRoot(StringBuffer buffer, String root, String name, String view) {
1954 buffer.append("<a href=\"");
1956 buffer.append(root);
1959 buffer.append(name);
1960 buffer.append("\">");
1961 buffer.append(Encoder.escape(view));
1962 buffer.append("</a>");
1967 * add an entry to the "table of content" TODO refactor this to a class
1974 private void addToTableOfContent(ArrayList toc, String head, String anchor, int headLevel) {
1976 if (level == headLevel) {
1977 String snipName = "";
1978 // if (fSnip != null) {
1979 // snipName = fSnip.getName();
1982 StringBuffer link = new StringBuffer(snipName.length() + 40 + head.length() + anchor.length());
1983 link.append("<li>");
1984 //TODO create link for table of content
1985 appendLink(link, snipName, head, anchor);
1986 link.append("</li>");
1987 toc.add(link.toString());
1989 if (toc.size() > 0) {
1990 if (toc.get(toc.size() - 1) instanceof ArrayList) {
1991 addToTableOfContent((ArrayList) toc.get(toc.size() - 1), head, anchor, --headLevel);
1995 ArrayList list = new ArrayList();
1997 addToTableOfContent(list, head, anchor, --headLevel);
2002 * handle head for table of content
2007 private void handleHead(String head, int headLevel) {
2009 String anchor = createAnchor(head.trim());
2011 if (fTableOfContent == null) {
2012 // create new table of content
2013 fTableOfContent = new ArrayList();
2014 // copy fResult and new initialization:
2016 fResultBufferHeader = fResultBuffer;
2017 fResultBuffer = new StringBuffer(fResultBuffer.capacity());
2019 addToTableOfContent(fTableOfContent, head, anchor, headLevel);
2021 fResultBuffer.append("<h");
2022 fResultBuffer.append(headLevel);
2023 fResultBuffer.append("><a name=\"");
2024 fResultBuffer.append(anchor);
2025 fResultBuffer.append("\">");
2026 fResultBuffer.append(head);
2027 fResultBuffer.append("</a></h");
2028 fResultBuffer.append(headLevel);
2029 fResultBuffer.append(">");
2030 // if (headLevel <= 2) {
2031 // fResultBuffer.append("<hr/>");
2036 private boolean getList(char listChar, String openTag, String closeTag) {
2037 int currentPosition = fCurrentPosition;
2038 int level = getNumberOfChar(listChar) + 1;
2039 if (getNextChar('.') && getNextChar(' ')) {
2040 int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 3 - level);
2041 if (tempPosition >= 0) {
2042 copyWhite(fWhiteStart, fWhiteStartPosition, 2 + level);
2043 fWhiteStart = false;
2044 AbstractTag tok = (AbstractTag) fTokenStack.peek();
2045 if (tok instanceof ListToken) {
2046 ListToken listToken = (ListToken) tok;
2047 int topLevel = listToken.getLevel();
2048 if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START) {
2049 if (level > topLevel) {
2050 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel + 1));
2051 fResultBuffer.append(openTag + "<li>");
2052 } else if (level < topLevel) {
2054 fResultBuffer.append("</li>" + closeTag + "</li><li>");
2056 fResultBuffer.append("</li><li>");
2059 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, level));
2060 fResultBuffer.append(openTag + "<li>");
2063 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, 1));
2064 fResultBuffer.append("\n" + openTag + "<li>");
2069 fCurrentPosition = currentPosition;
2074 * read until the string is found
2079 private final boolean readUntilString(String testedString) {
2080 int temp = fCurrentPosition;
2081 int index = fStringSource.indexOf(testedString, fCurrentPosition);
2082 if (index != (-1)) {
2083 fCurrentPosition = index + testedString.length();
2090 * read until character is found
2095 private final boolean readUntilChar(char testedChar) {
2096 int temp = fCurrentPosition;
2098 while ((fCurrentCharacter = fSource[fCurrentPosition++]) != testedChar) {
2101 } catch (IndexOutOfBoundsException e) {
2102 fCurrentPosition = temp;
2108 * read until character is found or end-of-line is reached
2111 * @return -1 - for IndexOutOfBoundsException; 0 - for LF found; 1 - for testedChar found
2113 private final int readUntilCharOrEOL(char testedChar) {
2114 int temp = fCurrentPosition;
2116 while ((fCurrentCharacter = fSource[fCurrentPosition++]) != testedChar) {
2117 // if (fCurrentCharacter == '\n') {
2122 } catch (IndexOutOfBoundsException e) {
2123 fCurrentPosition = temp;
2129 * read until character is found or end-of-line is reached
2132 * @return -1 - for IndexOutOfBoundsException; 0 - for LF found; 1 - for testedChar found
2134 private final boolean readUntilEOL() {
2135 int temp = fCurrentPosition;
2138 fCurrentCharacter = fSource[fCurrentPosition++];
2139 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
2143 } catch (IndexOutOfBoundsException e) {
2150 * Returns the view of the wiki name that is shown to the fUser. Overwrite to support other views for example transform
2151 * "WikiLinking" to "Wiki Linking". Does nothing by default.
2153 * @return view The view of the wiki name
2155 // protected String getWikiView(String name) {
2158 private void handleMacro(String completeMacroSubString, String command, String unsplittedMacroParameters, String group3) {
2159 if (command != null) {
2160 // {$peng} are variables not macros.
2161 if (!command.startsWith("$")) {
2162 MacroParameter mParams = fContext.getMacroParameter();
2164 if (group3 != null) {
2165 mParams.setContent(group3);
2166 mParams.setContentStart(0);
2167 mParams.setContentEnd(group3.length());
2169 if (unsplittedMacroParameters != null && unsplittedMacroParameters.length() > 1) {
2170 // mParams.setParams(parseParameters(unsplittedMacroParameters));
2171 mParams.setParams(unsplittedMacroParameters);
2173 mParams.setStart(0);
2174 mParams.setEnd(completeMacroSubString.length());
2176 // @DANGER: recursive calls may replace macros in included
2179 if (fMacros.containsKey(command)) {
2180 Macro macro = (Macro) fMacros.get(command);
2182 // recursively filter macros within macros
2183 if (null != mParams.getContent() && !(macro instanceof INoParserBodyFilterMacro)) {
2184 mParams.setContent(WikipediaFilter.filterParser(mParams.getContent(), fContext, fMacros, fRecursionLevel));
2186 StringBufferWriter writer = new StringBufferWriter(new StringBuffer(256));
2187 macro.execute(writer, mParams);
2188 StringBuffer buffer = writer.getBuffer();
2189 if (macro instanceof IRenderResultMacro) {
2190 fResultBuffer.append(WikipediaFilter.filterParser(buffer.toString(), fContext, fMacros, fRecursionLevel));
2192 fResultBuffer.append(buffer);
2195 } else if (command.startsWith("!")) {
2197 RenderEngine engine = fContext.getRenderContext().getRenderEngine();
2198 if (engine instanceof IncludeRenderEngine) {
2199 String include = ((IncludeRenderEngine) engine).include(command.substring(1));
2200 if (null != include) {
2201 // Filter paramFilter = new
2202 // ParamFilter(mParams);
2203 // included = paramFilter.filter(included,
2205 // fResult.append(include);
2207 fResultBuffer.append(WikipediaFilter.filterParser(include, fContext, fMacros, fRecursionLevel));
2210 fResultBuffer.append(command.substring(1) + " not found.");
2216 // fResult.append(group0);
2217 copyWhite(completeMacroSubString);
2220 } catch (IllegalArgumentException e) {
2222 fResultBuffer.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
2224 e.printStackTrace();
2226 } catch (Throwable e) {
2227 // log.warn("MacroFilter: unable to format macro: " + command, e);
2228 fResultBuffer.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
2229 e.printStackTrace();
2233 fResultBuffer.append("<");
2234 fResultBuffer.append(command.substring(1));
2235 fResultBuffer.append(">");
2238 // fResult.append(group0);
2239 copyWhite(completeMacroSubString);
2243 public void parse() {
2244 int token = WikipediaFilter.TokenSTART;
2245 fTokenStack.add(WikipediaFilter.START);
2246 // fListStack.add(START);
2248 while ((token = getNextToken()) != WikipediaFilter.TokenEOF) {
2250 case WikipediaFilter.TokenBOLD:
2251 if (fTokenStack.peek() == WikipediaFilter.BOLD) {
2253 fResultBuffer.append("</b>");
2255 fTokenStack.push(WikipediaFilter.BOLD);
2256 fResultBuffer.append("<b>");
2259 case WikipediaFilter.TokenITALIC:
2260 if (fTokenStack.peek() == WikipediaFilter.ITALIC) {
2262 fResultBuffer.append("</i>");
2264 fTokenStack.push(WikipediaFilter.ITALIC);
2265 fResultBuffer.append("<i>");
2268 case WikipediaFilter.TokenSTRONG:
2269 if (fTokenStack.peek() == WikipediaFilter.STRONG) {
2271 fResultBuffer.append("</strong>");
2273 fTokenStack.push(WikipediaFilter.STRONG);
2274 fResultBuffer.append("<strong>");
2277 case WikipediaFilter.TokenEM:
2278 if (fTokenStack.peek() == WikipediaFilter.EM) {
2280 fResultBuffer.append("</em>");
2282 fTokenStack.push(WikipediaFilter.EM);
2283 fResultBuffer.append("<em>");
2286 case WikipediaFilter.TokenSTRIKETHROUGH:
2287 if (fTokenStack.peek() == WikipediaFilter.STRIKETHROUGH) {
2289 fResultBuffer.append("</strike>");
2291 fTokenStack.push(WikipediaFilter.STRIKETHROUGH);
2292 fResultBuffer.append("<strike>");
2295 // case TokenLIST_UL_START :
2296 // if (fTokenStack.peek().equals(LIST_UL_START)) {
2297 // fResult.append("</li>\n<li>");
2299 // fTokenStack.push(LIST_UL_START);
2300 // fResult.append("\n<ul class=\"star\">\n<li>");
2303 // case TokenLIST_UL_END :
2304 // fTokenStack.pop();
2305 // fResult.append("</li>\n</ul>\n");
2307 // case TokenLIST_OL_START :
2308 // if (fTokenStack.peek().equals(LIST_OL_START)) {
2309 // fResult.append("</li>\n<li>");
2311 // fTokenStack.push(LIST_OL_START);
2312 // fResult.append("\n<ol>\n<li>");
2315 // case TokenLIST_OL_END :
2316 // fTokenStack.pop();
2317 // fResult.append("</li>\n</ol>\n");
2321 } catch (InvalidInputException e) {
2324 // clear rest of stack if necessary (case of error in syntax!?)
2326 while ((tok = (AbstractTag) fTokenStack.pop()) != WikipediaFilter.START) {
2327 if (tok instanceof OpenTagToken) {
2329 CloseTagToken closeToken = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tok.getTagName());
2330 if (closeToken == null) {
2331 // here is something wrong ???
2332 fResultBuffer.append("</" + (tok.getTagName()) + ">");
2334 fResultBuffer.append(closeToken.getCloseTag());
2336 } else if (tok == WikipediaFilter.BOLD) {
2337 fResultBuffer.append("</b>");
2338 } else if (tok == WikipediaFilter.ITALIC) {
2339 fResultBuffer.append("</i>");
2340 } else if (tok == WikipediaFilter.STRONG) {
2341 fResultBuffer.append("</strong>");
2342 } else if (tok == WikipediaFilter.EM) {
2343 fResultBuffer.append("</em>");
2344 } else if (tok == WikipediaFilter.STRIKETHROUGH) {
2345 fResultBuffer.append("</strike>");
2346 } else if (tok.equals(WikipediaFilter.LIST_UL_START)) {
2347 fResultBuffer.append("</li>\n</ul>\n");
2348 } else if (tok.equals(WikipediaFilter.LIST_OL_START)) {
2349 fResultBuffer.append("</li>\n</ol>\n");
2353 if (fResultBufferHeader != null) {
2354 int tocStart = fResultBufferHeader.length();
2355 if (isToC(fTableOfContent) > 3) {
2356 fResultBufferHeader.append("<table id=\"toc\" border=\"0\"><tr><th>Table of contents</th></tr><tr><td>");
2357 fResultBufferHeader.append("<ol>");
2358 createToC(fTableOfContent);
2359 fResultBufferHeader.append("</ol>");
2360 fResultBufferHeader.append("</td></tr></table><hr/>");
2363 fResultBufferHeader.append(fResultBuffer);
2364 fResultBuffer = fResultBufferHeader;
2365 fResultBufferHeader = null;
2366 fTableOfContent = null;
2371 * count the number of wiki headers in this document
2376 private int isToC(ArrayList toc) {
2378 if (toc.size() == 1 && (toc.get(0) instanceof ArrayList)) {
2379 return isToC((ArrayList) toc.get(0));
2382 for (int i = 0; i < toc.size(); i++) {
2383 if (toc.get(i) instanceof ArrayList) {
2384 result += isToC((ArrayList) toc.get(i));
2392 private void createToC(ArrayList toc) {
2393 if (toc.size() == 1 && (toc.get(0) instanceof ArrayList)) {
2394 createToC((ArrayList) toc.get(0));
2397 for (int i = 0; i < toc.size(); i++) {
2398 if (toc.get(i) instanceof ArrayList) {
2399 fResultBufferHeader.append("<ol>");
2400 createToC((ArrayList) toc.get(i));
2401 fResultBufferHeader.append("</ol>");
2403 fResultBufferHeader.append(toc.get(i));
2408 // public int readUntil(String testString) throws InvalidInputException {
2409 // startPosition = currentPosition;
2410 // int tempPosition;
2414 // currentCharacter = source[currentPosition++];
2415 // if (currentCharacter == testString.charAt(0)) {
2416 // tempPosition = currentPosition;
2418 // for (int i = 1; i < testString.length(); i++) {
2419 // currentCharacter = source[currentPosition++];
2420 // if (currentCharacter != testString.charAt(i)) {
2422 // currentPosition = tempPosition;
2427 // return TokenBODY;
2431 // } catch (IndexOutOfBoundsException e) {
2432 // // end of scanner text
2437 public int scanIdentifierOrKeyword(boolean isVariable) throws InvalidInputException {
2438 while (getNextCharAsWikiPluginIdentifierPart()) {
2441 return WikipediaFilter.TokenIdentifier;
2444 private final void setSource(char[] source) {
2445 //the source-buffer is set to sourceString
2446 if (source == null) {
2447 this.fSource = new char[0];
2449 this.fSource = source;
2451 // this.fEOFPosition = this.fSource.length;
2452 // fStartPosition = -1;
2455 private void unexpectedTag(String tag) {
2456 fResultBuffer.append("<div class=\"error\">Unexpected end for tag: <" + tag + "></div>");
2460 * @return Returns the context.
2462 public FilterContext getContext() {
2468 * The context to set.
2470 public void setContext(FilterContext context) {
2475 * @return Returns the wikiEngine.
2477 public RenderEngine getWikiEngine() {
2483 * The wikiEngine to set.
2485 public void setWikiEngine(RenderEngine wikiEngine) {
2486 fWikiEngine = wikiEngine;