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;
107 public WikipediaParser(MacroRepository macros, String stringSource, StringBuffer result, FilterContext context, int recursionLevel) {
109 fWikiEngine = context.getRenderContext().getRenderEngine();
112 // SnipMacroParameter params = (SnipMacroParameter)
113 // fContext.getMacroParameter();
114 // fSnip = params.getSnipRenderContext().getSnip();
115 // } catch (ClassCastException e) {
116 // e.printStackTrace();
119 fResultBuffer = result;
120 fStringSource = stringSource;
121 setSource(stringSource.toCharArray());
122 fRecursionLevel = recursionLevel;
123 fTokenStack = new Stack();
124 // fTableStack = new Stack();
125 // fTeXParser = new TeXParser("", "m:");
126 // fTeXImageParser = new TeXParser("", "");
129 // fSrcPath = (String) fContext.getRenderContext().get("srcpath");
130 // if (fSrcPath==null) {
133 // fBinPath = (String) fContext.getRenderContext().get("binpath");
134 // if (fBinPath==null) {
140 * Check until a new-line was found, if there are only whitespace characters before the given endposition.
142 * @param startPosition
144 * @return -1 if no whitespace line is found from the end (i.e. endPosition); otherwise the offset directly after where the
147 private int checkWhitespaces(int startPosition, int endPosition) {
149 while (endPosition >= startPosition) {
150 if ((tempChar = fSource[endPosition--]) == '\n') {
151 return endPosition + 2;
153 if (tempChar != ' ' && tempChar != '\t' && tempChar != '\r') {
157 if (endPosition < startPosition && endPosition >= 0) {
158 if ((tempChar = fSource[endPosition]) != '\n') {
161 } else if (endPosition == (-1) && startPosition == 0) {
162 // special case at the start of a string
165 return startPosition;
169 * copy the content in the resulting buffer and escape special html characters (< > " & ')
171 private void copyWhite(boolean whiteStart, final int whiteStartPosition, final int diff) {
173 final int len = fCurrentPosition - diff;
174 int currentIndex = whiteStartPosition;
175 int lastIndex = currentIndex;
176 while (currentIndex < len) {
177 switch (fSource[currentIndex++]) {
178 case '<': // special html escape character
179 if (lastIndex < (currentIndex - 1)) {
180 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
181 lastIndex = currentIndex;
185 fResultBuffer.append("<");
187 case '>': // special html escape character
188 if (lastIndex < (currentIndex - 1)) {
189 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
190 lastIndex = currentIndex;
194 fResultBuffer.append(">");
196 case '&': // special html escape character
197 if (lastIndex < (currentIndex - 1)) {
198 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
199 lastIndex = currentIndex;
203 fResultBuffer.append("&");
205 case '\'': // special html escape character
206 if (lastIndex < (currentIndex - 1)) {
207 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
208 lastIndex = currentIndex;
212 fResultBuffer.append("'");
214 case '\"': // special html escape character
215 if (lastIndex < (currentIndex - 1)) {
216 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex - 1);
217 lastIndex = currentIndex;
221 fResultBuffer.append(""");
225 if (lastIndex < (currentIndex)) {
226 fResultBuffer.append(fSource, lastIndex, currentIndex - lastIndex);
233 * copy the text in the resulting buffer and escape special html characters (< > " & ')
235 private void copyWhite(String text) {
236 final int len = text.length();
237 int currentIndex = 0;
238 int lastIndex = currentIndex;
239 while (currentIndex < len) {
240 switch (text.charAt(currentIndex++)) {
241 case '<': // special html escape character
242 if (lastIndex < (currentIndex - 1)) {
243 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
244 lastIndex = currentIndex;
246 fResultBuffer.append("<");
248 case '>': // special html escape character
249 if (lastIndex < (currentIndex - 1)) {
250 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
251 lastIndex = currentIndex;
255 fResultBuffer.append(">");
257 case '&': // special html escape character
258 if (lastIndex < (currentIndex - 1)) {
259 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
260 lastIndex = currentIndex;
264 fResultBuffer.append("&");
266 case '\'': // special html escape character
267 if (lastIndex < (currentIndex - 1)) {
268 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
269 lastIndex = currentIndex;
273 fResultBuffer.append("'");
275 case '\"': // special html escape character
276 if (lastIndex < (currentIndex - 1)) {
277 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
278 lastIndex = currentIndex;
282 fResultBuffer.append(""");
286 if (lastIndex < (currentIndex)) {
287 fResultBuffer.append(text.substring(lastIndex, currentIndex));
292 * Copy the text in the resulting buffer and escape special html characters (< > " & ') Additionally every
293 * newline will be replaced by <br/>
295 private void copyNowikiNewLine(String text) {
296 final int len = text.length();
297 int currentIndex = 0;
298 int lastIndex = currentIndex;
299 while (currentIndex < len) {
300 switch (text.charAt(currentIndex++)) {
302 if (lastIndex < (currentIndex - 1)) {
303 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
304 lastIndex = currentIndex;
308 fResultBuffer.append("<br/>");
310 case '<': // special html escape character
311 if (lastIndex < (currentIndex - 1)) {
312 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
313 lastIndex = currentIndex;
317 fResultBuffer.append("<");
319 case '>': // special html escape character
320 if (lastIndex < (currentIndex - 1)) {
321 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
322 lastIndex = currentIndex;
326 fResultBuffer.append(">");
328 // case '&': // special html escape character
329 // if (lastIndex < (currentIndex - 1)) {
330 // fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
331 // lastIndex = currentIndex;
335 // fResultBuffer.append("&");
337 case '\'': // special html escape character
338 if (lastIndex < (currentIndex - 1)) {
339 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
340 lastIndex = currentIndex;
344 fResultBuffer.append("'");
346 case '\"': // special html escape character
347 if (lastIndex < (currentIndex - 1)) {
348 fResultBuffer.append(text.substring(lastIndex, currentIndex - 1));
349 lastIndex = currentIndex;
353 fResultBuffer.append(""");
357 if (lastIndex < (currentIndex)) {
358 fResultBuffer.append(text.substring(lastIndex, currentIndex));
363 * Render the HTML token which are defined in the OPEN_TAGS and CLOSE_TAGS map
367 public int getHTMLToken() {
368 int currentHtmlPosition = fCurrentPosition;
372 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++])) {
416 tokenString = new String(fSource, tagNameStart, fCurrentPosition - tagNameStart - 1); //tagTokenizer.nextToken();
417 OpenTagToken token = (OpenTagToken) WikipediaFilter.OPEN_TAGS.get(tokenString);
419 return WikipediaFilter.TokenNotFound;
421 copyWhite(fWhiteStart, fWhiteStartPosition, (fCurrentPosition - tagNameStart) + 1);
424 if (token instanceof SpecialTagToken) {
425 fResultBuffer.append(token.getOpenTag());
426 while (Character.isWhitespace(fSource[fCurrentPosition])) {
429 if (fSource[fCurrentPosition] == '/') {
432 if (fSource[fCurrentPosition] == '>') {
435 } else if (token instanceof OpenTagToken) {
436 fResultBuffer.append("<");
437 fResultBuffer.append(token.getTagName());
438 fTokenStack.push(token);
439 fCurrentPosition = token.scan(fResultBuffer, fSource, fCurrentPosition - 1);
440 fResultBuffer.append(">");
443 // System.out.println(fResultBuffer);
444 return WikipediaFilter.TokenIgnore;
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;
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>");
719 // case '\\': // special characters follow
720 // copyWhite(fWhiteStart, fWhiteStartPosition, 1);
721 // fWhiteStart = false;
723 // fCurrentCharacter = fSource[fCurrentPosition++];
724 // switch (fCurrentCharacter) {
725 // case '\\': // newline
726 // if ((fCurrentCharacter = fSource[fCurrentPosition++]) == '\\') {
727 // fResultBuffer.append(Encoder
728 // .toEntity(fCurrentCharacter));
731 // fResultBuffer.append("<br />");
735 // fResultBuffer.append(Encoder
736 // .toEntity(fCurrentCharacter));
738 // } catch (IndexOutOfBoundsException e) {
742 // case '$' : // detect tex math
743 // copyWhite(fWhiteStart, fWhiteStartPosition, 1);
744 // fWhiteStart = false;
745 // startOfIndent = false;
746 // int startMathPosition = fCurrentPosition;
747 // if (getNextChar('$')) {
748 // startMathPosition = fCurrentPosition;
749 // copyWhite(fWhiteStart, fWhiteStartPosition, 2);
750 // fWhiteStart = false;
751 // if (readUntilString("$$")) {
752 // String mathContent = new String(fSource, startMathPosition,
753 // fCurrentPosition - startMathPosition - 2);
754 // if (mathContent != null) {
755 // handleTeXMath(mathContent, false);
760 // if (readUntilChar('$')) {
761 // String mathContent = new String(fSource, startMathPosition,
762 // fCurrentPosition - startMathPosition - 1);
763 // if (mathContent != null) {
764 // handleTeXMath(mathContent, true);
772 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
774 // boolean scanBody = true;
775 int startMacroPosition = fCurrentPosition;
776 if (getNextChar('|') && handleWikipediaTable()) { // Wikipedia
781 if (readUntilChar('}')) {
782 String macroStartTag;
784 macroStartTag = new String(fSource, startMacroPosition, fCurrentPosition - startMacroPosition - 1);
785 if (macroStartTag != null) {
786 createMacro(startMacroPosition, macroStartTag);
793 int startLinkPosition = fCurrentPosition;
794 if (getNextChar('[')) { // wikipedia link style
795 startLinkPosition = fCurrentPosition;
796 copyWhite(fWhiteStart, fWhiteStartPosition, 2);
798 if (readUntilString("]]")) {
799 String name = new String(fSource, startLinkPosition, fCurrentPosition - startLinkPosition - 2);
800 // test for suffix string
801 int temp = fCurrentPosition;
802 StringBuffer suffixBuffer = new StringBuffer();
805 fCurrentCharacter = fSource[fCurrentPosition++];
806 if (!Character.isLetterOrDigit(fCurrentCharacter)) {
810 suffixBuffer.append(fCurrentCharacter);
812 handleWikipediaLink(name, suffixBuffer.toString());
814 } catch (IndexOutOfBoundsException e) {
815 fCurrentPosition = temp;
818 handleWikipediaLink(name, "");
823 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
826 if (readUntilChar(']')) {
827 String name = new String(fSource, startLinkPosition, fCurrentPosition - startLinkPosition - 1);
828 handleSnipLink(name);
833 // case '1': // heading filter ?
834 // int temp1Position = checkWhitespaces(fWhiteStartPosition,
835 // fCurrentPosition - 2);
836 // if (temp1Position >= 0) {
837 // copyWhite(fWhiteStart, fWhiteStartPosition, 1);
838 // fWhiteStart = false;
839 // int simpleHeader = getNextChar(' ', '.');
840 // if (simpleHeader < 0) {
841 // if (getNextChar('1')) {
842 // fCurrentPosition--;
843 // if (getList('1', "<ol>", "</ol>")) {
849 // if (simpleHeader == 1 && !getNextChar('1')) {
850 // fCurrentPosition--;
851 // if (getList('1', "<ol>", "</ol>")) {
856 // temp1Position = fCurrentPosition;
857 // if (simpleHeader >= 0 && readUntilChar('\n')) {
858 // String heading = new String(fSource, temp1Position,
859 // fCurrentPosition - temp1Position - 1);
860 // if (heading != null) {
861 // fResultBuffer.append("<h3 class=\"heading-");
862 // if (simpleHeader == 1) {
863 // fResultBuffer.append("1");
865 // fResultBuffer.append("1-1");
867 // fResultBuffer.append("\">");
868 // // System.out.println(heading);
870 // .append(WikipediaFilter
874 // WikipediaFilter.DUMMY_CACHED_PAGE,
876 // fRecursionLevel));
877 // fResultBuffer.append("</h3>");
883 case '*': // <ul> list
884 case '#': // <ol> list
885 if (isStartOfLine()) {
886 char[] listChars = getListChars();
887 int tempStarPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - listChars.length);
888 if (tempStarPosition >= 0) {
889 appendList(listChars);
894 // case '#': // <ol> list
895 // if (fCurrentPosition >= 2) {
896 // char beforeChar = fSource[fCurrentPosition - 2];
897 // if (beforeChar == '\n' || beforeChar == '\r') {
899 // int levelHash = getNumberOfChar('#') + 1;
901 // int tempHashPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - levelHash);
902 // if (tempHashPosition >= 0) {
903 // copyWhite(fWhiteStart, fWhiteStartPosition, levelHash);
904 // fWhiteStart = false;
905 // AbstractTag tok = (AbstractTag) fTokenStack.peek();
906 // if (tok instanceof ListToken) {
907 // ListToken listToken = (ListToken) tok;
908 // int topLevel = listToken.getLevel();
909 // if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START) {
910 // if (levelHash > topLevel) {
911 // fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel + 1));
912 // fResultBuffer.append("<ol><li>");
913 // } else if (levelHash < topLevel) {
914 // fTokenStack.pop();
915 // fResultBuffer.append("</li></ol></li><li>");
917 // fResultBuffer.append("</li><li>");
920 // fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, levelHash));
921 // fResultBuffer.append("<ol><li>");
924 // fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, 1));
925 // fResultBuffer.append("\n<ol><li>");
934 // case 'i': // <ol> list
935 // if (getList('i', "<ol class=\"roman\">", "</ol>")) {
939 // case 'I': // <ol> list
940 // if (getList('i', "<ol class=\"ROMAN\">", "</ol>")) {
944 // case 'a' : // <ol> list
945 // if (getList('a', "<ol class=\"alpha\">", "</ol>")) {
949 // case 'A' : // <ol> list
950 // if (getList('A', "<ol class=\"ALPHA\">", "</ol>")) {
954 // case 'g' : // <ol> list
955 // if (getList('g', "<ol class=\"greek\">", "</ol>")) {
959 // case 'H' : // <ol> list
960 // if (getList('H', "<ol class=\"HIRAGANA\">", "</ol>")) {
964 // case 'k' : // <ol> list
965 // if (getList('k', "<ol class=\"katakana\">", "</ol>")) {
969 // case 'K' : // <ol> list
970 // if (getList('K', "<ol class=\"KATAKANA\">", "</ol>")) {
974 // case 'j' : // <ol> list
975 // if (getList('j', "<ol class=\"HEBREW\">", "</ol>")) {
981 if (getNextChar('\'')) {
982 if (getNextChar('\'')) {
983 copyWhite(fWhiteStart, fWhiteStartPosition, 3);
985 return WikipediaFilter.TokenSTRONG;
987 copyWhite(fWhiteStart, fWhiteStartPosition, 2);
989 return WikipediaFilter.TokenEM;
993 // if (getNextChar('_')) {
994 // copyWhite(fWhiteStart, fWhiteStartPosition, 2);
995 // fWhiteStart = false;
996 // return WikipediaFilter.TokenBOLD;
1000 // if (getNextChar('~')) {
1001 // copyWhite(fWhiteStart, fWhiteStartPosition, 2);
1002 // fWhiteStart = false;
1003 // return WikipediaFilter.TokenITALIC;
1007 int tempCurrPosition = fCurrentPosition;
1009 if (fSource[tempCurrPosition++] == '-' && fSource[tempCurrPosition++] == '-' && fSource[tempCurrPosition++] == '-') {
1010 if (fSource[tempCurrPosition] == '\n') {
1011 fCurrentPosition = tempCurrPosition;
1012 fResultBuffer.append("<hr/>");
1013 fWhiteStart = false;
1015 } else if (fSource[tempCurrPosition++] == '\r' && fSource[tempCurrPosition++] == '\n') {
1016 fCurrentPosition = tempCurrPosition - 1;
1017 fResultBuffer.append("<hr/>");
1018 fWhiteStart = false;
1022 } catch (IndexOutOfBoundsException e) {
1026 // int levelMinus = getNumberOfChar('-') + 1;
1027 // if (getNextChar(' ')) {
1028 // int tempPosition = checkWhitespaces(
1029 // fWhiteStartPosition, fCurrentPosition - 2
1031 // if (tempPosition >= 0) {
1032 // copyWhite(fWhiteStart, fWhiteStartPosition,
1034 // fWhiteStart = false;
1035 // AbstractTag tok = (AbstractTag) fTokenStack.peek();
1036 // if (tok instanceof ListToken) {
1037 // ListToken listToken = (ListToken) tok;
1038 // int topLevel = listToken.getLevel();
1039 // if (listToken.getToken() ==
1040 // WikipediaFilter.TokenLIST_UL_START) {
1041 // if (levelMinus > topLevel) {
1043 // .push(new ListToken(
1044 // WikipediaFilter.TokenLIST_UL_START,
1047 // .append("<ul class=\"minus\"><li>");
1048 // } else if (levelMinus < topLevel) {
1049 // fTokenStack.pop();
1051 // .append("</li></ul></li><li>");
1053 // fResultBuffer.append("</li><li>");
1057 // .push(new ListToken(
1058 // WikipediaFilter.TokenLIST_UL_START,
1061 // .append("<ul class=\"minus\"><li>");
1065 // .push(new ListToken(
1066 // WikipediaFilter.TokenLIST_UL_START,
1069 // .append("\n<ul class=\"minus\"><li>");
1074 // if (levelMinus == 2) {
1075 // copyWhite(fWhiteStart, fWhiteStartPosition, 2);
1076 // fWhiteStart = false;
1077 // return WikipediaFilter.TokenSTRIKETHROUGH;
1080 case 'h': // http(s)://
1081 int urlStartPosition = fCurrentPosition;
1082 boolean foundUrl = false;
1085 String urlString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 3);
1086 if (urlString.equals("http")) {
1087 fCurrentPosition += 3;
1088 fCurrentCharacter = fSource[fCurrentPosition++];
1089 if (fCurrentCharacter == 's') { // optional
1090 fCurrentCharacter = fSource[fCurrentPosition++];
1094 if (fCurrentCharacter == ':' && fSource[fCurrentPosition++] == '/' && fSource[fCurrentPosition++] == '/') {
1095 copyWhite(fWhiteStart, fWhiteStartPosition, diff);
1096 fWhiteStart = false;
1098 while (WikipediaFilter.isUrlIdentifierPart(fSource[fCurrentPosition++])) {
1102 } catch (IndexOutOfBoundsException e) {
1104 // rollback work :-)
1105 fCurrentPosition = urlStartPosition;
1109 String urlString = new String(fSource, urlStartPosition - 1, fCurrentPosition - urlStartPosition);
1111 WikipediaFilter.createExternalLink(fResultBuffer, fWikiEngine, urlString);
1116 // case '@': // images @xml@ -> /static/rss-small.png
1117 // copyWhite(fWhiteStart, fWhiteStartPosition, 1);
1118 // fWhiteStart = false;
1119 // int atStart = fCurrentPosition;
1120 // if (readUntilChar('@')) {
1121 // String imageTag = new String(fSource, atStart, fCurrentPosition - atStart - 1);
1122 // if (imageTag != null) {
1123 // if (WikipediaFilter.createStaticImage(imageTag, fResultBuffer)) {
1128 // fCurrentPosition = atStart;
1131 int ampersandStart = fCurrentPosition - 1;
1132 if (getNextChar('#')) {
1134 StringBuffer num = new StringBuffer(5);
1135 char ch = fSource[fCurrentPosition++];
1136 while (Character.isDigit(ch)) {
1138 ch = fSource[fCurrentPosition++];
1140 if (num.length() > 0 && ch == ';') {
1141 Integer i = Integer.valueOf(num.toString());
1142 if (i.intValue() < 65536) {
1143 copyWhite(fWhiteStart, fWhiteStartPosition, 3 + num.length());
1144 fWhiteStart = false;
1145 fResultBuffer.append(fSource, ampersandStart, fCurrentPosition - ampersandStart);
1149 } catch (IndexOutOfBoundsException e) {
1151 } catch (NumberFormatException e) {
1156 StringBuffer entity = new StringBuffer(10);
1157 char ch = fSource[fCurrentPosition++];
1158 while (Character.isLetterOrDigit(ch)) {
1160 ch = fSource[fCurrentPosition++];
1162 if (entity.length() > 0 && ch == ';') {
1163 if (WikipediaFilter.ENTITY_SET.contains(entity.toString())) {
1164 copyWhite(fWhiteStart, fWhiteStartPosition, 2 + entity.length());
1165 fWhiteStart = false;
1166 fResultBuffer.append(fSource, ampersandStart, fCurrentPosition - ampersandStart);
1170 } catch (IndexOutOfBoundsException e) {
1172 } catch (NumberFormatException e) {
1178 int htmlStartPosition = fCurrentPosition;
1180 switch (fStringSource.charAt(fCurrentPosition)) {
1181 case '!': // <!-- html comment -->
1182 String htmlCommentString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 3);
1184 if (htmlCommentString.equals("<!--")) {
1185 fCurrentPosition += 3;
1186 if (readUntilString("-->")) {
1187 String htmlCommentContent = new String(fSource, htmlStartPosition + 3, fCurrentPosition - htmlStartPosition - 6);
1188 if (htmlCommentContent != null) {
1189 copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - htmlStartPosition + 1);
1190 fWhiteStart = false;
1191 // insert html comment for visual checks
1194 * fResultBuffer.append(" <!--"); copyWhite(htmlCommentContent); fResultBuffer.append("--> ");
1201 // case 'm' : // math
1202 // String mathString =
1203 // fStringSource.substring(fCurrentPosition - 1,
1204 // fCurrentPosition + 5);
1206 // if (mathString.equals("<math>")) {
1207 // fCurrentPosition += 5;
1208 // if (readUntilString("</math>")) {
1209 // String mathContent = new String(fSource,
1210 // htmlStartPosition + 5, fCurrentPosition -
1211 // htmlStartPosition - 12);
1212 // if (mathContent != null) {
1213 // copyWhite(fWhiteStart, fWhiteStartPosition,
1214 // fCurrentPosition - htmlStartPosition + 1);
1215 // fWhiteStart = false;
1216 // if (startOfIndent) {
1217 // startOfIndent = false;
1218 // handleTeXMath(mathContent, false);
1220 // handleTeXMath(mathContent, true);
1228 String nowikiString = fStringSource.substring(fCurrentPosition - 1, fCurrentPosition + 7);
1230 if (nowikiString.equals("<nowiki>")) {
1231 fCurrentPosition += 7;
1232 if (readUntilString("</nowiki>")) {
1233 String nowikiContent = new String(fSource, htmlStartPosition + 7, fCurrentPosition - htmlStartPosition - 16);
1234 if (nowikiContent != null) {
1235 copyWhite(fWhiteStart, fWhiteStartPosition, fCurrentPosition - htmlStartPosition + 1);
1236 fWhiteStart = false;
1237 copyNowikiNewLine(nowikiContent);
1244 } catch (IndexOutOfBoundsException e) {
1247 startOfIndent = false;
1248 fCurrentPosition = htmlStartPosition;
1249 // detect special html tags
1250 int htmlToken = getHTMLToken();
1251 if (htmlToken == WikipediaFilter.TokenIgnore) {
1253 // } else if (htmlToken > TokenIgnore) {
1254 // return htmlToken;
1256 fCurrentPosition = htmlStartPosition;
1258 case '=': // wikipedia header ?
1259 if (isStartOfLine()) {
1260 int levelHeader = getNumberOfChar('=') + 1;
1261 // int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 1 - levelHeader);
1262 // if (tempPosition >= 0) {
1263 copyWhite(fWhiteStart, fWhiteStartPosition, levelHeader);
1264 fWhiteStart = false;
1265 int startHeadPosition = fCurrentPosition;
1266 // int initialOffset = levelHeader;
1267 if (levelHeader > 6) {
1271 if (readUntilString(WikipediaFilter.HEADER_STRINGS[levelHeader])) {
1272 String head = new String(fSource, startHeadPosition, fCurrentPosition - startHeadPosition - (1 + levelHeader));
1274 handleHead(head, levelHeader);
1283 fWhiteStartPosition = fCurrentPosition - 1;
1286 startOfIndent = false;
1288 // -----------------end switch while try--------------------
1289 } catch (IndexOutOfBoundsException e) {
1290 // end of scanner text
1292 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
1294 return WikipediaFilter.TokenEOF;
1300 private boolean isStartOfLine() {
1301 boolean isListStart = false;
1302 if (fCurrentPosition >= 2) {
1303 char beforeChar = fSource[fCurrentPosition - 2];
1304 if (beforeChar == '\n' || beforeChar == '\r') {
1308 if (fCurrentPosition == 1) {
1319 private void appendList(char[] listChars) {
1321 int levelStar = listChars.length;
1322 copyWhite(fWhiteStart, fWhiteStartPosition, levelStar);
1323 fWhiteStart = false;
1324 AbstractTag tok = (AbstractTag) fTokenStack.peek();
1326 if (tok instanceof ListToken) {
1327 ListToken listToken = (ListToken) tok;
1328 topLevel = listToken.getLevel();
1330 if (levelStar > topLevel) {
1331 while (levelStar > topLevel) {
1332 if (listChars[topLevel] == '*') {
1333 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, ++topLevel));
1334 fResultBuffer.append("<ul><li>");
1336 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, ++topLevel));
1337 fResultBuffer.append("<ol><li>");
1340 } else if (levelStar < topLevel) {
1341 while (levelStar < topLevel) {
1342 tok = (AbstractTag) fTokenStack.peek();
1343 if (tok instanceof ListToken) {
1345 listToken = (ListToken) tok;
1346 if (listToken.getToken() == WikipediaFilter.TokenLIST_UL_START) {
1347 fResultBuffer.append("</li></ul></li><li>");
1349 fResultBuffer.append("</li></ol></li><li>");
1358 if (listToken.getToken() == WikipediaFilter.TokenLIST_UL_START && listChars[topLevel] == '#') {
1360 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel));
1361 fResultBuffer.append("</li></ul><ol><li>");
1362 } else if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START && listChars[topLevel] == '*') {
1364 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, topLevel));
1365 fResultBuffer.append("</li></ol><ul><li>");
1367 fResultBuffer.append("</li><li>");
1371 while (levelStar > topLevel) {
1372 if (listChars[topLevel] == '*') {
1373 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_UL_START, ++topLevel));
1374 fResultBuffer.append("\n<ul><li>");
1376 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, ++topLevel));
1377 fResultBuffer.append("\n<ol><li>");
1383 private void createMacro(int startMacroPosition, String macroStartTag) {
1384 String command = "";
1387 String parameterString = null;
1388 String macroBodyString = "";
1391 if ((index0 = macroStartTag.indexOf(':')) >= 0) {
1392 command = macroStartTag.substring(0, index0);
1393 parameterString = macroStartTag.substring(index0 + 1, macroStartTag.length());
1395 command = macroStartTag;
1397 Macro macro = (Macro) fMacros.get(command);
1399 String completeMacroSubString;
1401 if ((macro != null) && (macro instanceof IBodyTagSupportMacro)) {
1402 endTag = '{' + command + '}';
1403 index0 = fStringSource.indexOf(endTag, fCurrentPosition);
1406 macroBodyString = fStringSource.substring(fCurrentPosition, index0);
1407 completeMacroSubString = new String(fSource, startMacroPosition - 1, index0 + endTag.length() - startMacroPosition + 1);
1408 fCurrentPosition = startMacroPosition + completeMacroSubString.length() - 1;
1410 completeMacroSubString = new String(fSource, startMacroPosition - 1, macroStartTag.length() + 2);
1413 completeMacroSubString = new String(fSource, startMacroPosition - 1, macroStartTag.length() + 2);
1416 copyWhite(fWhiteStart, fWhiteStartPosition, 1);
1418 handleMacro(completeMacroSubString, command, parameterString, macroBodyString);
1421 // private void createExternalLink(String urlString) {
1423 // // Does our engine know images?
1424 // if (fWikiEngine instanceof ImageRenderEngine) {
1425 // fResult.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
1427 // fResult.append("<span class=\"nobr\">");
1428 // fResult.append("<a href=\"");
1429 // fResult.append(Encoder.escape(urlString));
1430 // fResult.append("\">");
1431 // fResult.append(Encoder.toEntity(urlString.charAt(0)) +
1432 // urlString.substring(1));
1433 // fResult.append("</a></span>");
1436 // private void handleTeXMath(String mathContent, boolean inlineExpression)
1438 // // TODO clean this up
1439 // Map map = Application.get().getParameters();
1440 // HttpServletRequest request = (HttpServletRequest) map.get("request");
1441 // MathSniffer sniffy = MathSniffer.getBrowserDetection(request);
1443 // if (fCacheStaticBlockActive) {
1444 // fCachedPage.addHTML(fResultBuffer.substring(fCacheStaticBlockStartPosition,
1445 // fResultBuffer.length()));
1446 // fCacheStaticBlockActive = false;
1448 // // if (inlineExpression) {
1449 // // fASMCompiler.compileMath(mathContent, "true");
1451 // // fASMCompiler.compileMath(mathContent, "false");
1453 // if (fCachedPage == WikipediaFilter.DUMMY_CACHED_PAGE) {
1454 // switch (sniffy.getBrowserId()) {
1455 // case MathSniffer.XMLID :
1456 // case MathSniffer.MATHPLAYERID :
1457 // if (inlineExpression) {
1458 // fResultBuffer.append("<m:math><m:mstyle mathcolor=\"Black\"
1459 // displaystyle=\"true\">");
1460 // fTeXParser.initialize(mathContent);
1461 // fTeXParser.parse2MML(fResultBuffer);
1462 // fResultBuffer.append("</m:mstyle></m:math>");
1464 // fResultBuffer.append("<dl><dd><m:math><m:mstyle mathcolor=\"Black\"
1465 // displaystyle=\"true\">");
1466 // fTeXParser.initialize(mathContent);
1467 // fTeXParser.parse2MML(fResultBuffer);
1468 // fResultBuffer.append("</m:mstyle></m:math></dd></dl>");
1471 // case MathSniffer.CSSID :
1472 // if (inlineExpression) {
1473 // fResultBuffer.append("<m>");
1474 // fTeXParser.initialize(mathContent);
1475 // fTeXParser.parse2CSS(fResultBuffer, true);
1476 // fResultBuffer.append("</m>");
1478 // fResultBuffer.append("<e>");
1479 // fTeXParser.initialize(mathContent);
1480 // fTeXParser.parse2CSS(fResultBuffer, true);
1481 // fResultBuffer.append("</e>");
1485 // copyWhite(mathContent);
1488 // String[] mathStrings = new String[3];
1489 // StringBuffer mathBuffer = new StringBuffer();
1490 // if (inlineExpression) {
1492 // mathBuffer.append("<m:math><m:mstyle mathcolor=\"Black\"
1493 // displaystyle=\"true\">");
1495 // fTeXParser.initialize(mathContent);
1496 // fTeXParser.parse2MML(mathBuffer);
1497 // mathBuffer.append("</m:mstyle></m:math>");
1499 // mathBuffer.append("<dl><dd><m:math><m:mstyle mathcolor=\"Black\"
1500 // displaystyle=\"true\">");
1501 // fTeXParser.initialize(mathContent);
1502 // fTeXParser.parse2MML(mathBuffer);
1503 // mathBuffer.append("</m:mstyle></m:math></dd></dl>");
1505 // mathStrings[0] = mathBuffer.toString();
1506 // mathBuffer.setLength(0);
1507 // // if (inlineExpression) {
1509 // // mathBuffer.append("<m>");
1510 // // fTeXParser.initialize(mathContent);
1511 // // fTeXParser.parse2CSS(mathBuffer, true);
1512 // // mathBuffer.append("</m>");
1514 // // // css block mode
1515 // // mathBuffer.append("<e>");
1516 // // fTeXParser.initialize(mathContent);
1517 // // fTeXParser.parse2CSS(mathBuffer, true);
1518 // // mathBuffer.append("</e>");
1521 // String encodedMathContent = Encoder.escape(mathContent);
1522 // StringBuffer mathmlBuffer = new StringBuffer();
1523 // String shortImageName = "____tex_" + (fImageCounter++);
1524 // String longImageName = shortImageName + ".gif";
1525 // mathmlBuffer.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
1526 // if (inlineExpression) {
1527 // mathmlBuffer.append("<math><mstyle mathcolor=\"Black\"
1528 // displaystyle=\"true\">");
1529 // fTeXImageParser.initialize(mathContent);
1530 // fTeXImageParser.parse2MML(mathmlBuffer);
1531 // mathmlBuffer.append("</mstyle></math>");
1533 // mathmlBuffer.append("<math><mstyle mathcolor=\"Black\"
1534 // displaystyle=\"true\">");
1535 // fTeXImageParser.initialize(mathContent);
1536 // fTeXImageParser.parse2MML(mathmlBuffer);
1537 // mathmlBuffer.append("</mstyle></math>");
1540 // String snipname = fSnip.getName();
1541 // String SnipSnapSpacePath =
1542 // Application.get().getConfiguration().getFilePath().getAbsolutePath();
1543 // // Remove old image
1544 // fSnip.getAttachments().removeAttachment(longImageName + ".gif");
1546 // String directoryName = SnipSnapSpacePath + "/" + snipname;
1547 // File directory = new File(directoryName);
1548 // if (!directory.exists()) {
1549 // directory.mkdirs();
1551 // String gifFilename = directoryName + "/" + longImageName;
1552 // // File file = new File();
1553 // // Get the number of bytes in the file
1554 // // long length = file.length();
1555 // MathMLToGIFConverter conv = new MathMLToGIFConverter();
1557 // // "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><math
1559 // mode=\"display\"><mrow><munderover><mo>∫</mo><mn>1</mn><mi>x</mi></munderover><mfrac><mi>dt</mi><mi>t</mi></mfrac></mrow></math>";
1561 // File imageFile = conv.convert(mathmlBuffer.toString(), gifFilename);
1562 // if (imageFile != null) {
1563 // Attachment attachment =
1564 // new Attachment(longImageName, "image/gif", imageFile.length(), new
1565 // Date(), snipname + "/" + longImageName, true);
1566 // // fSnip.getAttachments().addAttachment(longImageName, "image/gif",
1567 // imageFile.length(), snipname + "/" + longImageName,
1569 // fSnip.getAttachments().addAttachment(attachment);
1570 // StringWriter writer = new StringWriter();
1572 // SnipLink.appendImage(writer, fSnip, shortImageName, encodedMathContent,
1575 // mathBuffer = writer.getBuffer();
1576 // mathStrings[1] = mathBuffer.toString();
1578 // mathStrings[1] = encodedMathContent;
1580 // } catch (IOException e) {
1581 // // TODO Auto-generated catch block
1582 // e.printStackTrace();
1583 // mathStrings[1] = encodedMathContent;
1585 // mathBuffer.setLength(0);
1586 // WikipediaFilter.copyWhite(mathBuffer, mathContent);
1587 // mathStrings[2] = mathBuffer.toString();
1588 // fCachedPage.addMath(mathStrings);
1590 // if (!fCacheStaticBlockActive) {
1591 // fCacheStaticBlockActive = true;
1592 // fCacheStaticBlockStartPosition = fResultBuffer.length();
1595 private void handleSnipLink(String name) {
1597 int index = name.indexOf("http://");
1598 // Configuration probably wrote [http://radeox.org] instead of
1599 // http://radeox.org
1601 // WikipediaFilter.createExternalLink(fResultBuffer,
1602 // fWikiEngine, name.substring(index));
1603 String urlString = name.substring(index);
1604 // Wikipedia like style:
1605 int pipeIndex = urlString.indexOf(' ');
1607 if (pipeIndex != (-1)) {
1608 alias = urlString.substring(pipeIndex + 1);
1609 urlString = urlString.substring(0, pipeIndex);
1614 if (fWikiEngine instanceof ImageRenderEngine) {
1615 fResultBuffer.append(((ImageRenderEngine) fWikiEngine).getExternalImageLink());
1617 fResultBuffer.append("<span class=\"nobr\">");
1618 fResultBuffer.append("<a href=\"");
1619 fResultBuffer.append(Encoder.escape(urlString));
1620 fResultBuffer.append("\">");
1621 fResultBuffer.append(Encoder.toEntity(alias.charAt(0)) + alias.substring(1));
1622 fResultBuffer.append("</a></span>");
1625 // // trim the name and unescape it
1626 // name = Encoder.unescape(name.trim());
1627 // // Is there an alias like [alias|link] ?
1628 // int pipeIndex = name.indexOf('|');
1629 // String alias = "";
1630 // if (-1 != pipeIndex) {
1631 // alias = name.substring(0, pipeIndex);
1632 // name = name.substring(pipeIndex + 1);
1635 // int hashIndex = name.lastIndexOf('#');
1637 // String hash = "";
1638 // if (-1 != hashIndex && hashIndex != name.length() - 1) {
1639 // hash = name.substring(hashIndex + 1);
1640 // name = name.substring(0, hashIndex);
1643 // int colonIndex = name.indexOf(':');
1645 // if (-1 != colonIndex) {
1646 // // for now throw away the fType information
1647 // name = name.substring(colonIndex + 1);
1650 // int atIndex = name.lastIndexOf('@');
1651 // // InterWiki link ?
1652 // if (-1 != atIndex) {
1653 // String extSpace = name.substring(atIndex + 1);
1654 // // known extarnal space ?
1655 // InterWiki interWiki = InterWiki.getInstance();
1656 // if (interWiki.contains(extSpace)) {
1657 // name = name.substring(0, atIndex);
1658 // Writer writer = new StringBufferWriter(fResultBuffer);
1660 // if (-1 != hashIndex) {
1661 // interWiki.expand(writer, extSpace, name, hash);
1663 // interWiki.expand(writer, extSpace, name, "");
1665 // } catch (IOException e) {
1666 // log.debug("InterWiki " + extSpace + " not found.");
1669 // fResultBuffer.append("[<span class=\"error\">");
1670 // fResultBuffer.append(name);
1671 // fResultBuffer.append("?</span>]");
1675 // if (fWikiEngine != null && fWikiEngine instanceof WikiRenderEngine) {
1676 // if (fCacheStaticBlockActive) {
1677 // fCachedPage.addHTML(fResultBuffer.substring(fCacheStaticBlockStartPosition, fResultBuffer.length()));
1678 // fCacheStaticBlockActive = false;
1680 // fCachedPage.addSnipLink(name);
1681 // if (fCachedPage == WikipediaFilter.DUMMY_CACHED_PAGE) {
1682 // if (((WikiRenderEngine) fWikiEngine).exists(name)) {
1683 // String view = name;
1684 // if (-1 != pipeIndex) {
1687 // // Do not add hash if an alias was given
1688 // if (-1 != hashIndex) {
1689 // ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view, hash);
1691 // ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view);
1693 // } else if (((WikiRenderEngine) fWikiEngine).showCreate()) {
1694 // ((WikiRenderEngine) fWikiEngine).appendCreateLink(fResultBuffer, name, name);
1695 // // links with "create" are not cacheable because
1696 // // a missing wiki could be created
1697 // fContext.getRenderContext().setCacheable(false);
1699 // // cannot display/create wiki, so just display
1701 // fResultBuffer.append(name);
1704 // if (!fCacheStaticBlockActive) {
1705 // fCacheStaticBlockActive = true;
1706 // fCacheStaticBlockStartPosition = fResultBuffer.length();
1709 // // cannot display/create wiki, so just display the text
1710 // fResultBuffer.append(name);
1717 private boolean handleWikipediaTable() {
1729 int temp = fCurrentPosition;
1730 int sequenceStart = 0;
1731 char lastChar = ' ';
1732 int sequenceLength = 0;
1733 int thStartPosition = 0;
1734 Stack wpTokenStack = new Stack();
1736 // add table attributes:
1737 fResultBuffer.append("<table ");
1738 sequenceStart = fCurrentPosition;
1739 fCurrentCharacter = fSource[fCurrentPosition++];
1740 while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
1742 fCurrentCharacter = fSource[fCurrentPosition++];
1744 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
1745 fCurrentCharacter = fSource[fCurrentPosition++];
1747 if (sequenceLength > 0) {
1748 fResultBuffer.append(fSource, sequenceStart + 1, sequenceLength - 1);
1750 fResultBuffer.append(">");
1751 wpTokenStack.push(WikipediaFilter.HTML_TABLE_OPEN);
1753 fResultBuffer.append("<tr>\n");
1754 wpTokenStack.push(WikipediaFilter.HTML_TR_OPEN);
1755 String attributes = null;
1756 // parse rest of table
1758 sequenceStart = fCurrentPosition;
1759 fCurrentCharacter = fSource[fCurrentPosition++];
1760 if (fCurrentCharacter == '{' && fSource[fCurrentPosition] == '|') { // nested table
1761 handleWikipediaTable();
1762 } else if (fCurrentCharacter == '!') {
1764 reduceTableCellStack(fResultBuffer, wpTokenStack);
1765 fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1766 sequenceStart = fCurrentPosition;
1767 // add header row cells
1770 fCurrentCharacter = fSource[fCurrentPosition++];
1771 if (fCurrentCharacter == '|' || fCurrentCharacter == '\n') {
1772 if (fSource[fCurrentPosition] == '|' || fCurrentCharacter == '\n') {
1773 reduceTableCellStack(fResultBuffer, wpTokenStack);
1774 if (attributes == null) {
1775 fResultBuffer.append("<th>");
1777 fResultBuffer.append("<th ");
1778 fResultBuffer.append(attributes);
1779 fResultBuffer.append(">");
1781 wpTokenStack.push(WikipediaFilter.HTML_TH_OPEN);
1782 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1783 - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1785 sequenceStart = fCurrentPosition;
1788 attributes = new String(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1789 sequenceStart = fCurrentPosition;
1792 if (fCurrentCharacter == '\n') {
1797 } else if (fCurrentCharacter == '|') {
1798 reduceTableCellStack(fResultBuffer, wpTokenStack);
1799 fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1801 sequenceStart = fCurrentPosition;
1802 fCurrentCharacter = fSource[fCurrentPosition++];
1803 switch (fCurrentCharacter) {
1804 case '+': // caption
1806 reduceTableRowStack(WikipediaFilter.HTML_TABLE_OPEN, fResultBuffer, wpTokenStack);
1807 fResultBuffer.append("<caption>\n");
1808 wpTokenStack.push(WikipediaFilter.HTML_CAPTION_OPEN);
1809 // read until end of line
1810 while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
1811 fCurrentCharacter = fSource[fCurrentPosition++];
1813 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
1814 fCurrentCharacter = fSource[fCurrentPosition++];
1816 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition - sequenceStart
1817 - 1), fContext, fMacros, fRecursionLevel));
1819 case '-': // new row
1821 reduceTableRowStack(WikipediaFilter.HTML_TR_OPEN, fResultBuffer, wpTokenStack);
1823 // read until end of line
1824 while (fCurrentCharacter != '\n' && fCurrentCharacter != '\r') {
1825 fCurrentCharacter = fSource[fCurrentPosition++];
1827 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
1828 fCurrentCharacter = fSource[fCurrentPosition++];
1830 // TODO handle row attributes
1831 fResultBuffer.append("<tr ");
1832 wpTokenStack.push(WikipediaFilter.HTML_TR_OPEN);
1833 fResultBuffer.append(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1834 fResultBuffer.append(">\n");
1835 // fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1836 // - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1838 case '}': // end of table
1839 clearTableStack(fResultBuffer, wpTokenStack);
1840 // System.out.println(fResultBuffer.toString());
1846 fCurrentCharacter = fSource[fCurrentPosition++];
1847 if (fCurrentCharacter == '|' || fCurrentCharacter == '\n') {
1848 if (fSource[fCurrentPosition] == '|' || fCurrentCharacter == '\n') {
1849 reduceTableCellStack(fResultBuffer, wpTokenStack);
1850 if (attributes == null) {
1851 fResultBuffer.append("<td>");
1853 fResultBuffer.append("<td ");
1854 fResultBuffer.append(attributes);
1855 fResultBuffer.append(">");
1857 wpTokenStack.push(WikipediaFilter.HTML_TD_OPEN);
1858 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1859 - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1860 // TODO reduce fTokenStack to <tr> element
1862 // fResultBuffer.append("</td>");
1863 // fTokenStack.pop();
1865 sequenceStart = fCurrentPosition;
1868 attributes = new String(fSource, sequenceStart, fCurrentPosition - sequenceStart - 1);
1870 sequenceStart = fCurrentPosition;
1873 if (fCurrentCharacter == '\n') {
1879 } else if (wpTokenStack.peek() == WikipediaFilter.HTML_TD_OPEN) {
1880 // continue a table cell in the next line
1882 if (fCurrentCharacter == '\n') {
1883 char ch0 = fSource[fCurrentPosition];
1884 char ch1 = fSource[fCurrentPosition + 1];
1885 if (ch0 == '|' || ch0 == '!' || (ch0 == '{' && ch1 == '|')) {
1886 fResultBuffer.append(WikipediaFilter.filterParser(new String(fSource, sequenceStart, fCurrentPosition
1887 - sequenceStart - 1), fContext, fMacros, fRecursionLevel));
1888 sequenceStart = fCurrentPosition;
1893 fCurrentCharacter = fSource[fCurrentPosition++];
1897 } catch (IndexOutOfBoundsException e) {
1898 if (sequenceStart + 1 < fCurrentPosition && fSource[sequenceStart + 1] == '}') {
1899 // TODO reduce fTokenStack to <tr> element if necessary
1900 // fResultBuffer.append("</tr></table>\n");
1901 // wpTokenStack.pop(); // tr
1902 // wpTokenStack.pop();// table
1903 // System.out.println(fResultBuffer.toString());
1904 clearTableStack(fResultBuffer, wpTokenStack);
1908 fCurrentPosition = temp - 1;
1909 // System.out.print(fResultBuffer.toString());
1911 } // private boolean handleWikipediaTable() {
1913 private void clearTableStack(StringBuffer buffer, Stack stack) {
1914 CloseTagToken closeTag;
1916 while (!stack.isEmpty()) {
1917 tag = (AbstractTag) stack.pop();
1918 closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
1919 buffer.append(closeTag.getCloseTag());
1923 private void reduceTableRowStack(AbstractTag stopTag, StringBuffer buffer, Stack stack) {
1924 CloseTagToken closeTag;
1926 while (!stack.isEmpty()) {
1927 tag = (AbstractTag) stack.peek();
1928 if (tag == WikipediaFilter.HTML_TABLE_OPEN) {
1932 closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
1933 buffer.append(closeTag.getCloseTag());
1934 if (tag == WikipediaFilter.HTML_TR_OPEN || tag == WikipediaFilter.HTML_CAPTION_OPEN) {
1940 private void reduceTableCellStack(StringBuffer buffer, Stack stack) {
1941 CloseTagToken closeTag;
1943 while (!stack.isEmpty()) {
1944 tag = (AbstractTag) stack.peek();
1945 if (tag != WikipediaFilter.HTML_TH_OPEN && tag != WikipediaFilter.HTML_TD_OPEN) {
1949 closeTag = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tag.getTagName());
1950 buffer.append(closeTag.getCloseTag());
1951 if (tag == WikipediaFilter.HTML_TR_OPEN || tag == WikipediaFilter.HTML_CAPTION_OPEN || tag == WikipediaFilter.HTML_TH_OPEN
1952 || tag == WikipediaFilter.HTML_TD_OPEN) {
1970 // int temp = fCurrentPosition;
1971 // // StringBuffer suffixBuffer = new StringBuffer();
1972 // Table table = new Table(fContext.getRenderContext());
1973 // // char currentChar = ' ';
1974 // char lastChar = ' ';
1975 // // int startPosition = 0;
1976 // // int currentPosition = 0;
1977 // StringBuffer buffer = new StringBuffer();
1978 // int thStartPosition = 0;
1980 // try { // read first line
1981 // fCurrentCharacter = fSource[fCurrentPosition++];
1982 // // TODO improve this for different table attributes
1983 // while (fCurrentCharacter != '\n' ) {
1984 // fCurrentCharacter = fSource[fCurrentPosition++];
1985 // // System.out.println(fCurrentCharacter);
1988 // lastChar = fCurrentCharacter;
1989 // fCurrentCharacter = fSource[fCurrentPosition++];
1992 // switch (fCurrentCharacter) {
1993 // // case '{' : // start of nested table ?
1994 // // if (getNextChar('|') && handleWikipediaTable()) { // Wikipedia table
2000 // if (lastChar == '\n') {
2001 // table.addCell(buffer.toString());
2002 // // System.out.println(buffer.toString());
2003 // buffer.setLength(0);
2004 // thStartPosition = fCurrentPosition;
2006 // lastChar = fCurrentCharacter;
2007 // fCurrentCharacter = fSource[fCurrentPosition++];
2008 // if (fCurrentCharacter == '|') {
2011 // if (fCurrentCharacter == '\n') {
2013 // fCurrentPosition = thStartPosition;
2018 // buffer.append(fCurrentCharacter);
2022 // if (lastChar == '\n') {
2023 // if (getNextChar('}')) { // Wikipedia table end reached
2024 // table.addCell(buffer.toString());
2025 // StringWriter writer = new StringWriter();
2027 // table.appendTo(writer);
2028 // fResultBuffer.append(writer.getBuffer());
2029 // } catch (IOException e1) {
2030 // // TODO Auto-generated catch block
2031 // e1.printStackTrace();
2035 // } else if (getNextChar('-')) {
2036 // table.addCell(buffer.toString());
2037 // buffer.setLength(0);
2040 // lastChar = fCurrentCharacter;
2041 // fCurrentCharacter = fSource[fCurrentPosition++];
2042 // if (fCurrentCharacter == '|' || fCurrentCharacter == '!') {
2048 // if (buffer.length()>0) {
2049 // table.addCell(buffer.toString());
2050 // buffer.setLength(0);
2053 // } else if (getNextChar('|')) {
2054 // table.addCell(buffer.toString());
2055 // // System.out.println(buffer.toString());
2056 // buffer.setLength(0);
2058 // buffer.append(fCurrentCharacter);
2062 // buffer.append(fCurrentCharacter);
2064 // lastChar = fCurrentCharacter;
2065 // fCurrentCharacter = fSource[fCurrentPosition++];
2068 // } catch (IndexOutOfBoundsException e) {
2071 // fCurrentPosition = temp - 1;
2074 private void handleWikipediaLink(String linkText, String suffix) {
2075 String name = linkText;
2077 int index = name.indexOf("http://");
2078 // Configuration probably wrote [http://radeox.org] instead of
2079 // http://radeox.org
2081 WikipediaFilter.createExternalLink(fResultBuffer, fWikiEngine, name.substring(index));
2083 // fResult.append("<div class=\"error\">Do not surround URLs
2084 // with [...].</div>");
2086 // trim the name and unescape it
2087 name = Encoder.unescape(name.trim());
2088 // Is there an alias like [alias|link] ?
2089 int pipeIndex = name.indexOf('|');
2091 if (-1 != pipeIndex) {
2092 alias = name.substring(pipeIndex + 1);
2093 name = name.substring(0, pipeIndex);
2096 int hashIndex = name.lastIndexOf('#');
2099 if (-1 != hashIndex && hashIndex != name.length() - 1) {
2100 hash = name.substring(hashIndex + 1);
2101 name = name.substring(0, hashIndex);
2104 // int colonIndex = name.indexOf(':');
2106 // if (-1 != colonIndex) {
2107 // // for now throw away the fType information
2108 // name = name.substring(colonIndex + 1);
2111 int atIndex = name.lastIndexOf('@');
2113 if (-1 != atIndex) {
2114 String extSpace = name.substring(atIndex + 1);
2115 // known extarnal space ?
2116 InterWiki interWiki = InterWiki.getInstance();
2117 if (interWiki.contains(extSpace)) {
2118 name = name.substring(0, atIndex);
2119 Writer writer = new StringBufferWriter(fResultBuffer);
2121 if (-1 != hashIndex) {
2122 interWiki.expand(writer, extSpace, name, hash);
2124 interWiki.expand(writer, extSpace, name, "");
2126 } catch (IOException e) {
2127 // log.debug("InterWiki " + extSpace + " not found.");
2130 fResultBuffer.append("[<span class=\"error\">");
2131 fResultBuffer.append(name);
2132 fResultBuffer.append("?</span>]");
2136 if (name.startsWith("Image:") && (fWikiEngine instanceof ImageRenderEngine)) {
2137 // server part of rendering images
2138 ImageRenderEngine imageEngine = (ImageRenderEngine) fWikiEngine;
2139 // fResultBuffer.append("<img src=\"space/1/2004-11-21/5/");
2140 fResultBuffer.append("<img src=\"");
2141 fResultBuffer.append(FilterUtil.createServerImage(null, name.substring(6), null));
2142 fResultBuffer.append("\">");
2143 } else if (fWikiEngine != null && fWikiEngine instanceof WikiRenderEngine) {
2144 if (((WikiRenderEngine) fWikiEngine).exists(name)) {
2145 String view = name + suffix;
2146 if (-1 != pipeIndex) {
2147 view = alias + suffix;
2149 if (name.startsWith("Image:")) {
2150 fResultBuffer.append("<img src=\"");
2152 fResultBuffer.append(FilterUtil.createHTMLLink(null, name, null));
2153 fResultBuffer.append("\">");
2155 // Do not add hash if an alias was given
2156 if (-1 != hashIndex) {
2157 ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view, hash);
2159 ((WikiRenderEngine) fWikiEngine).appendLink(fResultBuffer, name, view);
2162 } else if (((WikiRenderEngine) fWikiEngine).showCreate()) {
2163 ((WikiRenderEngine) fWikiEngine).appendCreateLink(fResultBuffer, name, name + suffix);
2164 // links with "create" are not cacheable because
2165 // a missing wiki could be created
2166 fContext.getRenderContext().setCacheable(false);
2168 // cannot display/create wiki, so just display
2170 fResultBuffer.append(name);
2173 // cannot display/create wiki, so just display the text
2174 fResultBuffer.append(name);
2181 public String createAnchor(String head) {
2182 StringBuffer result = new StringBuffer(head.length() + 1);
2185 // reduce Anchorstring
2186 for (int i = 0; i < head.length(); i++) {
2187 ch = head.charAt(i);
2188 if ('a' <= ch && 'z' >= ch) {
2190 } else if ('A' <= ch && 'Z' >= ch) {
2192 } else if ('0' <= ch && '9' >= ch) {
2197 // result.append('_');
2199 // case '<' : // special html escape character
2200 // fResult.append(Encoder.toEntity('<'));
2202 // case '>' : // special html escape character
2203 // fResult.append(Encoder.toEntity('>'));
2205 // case '&' : // special html escape character
2206 // fResult.append(Encoder.toEntity('&'));
2208 // case '\'' : // special html escape character
2209 // fResult.append(Encoder.toEntity('\''));
2211 // case '\"' : // special html escape character
2212 // fResult.append(Encoder.toEntity('\"'));
2215 // result.append(ch);
2218 return result.toString();
2221 public static StringBuffer appendLink(StringBuffer buffer, String name, String view, String target) {
2222 return appendLinkWithRoot(buffer, null, name + "#" + target, view);
2226 * Create a link with a root and a special view. The name will not be url encoded!
2228 public static StringBuffer appendLinkWithRoot(StringBuffer buffer, String root, String name, String view) {
2229 buffer.append("<a href=\"");
2231 buffer.append(root);
2234 buffer.append(name);
2235 buffer.append("\">");
2236 buffer.append(Encoder.escape(view));
2237 buffer.append("</a>");
2242 * add an entry to the "table of content" TODO refactor this to a class
2249 private void addToTableOfContent(ArrayList toc, String head, String anchor, int headLevel) {
2251 if (level == headLevel) {
2252 String snipName = "";
2253 // if (fSnip != null) {
2254 // snipName = fSnip.getName();
2257 StringBuffer link = new StringBuffer(snipName.length() + 40 + head.length() + anchor.length());
2258 link.append("<li>");
2259 //TODO create link for table of content
2260 appendLink(link, snipName, head, anchor);
2261 link.append("</li>");
2262 toc.add(link.toString());
2264 if (toc.size() > 0) {
2265 if (toc.get(toc.size() - 1) instanceof ArrayList) {
2266 addToTableOfContent((ArrayList) toc.get(toc.size() - 1), head, anchor, --headLevel);
2270 ArrayList list = new ArrayList();
2272 addToTableOfContent(list, head, anchor, --headLevel);
2277 * handle head for table of content
2282 private void handleHead(String head, int headLevel) {
2284 String anchor = createAnchor(head.trim());
2286 if (fTableOfContent == null) {
2287 // create new table of content
2288 fTableOfContent = new ArrayList();
2289 // copy fResult and new initialization:
2291 fResultBufferHeader = fResultBuffer;
2292 fResultBuffer = new StringBuffer(fResultBuffer.capacity());
2294 addToTableOfContent(fTableOfContent, head, anchor, headLevel);
2296 fResultBuffer.append("<h");
2297 fResultBuffer.append(headLevel);
2298 fResultBuffer.append("><a name=\"");
2299 fResultBuffer.append(anchor);
2300 fResultBuffer.append("\">");
2301 fResultBuffer.append(head);
2302 fResultBuffer.append("</a></h");
2303 fResultBuffer.append(headLevel);
2304 fResultBuffer.append(">");
2305 // if (headLevel <= 2) {
2306 // fResultBuffer.append("<hr/>");
2311 private boolean getList(char listChar, String openTag, String closeTag) {
2312 int currentPosition = fCurrentPosition;
2313 int level = getNumberOfChar(listChar) + 1;
2314 if (getNextChar('.') && getNextChar(' ')) {
2315 int tempPosition = checkWhitespaces(fWhiteStartPosition, fCurrentPosition - 3 - level);
2316 if (tempPosition >= 0) {
2317 copyWhite(fWhiteStart, fWhiteStartPosition, 2 + level);
2318 fWhiteStart = false;
2319 AbstractTag tok = (AbstractTag) fTokenStack.peek();
2320 if (tok instanceof ListToken) {
2321 ListToken listToken = (ListToken) tok;
2322 int topLevel = listToken.getLevel();
2323 if (listToken.getToken() == WikipediaFilter.TokenLIST_OL_START) {
2324 if (level > topLevel) {
2325 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, topLevel + 1));
2326 fResultBuffer.append(openTag + "<li>");
2327 } else if (level < topLevel) {
2329 fResultBuffer.append("</li>" + closeTag + "</li><li>");
2331 fResultBuffer.append("</li><li>");
2334 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, level));
2335 fResultBuffer.append(openTag + "<li>");
2338 fTokenStack.push(new ListToken(WikipediaFilter.TokenLIST_OL_START, 1));
2339 fResultBuffer.append("\n" + openTag + "<li>");
2344 fCurrentPosition = currentPosition;
2349 * read until the string is found
2354 private final boolean readUntilString(String testedString) {
2355 int temp = fCurrentPosition;
2356 int index = fStringSource.indexOf(testedString, fCurrentPosition);
2357 if (index != (-1)) {
2358 fCurrentPosition = index + testedString.length();
2365 * read until character is found
2370 private final boolean readUntilChar(char testedChar) {
2371 int temp = fCurrentPosition;
2373 while ((fCurrentCharacter = fSource[fCurrentPosition++]) != testedChar) {
2376 } catch (IndexOutOfBoundsException e) {
2377 fCurrentPosition = temp;
2383 * read until character is found or end-of-line is reached
2386 * @return -1 - for IndexOutOfBoundsException; 0 - for LF found; 1 - for testedChar found
2388 private final int readUntilCharOrEOL(char testedChar) {
2389 int temp = fCurrentPosition;
2391 while ((fCurrentCharacter = fSource[fCurrentPosition++]) != testedChar) {
2392 // if (fCurrentCharacter == '\n') {
2397 } catch (IndexOutOfBoundsException e) {
2398 fCurrentPosition = temp;
2404 * read until character is found or end-of-line is reached
2407 * @return -1 - for IndexOutOfBoundsException; 0 - for LF found; 1 - for testedChar found
2409 private final boolean readUntilEOL() {
2410 int temp = fCurrentPosition;
2413 fCurrentCharacter = fSource[fCurrentPosition++];
2414 if (fCurrentCharacter == '\n' || fCurrentCharacter == '\r') {
2418 } catch (IndexOutOfBoundsException e) {
2425 * Returns the view of the wiki name that is shown to the fUser. Overwrite to support other views for example transform
2426 * "WikiLinking" to "Wiki Linking". Does nothing by default.
2428 * @return view The view of the wiki name
2430 // protected String getWikiView(String name) {
2433 private void handleMacro(String completeMacroSubString, String command, String unsplittedMacroParameters, String group3) {
2434 if (command != null) {
2435 // {$peng} are variables not macros.
2436 if (!command.startsWith("$")) {
2437 MacroParameter mParams = fContext.getMacroParameter();
2439 if (group3 != null) {
2440 mParams.setContent(group3);
2441 mParams.setContentStart(0);
2442 mParams.setContentEnd(group3.length());
2444 if (unsplittedMacroParameters != null && unsplittedMacroParameters.length() > 1) {
2445 // mParams.setParams(parseParameters(unsplittedMacroParameters));
2446 mParams.setParams(unsplittedMacroParameters);
2448 mParams.setStart(0);
2449 mParams.setEnd(completeMacroSubString.length());
2451 // @DANGER: recursive calls may replace macros in included
2454 if (fMacros.containsKey(command)) {
2455 Macro macro = (Macro) fMacros.get(command);
2457 // recursively filter macros within macros
2458 if (null != mParams.getContent() && !(macro instanceof INoParserBodyFilterMacro)) {
2459 mParams.setContent(WikipediaFilter.filterParser(mParams.getContent(), fContext, fMacros, fRecursionLevel));
2461 StringBufferWriter writer = new StringBufferWriter(new StringBuffer(256));
2462 macro.execute(writer, mParams);
2463 StringBuffer buffer = writer.getBuffer();
2464 if (macro instanceof IRenderResultMacro) {
2465 fResultBuffer.append(WikipediaFilter.filterParser(buffer.toString(), fContext, fMacros, fRecursionLevel));
2467 fResultBuffer.append(buffer);
2470 } else if (command.startsWith("!")) {
2472 RenderEngine engine = fContext.getRenderContext().getRenderEngine();
2473 if (engine instanceof IncludeRenderEngine) {
2474 String include = ((IncludeRenderEngine) engine).include(command.substring(1));
2475 if (null != include) {
2476 // Filter paramFilter = new
2477 // ParamFilter(mParams);
2478 // included = paramFilter.filter(included,
2480 // fResult.append(include);
2482 fResultBuffer.append(WikipediaFilter.filterParser(include, fContext, fMacros, fRecursionLevel));
2485 fResultBuffer.append(command.substring(1) + " not found.");
2491 // fResult.append(group0);
2492 copyWhite(completeMacroSubString);
2495 } catch (IllegalArgumentException e) {
2497 fResultBuffer.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
2499 e.printStackTrace();
2501 } catch (Throwable e) {
2502 // log.warn("MacroFilter: unable to format macro: " + command, e);
2503 fResultBuffer.append("<div class=\"error\">" + command + ": " + e.getMessage() + "</div>");
2504 e.printStackTrace();
2508 fResultBuffer.append("<");
2509 fResultBuffer.append(command.substring(1));
2510 fResultBuffer.append(">");
2513 // fResult.append(group0);
2514 copyWhite(completeMacroSubString);
2518 public void parse() {
2519 int token = WikipediaFilter.TokenSTART;
2520 fTokenStack.add(WikipediaFilter.START);
2521 // fListStack.add(START);
2523 while ((token = getNextToken()) != WikipediaFilter.TokenEOF) {
2525 case WikipediaFilter.TokenBOLD:
2526 if (fTokenStack.peek() == WikipediaFilter.BOLD) {
2528 fResultBuffer.append("</b>");
2530 fTokenStack.push(WikipediaFilter.BOLD);
2531 fResultBuffer.append("<b>");
2534 case WikipediaFilter.TokenITALIC:
2535 if (fTokenStack.peek() == WikipediaFilter.ITALIC) {
2537 fResultBuffer.append("</i>");
2539 fTokenStack.push(WikipediaFilter.ITALIC);
2540 fResultBuffer.append("<i>");
2543 case WikipediaFilter.TokenSTRONG:
2544 if (fTokenStack.peek() == WikipediaFilter.STRONG) {
2546 fResultBuffer.append("</strong>");
2548 fTokenStack.push(WikipediaFilter.STRONG);
2549 fResultBuffer.append("<strong>");
2552 case WikipediaFilter.TokenEM:
2553 if (fTokenStack.peek() == WikipediaFilter.EM) {
2555 fResultBuffer.append("</em>");
2557 fTokenStack.push(WikipediaFilter.EM);
2558 fResultBuffer.append("<em>");
2561 case WikipediaFilter.TokenSTRIKETHROUGH:
2562 if (fTokenStack.peek() == WikipediaFilter.STRIKETHROUGH) {
2564 fResultBuffer.append("</strike>");
2566 fTokenStack.push(WikipediaFilter.STRIKETHROUGH);
2567 fResultBuffer.append("<strike>");
2570 // case TokenLIST_UL_START :
2571 // if (fTokenStack.peek().equals(LIST_UL_START)) {
2572 // fResult.append("</li>\n<li>");
2574 // fTokenStack.push(LIST_UL_START);
2575 // fResult.append("\n<ul class=\"star\">\n<li>");
2578 // case TokenLIST_UL_END :
2579 // fTokenStack.pop();
2580 // fResult.append("</li>\n</ul>\n");
2582 // case TokenLIST_OL_START :
2583 // if (fTokenStack.peek().equals(LIST_OL_START)) {
2584 // fResult.append("</li>\n<li>");
2586 // fTokenStack.push(LIST_OL_START);
2587 // fResult.append("\n<ol>\n<li>");
2590 // case TokenLIST_OL_END :
2591 // fTokenStack.pop();
2592 // fResult.append("</li>\n</ol>\n");
2596 } catch (InvalidInputException e) {
2599 // clear rest of stack if necessary (case of error in syntax!?)
2601 while ((tok = (AbstractTag) fTokenStack.pop()) != WikipediaFilter.START) {
2602 if (tok instanceof OpenTagToken) {
2604 CloseTagToken closeToken = (CloseTagToken) WikipediaFilter.CLOSE_TAGS.get(tok.getTagName());
2605 if (closeToken == null) {
2606 // here is something wrong ???
2607 fResultBuffer.append("</" + (tok.getTagName()) + ">");
2609 fResultBuffer.append(closeToken.getCloseTag());
2611 } else if (tok == WikipediaFilter.BOLD) {
2612 fResultBuffer.append("</b>");
2613 } else if (tok == WikipediaFilter.ITALIC) {
2614 fResultBuffer.append("</i>");
2615 } else if (tok == WikipediaFilter.STRONG) {
2616 fResultBuffer.append("</strong>");
2617 } else if (tok == WikipediaFilter.EM) {
2618 fResultBuffer.append("</em>");
2619 } else if (tok == WikipediaFilter.STRIKETHROUGH) {
2620 fResultBuffer.append("</strike>");
2621 } else if (tok.equals(WikipediaFilter.LIST_UL_START)) {
2622 fResultBuffer.append("</li>\n</ul>\n");
2623 } else if (tok.equals(WikipediaFilter.LIST_OL_START)) {
2624 fResultBuffer.append("</li>\n</ol>\n");
2628 if (fResultBufferHeader != null) {
2629 int tocStart = fResultBufferHeader.length();
2630 fResultBufferHeader.append("<table id=\"toc\" border=\"0\"><tr><th>Table of contents</th></tr><tr><td>");
2631 fResultBufferHeader.append("<ol>");
2632 createToC(fTableOfContent);
2633 fResultBufferHeader.append("</ol>");
2634 fResultBufferHeader.append("</td></tr></table><hr/>");
2636 fResultBufferHeader.append(fResultBuffer);
2637 fResultBuffer = fResultBufferHeader;
2638 fResultBufferHeader = null;
2639 fTableOfContent = null;
2643 private void createToC(ArrayList toc) {
2644 if (toc.size() == 1 && (toc.get(0) instanceof ArrayList)) {
2645 createToC((ArrayList) toc.get(0));
2648 for (int i = 0; i < toc.size(); i++) {
2649 if (toc.get(i) instanceof ArrayList) {
2650 fResultBufferHeader.append("<ol>");
2651 createToC((ArrayList) toc.get(i));
2652 fResultBufferHeader.append("</ol>");
2654 fResultBufferHeader.append(toc.get(i));
2659 // public int readUntil(String testString) throws InvalidInputException {
2660 // startPosition = currentPosition;
2661 // int tempPosition;
2665 // currentCharacter = source[currentPosition++];
2666 // if (currentCharacter == testString.charAt(0)) {
2667 // tempPosition = currentPosition;
2669 // for (int i = 1; i < testString.length(); i++) {
2670 // currentCharacter = source[currentPosition++];
2671 // if (currentCharacter != testString.charAt(i)) {
2673 // currentPosition = tempPosition;
2678 // return TokenBODY;
2682 // } catch (IndexOutOfBoundsException e) {
2683 // // end of scanner text
2688 public int scanIdentifierOrKeyword(boolean isVariable) throws InvalidInputException {
2689 while (getNextCharAsWikiPluginIdentifierPart()) {
2692 return WikipediaFilter.TokenIdentifier;
2695 private final void setSource(char[] source) {
2696 //the source-buffer is set to sourceString
2697 if (source == null) {
2698 this.fSource = new char[0];
2700 this.fSource = source;
2702 // this.fEOFPosition = this.fSource.length;
2703 // fStartPosition = -1;
2706 private void unexpectedTag(String tag) {
2707 fResultBuffer.append("<div class=\"error\">Unexpected end for tag: <" + tag + "></div>");
2711 * @return Returns the context.
2713 public FilterContext getContext() {
2719 * The context to set.
2721 public void setContext(FilterContext context) {
2726 * @return Returns the wikiEngine.
2728 public RenderEngine getWikiEngine() {
2734 * The wikiEngine to set.
2736 public void setWikiEngine(RenderEngine wikiEngine) {
2737 fWikiEngine = wikiEngine;