1 package org.plog4u.wiki.filter;
3 import java.util.ArrayList;
4 import java.util.NoSuchElementException;
5 import java.util.Stack;
6 import java.util.StringTokenizer;
8 import org.plog4u.wiki.filter.WikipediaFilter.InvalidInputException;
9 import org.plog4u.wiki.filter.tags.AbstractTag;
10 import org.plog4u.wiki.filter.tags.CloseTagToken;
11 import org.plog4u.wiki.filter.tags.ListToken;
12 import org.plog4u.wiki.filter.tags.OpenTagToken;
13 import org.plog4u.wiki.filter.tags.SpecialTagToken;
14 import org.radeox.api.engine.ImageRenderEngine;
15 import org.radeox.api.engine.IncludeRenderEngine;
16 import org.radeox.api.engine.RenderEngine;
17 import org.radeox.api.engine.WikiRenderEngine;
18 import org.radeox.filter.context.FilterContext;
19 import org.radeox.macro.Macro;
20 import org.radeox.macro.MacroRepository;
21 import org.radeox.macro.parameter.MacroParameter;
22 import org.radeox.util.StringBufferWriter;
25 * A parser for the WikipediaFilter
27 * @see org.plog4u.wiki.filter.WikipediaFilter
29 public class WikipediaParser {
30 // private static Log log = LogFactory.getLog(WikipediaFilter.class);
32 MacroRepository fMacros;
34 private FilterContext fContext;
36 private RenderEngine fWikiEngine;
38 // TODO check, if this counter is correct in recursions:
39 private int fImageCounter;
44 // private Snip fSnip;
46 * If the snip contains headings for a "table of content" this buffer temporarily contains the start of the snip and the
47 * "table of content"
49 private StringBuffer fResultBufferHeader = null;
52 * The buffer for the resulting HTML rendering from the current snip.
54 private StringBuffer fResultBuffer;
57 * The wiki syntax string which should be parsed
59 private char[] fSource;
62 * The corresponding String for the character source array
64 private final String fStringSource;
67 * The current scanned character
69 private char fCurrentCharacter;
72 * The current offset in the character source array
74 private int fCurrentPosition;
77 * The current recursion level for this parser
79 private int fRecursionLevel;
81 private Stack fTokenStack;
83 // private Stack fTableStack;
85 private boolean fWhiteStart = false;
87 private int fWhiteStartPosition = 0;
89 // private TeXParser fTeXParser;
90 // private TeXParser fTeXImageParser;
93 * "table of content"
96 private ArrayList fTableOfContent = null;
98 // private String fSrcPath;
99 // private String fBinPath;
100 public WikipediaParser(MacroRepository macros, String stringSource, StringBuffer result, FilterContext context, int recursionLevel) {
102 fWikiEngine = context.getRenderContext().getRenderEngine();
105 // SnipMacroParameter params = (SnipMacroParameter)
106 // fContext.getMacroParameter();
107 // fSnip = params.getSnipRenderContext().getSnip();
108 // } catch (ClassCastException e) {
109 // e.printStackTrace();
112 fResultBuffer = result;
113 fStringSource = stringSource;
114 setSource(stringSource.toCharArray());
115 fRecursionLevel = recursionLevel;
116 fTokenStack = new Stack();
117 // fTableStack = new Stack();
118 // fTeXParser = new TeXParser("", "m:");
119 // fTeXImageParser = new TeXParser("", "");
122 // fSrcPath = (String) fContext.getRenderContext().get("srcpath");
123 // if (fSrcPath==null) {
126 // fBinPath = (String) fContext.getRenderContext().get("binpath");
127 // if (fBinPath==null) {
133 * Check until a new-line was found, if there are only whitespace characters before the given endposition.
135 * @param startPosition
137 * @return -1 if no whitespace line is found from the end (i.e. endPosition); otherwise the offset directly after where the
140 private int checkWhitespaces(int startPosition, int endPosition) {
142 while (endPosition >= startPosition) {
143 if ((tempChar = fSource[endPosition--]) == '\n') {
144 return endPosition + 2;
146 if (tempChar != ' ' && tempChar != '\t' && tempChar != '\r') {
150 if (endPosition < startPosition && endPosition >= 0) {
151 if ((tempChar = fSource[endPosition]) != '\n') {
154 } else if (endPosition == (-1) && startPosition == 0) {
155 // special case at the start of a string
158 return startPosition;
162 * copy the content in the resulting buffer and escape special html characters (< > " & ')
164 private void copyWhite(boolean whiteStart, final int whiteStartPosition, final int diff) {
166 final int len = fCurrentPosition - diff;
167 int currentIndex = whiteStartPosition;
168 int lastIndex = currentIndex;
169 while (currentIndex < len) {
170 switch (fSource[currentIndex++]) {
171 case '<': // special html escape character
172 if (lastIndex < (currentIndex - 1)) {
173 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
174 lastIndex = currentIndex;
178 fResultBuffer.append("<");
180 case '>': // special html escape character
181 if (lastIndex < (currentIndex - 1)) {
182 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
183 lastIndex = currentIndex;
187 fResultBuffer.append(">");
189 case '&': // special html escape character
190 if (lastIndex < (currentIndex - 1)) {
191 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
192 lastIndex = currentIndex;
196 fResultBuffer.append("&");
198 case '\'': // special html escape character
199 if (lastIndex < (currentIndex - 1)) {
200 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
201 lastIndex = currentIndex;
205 fResultBuffer.append("'");
207 case '\"': // special html escape character
208 if (lastIndex < (currentIndex - 1)) {
209 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
210 lastIndex = currentIndex;
214 fResultBuffer.append(""");
218 if (lastIndex < (currentIndex)) {
219 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex);
226 * copy the text in the resulting buffer and escape special html characters (< > " & ')
228 private void copyWhite(String text) {
229 final int len = text.length();
230 int currentIndex = 0;
231 int lastIndex = currentIndex;
232 while (currentIndex < len) {
233 switch (text.charAt(currentIndex++)) {
234 case '<': // special html escape character
235 if (lastIndex < (currentIndex - 1)) {
236 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
237 lastIndex = currentIndex;
239 fResultBuffer.append("<");
241 case '>': // special html escape character
242 if (lastIndex < (currentIndex - 1)) {
243 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
244 lastIndex = currentIndex;
248 fResultBuffer.append(">");
250 case '&': // special html escape character
251 if (lastIndex < (currentIndex - 1)) {
252 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
253 lastIndex = currentIndex;
257 fResultBuffer.append("&");
259 case '\'': // special html escape character
260 if (lastIndex < (currentIndex - 1)) {
261 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
262 lastIndex = currentIndex;
266 fResultBuffer.append("'");
268 case '\"': // special html escape character
269 if (lastIndex < (currentIndex - 1)) {
270 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
271 lastIndex = currentIndex;
275 fResultBuffer.append(""");
279 if (lastIndex < (currentIndex)) {
280 fResultBuffer.append(text.substring(lastIndex, currentIndex));
285 * Copy the text in the resulting buffer and escape special html characters (< > " & ') Additionally every
286 * newline will be replaced by <br/>
288 private void copyNowikiNewLine(String text) {
289 final int len = text.length();
290 int currentIndex = 0;
291 int lastIndex = currentIndex;
292 while (currentIndex < len) {
293 switch (text.charAt(currentIndex++)) {
295 if (lastIndex < (currentIndex - 1)) {
296 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
297 lastIndex = currentIndex;
301 fResultBuffer.append("<br/>");
303 case '<': // special html escape character
304 if (lastIndex < (currentIndex - 1)) {
305 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
306 lastIndex = currentIndex;
310 fResultBuffer.append("<");
312 case '>': // special html escape character
313 if (lastIndex < (currentIndex - 1)) {
314 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
315 lastIndex = currentIndex;
319 fResultBuffer.append(">");
321 // case '&': // special html escape character
322 // if (lastIndex < (currentIndex - 1)) {
323 // fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
324 // lastIndex = currentIndex;
328 // fResultBuffer.append("&");
330 case '\'': // special html escape character
331 if (lastIndex < (currentIndex - 1)) {
332 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
333 lastIndex = currentIndex;
337 fResultBuffer.append("'");
339 case '\"': // special html escape character
340 if (lastIndex < (currentIndex - 1)) {
341 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
342 lastIndex = currentIndex;
346 fResultBuffer.append(""");
350 if (lastIndex < (currentIndex)) {
351 fResultBuffer.append(text.substring(lastIndex, currentIndex));
356 * Render the HTML token which are defined in the OPEN_TAGS and CLOSE_TAGS map
360 public int getHTMLToken() {
361 int currentHtmlPosition = fCurrentPosition;
365 if (getNextChar('/')) {
367 currentHtmlPosition++;
369 int r = readUntilCharOrEOL('>');
371 return WikipediaFilter.TokenNotFound;
373 String closeTagString = new String(fSource, currentHtmlPosition, fCurrentPosition - currentHtmlPosition - 1).toLowerCase();
374 // System.out.println(closeTagString);
375 StringTokenizer tagTokenizer = new StringTokenizer(closeTagString);
378 tokenString = tagTokenizer.nextToken();
379 CloseTagToken token = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tokenString);
381 return WikipediaFilter.TokenNotFound;
383 Object topToken = fTokenStack.peek();
384 if (topToken instanceof OpenTagToken && ((OpenTagToken) topToken).getTagName() == token.getTagName()) {
386 // if (token.getTagName().equals("table")) {
387 // fTableStack.pop();
389 copyWhite(fWhiteStart, fWhiteStartPosition, 3 + tokenString.length());
391 fResultBuffer.append(token.getCloseTag());
392 return WikipediaFilter.TokenIgnore;
395 unexpectedTag(token.getTagName());
396 return WikipediaFilter.TokenIgnore;
397 } catch (NoSuchElementException e) {
398 return WikipediaFilter.TokenNotFound;
404 int tagNameStart = fCurrentPosition;
406 while (Character.isJavaIdentifierStart(fSource[fCurrentPosition])) {
411 tokenString = new String(fSource, tagNameStart, fCurrentPosition - tagNameStart); //tagTokenizer.nextToken();
413 OpenTagToken token = (OpenTagToken) WikipediaFilter.OPEN_TAGS.get(tokenString);
415 return WikipediaFilter.TokenNotFound;
417 copyWhite(fWhiteStart, fWhiteStartPosition, (fCurrentPosition - tagNameStart) + 1);
419 if (token instanceof SpecialTagToken) {
420 // for <br> <br/> <br /> <hr> <hr/>
422 while (Character.isWhitespace(fSource[fCurrentPosition])) {
425 if (fSource[fCurrentPosition] == '/') {
428 if (fSource[fCurrentPosition] == '>') {
430 fWhiteStartPosition = fCurrentPosition;
431 // insert the special tag :
432 fResultBuffer.append(token.getOpenTag());
433 return WikipediaFilter.TokenIgnore;
436 } else if (token instanceof OpenTagToken) {
437 fResultBuffer.append("<");
438 fResultBuffer.append(token.getTagName());
439 fTokenStack.push(token);
440 fCurrentPosition = token.scan(fResultBuffer, fSource, fCurrentPosition);
441 fResultBuffer.append(">");
442 return WikipediaFilter.TokenIgnore;
444 return WikipediaFilter.TokenNotFound;
445 } catch (NoSuchElementException e) {
446 return WikipediaFilter.TokenNotFound;
450 } catch (IndexOutOfBoundsException e) {
453 fCurrentPosition = currentHtmlPosition;
454 return WikipediaFilter.TokenNotFound;
457 public final boolean getNextChar(char testedChar) {
458 int temp = fCurrentPosition;
460 fCurrentCharacter = fSource[fCurrentPosition++];
461 if (fCurrentCharacter != testedChar) {
462 fCurrentPosition = temp;
467 } catch (IndexOutOfBoundsException e) {
468 fCurrentPosition = temp;
473 public final int getNextChar(char testedChar1, char testedChar2) {
474 int temp = fCurrentPosition;
477 fCurrentCharacter = fSource[fCurrentPosition++];
478 if (fCurrentCharacter == testedChar1)
480 else if (fCurrentCharacter == testedChar2)
483 fCurrentPosition = temp;
487 } catch (IndexOutOfBoundsException e) {
488 fCurrentPosition = temp;
493 public final boolean getNextCharAsDigit() {
494 int temp = fCurrentPosition;
496 fCurrentCharacter = fSource[fCurrentPosition++];
497 if (!Character.isDigit(fCurrentCharacter)) {
498 fCurrentPosition = temp;
502 } catch (IndexOutOfBoundsException e) {
503 fCurrentPosition = temp;
508 public final boolean getNextCharAsDigit(int radix) {
510 int temp = fCurrentPosition;
512 fCurrentCharacter = fSource[fCurrentPosition++];
514 if (Character.digit(fCurrentCharacter, radix) == -1) {
515 fCurrentPosition = temp;
519 } catch (IndexOutOfBoundsException e) {
520 fCurrentPosition = temp;
525 public final int getNumberOfChar(char testedChar) {
528 while ((fCurrentCharacter = fSource[fCurrentPosition++]) == testedChar) {
531 } catch (IndexOutOfBoundsException e) {
538 public final char[] getListChars() {
540 int startPosition = fCurrentPosition - 1;
543 fCurrentCharacter = fSource[fCurrentPosition++];
544 if (fCurrentCharacter != '*' && fCurrentCharacter != '#') {
548 } catch (IndexOutOfBoundsException e) {
552 char[] result = new char[fCurrentPosition - startPosition];
553 System.arraycopy(fSource, startPosition, result, 0, fCurrentPosition - startPosition);
557 public boolean getNextCharAsWikiPluginIdentifierPart() {
558 int temp = fCurrentPosition;
560 fCurrentCharacter = fSource[fCurrentPosition++];
562 if (!WikipediaFilter.isWikiPluginIdentifierPart(fCurrentCharacter)) {
563 fCurrentPosition = temp;
567 } catch (IndexOutOfBoundsException e) {
568 fCurrentPosition = temp;
573 private void stopList() {
574 while (!fTokenStack.isEmpty()) {
575 AbstractTag tok = (AbstractTag) fTokenStack.peek();
576 if (tok.equals(WikipediaFilter.LIST_UL_START)) {
578 fResultBuffer.append("</li></ul>");
579 } else if (tok.equals(WikipediaFilter.LIST_OL_START)) {
581 fResultBuffer.append("</li></ol>");
582 } else if (tok == WikipediaFilter.BOLD) {
584 fResultBuffer.append("</b>");
585 } else if (tok == WikipediaFilter.ITALIC) {
587 fResultBuffer.append("</i>");
588 } else if (tok == WikipediaFilter.STRONG) {
590 fResultBuffer.append("</strong>");
591 } else if (tok == WikipediaFilter.EM) {
593 fResultBuffer.append("</em>");
594 } else if (tok == WikipediaFilter.STRIKETHROUGH) {
596 fResultBuffer.append("</strike>");
603 protected int getNextToken() throws InvalidInputException {
604 boolean startOfIndent = false;
605 fWhiteStartPosition = 0;
609 // fStartPosition = fCurrentPosition;
610 fCurrentCharacter = fSource[fCurrentPosition++];
612 // ---------Identify the next token-------------
613 switch (fCurrentCharacter) {
616 int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 2);
617 if (tempPosition >= 0) {
618 copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - (++tempPosition));
621 fResultBuffer.append("<p/>");
626 int fStartPrePosition = fCurrentPosition;
627 boolean preSection = false;
629 while (fSource[fCurrentPosition++] == ' ') {
630 fCurrentCharacter = fSource[fCurrentPosition++];
631 while (fCurrentCharacter != '\n') {
632 if (!Character.isWhitespace(fCurrentCharacter)) {
633 // preformatted section starts here
636 fCurrentCharacter = fSource[fCurrentPosition++];
640 } catch (IndexOutOfBoundsException e) {
643 if (preSection && fRecursionLevel == 1) {
645 copyWhite(fWhiteStart, fStartPrePosition, fCurrentPosition - fStartPrePosition);
647 fResultBuffer.append("<pre>");
648 // copyWhite(fWhiteStart, fStartPrePosition, 1);
649 preString = new String(fSource, fStartPrePosition, fCurrentPosition - fStartPrePosition - 1) + '\n';
650 fResultBuffer.append(WikipediaFilter.filterParser(preString, fContext, fMacros, fRecursionLevel));
651 // preString = new String(fSource, fStartPrePosition, fCurrentPosition - fStartPrePosition - 1)+'\n';
653 // int lastIndex = 0;
654 // while (preIndex>=0) {
655 // preIndex = preString.indexOf('\n', lastIndex);
656 // if (preIndex>=0) {
657 // fResultBuffer.append(WikipediaFilter.filterParser(preString.substring(lastIndex,preIndex), fContext,
658 // fCachedPage, fMacros, fRecursionLevel));
659 // fResultBuffer.append('\n');
660 // lastIndex = ++preIndex;
663 fResultBuffer.append("</pre>");
667 fCurrentPosition = fStartPrePosition;
671 if (isStartOfLine()) {
672 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
675 int levelHeader = getNumberOfChar(':') + 1;
676 int startHeadPosition = fCurrentPosition;
677 if (readUntilEOL()) {
678 String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition);
679 for (int i = 0; i < levelHeader; i++) {
680 fResultBuffer.append("<dl><dd>");
682 fResultBuffer.append(head);
683 for (int i = 0; i < levelHeader; i++) {
684 fResultBuffer.append("</dd></dl>");
693 if (isStartOfLine() && getNextChar(' ')) {
694 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
697 int startHeadPosition = fCurrentPosition - 1;
698 if (readUntilEOL()) {
699 // TODO not correct - improve this
700 String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition);
701 int index = head.indexOf(" : ");
703 fResultBuffer.append("<dl><dt>");
704 fResultBuffer.append(head.substring(0, index));
705 fResultBuffer.append(" </dt><dd>");
706 fResultBuffer.append(head.substring(index + 2));
707 fResultBuffer.append("</dd></dl>");
709 fResultBuffer.append("<dl><dt>");
710 fResultBuffer.append(head);
711 fResultBuffer.append(" </dt></dl>");
720 int startLinkPosition = fCurrentPosition;
721 if (getNextChar('[')) { // wikipedia link style
722 startLinkPosition = fCurrentPosition;
723 copyWhite(fWhiteStart, fWhiteStartPosition, 2);
725 if (readUntilString("]]")) {
726 String name = new String(fSource, startLinkPosition, fCurrentPosition - startLinkPosition - 2);
727 // test for suffix string
728 int temp = fCurrentPosition;
729 StringBuffer suffixBuffer = new StringBuffer();
732 fCurrentCharacter = fSource[fCurrentPosition++];
733 if (!Character.isLetterOrDigit(fCurrentCharacter)) {
737 suffixBuffer.append(fCurrentCharacter);
739 handleWikipediaLink(name, suffixBuffer.toString());
741 } catch (IndexOutOfBoundsException e) {
742 fCurrentPosition = temp;
745 handleWikipediaLink(name, "");
750 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
753 if (readUntilChar(']')) {
754 String name = new String(fSource, startLinkPosition, fCurrentPosition - startLinkPosition - 1);
755 handleSnipLink(name);
760 case '*': // <ul> list
761 case '#': // <ol> list
762 if (isStartOfLine()) {
763 char[] listChars = getListChars();
764 int tempStarPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - listChars.length);
765 if (tempStarPosition >= 0) {
766 appendList(listChars);
772 if (getNextChar('\'')) {
773 if (getNextChar('\'')) {
774 copyWhite(fWhiteStart, fWhiteStartPosition, 3);
776 return WikipediaFilter.TokenSTRONG;
778 copyWhite(fWhiteStart, fWhiteStartPosition, 2);
780 return WikipediaFilter.TokenEM;
784 int tempCurrPosition = fCurrentPosition;
786 if (fSource[tempCurrPosition++] == '-' && fSource[tempCurrPosition++] == '-' && fSource[tempCurrPosition++] == '-') {
787 if (fSource[tempCurrPosition] == '\n') {
788 fCurrentPosition = tempCurrPosition;
789 fResultBuffer.append("<hr/>");
792 } else if (fSource[tempCurrPosition++] == '\r' && fSource[tempCurrPosition++] == '\n') {
793 fCurrentPosition = tempCurrPosition - 1;
794 fResultBuffer.append("<hr/>");
799 } catch (IndexOutOfBoundsException e) {
803 case 'h': // http(s)://
804 int urlStartPosition = fCurrentPosition;
805 boolean foundUrl = false;
808 String urlString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 3);
809 if (urlString.equals("http")) {
810 fCurrentPosition += 3;
811 fCurrentCharacter = fSource[fCurrentPosition++];
812 if (fCurrentCharacter == 's') { // optional
813 fCurrentCharacter = fSource[fCurrentPosition++];
817 if (fCurrentCharacter == ':' && fSource[fCurrentPosition++] == '/' && fSource[fCurrentPosition++] == '/') {
818 copyWhite(fWhiteStart, fWhiteStartPosition, diff);
821 while (WikipediaFilter.isUrlIdentifierPart(fSource[fCurrentPosition++])) {
825 } catch (IndexOutOfBoundsException e) {
828 fCurrentPosition = urlStartPosition;
832 String urlString = new String(fSource, urlStartPosition - 1, fCurrentPosition - urlStartPosition);
834 createExternalLink(urlString);
839 // case '@': // images @xml@ -> /static/rss-small.png
840 // copyWhite(fWhiteStart, fWhiteStartPosition, 1);
841 // fWhiteStart = false;
842 // int atStart = fCurrentPosition;
843 // if (readUntilChar('@')) {
844 // String imageTag = new String(fSource, atStart, fCurrentPosition - atStart - 1);
845 // if (imageTag != null) {
846 // if (WikipediaFilter.createStaticImage(imageTag, fResultBuffer)) {
851 // fCurrentPosition = atStart;
854 int ampersandStart = fCurrentPosition - 1;
855 if (getNextChar('#')) {
857 StringBuffer num = new StringBuffer(5);
858 char ch = fSource[fCurrentPosition++];
859 while (Character.isDigit(ch)) {
861 ch = fSource[fCurrentPosition++];
863 if (num.length() > 0 && ch == ';') {
864 Integer i = Integer.valueOf(num.toString());
865 if (i.intValue() < 65536) {
866 copyWhite(fWhiteStart, fWhiteStartPosition, 3 + num.length());
868 fResultBuffer.append(fSource, ampersandStart, fCurrentPosition - ampersandStart);
872 } catch (IndexOutOfBoundsException e) {
874 } catch (NumberFormatException e) {
879 StringBuffer entity = new StringBuffer(10);
880 char ch = fSource[fCurrentPosition++];
881 while (Character.isLetterOrDigit(ch)) {
883 ch = fSource[fCurrentPosition++];
885 if (entity.length() > 0 && ch == ';') {
886 if (WikipediaFilter.ENTITY_SET.contains(entity.toString())) {
887 copyWhite(fWhiteStart, fWhiteStartPosition, 2 + entity.length());
889 fResultBuffer.append(fSource, ampersandStart, fCurrentPosition - ampersandStart);
893 } catch (IndexOutOfBoundsException e) {
895 } catch (NumberFormatException e) {
902 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
904 int startMacroPosition = fCurrentPosition;
905 if (getNextChar('|') && handleWikipediaTable()) { // Wikipedia
910 // SnipSnap / Radeox Macro Syntax
911 // if (readUntilChar('}')) {
912 // String macroStartTag;
914 // macroStartTag = new String(fSource, startMacroPosition, fCurrentPosition - startMacroPosition - 1);
915 // if (macroStartTag != null) {
916 // createMacro(startMacroPosition, macroStartTag);
923 int htmlStartPosition = fCurrentPosition;
925 switch (fStringSource.charAt(fCurrentPosition)) {
926 case '!': // <!-- html comment -->
927 String htmlCommentString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 3);
929 if (htmlCommentString.equals("<!--")) {
930 fCurrentPosition += 3;
931 if (readUntilString("-->")) {
932 String htmlCommentContent = new String(fSource, htmlStartPosition + 3, fCurrentPosition - htmlStartPosition - 6);
933 if (htmlCommentContent != null) {
934 copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - htmlStartPosition + 1);
936 // insert html comment for visual checks
939 * fResultBuffer.append(" <!--"); copyWhite(htmlCommentContent); fResultBuffer.append("--> ");
947 String nowikiString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 7);
949 if (nowikiString.equals("<nowiki>")) {
950 fCurrentPosition += 7;
951 if (readUntilString("</nowiki>")) {
952 String nowikiContent = new String(fSource, htmlStartPosition + 7, fCurrentPosition - htmlStartPosition - 16);
953 if (nowikiContent != null) {
954 copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - htmlStartPosition + 1);
956 copyNowikiNewLine(nowikiContent);
963 } catch (IndexOutOfBoundsException e) {
966 startOfIndent = false;
967 fCurrentPosition = htmlStartPosition;
968 // detect special html tags
969 int htmlToken = getHTMLToken();
970 if (htmlToken == WikipediaFilter.TokenIgnore) {
972 // } else if (htmlToken > TokenIgnore) {
975 fCurrentPosition = htmlStartPosition;
977 case '=': // wikipedia header ?
978 if (isStartOfLine()) {
979 int levelHeader = getNumberOfChar('=') + 1;
980 // int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - levelHeader);
981 // if (tempPosition >= 0) {
982 copyWhite(fWhiteStart, fWhiteStartPosition, levelHeader);
984 int startHeadPosition = fCurrentPosition;
985 // int initialOffset = levelHeader;
986 if (levelHeader > 6) {
990 if (readUntilString(WikipediaFilter.HEADER_STRINGS[levelHeader])) {
991 String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition - (1 + levelHeader));
993 handleHead(head, levelHeader);
1002 fWhiteStartPosition = fCurrentPosition - 1;
1005 startOfIndent = false;
1007 // -----------------end switch while try--------------------
1008 } catch (IndexOutOfBoundsException e) {
1009 // end of scanner text
1011 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
1013 return WikipediaFilter.TokenEOF;
1019 private boolean isStartOfLine() {
1020 boolean isListStart = false;
1021 if (fCurrentPosition >= 2) {
1022 char beforeChar = fSource[fCurrentPosition - 2];
1023 if (beforeChar == '\n' || beforeChar == '\r') {
1027 if (fCurrentPosition == 1) {
1038 private void appendList(char[] listChars) {
1040 int levelStar = listChars.length;
1041 copyWhite(fWhiteStart, fWhiteStartPosition, levelStar);
1042 fWhiteStart = false;
1043 AbstractTag tok = (AbstractTag) fTokenStack.peek();
1045 if (tok instanceof ListToken) {
1046 ListToken listToken = (ListToken) tok;
1047 topLevel = listToken.getLevel();
1049 if (levelStar > topLevel) {
1050 while (levelStar > topLevel) {
1051 if (listChars[topLevel] == '*') {
1052 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, ++topLevel));
1053 fResultBuffer.append("<ul><li>");
1055 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, ++topLevel));
1056 fResultBuffer.append("<ol><li>");
1059 } else if (levelStar < topLevel) {
1060 while (levelStar < topLevel) {
1061 tok = (AbstractTag) fTokenStack.peek();
1062 if (tok instanceof ListToken) {
1064 listToken = (ListToken) tok;
1065 if (listToken.getToken() == WikipediaFilter.TokenLIST_UL_START) {
1066 fResultBuffer.append("</li></ul></li><li>");
1068 fResultBuffer.append("</li></ol></li><li>");
1077 if (listToken.getToken() == WikipediaFilter.TokenLIST_UL_START && listChars[topLevel] == '#') {
1079 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel));
1080 fResultBuffer.append("</li></ul><ol><li>");
1081 } else if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START && listChars[topLevel] == '*') {
1083 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, topLevel));
1084 fResultBuffer.append("</li></ol><ul><li>");
1086 fResultBuffer.append("</li><li>");
1090 while (levelStar > topLevel) {
1091 if (listChars[topLevel] == '*') {
1092 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, ++topLevel));
1093 fResultBuffer.append("\n<ul><li>");
1095 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, ++topLevel));
1096 fResultBuffer.append("\n<ol><li>");
1102 private void createMacro(int startMacroPosition, String macroStartTag) {
1103 String command = "";
1106 String parameterString = null;
1107 String macroBodyString = "";
1110 if ((index0 = macroStartTag.indexOf(':')) >= 0) {
1111 command = macroStartTag.substring(0, index0);
1112 parameterString = macroStartTag.substring(index0 + 1, macroStartTag.length());
1114 command = macroStartTag;
1116 Macro macro = (Macro) fMacros.get(command);
1118 String completeMacroSubString;
1120 if ((macro != null) && (macro instanceof IBodyTagSupportMacro)) {
1121 endTag = '{' + command + '}';
1122 index0 = fStringSource.indexOf(endTag, fCurrentPosition);
1125 macroBodyString = fStringSource.substring(fCurrentPosition, index0);
1126 completeMacroSubString = new String(fSource, startMacroPosition - 1, index0 + endTag.length() - startMacroPosition + 1);
1127 fCurrentPosition = startMacroPosition + completeMacroSubString.length() - 1;
1129 completeMacroSubString = new String(fSource, startMacroPosition - 1, macroStartTag.length() + 2);
1132 completeMacroSubString = new String(fSource, startMacroPosition - 1, macroStartTag.length() + 2);
1135 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
1137 handleMacro(completeMacroSubString, command, parameterString, macroBodyString);
1140 // private void createExternalLink(String urlString) {
1142 // // Does our engine know images?
1143 // if (fWikiEngine instanceof ImageRenderEngine) {
1144 // fResult.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
1146 // fResult.append("<span class=\"nobr\">");
1147 // fResult.append("<a href=\"");
1148 // fResult.append(Encoder.escape(urlString));
1149 // fResult.append("\">");
1150 // fResult.append(Encoder.toEntity(urlString.charAt(0)) +
1151 // urlString.substring(1));
1152 // fResult.append("</a></span>");
1155 // private void handleTeXMath(String mathContent, boolean inlineExpression)
1157 // // TODO clean this up
1158 // Map map = Application.get().getParameters();
1159 // HttpServletRequest request = (HttpServletRequest) map.get("request");
1160 // MathSniffer sniffy = MathSniffer.getBrowserDetection(request);
1162 // if (fCacheStaticBlockActive) {
1163 // fCachedPage.addHTML(fResultBuffer.substring(fCacheStaticBlockStartPosition,
1164 // fResultBuffer.length()));
1165 // fCacheStaticBlockActive = false;
1167 // // if (inlineExpression) {
1168 // // fASMCompiler.compileMath(mathContent, "true");
1170 // // fASMCompiler.compileMath(mathContent, "false");
1172 // if (fCachedPage == WikipediaFilter.DUMMY_CACHED_PAGE) {
1173 // switch (sniffy.getBrowserId()) {
1174 // case MathSniffer.XMLID :
1175 // case MathSniffer.MATHPLAYERID :
1176 // if (inlineExpression) {
1177 // fResultBuffer.append("<m:math><m:mstyle mathcolor=\"Black\"
1178 // displaystyle=\"true\">");
1179 // fTeXParser.initialize(mathContent);
1180 // fTeXParser.parse2MML(fResultBuffer);
1181 // fResultBuffer.append("</m:mstyle></m:math>");
1183 // fResultBuffer.append("<dl><dd><m:math><m:mstyle mathcolor=\"Black\"
1184 // displaystyle=\"true\">");
1185 // fTeXParser.initialize(mathContent);
1186 // fTeXParser.parse2MML(fResultBuffer);
1187 // fResultBuffer.append("</m:mstyle></m:math></dd></dl>");
1190 // case MathSniffer.CSSID :
1191 // if (inlineExpression) {
1192 // fResultBuffer.append("<m>");
1193 // fTeXParser.initialize(mathContent);
1194 // fTeXParser.parse2CSS(fResultBuffer, true);
1195 // fResultBuffer.append("</m>");
1197 // fResultBuffer.append("<e>");
1198 // fTeXParser.initialize(mathContent);
1199 // fTeXParser.parse2CSS(fResultBuffer, true);
1200 // fResultBuffer.append("</e>");
1204 // copyWhite(mathContent);
1207 // String[] mathStrings = new String[3];
1208 // StringBuffer mathBuffer = new StringBuffer();
1209 // if (inlineExpression) {
1211 // mathBuffer.append("<m:math><m:mstyle mathcolor=\"Black\"
1212 // displaystyle=\"true\">");
1214 // fTeXParser.initialize(mathContent);
1215 // fTeXParser.parse2MML(mathBuffer);
1216 // mathBuffer.append("</m:mstyle></m:math>");
1218 // mathBuffer.append("<dl><dd><m:math><m:mstyle mathcolor=\"Black\"
1219 // displaystyle=\"true\">");
1220 // fTeXParser.initialize(mathContent);
1221 // fTeXParser.parse2MML(mathBuffer);
1222 // mathBuffer.append("</m:mstyle></m:math></dd></dl>");
1224 // mathStrings[0] = mathBuffer.toString();
1225 // mathBuffer.setLength(0);
1226 // // if (inlineExpression) {
1228 // // mathBuffer.append("<m>");
1229 // // fTeXParser.initialize(mathContent);
1230 // // fTeXParser.parse2CSS(mathBuffer, true);
1231 // // mathBuffer.append("</m>");
1233 // // // css block mode
1234 // // mathBuffer.append("<e>");
1235 // // fTeXParser.initialize(mathContent);
1236 // // fTeXParser.parse2CSS(mathBuffer, true);
1237 // // mathBuffer.append("</e>");
1240 // String encodedMathContent = Encoder.escape(mathContent);
1241 // StringBuffer mathmlBuffer = new StringBuffer();
1242 // String shortImageName = "____tex_" + (fImageCounter++);
1243 // String longImageName = shortImageName + ".gif";
1244 // mathmlBuffer.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
1245 // if (inlineExpression) {
1246 // mathmlBuffer.append("<math><mstyle mathcolor=\"Black\"
1247 // displaystyle=\"true\">");
1248 // fTeXImageParser.initialize(mathContent);
1249 // fTeXImageParser.parse2MML(mathmlBuffer);
1250 // mathmlBuffer.append("</mstyle></math>");
1252 // mathmlBuffer.append("<math><mstyle mathcolor=\"Black\"
1253 // displaystyle=\"true\">");
1254 // fTeXImageParser.initialize(mathContent);
1255 // fTeXImageParser.parse2MML(mathmlBuffer);
1256 // mathmlBuffer.append("</mstyle></math>");
1259 // String snipname = fSnip.getName();
1260 // String SnipSnapSpacePath =
1261 // Application.get().getConfiguration().getFilePath().getAbsolutePath();
1262 // // Remove old image
1263 // fSnip.getAttachments().removeAttachment(longImageName + ".gif");
1265 // String directoryName = SnipSnapSpacePath + "/" + snipname;
1266 // File directory = new File(directoryName);
1267 // if (!directory.exists()) {
1268 // directory.mkdirs();
1270 // String gifFilename = directoryName + "/" + longImageName;
1271 // // File file = new File();
1272 // // Get the number of bytes in the file
1273 // // long length = file.length();
1274 // MathMLToGIFConverter conv = new MathMLToGIFConverter();
1276 // // "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><math
1278 // mode=\"display\"><mrow><munderover><mo>∫</mo><mn>1</mn><mi>x</mi></munderover><mfrac><mi>dt</mi><mi>t</mi></mfrac></mrow></math>";
1280 // File imageFile = conv.convert(mathmlBuffer.toString(), gifFilename);
1281 // if (imageFile != null) {
1282 // Attachment attachment =
1283 // new Attachment(longImageName, "image/gif", imageFile.length(), new
1284 // Date(), snipname + "/" + longImageName, true);
1285 // // fSnip.getAttachments().addAttachment(longImageName, "image/gif",
1286 // imageFile.length(), snipname + "/" + longImageName,
1288 // fSnip.getAttachments().addAttachment(attachment);
1289 // StringWriter writer = new StringWriter();
1291 // SnipLink.appendImage(writer, fSnip, shortImageName, encodedMathContent,
1294 // mathBuffer = writer.getBuffer();
1295 // mathStrings[1] = mathBuffer.toString();
1297 // mathStrings[1] = encodedMathContent;
1299 // } catch (IOException e) {
1300 // // TODO Auto-generated catch block
1301 // e.printStackTrace();
1302 // mathStrings[1] = encodedMathContent;
1304 // mathBuffer.setLength(0);
1305 // WikipediaFilter.copyWhite(mathBuffer, mathContent);
1306 // mathStrings[2] = mathBuffer.toString();
1307 // fCachedPage.addMath(mathStrings);
1309 // if (!fCacheStaticBlockActive) {
1310 // fCacheStaticBlockActive = true;
1311 // fCacheStaticBlockStartPosition = fResultBuffer.length();
1314 private void handleSnipLink(String name) {
1316 int index = name.indexOf("http://");
1317 // Configuration probably wrote [http://radeox.org] instead of
1318 // http://radeox.org
1320 // WikipediaFilter.createExternalLink(fResultBuffer,
1321 // fWikiEngine, name.substring(index));
1322 String urlString = name.substring(index);
1323 // Wikipedia like style:
1324 int pipeIndex = urlString.indexOf(' ');
1326 if (pipeIndex != (-1)) {
1327 alias = urlString.substring(pipeIndex + 1);
1328 urlString = urlString.substring(0, pipeIndex);
1333 if (fWikiEngine instanceof ImageRenderEngine) {
1334 fResultBuffer.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
1336 fResultBuffer.append("<span class=\"nobr\">");
1337 fResultBuffer.append("<a href=\"");
1338 // fResultBuffer.append(Encoder.escape(urlString));
1339 copyWhite(urlString);
1340 fResultBuffer.append("\">");
1341 // fResultBuffer.append(Encoder.toEntity(alias.charAt(0)) + alias.substring(1));
1343 fResultBuffer.append("</a></span>");
1346 // // trim the name and unescape it
1347 // name = Encoder.unescape(name.trim());
1348 // // Is there an alias like [alias|link] ?
1349 // int pipeIndex = name.indexOf('|');
1350 // String alias = "";
1351 // if (-1 != pipeIndex) {
1352 // alias = name.substring(0, pipeIndex);
1353 // name = name.substring(pipeIndex + 1);
1356 // int hashIndex = name.lastIndexOf('#');
1358 // String hash = "";
1359 // if (-1 != hashIndex && hashIndex != name.length() - 1) {
1360 // hash = name.substring(hashIndex + 1);
1361 // name = name.substring(0, hashIndex);
1364 // int colonIndex = name.indexOf(':');
1366 // if (-1 != colonIndex) {
1367 // // for now throw away the fType information
1368 // name = name.substring(colonIndex + 1);
1371 // int atIndex = name.lastIndexOf('@');
1372 // // InterWiki link ?
1373 // if (-1 != atIndex) {
1374 // String extSpace = name.substring(atIndex + 1);
1375 // // known extarnal space ?
1376 // InterWiki interWiki = InterWiki.getInstance();
1377 // if (interWiki.contains(extSpace)) {
1378 // name = name.substring(0, atIndex);
1379 // Writer writer = new StringBufferWriter(fResultBuffer);
1381 // if (-1 != hashIndex) {
1382 // interWiki.expand(writer, extSpace, name, hash);
1384 // interWiki.expand(writer, extSpace, name, "");
1386 // } catch (IOException e) {
1387 // log.debug("InterWiki " + extSpace + " not found.");
1390 // fResultBuffer.append("[<span class=\"error\">");
1391 // fResultBuffer.append(name);
1392 // fResultBuffer.append("?</span>]");
1396 // if (fWikiEngine != null && fWikiEngine instanceof WikiRenderEngine) {
1397 // if (fCacheStaticBlockActive) {
1398 // fCachedPage.addHTML(fResultBuffer.substring(fCacheStaticBlockStartPosition, fResultBuffer.length()));
1399 // fCacheStaticBlockActive = false;
1401 // fCachedPage.addSnipLink(name);
1402 // if (fCachedPage == WikipediaFilter.DUMMY_CACHED_PAGE) {
1403 // if (((WikiRenderEngine) fWikiEngine).exists(name)) {
1404 // String view = name;
1405 // if (-1 != pipeIndex) {
1408 // // Do not add hash if an alias was given
1409 // if (-1 != hashIndex) {
1410 // ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view, hash);
1412 // ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view);
1414 // } else if (((WikiRenderEngine) fWikiEngine).showCreate()) {
1415 // ((WikiRenderEngine) fWikiEngine).appendCreateLink(fResultBuffer, name, name);
1416 // // links with "create" are not cacheable because
1417 // // a missing wiki could be created
1418 // fContext.getRenderContext().setCacheable(false);
1420 // // cannot display/create wiki, so just display
1422 // fResultBuffer.append(name);
1425 // if (!fCacheStaticBlockActive) {
1426 // fCacheStaticBlockActive = true;
1427 // fCacheStaticBlockStartPosition = fResultBuffer.length();
1430 // // cannot display/create wiki, so just display the text
1431 // fResultBuffer.append(name);
1438 private boolean handleWikipediaTable() {
1450 int temp = fCurrentPosition;
1451 int sequenceStart = 0;
1452 char lastChar = ' ';
1453 int sequenceLength = 0;
1454 int thStartPosition = 0;
1455 Stack wpTokenStack = new Stack();
1457 // add table attributes:
1458 fResultBuffer.append("<table ");
1459 sequenceStart = fCurrentPosition;
1460 fCurrentCharacter = fSource[fCurrentPosition++];
1461 while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
1463 fCurrentCharacter = fSource[fCurrentPosition++];
1465 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
1466 fCurrentCharacter = fSource[fCurrentPosition++];
1468 if (sequenceLength > 0) {
1469 fResultBuffer.append(fSource, sequenceStart + 1, sequenceLength - 1);
1471 fResultBuffer.append(">");
1472 wpTokenStack.push(WikipediaFilter.HTML_TABLE_OPEN);
1474 fResultBuffer.append("<tr>\n");
1475 wpTokenStack.push(WikipediaFilter.HTML_TR_OPEN);
1476 String attributes = null;
1477 // parse rest of table
1479 sequenceStart = fCurrentPosition;
1480 fCurrentCharacter = fSource[fCurrentPosition++];
1481 if (fCurrentCharacter == '{' && fSource[fCurrentPosition] == '|') { // nested table
1482 handleWikipediaTable();
1483 } else if (fCurrentCharacter == '!') {
1485 reduceTableCellStack(fResultBuffer, wpTokenStack);
1486 fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1487 sequenceStart = fCurrentPosition;
1488 // add header row cells
1491 fCurrentCharacter = fSource[fCurrentPosition++];
1492 if (fCurrentCharacter == '|' || fCurrentCharacter == '\n') {
1493 if (fSource[fCurrentPosition] == '|' || fCurrentCharacter == '\n') {
1494 reduceTableCellStack(fResultBuffer, wpTokenStack);
1495 if (attributes == null) {
1496 fResultBuffer.append("<th>");
1498 fResultBuffer.append("<th ");
1499 fResultBuffer.append(attributes);
1500 fResultBuffer.append(">");
1502 wpTokenStack.push(WikipediaFilter.HTML_TH_OPEN);
1503 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1504 - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1506 sequenceStart = fCurrentPosition;
1509 attributes = new String(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1510 sequenceStart = fCurrentPosition;
1513 if (fCurrentCharacter == '\n') {
1518 } else if (fCurrentCharacter == '|') {
1519 reduceTableCellStack(fResultBuffer, wpTokenStack);
1520 fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1522 sequenceStart = fCurrentPosition;
1523 fCurrentCharacter = fSource[fCurrentPosition++];
1524 switch (fCurrentCharacter) {
1525 case '+': // caption
1527 reduceTableRowStack(WikipediaFilter.HTML_TABLE_OPEN, fResultBuffer, wpTokenStack);
1528 fResultBuffer.append("<caption>\n");
1529 wpTokenStack.push(WikipediaFilter.HTML_CAPTION_OPEN);
1530 // read until end of line
1531 while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
1532 fCurrentCharacter = fSource[fCurrentPosition++];
1534 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
1535 fCurrentCharacter = fSource[fCurrentPosition++];
1537 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition - sequenceStart
1538 - 1), fContext, fMacros, fRecursionLevel));
1540 case '-': // new row
1542 reduceTableRowStack(WikipediaFilter.HTML_TR_OPEN, fResultBuffer, wpTokenStack);
1544 // read until end of line
1545 while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
1546 fCurrentCharacter = fSource[fCurrentPosition++];
1548 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
1549 fCurrentCharacter = fSource[fCurrentPosition++];
1551 // TODO handle row attributes
1552 fResultBuffer.append("<tr ");
1553 wpTokenStack.push(WikipediaFilter.HTML_TR_OPEN);
1554 fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1555 fResultBuffer.append(">\n");
1556 // fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1557 // - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1559 case '}': // end of table
1560 clearTableStack(fResultBuffer, wpTokenStack);
1561 // System.out.println(fResultBuffer.toString());
1567 fCurrentCharacter = fSource[fCurrentPosition++];
1568 if (fCurrentCharacter == '|' || fCurrentCharacter == '\n') {
1569 if (fSource[fCurrentPosition] == '|' || fCurrentCharacter == '\n') {
1570 reduceTableCellStack(fResultBuffer, wpTokenStack);
1571 if (attributes == null) {
1572 fResultBuffer.append("<td>");
1574 fResultBuffer.append("<td ");
1575 fResultBuffer.append(attributes);
1576 fResultBuffer.append(">");
1578 wpTokenStack.push(WikipediaFilter.HTML_TD_OPEN);
1579 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1580 - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1581 // TODO reduce fTokenStack to <tr> element
1583 // fResultBuffer.append("</td>");
1584 // fTokenStack.pop();
1586 sequenceStart = fCurrentPosition;
1589 attributes = new String(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1591 sequenceStart = fCurrentPosition;
1594 if (fCurrentCharacter == '\n') {
1600 } else if (wpTokenStack.peek() == WikipediaFilter.HTML_TD_OPEN) {
1601 // continue a table cell in the next line
1603 if (fCurrentCharacter == '\n') {
1604 char ch0 = fSource[fCurrentPosition];
1605 char ch1 = fSource[fCurrentPosition + 1];
1606 if (ch0 == '|' || ch0 == '!' || (ch0 == '{' && ch1 == '|')) {
1607 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1608 - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1609 sequenceStart = fCurrentPosition;
1614 fCurrentCharacter = fSource[fCurrentPosition++];
1618 } catch (IndexOutOfBoundsException e) {
1619 if (sequenceStart + 1 < fCurrentPosition && fSource[sequenceStart + 1] == '}') {
1620 // TODO reduce fTokenStack to <tr> element if necessary
1621 // fResultBuffer.append("</tr></table>\n");
1622 // wpTokenStack.pop(); // tr
1623 // wpTokenStack.pop();// table
1624 // System.out.println(fResultBuffer.toString());
1625 clearTableStack(fResultBuffer, wpTokenStack);
1629 fCurrentPosition = temp - 1;
1630 // System.out.print(fResultBuffer.toString());
1632 } // private boolean handleWikipediaTable() {
1634 private void clearTableStack(StringBuffer buffer, Stack stack) {
1635 CloseTagToken closeTag;
1637 while (!stack.isEmpty()) {
1638 tag = (AbstractTag) stack.pop();
1639 closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
1640 buffer.append(closeTag.getCloseTag());
1644 private void reduceTableRowStack(AbstractTag stopTag, StringBuffer buffer, Stack stack) {
1645 CloseTagToken closeTag;
1647 while (!stack.isEmpty()) {
1648 tag = (AbstractTag) stack.peek();
1649 if (tag == WikipediaFilter.HTML_TABLE_OPEN) {
1653 closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
1654 buffer.append(closeTag.getCloseTag());
1655 if (tag == WikipediaFilter.HTML_TR_OPEN || tag == WikipediaFilter.HTML_CAPTION_OPEN) {
1661 private void reduceTableCellStack(StringBuffer buffer, Stack stack) {
1662 CloseTagToken closeTag;
1664 while (!stack.isEmpty()) {
1665 tag = (AbstractTag) stack.peek();
1666 if (tag != WikipediaFilter.HTML_TH_OPEN && tag != WikipediaFilter.HTML_TD_OPEN) {
1670 closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
1671 buffer.append(closeTag.getCloseTag());
1672 if (tag == WikipediaFilter.HTML_TR_OPEN || tag == WikipediaFilter.HTML_CAPTION_OPEN || tag == WikipediaFilter.HTML_TH_OPEN
1673 || tag == WikipediaFilter.HTML_TD_OPEN) {
1691 // int temp = fCurrentPosition;
1692 // // StringBuffer suffixBuffer = new StringBuffer();
1693 // Table table = new Table(fContext.getRenderContext());
1694 // // char currentChar = ' ';
1695 // char lastChar = ' ';
1696 // // int startPosition = 0;
1697 // // int currentPosition = 0;
1698 // StringBuffer buffer = new StringBuffer();
1699 // int thStartPosition = 0;
1701 // try { // read first line
1702 // fCurrentCharacter = fSource[fCurrentPosition++];
1703 // // TODO improve this for different table attributes
1704 // while (fCurrentCharacter != '\n' ) {
1705 // fCurrentCharacter = fSource[fCurrentPosition++];
1706 // // System.out.println(fCurrentCharacter);
1709 // lastChar = fCurrentCharacter;
1710 // fCurrentCharacter = fSource[fCurrentPosition++];
1713 // switch (fCurrentCharacter) {
1714 // // case '{' : // start of nested table ?
1715 // // if (getNextChar('|') && handleWikipediaTable()) { // Wikipedia table
1721 // if (lastChar == '\n') {
1722 // table.addCell(buffer.toString());
1723 // // System.out.println(buffer.toString());
1724 // buffer.setLength(0);
1725 // thStartPosition = fCurrentPosition;
1727 // lastChar = fCurrentCharacter;
1728 // fCurrentCharacter = fSource[fCurrentPosition++];
1729 // if (fCurrentCharacter == '|') {
1732 // if (fCurrentCharacter == '\n') {
1734 // fCurrentPosition = thStartPosition;
1739 // buffer.append(fCurrentCharacter);
1743 // if (lastChar == '\n') {
1744 // if (getNextChar('}')) { // Wikipedia table end reached
1745 // table.addCell(buffer.toString());
1746 // StringWriter writer = new StringWriter();
1748 // table.appendTo(writer);
1749 // fResultBuffer.append(writer.getBuffer());
1750 // } catch (IOException e1) {
1751 // // TODO Auto-generated catch block
1752 // e1.printStackTrace();
1756 // } else if (getNextChar('-')) {
1757 // table.addCell(buffer.toString());
1758 // buffer.setLength(0);
1761 // lastChar = fCurrentCharacter;
1762 // fCurrentCharacter = fSource[fCurrentPosition++];
1763 // if (fCurrentCharacter == '|' || fCurrentCharacter == '!') {
1769 // if (buffer.length()>0) {
1770 // table.addCell(buffer.toString());
1771 // buffer.setLength(0);
1774 // } else if (getNextChar('|')) {
1775 // table.addCell(buffer.toString());
1776 // // System.out.println(buffer.toString());
1777 // buffer.setLength(0);
1779 // buffer.append(fCurrentCharacter);
1783 // buffer.append(fCurrentCharacter);
1785 // lastChar = fCurrentCharacter;
1786 // fCurrentCharacter = fSource[fCurrentPosition++];
1789 // } catch (IndexOutOfBoundsException e) {
1792 // fCurrentPosition = temp - 1;
1795 public void createExternalLink(String urlString) {
1796 // Does our engine know images?
1797 if (fWikiEngine instanceof ImageRenderEngine) {
1798 fResultBuffer.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
1800 fResultBuffer.append("<span class=\"nobr\">");
1801 fResultBuffer.append("<a href=\"");
1802 // fResultBuffer.append(Encoder.escape(urlString));
1803 copyWhite(urlString);
1804 fResultBuffer.append("\">");
1805 // fResultBuffer.append(Encoder.escape(urlString));
1806 copyWhite(urlString);
1807 fResultBuffer.append("</a></span>");
1810 private void handleWikipediaLink(String linkText, String suffix) {
1811 String name = linkText;
1813 int index = name.indexOf("http://");
1814 // Configuration probably wrote [http://radeox.org] instead of
1815 // http://radeox.org
1817 createExternalLink(name.substring(index));
1819 // fResult.append("<div class=\"error\">Do not surround URLs
1820 // with [...].</div>");
1822 // trim the name and unescape it
1823 name = Encoder.unescape(name.trim());
1824 // Is there an alias like [alias|link] ?
1825 int pipeIndex = name.indexOf('|');
1827 if (-1 != pipeIndex) {
1828 alias = name.substring(pipeIndex + 1);
1829 name = name.substring(0, pipeIndex);
1832 int hashIndex = name.lastIndexOf('#');
1835 if (-1 != hashIndex && hashIndex != name.length() - 1) {
1836 hash = name.substring(hashIndex + 1);
1837 name = name.substring(0, hashIndex);
1840 // int colonIndex = name.indexOf(':');
1842 // if (-1 != colonIndex) {
1843 // // for now throw away the fType information
1844 // name = name.substring(colonIndex + 1);
1847 // int atIndex = name.lastIndexOf('@');
1849 // if (-1 != atIndex) {
1850 // String extSpace = name.substring(atIndex + 1);
1851 // // known extarnal space ?
1852 // InterWiki interWiki = InterWiki.getInstance();
1853 // if (interWiki.contains(extSpace)) {
1854 // name = name.substring(0, atIndex);
1855 // Writer writer = new StringBufferWriter(fResultBuffer);
1857 // if (-1 != hashIndex) {
1858 // interWiki.expand(writer, extSpace, name, hash);
1860 // interWiki.expand(writer, extSpace, name, "");
1862 // } catch (IOException e) {
1863 // // log.debug("InterWiki " + extSpace + " not found.");
1866 // fResultBuffer.append("[<span class=\"error\">");
1867 // fResultBuffer.append(name);
1868 // fResultBuffer.append("?</span>]");
1872 name = Encoder.escape(name);
1873 if (name.startsWith("Image:") && (fWikiEngine instanceof ImageRenderEngine)) {
1874 // server part of rendering images
1875 ImageRenderEngine imageEngine = (ImageRenderEngine) fWikiEngine;
1876 // fResultBuffer.append("<img src=\"space/1/2004-11-21/5/");
1877 fResultBuffer.append("<img src=\"");
1878 fResultBuffer.append(FilterUtil.createServerImage(null, name.substring(6), null));
1879 fResultBuffer.append("\">");
1880 } else if (fWikiEngine != null && fWikiEngine instanceof WikiRenderEngine) {
1881 if (((WikiRenderEngine) fWikiEngine).exists(name)) {
1882 String view = name + suffix;
1883 if (-1 != pipeIndex) {
1884 view = alias + suffix;
1886 if (name.startsWith("Image:")) {
1887 fResultBuffer.append("<img src=\"");
1889 fResultBuffer.append(FilterUtil.createHTMLLink(null, name, null));
1890 fResultBuffer.append("\">");
1892 // Do not add hash if an alias was given
1893 if (-1 != hashIndex) {
1894 ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view, hash);
1896 ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view);
1899 } else if (((WikiRenderEngine) fWikiEngine).showCreate()) {
1900 ((WikiRenderEngine) fWikiEngine).appendCreateLink(fResultBuffer, name, name + suffix);
1901 // links with "create" are not cacheable because
1902 // a missing wiki could be created
1903 fContext.getRenderContext().setCacheable(false);
1905 // cannot display/create wiki, so just display
1907 fResultBuffer.append(name);
1910 // cannot display/create wiki, so just display the text
1911 fResultBuffer.append(name);
1918 public String createAnchor(String head) {
1919 StringBuffer result = new StringBuffer(head.length() + 1);
1922 // reduce Anchorstring
1923 for (int i = 0; i < head.length(); i++) {
1924 ch = head.charAt(i);
1925 if ('a' <= ch && 'z' >= ch) {
1927 } else if ('A' <= ch && 'Z' >= ch) {
1929 } else if ('0' <= ch && '9' >= ch) {
1934 // result.append('_');
1936 // case '<' : // special html escape character
1937 // fResult.append(Encoder.toEntity('<'));
1939 // case '>' : // special html escape character
1940 // fResult.append(Encoder.toEntity('>'));
1942 // case '&' : // special html escape character
1943 // fResult.append(Encoder.toEntity('&'));
1945 // case '\'' : // special html escape character
1946 // fResult.append(Encoder.toEntity('\''));
1948 // case '\"' : // special html escape character
1949 // fResult.append(Encoder.toEntity('\"'));
1952 // result.append(ch);
1955 return result.toString();
1958 public static StringBuffer appendLink(StringBuffer buffer, String name, String view, String target) {
1959 return appendLinkWithRoot(buffer, null, name + "#" + target, view);
1963 * Create a link with a root and a special view. The name will not be url encoded!
1965 public static StringBuffer appendLinkWithRoot(StringBuffer buffer, String root, String name, String view) {
1966 buffer.append("<a href=\"");
1968 buffer.append(root);
1971 buffer.append(name);
1972 buffer.append("\">");
1973 buffer.append(Encoder.escape(view));
1974 buffer.append("</a>");
1979 * add an entry to the "table of content" TODO refactor this to a class
1986 private void addToTableOfContent(ArrayList toc, String head, String anchor, int headLevel) {
1988 if (level == headLevel) {
1989 String snipName = "";
1990 // if (fSnip != null) {
1991 // snipName = fSnip.getName();
1994 StringBuffer link = new StringBuffer(snipName.length() + 40 + head.length() + anchor.length());
1995 link.append("<li>");
1996 //TODO create link for table of content
1997 appendLink(link, snipName, head, anchor);
1998 link.append("</li>");
1999 toc.add(link.toString());
2001 if (toc.size() > 0) {
2002 if (toc.get(toc.size() - 1) instanceof ArrayList) {
2003 addToTableOfContent((ArrayList) toc.get(toc.size() - 1), head, anchor, --headLevel);
2007 ArrayList list = new ArrayList();
2009 addToTableOfContent(list, head, anchor, --headLevel);
2014 * handle head for table of content
2019 private void handleHead(String head, int headLevel) {
2021 String anchor = createAnchor(head.trim());
2023 if (fTableOfContent == null) {
2024 // create new table of content
2025 fTableOfContent = new ArrayList();
2026 // copy fResult and new initialization:
2028 fResultBufferHeader = fResultBuffer;
2029 fResultBuffer = new StringBuffer(fResultBuffer.capacity());
2031 addToTableOfContent(fTableOfContent, head, anchor, headLevel);
2033 fResultBuffer.append("<h");
2034 fResultBuffer.append(headLevel);
2035 fResultBuffer.append("><a name=\"");
2036 fResultBuffer.append(anchor);
2037 fResultBuffer.append("\">");
2038 fResultBuffer.append(head);
2039 fResultBuffer.append("</a></h");
2040 fResultBuffer.append(headLevel);
2041 fResultBuffer.append(">");
2042 // if (headLevel <= 2) {
2043 // fResultBuffer.append("<hr/>");
2048 private boolean getList(char listChar, String openTag, String closeTag) {
2049 int currentPosition = fCurrentPosition;
2050 int level = getNumberOfChar(listChar) + 1;
2051 if (getNextChar('.') && getNextChar(' ')) {
2052 int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 3 - level);
2053 if (tempPosition >= 0) {
2054 copyWhite(fWhiteStart, fWhiteStartPosition, 2 + level);
2055 fWhiteStart = false;
2056 AbstractTag tok = (AbstractTag) fTokenStack.peek();
2057 if (tok instanceof ListToken) {
2058 ListToken listToken = (ListToken) tok;
2059 int topLevel = listToken.getLevel();
2060 if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START) {
2061 if (level > topLevel) {
2062 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel + 1));
2063 fResultBuffer.append(openTag + "<li>");
2064 } else if (level < topLevel) {
2066 fResultBuffer.append("</li>" + closeTag + "</li><li>");
2068 fResultBuffer.append("</li><li>");
2071 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, level));
2072 fResultBuffer.append(openTag + "<li>");
2075 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, 1));
2076 fResultBuffer.append("\n" + openTag + "<li>");
2081 fCurrentPosition = currentPosition;
2086 * read until the string is found
2091 private final boolean readUntilString(String testedString) {
2092 int temp = fCurrentPosition;
2093 int index = fStringSource.indexOf(testedString, fCurrentPosition);
2094 if (index != (-1)) {
2095 fCurrentPosition = index + testedString.length();
2102 * read until character is found
2107 private final boolean readUntilChar(char testedChar) {
2108 int temp = fCurrentPosition;
2110 while ((fCurrentCharacter = fSource[fCurrentPosition++]) != testedChar) {
2113 } catch (IndexOutOfBoundsException e) {
2114 fCurrentPosition = temp;
2120 * read until character is found or end-of-line is reached
2123 * @return -1 - for IndexOutOfBoundsException; 0 - for LF found; 1 - for testedChar found
2125 private final int readUntilCharOrEOL(char testedChar) {
2126 int temp = fCurrentPosition;
2128 while ((fCurrentCharacter = fSource[fCurrentPosition++]) != testedChar) {
2129 // if (fCurrentCharacter == '\n') {
2134 } catch (IndexOutOfBoundsException e) {
2135 fCurrentPosition = temp;
2141 * read until character is found or end-of-line is reached
2144 * @return -1 - for IndexOutOfBoundsException; 0 - for LF found; 1 - for testedChar found
2146 private final boolean readUntilEOL() {
2147 int temp = fCurrentPosition;
2150 fCurrentCharacter = fSource[fCurrentPosition++];
2151 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
2155 } catch (IndexOutOfBoundsException e) {
2162 * Returns the view of the wiki name that is shown to the fUser. Overwrite to support other views for example transform
2163 * "WikiLinking" to "Wiki Linking". Does nothing by default.
2165 * @return view The view of the wiki name
2167 // protected String getWikiView(String name) {
2170 private void handleMacro(String completeMacroSubString, String command, String unsplittedMacroParameters, String group3) {
2171 if (command != null) {
2172 // {$peng} are variables not macros.
2173 if (!command.startsWith("$")) {
2174 MacroParameter mParams = fContext.getMacroParameter();
2176 if (group3 != null) {
2177 mParams.setContent(group3);
2178 mParams.setContentStart(0);
2179 mParams.setContentEnd(group3.length());
2181 if (unsplittedMacroParameters != null && unsplittedMacroParameters.length() > 1) {
2182 // mParams.setParams(parseParameters(unsplittedMacroParameters));
2183 mParams.setParams(unsplittedMacroParameters);
2185 mParams.setStart(0);
2186 mParams.setEnd(completeMacroSubString.length());
2188 // @DANGER: recursive calls may replace macros in included
2191 if (fMacros.containsKey(command)) {
2192 Macro macro = (Macro) fMacros.get(command);
2194 // recursively filter macros within macros
2195 if (null != mParams.getContent() && !(macro instanceof INoParserBodyFilterMacro)) {
2196 mParams.setContent(WikipediaFilter.filterParser(mParams.getContent(), fContext, fMacros, fRecursionLevel));
2198 StringBufferWriter writer = new StringBufferWriter(new StringBuffer(256));
2199 macro.execute(writer, mParams);
2200 StringBuffer buffer = writer.getBuffer();
2201 if (macro instanceof IRenderResultMacro) {
2202 fResultBuffer.append(WikipediaFilter.filterParser(buffer.toString(), fContext, fMacros, fRecursionLevel));
2204 fResultBuffer.append(buffer);
2207 } else if (command.startsWith("!")) {
2209 RenderEngine engine = fContext.getRenderContext().getRenderEngine();
2210 if (engine instanceof IncludeRenderEngine) {
2211 String include = ((IncludeRenderEngine) engine).include(command.substring(1));
2212 if (null != include) {
2213 // Filter paramFilter = new
2214 // ParamFilter(mParams);
2215 // included = paramFilter.filter(included,
2217 // fResult.append(include);
2219 fResultBuffer.append(WikipediaFilter.filterParser(include, fContext, fMacros, fRecursionLevel));
2222 fResultBuffer.append(command.substring(1) + " not found.");
2228 // fResult.append(group0);
2229 copyWhite(completeMacroSubString);
2232 } catch (IllegalArgumentException e) {
2234 fResultBuffer.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
2236 e.printStackTrace();
2238 } catch (Throwable e) {
2239 // log.warn("MacroFilter: unable to format macro: " + command, e);
2240 fResultBuffer.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
2241 e.printStackTrace();
2245 fResultBuffer.append("<");
2246 fResultBuffer.append(command.substring(1));
2247 fResultBuffer.append(">");
2250 // fResult.append(group0);
2251 copyWhite(completeMacroSubString);
2255 public void parse() {
2256 int token = WikipediaFilter.TokenSTART;
2257 fTokenStack.add(WikipediaFilter.START);
2258 // fListStack.add(START);
2260 while ((token = getNextToken()) != WikipediaFilter.TokenEOF) {
2262 case WikipediaFilter.TokenBOLD:
2263 if (fTokenStack.peek() == WikipediaFilter.BOLD) {
2265 fResultBuffer.append("</b>");
2267 fTokenStack.push(WikipediaFilter.BOLD);
2268 fResultBuffer.append("<b>");
2271 case WikipediaFilter.TokenITALIC:
2272 if (fTokenStack.peek() == WikipediaFilter.ITALIC) {
2274 fResultBuffer.append("</i>");
2276 fTokenStack.push(WikipediaFilter.ITALIC);
2277 fResultBuffer.append("<i>");
2280 case WikipediaFilter.TokenSTRONG:
2281 if (fTokenStack.peek() == WikipediaFilter.STRONG) {
2283 fResultBuffer.append("</strong>");
2285 fTokenStack.push(WikipediaFilter.STRONG);
2286 fResultBuffer.append("<strong>");
2289 case WikipediaFilter.TokenEM:
2290 if (fTokenStack.peek() == WikipediaFilter.EM) {
2292 fResultBuffer.append("</em>");
2294 fTokenStack.push(WikipediaFilter.EM);
2295 fResultBuffer.append("<em>");
2298 case WikipediaFilter.TokenSTRIKETHROUGH:
2299 if (fTokenStack.peek() == WikipediaFilter.STRIKETHROUGH) {
2301 fResultBuffer.append("</strike>");
2303 fTokenStack.push(WikipediaFilter.STRIKETHROUGH);
2304 fResultBuffer.append("<strike>");
2307 // case TokenLIST_UL_START :
2308 // if (fTokenStack.peek().equals(LIST_UL_START)) {
2309 // fResult.append("</li>\n<li>");
2311 // fTokenStack.push(LIST_UL_START);
2312 // fResult.append("\n<ul class=\"star\">\n<li>");
2315 // case TokenLIST_UL_END :
2316 // fTokenStack.pop();
2317 // fResult.append("</li>\n</ul>\n");
2319 // case TokenLIST_OL_START :
2320 // if (fTokenStack.peek().equals(LIST_OL_START)) {
2321 // fResult.append("</li>\n<li>");
2323 // fTokenStack.push(LIST_OL_START);
2324 // fResult.append("\n<ol>\n<li>");
2327 // case TokenLIST_OL_END :
2328 // fTokenStack.pop();
2329 // fResult.append("</li>\n</ol>\n");
2333 } catch (InvalidInputException e) {
2336 // clear rest of stack if necessary (case of error in syntax!?)
2338 while ((tok = (AbstractTag) fTokenStack.pop()) != WikipediaFilter.START) {
2339 if (tok instanceof OpenTagToken) {
2341 CloseTagToken closeToken = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tok.getTagName());
2342 if (closeToken == null) {
2343 // here is something wrong ???
2344 fResultBuffer.append("</" + (tok.getTagName()) + ">");
2346 fResultBuffer.append(closeToken.getCloseTag());
2348 } else if (tok == WikipediaFilter.BOLD) {
2349 fResultBuffer.append("</b>");
2350 } else if (tok == WikipediaFilter.ITALIC) {
2351 fResultBuffer.append("</i>");
2352 } else if (tok == WikipediaFilter.STRONG) {
2353 fResultBuffer.append("</strong>");
2354 } else if (tok == WikipediaFilter.EM) {
2355 fResultBuffer.append("</em>");
2356 } else if (tok == WikipediaFilter.STRIKETHROUGH) {
2357 fResultBuffer.append("</strike>");
2358 } else if (tok.equals(WikipediaFilter.LIST_UL_START)) {
2359 fResultBuffer.append("</li>\n</ul>\n");
2360 } else if (tok.equals(WikipediaFilter.LIST_OL_START)) {
2361 fResultBuffer.append("</li>\n</ol>\n");
2365 if (fResultBufferHeader != null) {
2366 int tocStart = fResultBufferHeader.length();
2367 if (isToC(fTableOfContent) > 3) {
2368 fResultBufferHeader.append("<table id=\"toc\" border=\"0\"><tr><th>Table of contents</th></tr><tr><td>");
2369 fResultBufferHeader.append("<ol>");
2370 createToC(fTableOfContent);
2371 fResultBufferHeader.append("</ol>");
2372 fResultBufferHeader.append("</td></tr></table><hr/>");
2375 fResultBufferHeader.append(fResultBuffer);
2376 fResultBuffer = fResultBufferHeader;
2377 fResultBufferHeader = null;
2378 fTableOfContent = null;
2383 * count the number of wiki headers in this document
2388 private int isToC(ArrayList toc) {
2390 if (toc.size() == 1 && (toc.get(0) instanceof ArrayList)) {
2391 return isToC((ArrayList) toc.get(0));
2394 for (int i = 0; i < toc.size(); i++) {
2395 if (toc.get(i) instanceof ArrayList) {
2396 result += isToC((ArrayList) toc.get(i));
2404 private void createToC(ArrayList toc) {
2405 if (toc.size() == 1 && (toc.get(0) instanceof ArrayList)) {
2406 createToC((ArrayList) toc.get(0));
2409 for (int i = 0; i < toc.size(); i++) {
2410 if (toc.get(i) instanceof ArrayList) {
2411 fResultBufferHeader.append("<ol>");
2412 createToC((ArrayList) toc.get(i));
2413 fResultBufferHeader.append("</ol>");
2415 fResultBufferHeader.append(toc.get(i));
2420 // public int readUntil(String testString) throws InvalidInputException {
2421 // startPosition = currentPosition;
2422 // int tempPosition;
2426 // currentCharacter = source[currentPosition++];
2427 // if (currentCharacter == testString.charAt(0)) {
2428 // tempPosition = currentPosition;
2430 // for (int i = 1; i < testString.length(); i++) {
2431 // currentCharacter = source[currentPosition++];
2432 // if (currentCharacter != testString.charAt(i)) {
2434 // currentPosition = tempPosition;
2439 // return TokenBODY;
2443 // } catch (IndexOutOfBoundsException e) {
2444 // // end of scanner text
2449 public int scanIdentifierOrKeyword(boolean isVariable) throws InvalidInputException {
2450 while (getNextCharAsWikiPluginIdentifierPart()) {
2453 return WikipediaFilter.TokenIdentifier;
2456 private final void setSource(char[] source) {
2457 //the source-buffer is set to sourceString
2458 if (source == null) {
2459 this.fSource = new char[0];
2461 this.fSource = source;
2463 // this.fEOFPosition = this.fSource.length;
2464 // fStartPosition = -1;
2467 private void unexpectedTag(String tag) {
2468 fResultBuffer.append("<div class=\"error\">Unexpected end for tag: <" + tag + "></div>");
2472 * @return Returns the context.
2474 public FilterContext getContext() {
2480 * The context to set.
2482 public void setContext(FilterContext context) {
2487 * @return Returns the wikiEngine.
2489 public RenderEngine getWikiEngine() {
2495 * The wikiEngine to set.
2497 public void setWikiEngine(RenderEngine wikiEngine) {
2498 fWikiEngine = wikiEngine;