2010-10-19 01:00:43 +02:00
// wikiCode.java
2005-08-06 19:03:12 +02:00
// -------------------------------------
// part of YACY
//
2009-05-09 15:43:38 +02:00
// (C) 2005, 2006 by Alexander Schier, Marc Nause, Franz Brausze
2006-05-12 16:35:56 +02:00
//
2009-05-09 15:43:38 +02:00
// $LastChangedDate$
// $LastChangedRevision$
// $LastChangedBy$
2005-08-06 19:03:12 +02:00
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2009-04-08 17:28:45 +02:00
package de.anomic.data.wiki ;
2005-08-06 19:03:12 +02:00
import java.io.BufferedReader ;
import java.io.IOException ;
2006-02-22 01:53:14 +01:00
import java.util.ArrayList ;
2007-06-05 13:37:19 +02:00
import java.util.Arrays ;
import java.util.HashMap ;
2009-05-09 15:43:38 +02:00
import java.util.List ;
import java.util.Map ;
2005-08-06 19:03:12 +02:00
2009-10-18 02:53:43 +02:00
import net.yacy.document.parser.html.CharacterCoding ;
2005-08-06 19:03:12 +02:00
import de.anomic.server.serverCore ;
2006-04-17 21:37:09 +02:00
/ * * This class provides methods to handle texts that have been posted in the yacyWiki or other
2010-10-19 01:00:43 +02:00
* parts of YaCy that use this class , like the blog or the profile .
*
* @author Alexander Schier [ AS ] , Franz Brausze [ FB ] , Marc Nause [ MN ]
* /
2007-05-20 15:29:12 +02:00
public class wikiCode extends abstractWikiParser implements wikiParser {
2010-09-04 16:01:34 +02:00
private static final String ASTERISK = " * " ;
2010-09-26 14:57:07 +02:00
private static final String EMPTY = " " ;
private static final String PIPE_ESCAPED = " | " ;
private static final String REGEX_NOT_CHAR_NUM_OR_UNDERSCORE = " [^a-zA-Z0-9_] " ;
private static final String HTML_OPEN_DEFINITION_DESCRIPTION = " <dd> " ;
private static final String HTML_CLOSE_DEFINITION_DESCRIPTION = " </dd> " ;
private static final String HTML_OPEN_DEFINITION_ITEM = " <dt> " ;
private static final String HTML_CLOSE_DEFINITION_ITEM = " </dt> " ;
private static final String HTML_OPEN_DEFINITION_LIST = " <dl> " ;
private static final String HTML_CLOSE_DEFINITION_LIST = " </dl> " ;
private static final String HTML_OPEN_UNORDERED_LIST = " <ul> " ;
private static final String HTML_CLOSE_UNORDERED_LIST = " </ul> " ;
private static final String HTML_CLOSE_BLOCKQUOTE = " </blockquote> " ;
private static final String HTML_CLOSE_LIST_ELEMENT = " </li> " ;
private static final String HTML_CLOSE_ORDERED_LIST = " </ol> " ;
private static final String HTML_OPEN_BLOCKQUOTE = " <blockquote> " ;
private static final String HTML_OPEN_LIST_ELEMENT = " <li> " ;
private static final String HTML_OPEN_ORDERED_LIST = " <ol> " ;
2010-10-19 01:00:43 +02:00
2010-09-26 14:57:07 +02:00
private static final String WIKI_CLOSE_LINK = " ]] " ;
private static final String WIKI_OPEN_LINK = " [[ " ;
2010-09-18 13:40:37 +02:00
private static final String WIKI_CLOSE_EXTERNAL_LINK = " ] " ;
private static final String WIKI_CLOSE_PRE_ESCAPED = " </pre> " ;
2010-09-26 14:57:07 +02:00
private static final String WIKI_OPEN_STRIKE = " <s> " ;
private static final String WIKI_CLOSE_STRIKE = " </s> " ;
private static final String WIKI_EMPHASIZE_1 = " \ ' \ ' " ;
private static final String WIKI_EMPHASIZE_2 = " \ ' \ ' \ ' " ;
2010-09-18 13:40:37 +02:00
private static final String WIKI_EMPHASIZE_3 = " \ ' \ ' \ ' \ ' \ ' " ;
2010-10-19 01:00:43 +02:00
private static final String WIKI_HEADLINE_TAG_1 = " = " ;
private static final String WIKI_HEADLINE_TAG_2 = " == " ;
private static final String WIKI_HEADLINE_TAG_3 = " === " ;
private static final String WIKI_HEADLINE_TAG_4 = " ==== " ;
private static final String WIKI_HEADLINE_TAG_5 = " ===== " ;
private static final String WIKI_HEADLINE_TAG_6 = " ====== " ;
2010-09-18 13:40:37 +02:00
private static final String WIKI_HR_LINE = " ---- " ;
private static final String WIKI_IMAGE = " Image: " ;
private static final String WIKI_OPEN_EXTERNAL_LINK = " [ " ;
private static final String WIKI_OPEN_PRE_ESCAPED = " <pre> " ;
2010-09-26 14:57:07 +02:00
private static final char ONE = '1' ;
private static final char TWO = '2' ;
2010-10-19 01:00:43 +02:00
private static final char THREE = '3' ;
private static final char FOUR = '4' ;
private static final char FIVE = '5' ;
private static final char SIX = '6' ;
2010-09-26 14:57:07 +02:00
private static final char WIKI_FORMATTED = ' ' ;
private static final char WIKI_INDENTION = ':' ;
2010-09-18 13:40:37 +02:00
private static final int LEN_WIKI_CLOSE_PRE_ESCAPED = WIKI_CLOSE_PRE_ESCAPED . length ( ) ;
private static final int LEN_WIKI_OPEN_PRE_ESCAPED = WIKI_OPEN_PRE_ESCAPED . length ( ) ;
private static final int LEN_WIKI_OPEN_LINK = WIKI_OPEN_LINK . length ( ) ;
private static final int LEN_WIKI_IMAGE = WIKI_IMAGE . length ( ) ;
private static final int LEN_WIKI_OPEN_EXTERNAL_LINK = WIKI_OPEN_EXTERNAL_LINK . length ( ) ;
private static final int LEN_WIKI_CLOSE_EXTERNAL_LINK = WIKI_CLOSE_EXTERNAL_LINK . length ( ) ;
private static final int LEN_WIKI_HR_LINE = WIKI_HR_LINE . length ( ) ;
private final List < String > tableOfContentElements = new ArrayList < String > ( ) ; //list of headlines used to create table of content of page
2010-09-04 16:01:34 +02:00
/** List of properties which can be used in tables. */
private final static String [ ] TABLE_PROPERTIES = { " rowspan " , " colspan " , " vspace " , " hspace " , " cellspacing " , " cellpadding " , " border " } ;
/** Map which contains possible values for deveral parameters. */
private final static Map < String , String [ ] > PROPERTY_VALUES = new HashMap < String , String [ ] > ( ) ;
/** Tags for different types of headlines in wikiCode. */
2010-10-19 01:00:43 +02:00
private final static String [ ] HEADLINE_TAGS = new String [ ] { WIKI_HEADLINE_TAG_6 , WIKI_HEADLINE_TAG_5 , WIKI_HEADLINE_TAG_4 , WIKI_HEADLINE_TAG_3 , WIKI_HEADLINE_TAG_2 , WIKI_HEADLINE_TAG_1 } ;
2010-09-18 13:40:37 +02:00
2010-10-19 01:00:43 +02:00
private final static char [ ] HEADLINE_LEVEL = new char [ ] { ONE , TWO , THREE , FOUR , FIVE , SIX } ;
2010-09-18 13:40:37 +02:00
private String numberedListLevel = EMPTY ;
private String unorderedListLevel = EMPTY ;
private String defListLevel = EMPTY ;
private boolean processingCell = false ; //needed for prevention of double-execution of replaceHTML
private boolean processingDefList = false ; //needed for definition lists
private boolean escape = false ; //needed for escape
private boolean escaped = false ; //needed for <pre> not getting in the way
private boolean newRowStart = false ; //needed for the first row not to be empty
private boolean noList = false ; //needed for handling of [= and <pre> in lists
private boolean processingPreformattedText = false ; //needed for preformatted text
private boolean preformattedSpanning = false ; //needed for <pre> and </pre> spanning over several lines
private boolean replacedHtmlAlready = false ; //indicates if method replaceHTML has been used with line already
private boolean processingTable = false ; //needed for tables, because they reach over several lines
private int preindented = 0 ; //needed for indented <pre>s
2009-05-01 09:28:59 +02:00
2007-06-05 13:37:19 +02:00
static {
2010-09-18 13:40:37 +02:00
/ * Arrays must be sorted since Arrays . searchBinary ( ) is used later . For more info go to
2009-05-09 15:43:38 +02:00
* http : //java.sun.com/javase/6/docs/api/java/util/Arrays.html#binarySearch(T[], T, java.util.Comparator)
* /
2010-09-18 13:40:37 +02:00
Arrays . sort ( HEADLINE_LEVEL ) ;
2010-09-04 16:01:34 +02:00
Arrays . sort ( HEADLINE_TAGS ) ;
Arrays . sort ( TABLE_PROPERTIES ) ;
2007-06-05 13:37:19 +02:00
String [ ] array ;
2009-05-01 09:28:59 +02:00
Arrays . sort ( array = new String [ ] { " void " , " above " , " below " , " hsides " , " lhs " , " rhs " , " vsides " , " box " , " border " } ) ;
2010-09-04 16:01:34 +02:00
PROPERTY_VALUES . put ( " frame " , array ) ;
2009-05-01 09:28:59 +02:00
Arrays . sort ( array = new String [ ] { " none " , " groups " , " rows " , " cols " , " all " } ) ;
2010-09-04 16:01:34 +02:00
PROPERTY_VALUES . put ( " rules " , array ) ;
2009-05-01 09:28:59 +02:00
Arrays . sort ( array = new String [ ] { " top " , " middle " , " bottom " , " baseline " } ) ;
2010-09-04 16:01:34 +02:00
PROPERTY_VALUES . put ( " valign " , array ) ;
2009-05-01 09:28:59 +02:00
Arrays . sort ( array = new String [ ] { " left " , " right " , " center " } ) ;
2010-09-04 16:01:34 +02:00
PROPERTY_VALUES . put ( " align " , array ) ;
2007-06-05 13:37:19 +02:00
}
2009-05-09 15:43:38 +02:00
2010-09-04 16:01:34 +02:00
/ * *
* Constructor
* @param address
* /
public wikiCode ( final String address ) {
2009-04-08 17:28:45 +02:00
super ( address ) ;
2007-02-03 16:20:12 +01:00
}
2009-05-01 09:28:59 +02:00
2010-09-04 16:01:34 +02:00
/ * *
* Transforms a text which contains wiki code to HTML fragment .
* @param reader contains the text to be transformed .
* @param length expected length of text , used to create buffer with right size .
* @return HTML fragment .
* @throws IOException in case input from reader can not be read .
* /
protected String transform ( final BufferedReader reader , final int length )
throws IOException {
2008-12-04 13:54:16 +01:00
final StringBuilder out = new StringBuilder ( length ) ;
2007-05-20 15:29:12 +02:00
String line ;
2009-05-01 09:28:59 +02:00
while ( ( line = reader . readLine ( ) ) ! = null ) {
2010-09-04 16:01:34 +02:00
out . append ( processLineOfWikiCode ( line ) ) . append ( serverCore . CRLF_STRING ) ;
2009-05-01 09:28:59 +02:00
}
2010-09-04 16:01:34 +02:00
return out . insert ( 0 , createTableOfContents ( ) ) . toString ( ) ;
2007-02-03 16:20:12 +01:00
}
2005-09-05 12:15:59 +02:00
2010-09-04 16:01:34 +02:00
// contributed by [FB], changes by [MN]
2009-05-09 15:43:38 +02:00
/ * *
2010-09-04 16:01:34 +02:00
* Processes tags which are connected to tables .
* @param line line of text to be transformed from wiki code to HTML
* @return HTML fragment
2009-05-01 09:28:59 +02:00
* /
2010-09-04 16:01:34 +02:00
private String processTable ( final String line ) {
2006-05-08 00:53:17 +02:00
//some variables that make it easier to change codes for the table
2010-09-04 16:01:34 +02:00
final StringBuilder out = new StringBuilder ( ) ;
final String tableStart = " { " + PIPE_ESCAPED ; // {|
final String newLine = PIPE_ESCAPED + " - " ; // |-
final String cellDivider = PIPE_ESCAPED + PIPE_ESCAPED ; // ||
final String tableEnd = PIPE_ESCAPED + " } " ; // |}
final String attribDivider = PIPE_ESCAPED ; // |
2008-08-02 14:12:04 +02:00
final int lenTableStart = tableStart . length ( ) ;
final int lenCellDivider = cellDivider . length ( ) ;
final int lenTableEnd = tableEnd . length ( ) ;
final int lenAttribDivider = attribDivider . length ( ) ;
2006-05-08 00:53:17 +02:00
2010-09-04 16:01:34 +02:00
if ( ( line . startsWith ( tableStart ) ) & & ( ! processingTable ) ) {
processingTable = true ;
newRowStart = true ;
out . append ( " <table " ) ;
if ( line . trim ( ) . length ( ) > lenTableStart ) {
out . append ( filterTableProperties ( line . substring ( lenTableStart ) . trim ( ) ) ) ;
2006-01-22 16:41:49 +01:00
}
2010-09-04 16:01:34 +02:00
out . append ( " > " ) ;
} else if ( line . startsWith ( newLine ) & & ( processingTable ) ) { // new row
if ( ! newRowStart ) {
out . append ( " \ t</tr> \ n " ) ;
2006-01-22 16:41:49 +01:00
} else {
2010-09-04 16:01:34 +02:00
newRowStart = false ;
2006-01-22 16:41:49 +01:00
}
2010-09-04 16:01:34 +02:00
out . append ( " \ t<tr> " ) ;
} else if ( ( line . startsWith ( cellDivider ) ) & & ( processingTable ) ) {
out . append ( " \ t \ t<td " ) ;
final int cellEnd = ( line . indexOf ( cellDivider , lenCellDivider ) > 0 ) ? ( line . indexOf ( cellDivider , lenCellDivider ) ) : ( line . length ( ) ) ;
int propEnd = line . indexOf ( attribDivider , lenCellDivider ) ;
final int occImage = line . indexOf ( " [[Image: " , lenCellDivider ) ;
final int occEscape = line . indexOf ( " [= " , lenCellDivider ) ;
2006-02-27 13:33:34 +01:00
//If resultOf("[[Image:") is less than propEnd, that means that there is no
//property for this cell, only an image. Without this, YaCy could get confused
//by a | in [[Image:picture.png|alt-text]] or [[Image:picture.png|alt-text]]
2006-05-08 00:53:17 +02:00
//Same for [= (part of [= =])
2009-05-01 09:28:59 +02:00
if ( ( propEnd > lenCellDivider ) & & ( ( occImage > propEnd ) | | ( occImage < 0 ) ) & & ( ( occEscape > propEnd ) | | ( occEscape < 0 ) ) ) {
2010-09-04 16:01:34 +02:00
propEnd = line . indexOf ( attribDivider , lenCellDivider ) + lenAttribDivider ;
2009-05-01 09:28:59 +02:00
} else {
2006-02-27 13:33:34 +01:00
propEnd = cellEnd ;
}
2006-01-23 14:59:40 +01:00
// both point at same place => new line
2009-05-01 09:28:59 +02:00
if ( propEnd = = cellEnd ) {
propEnd = lenCellDivider ;
} else {
2010-09-04 16:01:34 +02:00
out . append ( filterTableProperties ( line . substring ( lenCellDivider , propEnd - lenAttribDivider ) . trim ( ) ) ) ;
2006-01-22 16:41:49 +01:00
}
2007-07-19 17:32:10 +02:00
// quick&dirty fix [MN]
2009-05-01 09:28:59 +02:00
if ( propEnd > cellEnd ) {
2006-09-18 00:57:10 +02:00
propEnd = lenCellDivider ;
}
2010-09-04 16:01:34 +02:00
processingTable = false ;
processingCell = true ;
out . append ( " > " ) ;
out . append ( processTable ( line . substring ( propEnd , cellEnd ) . trim ( ) ) ) ;
out . append ( " </td> " ) ;
processingTable = true ;
processingCell = false ;
if ( cellEnd < line . length ( ) ) {
out . append ( " \ n " ) ;
out . append ( processTable ( line . substring ( cellEnd ) ) ) ;
2006-01-23 14:59:40 +01:00
}
2010-09-04 16:01:34 +02:00
} else if ( line . startsWith ( tableEnd ) & & ( processingTable ) ) { // Table end
processingTable = false ;
out . append ( " \ t</tr> \ n</table> " ) ;
out . append ( line . substring ( lenTableEnd ) ) ;
2009-05-09 15:43:38 +02:00
} else {
2010-09-04 16:01:34 +02:00
out . append ( line ) ;
2006-01-23 14:59:40 +01:00
}
2010-09-04 16:01:34 +02:00
return out . toString ( ) ;
2006-01-22 16:41:49 +01:00
}
2009-05-01 09:28:59 +02:00
2007-06-05 13:37:19 +02:00
// contributed by [MN], changes by [FB]
2006-02-24 02:14:38 +01:00
/ * * This method takes possible table properties and tests if they are valid .
2009-05-01 09:28:59 +02:00
* Valid in this case means if they are a property for the table , tr or td
* tag as stated in the HTML Pocket Reference by Jennifer Niederst ( 1st edition )
* The method is important to avoid XSS attacks on the wiki via table properties .
2010-09-04 16:01:34 +02:00
* @param properties String which may contain several table properties and / or junk .
* @return String containing only table properties .
2009-05-01 09:28:59 +02:00
* /
2010-09-04 16:01:34 +02:00
private StringBuilder filterTableProperties ( final String properties ) {
final String [ ] values = properties . replaceAll ( " " " , EMPTY ) . split ( " [= ] " ) ; //splitting the string at = and blanks
final StringBuilder stringBuilder = new StringBuilder ( properties . length ( ) ) ;
2007-06-05 13:37:19 +02:00
String key , value ;
String [ ] posVals ;
2010-09-04 16:01:34 +02:00
final int numberOfValues = values . length ;
for ( int i = 0 ; i < numberOfValues ; i + + ) {
2007-06-05 13:37:19 +02:00
key = values [ i ] . trim ( ) ;
if ( key . equals ( " nowrap " ) ) {
2010-09-04 16:01:34 +02:00
appendKeyValuePair ( " nowrap " , " nowrap " , stringBuilder ) ;
} else if ( i + 1 < numberOfValues ) {
2007-06-05 13:37:19 +02:00
value = values [ + + i ] . trim ( ) ;
2010-09-04 16:01:34 +02:00
if ( ( key . equals ( " summary " ) )
| | ( key . equals ( " bgcolor " ) & & value . matches ( " #{0,1}[0-9a-fA-F]{1,6}|[a-zA-Z]{3,} " ) )
| | ( ( key . equals ( " width " ) | | key . equals ( " height " ) ) & & value . matches ( " \\ d+%{0,1} " ) )
| | ( ( posVals = PROPERTY_VALUES . get ( key ) ) ! = null & & Arrays . binarySearch ( posVals , value ) > = 0 )
| | ( Arrays . binarySearch ( TABLE_PROPERTIES , key ) > = 0 & & value . matches ( " \\ d+ " ) ) ) {
appendKeyValuePair ( key , value , stringBuilder ) ;
2006-02-24 02:14:38 +01:00
}
}
}
2010-09-04 16:01:34 +02:00
return stringBuilder ;
2007-06-05 13:37:19 +02:00
}
2009-05-01 09:28:59 +02:00
2010-09-04 16:01:34 +02:00
/ * *
* Appends a key / value pair in HTML syntax to a given StringBuilder .
* @param key key to be appended .
* @param value value of key .
* @param stringBuilder this is what key / value are appended to .
* @return
* /
private StringBuilder appendKeyValuePair ( final String key , final String value , final StringBuilder stringBuilder ) {
return stringBuilder . append ( " " ) . append ( key ) . append ( " = \" " ) . append ( value ) . append ( " \" " ) ;
2007-06-05 13:37:19 +02:00
}
2006-02-24 02:14:38 +01:00
2010-09-04 16:01:34 +02:00
/ * *
* Processes tags which are connected to ordered lists .
* @param line line of text to be transformed from wiki code to HTML
* @return HTML fragment
2009-05-01 09:28:59 +02:00
* /
2010-09-04 16:01:34 +02:00
private String processOrderedList ( String line ) {
if ( ! noList ) { //lists only get processed if not forbidden (see code for [= and <pre>). [MN]
2006-04-17 21:37:09 +02:00
//# sorted Lists contributed by [AS]
//## Sublist
2010-09-04 16:01:34 +02:00
if ( line . startsWith ( numberedListLevel + " # " ) ) { //more #
2010-09-26 14:57:07 +02:00
line = HTML_OPEN_ORDERED_LIST + serverCore . CRLF_STRING
+ HTML_OPEN_LIST_ELEMENT
2010-09-04 16:01:34 +02:00
+ line . substring ( numberedListLevel . length ( ) + 1 , line . length ( ) )
2010-09-26 14:57:07 +02:00
+ HTML_CLOSE_LIST_ELEMENT ;
2010-09-04 16:01:34 +02:00
numberedListLevel + = " # " ;
} else if ( numberedListLevel . length ( ) > 0 & & line . startsWith ( numberedListLevel ) ) { //equal number of #
2010-09-26 14:57:07 +02:00
line = HTML_OPEN_LIST_ELEMENT
2010-09-04 16:01:34 +02:00
+ line . substring ( numberedListLevel . length ( ) , line . length ( ) )
2010-09-26 14:57:07 +02:00
+ HTML_CLOSE_LIST_ELEMENT ;
2010-09-04 16:01:34 +02:00
} else if ( numberedListLevel . length ( ) > 0 ) { //less #
int i = numberedListLevel . length ( ) ;
String tmp = EMPTY ;
while ( ! line . startsWith ( numberedListLevel . substring ( 0 , i ) ) ) {
2010-09-26 14:57:07 +02:00
tmp + = HTML_CLOSE_ORDERED_LIST ;
2006-04-17 21:37:09 +02:00
i - - ;
}
2010-09-04 16:01:34 +02:00
numberedListLevel = numberedListLevel . substring ( 0 , i ) ;
final int positionOfOpeningTag = numberedListLevel . length ( ) ;
final int positionOfClosingTag = line . length ( ) ;
if ( numberedListLevel . length ( ) > 0 ) {
line = tmp
2010-09-26 14:57:07 +02:00
+ HTML_OPEN_LIST_ELEMENT
2010-09-04 16:01:34 +02:00
+ line . substring ( positionOfOpeningTag , positionOfClosingTag )
2010-09-26 14:57:07 +02:00
+ HTML_CLOSE_LIST_ELEMENT ;
2009-05-01 09:28:59 +02:00
} else {
2010-09-04 16:01:34 +02:00
line = tmp + line . substring ( positionOfOpeningTag , positionOfClosingTag ) ;
2006-04-17 21:37:09 +02:00
}
2006-02-22 01:53:14 +01:00
}
2010-09-04 16:01:34 +02:00
// end contrib [AS]
2006-02-22 01:53:14 +01:00
}
2010-09-04 16:01:34 +02:00
return line ;
2006-02-22 01:53:14 +01:00
}
2006-04-11 00:04:52 +02:00
//contributed by [AS] put into it's own method by [MN]
2010-09-04 16:01:34 +02:00
/ * *
* Processes tags which are connected to unordered lists .
* @param line line of text to be transformed from wiki code to HTML
* @return HTML fragment
* /
private String processUnorderedList ( String line ) {
if ( ! noList ) { //lists only get processed if not forbidden (see code for [= and <pre>). [MN]
2006-04-17 21:37:09 +02:00
//contributed by [AS]
2010-09-04 16:01:34 +02:00
if ( line . startsWith ( unorderedListLevel + ASTERISK ) ) { //more stars
2010-09-26 14:57:07 +02:00
line = HTML_OPEN_UNORDERED_LIST + serverCore . CRLF_STRING
+ HTML_OPEN_LIST_ELEMENT
2010-09-04 16:01:34 +02:00
+ line . substring ( unorderedListLevel . length ( ) + 1 , line . length ( ) )
2010-09-26 14:57:07 +02:00
+ HTML_CLOSE_LIST_ELEMENT ;
2010-09-04 16:01:34 +02:00
unorderedListLevel + = ASTERISK ;
} else if ( unorderedListLevel . length ( ) > 0 & & line . startsWith ( unorderedListLevel ) ) { //equal number of stars
2010-09-26 14:57:07 +02:00
line = HTML_OPEN_LIST_ELEMENT
2010-09-04 16:01:34 +02:00
+ line . substring ( unorderedListLevel . length ( ) , line . length ( ) )
2010-09-26 14:57:07 +02:00
+ HTML_CLOSE_LIST_ELEMENT ;
2010-09-04 16:01:34 +02:00
} else if ( unorderedListLevel . length ( ) > 0 ) { //less stars
int i = unorderedListLevel . length ( ) ;
String tmp = EMPTY ;
while ( unorderedListLevel . length ( ) > = i & & ! line . startsWith ( unorderedListLevel . substring ( 0 , i ) ) ) {
2010-09-26 14:57:07 +02:00
tmp + = HTML_CLOSE_UNORDERED_LIST ;
2006-04-17 21:37:09 +02:00
i - - ;
}
2010-09-04 16:01:34 +02:00
int positionOfOpeningTag = unorderedListLevel . length ( ) ;
if ( i < positionOfOpeningTag ) {
unorderedListLevel = unorderedListLevel . substring ( 0 , i ) ;
positionOfOpeningTag = unorderedListLevel . length ( ) ;
2009-05-01 00:03:35 +02:00
}
2010-09-04 16:01:34 +02:00
final int positionOfClosingTag = line . length ( ) ;
2006-04-17 21:37:09 +02:00
2010-09-04 16:01:34 +02:00
if ( unorderedListLevel . length ( ) > 0 ) {
line = tmp
2010-09-26 14:57:07 +02:00
+ HTML_OPEN_LIST_ELEMENT
2010-09-04 16:01:34 +02:00
+ line . substring ( positionOfOpeningTag , positionOfClosingTag )
2010-09-26 14:57:07 +02:00
+ HTML_CLOSE_LIST_ELEMENT ;
2009-05-01 09:28:59 +02:00
} else {
2010-09-04 16:01:34 +02:00
line = tmp + line . substring ( positionOfOpeningTag , positionOfClosingTag ) ;
2006-04-17 21:37:09 +02:00
}
2006-04-11 00:04:52 +02:00
}
2010-09-04 16:01:34 +02:00
//end contrib [AS]
2006-04-11 00:04:52 +02:00
}
2010-09-04 16:01:34 +02:00
return line ;
2006-04-11 00:04:52 +02:00
}
//contributed by [MN] based on unordered list code by [AS]
2010-09-04 16:01:34 +02:00
/ * *
* Processes tags which are connected to definition lists .
* @param line line of text to be transformed from wiki code to HTML
* @return HTML fragment
* /
private String processDefinitionList ( String line ) {
if ( ! noList ) { //lists only get processed if not forbidden (see code for [= and <pre>). [MN]
if ( line . startsWith ( defListLevel + " ; " ) ) { //more semicolons
String definitionItem = EMPTY ;
String definitionDescription = EMPTY ;
final int positionOfOpeningTag ;
final int positionOfClosingTag = line . length ( ) ;
final String copyOfLine = line . substring ( defListLevel . length ( ) + 1 , positionOfClosingTag ) ;
if ( ( positionOfOpeningTag = copyOfLine . indexOf ( " : " ) ) > 0 ) {
definitionItem = copyOfLine . substring ( 0 , positionOfOpeningTag ) ;
definitionDescription = copyOfLine . substring ( positionOfOpeningTag + 1 ) ;
2010-09-26 14:57:07 +02:00
line = HTML_OPEN_DEFINITION_LIST +
HTML_OPEN_DEFINITION_ITEM +
2010-09-04 16:01:34 +02:00
definitionItem +
2010-09-26 14:57:07 +02:00
HTML_CLOSE_DEFINITION_ITEM +
HTML_OPEN_DEFINITION_DESCRIPTION +
2010-09-04 16:01:34 +02:00
definitionDescription ;
processingDefList = true ;
2006-04-11 00:04:52 +02:00
}
2006-04-17 21:37:09 +02:00
defListLevel + = " ; " ;
2010-09-04 16:01:34 +02:00
} else if ( defListLevel . length ( ) > 0 & & line . startsWith ( defListLevel ) ) { //equal number of semicolons
String definitionItem = EMPTY ;
String definitionDescription = EMPTY ;
final int positionOfOpeningTag ;
final int positionOfClosingTag = line . length ( ) ;
final String copyOfLine = line . substring ( defListLevel . length ( ) , positionOfClosingTag ) ;
if ( ( positionOfOpeningTag = copyOfLine . indexOf ( " : " ) ) > 0 ) {
definitionItem = copyOfLine . substring ( 0 , positionOfOpeningTag ) ;
definitionDescription = copyOfLine . substring ( positionOfOpeningTag + 1 ) ;
2010-09-26 14:57:07 +02:00
line = HTML_OPEN_DEFINITION_ITEM +
2010-09-04 16:01:34 +02:00
definitionItem +
2010-09-26 14:57:07 +02:00
HTML_CLOSE_DEFINITION_ITEM +
HTML_OPEN_DEFINITION_DESCRIPTION +
2010-09-04 16:01:34 +02:00
definitionDescription ;
processingDefList = true ;
2006-04-17 21:37:09 +02:00
}
2009-05-01 09:28:59 +02:00
} else if ( defListLevel . length ( ) > 0 ) { //less semicolons
2010-09-04 16:01:34 +02:00
String definitionItem = EMPTY ;
String definitionDescription = EMPTY ;
2006-04-17 21:37:09 +02:00
int i = defListLevel . length ( ) ;
2010-09-04 16:01:34 +02:00
String tmp = EMPTY ;
while ( ! line . startsWith ( defListLevel . substring ( 0 , i ) ) ) {
2010-09-26 14:57:07 +02:00
tmp = HTML_CLOSE_DEFINITION_DESCRIPTION + HTML_CLOSE_DEFINITION_LIST ;
2006-04-17 21:37:09 +02:00
i - - ;
}
2009-05-01 09:28:59 +02:00
defListLevel = defListLevel . substring ( 0 , i ) ;
2010-09-04 16:01:34 +02:00
int positionOfOpeningTag = defListLevel . length ( ) ;
final int positionOfClosingTag = line . length ( ) ;
2009-05-01 09:28:59 +02:00
if ( defListLevel . length ( ) > 0 ) {
2010-09-04 16:01:34 +02:00
final String copyOfLine = line . substring ( positionOfOpeningTag , positionOfClosingTag ) ;
if ( ( positionOfOpeningTag = copyOfLine . indexOf ( " : " ) ) > 0 ) {
definitionItem = copyOfLine . substring ( 0 , positionOfOpeningTag ) ;
definitionDescription = copyOfLine . substring ( positionOfOpeningTag + 1 ) ;
2010-09-26 14:57:07 +02:00
line = tmp + HTML_OPEN_DEFINITION_ITEM + definitionItem + HTML_CLOSE_DEFINITION_ITEM + HTML_OPEN_DEFINITION_DESCRIPTION + definitionDescription ;
2010-09-04 16:01:34 +02:00
processingDefList = true ;
2006-04-17 21:37:09 +02:00
}
2009-05-01 09:28:59 +02:00
} else {
2010-09-04 16:01:34 +02:00
line = tmp + line . substring ( positionOfOpeningTag , positionOfClosingTag ) ;
2006-04-17 21:37:09 +02:00
}
2006-04-11 00:04:52 +02:00
}
}
2010-09-04 16:01:34 +02:00
return line ;
2006-04-11 00:04:52 +02:00
}
//contributed by [AS] except where stated otherwise
2010-09-04 16:01:34 +02:00
/ * *
* Processes tags which are connected to links and images .
* @param line line of text to be transformed from wiki code to HTML
* @return HTML fragment
* /
private String processLinksAndImages ( String line ) {
2006-04-11 00:04:52 +02:00
// create links
String kl , kv , alt , align ;
int p ;
2010-09-04 16:01:34 +02:00
int positionOfOpeningTag ;
int positionOfClosingTag ;
2006-04-11 00:04:52 +02:00
// internal links and images
2010-09-04 16:01:34 +02:00
while ( ( positionOfOpeningTag = line . indexOf ( WIKI_OPEN_LINK ) ) > = 0 ) {
2010-09-18 13:40:37 +02:00
positionOfClosingTag = line . indexOf ( WIKI_CLOSE_LINK , positionOfOpeningTag + LEN_WIKI_OPEN_LINK ) ;
2010-09-04 16:01:34 +02:00
if ( positionOfClosingTag < = positionOfOpeningTag ) {
2009-05-01 09:28:59 +02:00
break ;
}
2010-09-18 13:40:37 +02:00
kl = line . substring ( positionOfOpeningTag + LEN_WIKI_OPEN_LINK , positionOfClosingTag ) ;
2006-04-11 00:04:52 +02:00
// this is the part of the code that's responsible for images
// contributed by [MN]
2010-09-18 13:40:37 +02:00
if ( kl . startsWith ( WIKI_IMAGE ) ) {
2010-09-04 16:01:34 +02:00
alt = EMPTY ;
align = EMPTY ;
kv = EMPTY ;
2010-09-18 13:40:37 +02:00
kl = kl . substring ( LEN_WIKI_IMAGE ) ;
2006-04-11 00:04:52 +02:00
// are there any arguments for the image?
2010-09-04 16:01:34 +02:00
if ( ( p = kl . indexOf ( PIPE_ESCAPED ) ) > 0 ) {
2010-09-18 13:40:37 +02:00
kv = kl . substring ( p + LEN_WIKI_IMAGE ) ;
2006-04-11 00:04:52 +02:00
kl = kl . substring ( 0 , p ) ;
// if there are 2 arguments, write them into ALIGN and ALT
2010-09-04 16:01:34 +02:00
if ( ( p = kv . indexOf ( PIPE_ESCAPED ) ) > 0 ) {
2006-04-11 00:04:52 +02:00
align = kv . substring ( 0 , p ) ;
//checking validity of value for align. Only non browser specific
//values get supported. Not supported: absmiddle, baseline, texttop
2010-09-04 16:01:34 +02:00
if ( ( align . equals ( " bottom " ) )
| | ( align . equals ( " center " ) )
| | ( align . equals ( " left " ) )
| | ( align . equals ( " middle " ) )
| | ( align . equals ( " right " ) )
| | ( align . equals ( " top " ) ) ) {
2006-04-11 00:04:52 +02:00
align = " align= \" " + align + " \" " ;
2009-05-01 09:28:59 +02:00
} else {
2010-09-04 16:01:34 +02:00
align = EMPTY ;
2006-04-11 00:04:52 +02:00
}
2010-09-18 13:40:37 +02:00
alt = " alt= \" " + kv . substring ( p + LEN_WIKI_IMAGE ) + " \" " ;
2009-05-01 09:28:59 +02:00
} // if there is just one, put it into ALT
else {
2006-04-11 00:04:52 +02:00
alt = " alt= \" " + kv + " \" " ;
2009-05-01 09:28:59 +02:00
}
2006-04-11 00:04:52 +02:00
}
// replace incomplete URLs and make them point to http://peerip:port/...
// with this feature you can access an image in DATA/HTDOCS/share/yacy.gif
// using the wikicode [[Image:share/yacy.gif]]
// or an image DATA/HTDOCS/grafics/kaskelix.jpg with [[Image:grafics/kaskelix.jpg]]
// you are free to use other sub-paths of DATA/HTDOCS
2009-05-01 09:28:59 +02:00
if ( kl . indexOf ( " :// " ) < 1 ) {
2009-04-08 17:28:45 +02:00
kl = " http:// " + super . address + " / " + kl ;
2006-04-11 00:04:52 +02:00
}
2010-09-04 16:01:34 +02:00
line = line . substring ( 0 , positionOfOpeningTag ) + " <img src= \" " + kl + " \" " + align + alt + " > " + line . substring ( positionOfClosingTag + 2 ) ;
2009-05-01 09:28:59 +02:00
} // end contrib [MN]
2006-04-11 00:04:52 +02:00
// if it's no image, it might be an internal link
else {
2010-09-04 16:01:34 +02:00
if ( ( p = kl . indexOf ( PIPE_ESCAPED ) ) > 0 ) {
2006-05-08 16:23:22 +02:00
kv = kl . substring ( p + 6 ) ;
2006-04-11 00:04:52 +02:00
kl = kl . substring ( 0 , p ) ;
} else {
kv = kl ;
}
2010-09-04 16:01:34 +02:00
line = line . substring ( 0 , positionOfOpeningTag ) + " <a class= \" known \" href= \" Wiki.html?page= " + kl + " \" > " + kv + " </a> " + line . substring ( positionOfClosingTag + 2 ) ; // oob exception in append() !
2006-04-11 00:04:52 +02:00
}
}
// external links
2010-09-18 13:40:37 +02:00
while ( ( positionOfOpeningTag = line . indexOf ( WIKI_OPEN_EXTERNAL_LINK ) ) > = 0 ) {
positionOfClosingTag = line . indexOf ( WIKI_CLOSE_EXTERNAL_LINK , positionOfOpeningTag + LEN_WIKI_OPEN_EXTERNAL_LINK ) ;
2010-09-04 16:01:34 +02:00
if ( positionOfClosingTag < = positionOfOpeningTag ) {
2009-05-01 09:28:59 +02:00
break ;
}
2010-09-18 13:40:37 +02:00
kl = line . substring ( positionOfOpeningTag + LEN_WIKI_OPEN_EXTERNAL_LINK , positionOfClosingTag ) ;
2006-04-11 00:04:52 +02:00
if ( ( p = kl . indexOf ( " " ) ) > 0 ) {
kv = kl . substring ( p + 1 ) ;
kl = kl . substring ( 0 , p ) ;
2009-05-01 09:28:59 +02:00
} // No text for the link? -> <a href="http://www.url.com/">http://www.url.com/</a>
2006-04-11 00:04:52 +02:00
else {
kv = kl ;
}
// replace incomplete URLs and make them point to http://peerip:port/...
// with this feature you can access a file at DATA/HTDOCS/share/page.html
// using the wikicode [share/page.html]
// or a file DATA/HTDOCS/www/page.html with [www/page.html]
// you are free to use other sub-paths of DATA/HTDOCS
2007-06-07 13:35:48 +02:00
if ( kl . indexOf ( " :// " ) < 1 ) {
2009-04-08 17:28:45 +02:00
kl = " http:// " + super . address + " / " + kl ;
2006-04-11 00:04:52 +02:00
}
2010-09-18 13:40:37 +02:00
line = line . substring ( 0 , positionOfOpeningTag ) + " <a class= \" extern \" href= \" " + kl + " \" > " + kv + " </a> " + line . substring ( positionOfClosingTag + LEN_WIKI_CLOSE_EXTERNAL_LINK ) ;
2006-04-11 00:04:52 +02:00
}
2010-09-04 16:01:34 +02:00
return line ;
2006-04-11 00:04:52 +02:00
}
2006-04-17 21:37:09 +02:00
//contributed by [MN]
2010-09-04 16:01:34 +02:00
/ * *
* Processes tags which are connected preformatted text ( & lt ; pre & gt ; & lt ; / pre & gt ; ) .
* @param line line of text to be transformed from wiki code to HTML
* @return HTML fragment
* /
private String processPreformattedText ( String line ) {
2010-09-18 13:40:37 +02:00
final int positionOfOpeningTag = line . indexOf ( WIKI_OPEN_PRE_ESCAPED ) ;
final int positionOfClosingTag = line . indexOf ( WIKI_CLOSE_PRE_ESCAPED ) ;
2006-04-17 21:37:09 +02:00
//both <pre> and </pre> in the same line
2010-09-18 13:40:37 +02:00
if ( ( positionOfOpeningTag > = 0 ) & & ( positionOfClosingTag > 0 ) & & ! escaped ) {
2010-09-04 16:01:34 +02:00
if ( positionOfOpeningTag < positionOfClosingTag ) {
2010-10-19 01:00:43 +02:00
String preformattedText = " <pre style= \" border:dotted;border-width:thin; \" > " + line . substring ( positionOfOpeningTag + LEN_WIKI_OPEN_PRE_ESCAPED , positionOfClosingTag ) + " </pre> " ;
2006-09-18 01:42:36 +02:00
preformattedText = preformattedText . replaceAll ( " !pre! " , " !pre!! " ) ;
2010-09-18 13:40:37 +02:00
line = processLineOfWikiCode ( line . substring ( 0 , positionOfOpeningTag ) . replaceAll ( " !pre! " , " !pre!! " ) + " !pre!txt! " + line . substring ( positionOfClosingTag + LEN_WIKI_CLOSE_PRE_ESCAPED ) . replaceAll ( " !pre! " , " !pre!! " ) ) ;
2010-09-04 16:01:34 +02:00
line = line . replaceAll ( " !pre!txt! " , preformattedText ) ;
line = line . replaceAll ( " !pre!! " , " !pre! " ) ;
2009-05-01 09:28:59 +02:00
} //handles cases like <pre><pre> </pre></pre> <pre> </pre> that would cause an exception otherwise
else {
2010-09-04 16:01:34 +02:00
processingPreformattedText = true ;
final String temp1 = processLineOfWikiCode ( line . substring ( 0 , positionOfOpeningTag - 1 ) . replaceAll ( " !tmp! " , " !tmp!! " ) + " !tmp!txt! " ) ;
noList = true ;
final String temp2 = processLineOfWikiCode ( line . substring ( positionOfOpeningTag ) ) ;
noList = false ;
line = temp1 . replaceAll ( " !tmp!txt! " , temp2 ) ;
line = line . replaceAll ( " !tmp!! " , " !tmp! " ) ;
processingPreformattedText = false ;
2006-04-17 21:37:09 +02:00
}
2009-05-01 09:28:59 +02:00
} //start <pre>
2010-09-18 13:40:37 +02:00
else if ( ( positionOfOpeningTag > = 0 ) & & ! preformattedSpanning & & ! escaped ) {
2010-09-04 16:01:34 +02:00
processingPreformattedText = true ; //prevent surplus line breaks
final StringBuilder openBlockQuoteTags = new StringBuilder ( ) ; //gets filled with <blockquote>s as needed
2010-10-19 01:00:43 +02:00
String preformattedText = " <pre style= \" border:dotted;border-width:thin; \" > " + line . substring ( positionOfOpeningTag + LEN_WIKI_OPEN_PRE_ESCAPED ) ;
2006-09-18 01:42:36 +02:00
preformattedText = preformattedText . replaceAll ( " !pre! " , " !pre!! " ) ;
2006-04-17 21:37:09 +02:00
//taking care of indented lines
2010-10-19 01:00:43 +02:00
while ( preindented < positionOfOpeningTag & & positionOfOpeningTag < line . length ( ) & &
line . substring ( preindented , positionOfOpeningTag ) . charAt ( 0 ) = = WIKI_INDENTION ) {
2006-04-17 21:37:09 +02:00
preindented + + ;
2010-09-26 14:57:07 +02:00
openBlockQuoteTags . append ( HTML_OPEN_BLOCKQUOTE ) ;
2006-04-17 21:37:09 +02:00
}
2010-09-04 16:01:34 +02:00
line = processLineOfWikiCode ( line . substring ( preindented , positionOfOpeningTag ) . replaceAll ( " !pre! " , " !pre!! " ) + " !pre!txt! " ) ;
line = openBlockQuoteTags + line . replaceAll ( " !pre!txt! " , preformattedText ) ;
line = line . replaceAll ( " !pre!! " , " !pre! " ) ;
preformattedSpanning = true ;
2009-05-01 09:28:59 +02:00
} //end </pre>
2010-10-19 01:00:43 +02:00
else if ( ( positionOfClosingTag > = 0 ) & & preformattedSpanning & & ! escaped ) {
2010-09-04 16:01:34 +02:00
preformattedSpanning = false ;
final StringBuilder endBlockQuoteTags = new StringBuilder ( ) ; //gets filled with </blockquote>s as needed
2010-10-19 01:00:43 +02:00
String preformattedText = line . substring ( 0 , positionOfClosingTag ) + " </pre> " ;
2006-09-18 01:42:36 +02:00
preformattedText = preformattedText . replaceAll ( " !pre! " , " !pre!! " ) ;
2009-05-01 09:28:59 +02:00
//taking care of indented lines
while ( preindented > 0 ) {
2010-09-26 14:57:07 +02:00
endBlockQuoteTags . append ( HTML_CLOSE_BLOCKQUOTE ) ;
2006-04-17 21:37:09 +02:00
preindented - - ;
}
2010-10-19 01:00:43 +02:00
line = processLineOfWikiCode ( " !pre!txt! " + line . substring ( positionOfClosingTag + LEN_WIKI_CLOSE_PRE_ESCAPED ) . replaceAll ( " !pre! " , " !pre!! " ) ) ;
2010-09-04 16:01:34 +02:00
line = line . replaceAll ( " !pre!txt! " , preformattedText ) + endBlockQuoteTags ;
line = line . replaceAll ( " !pre!! " , " !pre! " ) ;
processingPreformattedText = false ;
2009-05-01 09:28:59 +02:00
} //Getting rid of surplus </pre>
2010-09-18 13:40:37 +02:00
else if ( ( positionOfOpeningTag > = 0 ) & & ! preformattedSpanning & & ! escaped ) {
int posTag ;
while ( ( posTag = line . indexOf ( WIKI_CLOSE_PRE_ESCAPED ) ) > = 0 ) {
line = line . substring ( 0 , posTag ) + line . substring ( posTag + LEN_WIKI_CLOSE_PRE_ESCAPED ) ;
2006-04-17 21:37:09 +02:00
}
2010-09-04 16:01:34 +02:00
line = processLineOfWikiCode ( line ) ;
2006-04-17 21:37:09 +02:00
}
2010-09-04 16:01:34 +02:00
return line ;
2006-04-17 21:37:09 +02:00
}
2006-02-22 01:53:14 +01:00
//method contributed by [MN]
2010-09-04 16:01:34 +02:00
/ * * Creates table of contents for a wiki page .
* @return HTML fragment
* /
private StringBuilder createTableOfContents ( ) {
final StringBuilder directory = new StringBuilder ( ) ;
2006-02-22 01:53:14 +01:00
String element ;
int s = 0 ;
int level = 1 ;
int level1 = 0 ;
int level2 = 0 ;
int level3 = 0 ;
2010-10-19 01:00:43 +02:00
int level4 = 0 ;
int level5 = 0 ;
int level6 = 0 ;
2006-03-08 00:58:30 +01:00
int doubles = 0 ;
2010-09-04 16:01:34 +02:00
String anchorext = EMPTY ;
if ( ( s = tableOfContentElements . size ( ) ) > 2 ) {
2009-05-09 15:43:38 +02:00
directory . append ( " <table><tr><td><div class= \" WikiTOCBox \" > \ n " ) ;
2009-05-01 00:03:35 +02:00
for ( int i = 0 ; i < s ; i + + ) {
2010-09-04 16:01:34 +02:00
if ( i > = tableOfContentElements . size ( ) ) {
2009-05-01 09:28:59 +02:00
break ;
}
2010-09-04 16:01:34 +02:00
element = tableOfContentElements . get ( i ) ;
if ( element = = null ) {
continue ;
}
2006-03-08 00:58:30 +01:00
//counting double headlines
doubles = 0 ;
2009-05-01 00:03:35 +02:00
for ( int j = 0 ; j < i ; j + + ) {
2010-09-04 16:01:34 +02:00
if ( j > = tableOfContentElements . size ( ) ) {
2009-05-01 09:28:59 +02:00
break ;
}
2010-09-04 16:01:34 +02:00
String d = tableOfContentElements . get ( j ) ;
2009-05-01 09:28:59 +02:00
if ( d = = null | | d . length ( ) < 1 ) {
continue ;
}
2010-09-18 13:40:37 +02:00
String a = d . substring ( 1 ) . replaceAll ( " " , " _ " ) . replaceAll ( REGEX_NOT_CHAR_NUM_OR_UNDERSCORE , EMPTY ) ;
String b = element . substring ( 1 ) . replaceAll ( " " , " _ " ) . replaceAll ( REGEX_NOT_CHAR_NUM_OR_UNDERSCORE , EMPTY ) ;
2009-05-01 09:28:59 +02:00
if ( a . equals ( b ) ) {
doubles + + ;
}
2006-03-08 00:58:30 +01:00
}
//if there are doubles, create anchorextension
2009-05-01 09:28:59 +02:00
if ( doubles > 0 ) {
anchorext = " _ " + ( doubles + 1 ) ;
2006-03-08 00:58:30 +01:00
}
2010-09-18 13:40:37 +02:00
final char l = element . charAt ( 0 ) ;
String temp = " " ;
if ( Arrays . binarySearch ( HEADLINE_LEVEL , l ) > = 0 & & element . length ( ) > 0 ) {
2010-10-19 01:00:43 +02:00
switch ( l ) {
case SIX : {
if ( level < 6 ) {
level = 6 ;
level6 = 0 ;
}
level6 + + ;
temp = element . substring ( 1 ) ;
element = level1 + " . " + level2 + " . " + level3 + " . " + level4 + " . " + level5 + " . " + level6 + " " + temp ;
directory . append ( " <a href= \" # " ) ;
break ;
}
case FIVE : {
if ( level = = 1 ) {
level2 = 0 ;
level = 2 ;
}
if ( level = = 3 ) {
level = 2 ;
}
level5 + + ;
temp = element . substring ( 1 ) ;
element = level1 + " . " + level2 + " . " + level3 + " . " + level4 + " . " + level5 + " " + temp ;
directory . append ( " <a href= \" # " ) ;
break ;
}
case FOUR : {
if ( level = = 1 ) {
level2 = 0 ;
level = 2 ;
}
if ( level = = 3 ) {
level = 2 ;
}
level4 + + ;
temp = element . substring ( 1 ) ;
element = level1 + " . " + level2 + " . " + level3 + " . " + level4 + " " + temp ;
directory . append ( " <a href= \" # " ) ;
break ;
2010-09-18 13:40:37 +02:00
}
2010-10-19 01:00:43 +02:00
case THREE : {
if ( level = = 1 ) {
level2 = 0 ;
level = 2 ;
}
if ( level = = 3 ) {
level = 2 ;
}
level3 + + ;
temp = element . substring ( 1 ) ;
element = level1 + " . " + level2 + " . " + level3 + " " + temp ;
directory . append ( " <a href= \" # " ) ;
break ;
2010-09-18 13:40:37 +02:00
}
2010-10-19 01:00:43 +02:00
case TWO : {
if ( level = = 1 ) {
level2 = 0 ;
level = 2 ;
}
if ( level = = 3 ) {
level = 2 ;
}
level2 + + ;
temp = element . substring ( 1 ) ;
element = level1 + " . " + level2 + " " + temp ;
directory . append ( " <a href= \" # " ) ;
break ;
2010-09-18 13:40:37 +02:00
}
2010-10-19 01:00:43 +02:00
case ONE : {
if ( level > 1 ) {
level = 1 ;
level2 = 0 ;
level3 = 0 ;
level4 = 0 ;
level5 = 0 ;
level6 = 0 ;
}
level1 + + ;
temp = element . substring ( 1 ) ;
element = level1 + " . " + temp ;
directory . append ( " <a href= \" # " ) ;
break ;
2010-09-18 13:40:37 +02:00
}
2006-02-22 01:53:14 +01:00
}
2010-09-18 13:40:37 +02:00
directory . append ( temp . replaceAll ( " " , " _ " ) . replaceAll ( REGEX_NOT_CHAR_NUM_OR_UNDERSCORE , EMPTY ) ) ;
2010-09-04 16:01:34 +02:00
directory . append ( anchorext ) ;
directory . append ( " \" class= \" WikiTOC \" > " ) ;
2009-05-09 15:43:38 +02:00
directory . append ( element ) ;
directory . append ( " </a><br /> \ n " ) ;
2010-09-26 14:57:07 +02:00
}
2010-09-04 16:01:34 +02:00
anchorext = EMPTY ;
2006-02-22 01:53:14 +01:00
}
2009-05-09 15:43:38 +02:00
directory . append ( " </div></td></tr></table> \ n " ) ;
2006-02-22 01:53:14 +01:00
}
2010-09-04 16:01:34 +02:00
if ( ! tableOfContentElements . isEmpty ( ) ) {
tableOfContentElements . clear ( ) ;
2007-05-25 18:36:09 +02:00
}
2006-02-22 01:53:14 +01:00
return directory ;
}
2010-10-19 01:00:43 +02:00
/ * * Replaces two occurences of a substring in a string by a pair of strings if
2009-05-01 09:28:59 +02:00
* that substring occurs twice in the string . This method is not greedy ! You ' ll
* have to run it in a loop if you want to replace all occurences of the substring .
* This method provides special treatment for headlines .
* @param input the string that something is to be replaced in
* @param pat substring to be replaced
* @param repl1 string substring gets replaced by on uneven occurences
* @param repl2 string substring gets replaced by on even occurences
* /
//[MN]
private String pairReplace ( String input , final String pat , final String repl1 , final String repl2 ) {
2010-09-26 14:57:07 +02:00
return pairReplace ( input , pat , pat , repl1 , repl2 ) ;
}
private String pairReplace ( String input , final String pat1 , final String pat2 ,
final String repl1 , final String repl2 ) {
2009-05-09 15:43:38 +02:00
String direlem = null ; //string to keep headlines until they get added to List dirElements
2010-09-04 16:01:34 +02:00
int firstPosition ;
final int secondPosition ;
2010-09-26 14:57:07 +02:00
final int pat1Len = pat1 . length ( ) ;
final int pat2Len = pat2 . length ( ) ;
2007-02-20 23:07:59 +01:00
//replace pattern if a pair of the pattern can be found in the line
2010-09-26 14:57:07 +02:00
if ( ( ( firstPosition = input . indexOf ( pat1 ) ) > = 0 ) & & ( ( secondPosition = input . indexOf ( pat2 , firstPosition + pat1Len ) ) > = 0 ) ) {
2007-02-20 23:07:59 +01:00
//extra treatment for headlines
2010-09-26 14:57:07 +02:00
if ( Arrays . binarySearch ( HEADLINE_TAGS , pat1 ) > = 0 ) {
2007-02-20 23:07:59 +01:00
//add anchor and create headline
2010-09-26 14:57:07 +02:00
direlem = input . substring ( firstPosition + pat1Len , secondPosition ) ;
2009-05-09 15:43:38 +02:00
if ( direlem ! = null ) {
//counting double headlines
int doubles = 0 ;
2010-09-04 16:01:34 +02:00
for ( int i = 0 ; i < tableOfContentElements . size ( ) ; i + + ) {
2009-05-09 15:43:38 +02:00
// no element with null value should ever be in directory
2010-09-04 16:01:34 +02:00
assert ( tableOfContentElements . get ( i ) ! = null ) ;
2009-05-09 15:43:38 +02:00
2010-09-04 16:01:34 +02:00
if ( tableOfContentElements . size ( ) > i & & tableOfContentElements . get ( i ) . substring ( 1 ) . equals ( direlem ) ) {
2009-05-09 15:43:38 +02:00
doubles + + ;
}
2009-05-01 09:28:59 +02:00
}
2010-09-18 13:40:37 +02:00
String anchor = direlem . replaceAll ( " " , " _ " ) . replaceAll ( REGEX_NOT_CHAR_NUM_OR_UNDERSCORE , EMPTY ) ; //replace blanks with underscores and delete everything thats not a regular character, a number or _
2009-05-09 15:43:38 +02:00
//if there are doubles, add underscore and number of doubles plus one
if ( doubles > 0 ) {
anchor = anchor + " _ " + ( doubles + 1 ) ;
}
2010-09-04 16:01:34 +02:00
input = input . substring ( 0 , firstPosition ) + " <a name= \" " + anchor + " \" ></a> " + repl1
2010-09-26 14:57:07 +02:00
+ direlem + repl2 + input . substring ( secondPosition + pat2Len ) ;
2009-05-09 15:43:38 +02:00
//add headlines to list of headlines (so TOC can be created)
2010-09-26 14:57:07 +02:00
if ( Arrays . binarySearch ( HEADLINE_TAGS , pat1 ) > = 0 ) {
tableOfContentElements . add ( ( pat1Len - 1 ) + direlem ) ;
2006-03-08 00:58:30 +01:00
}
2009-05-01 09:28:59 +02:00
}
} else {
2010-09-04 16:01:34 +02:00
input = input . substring ( 0 , firstPosition ) + repl1
2010-09-26 14:57:07 +02:00
+ ( input . substring ( firstPosition + pat1Len , secondPosition ) ) + repl2
+ input . substring ( secondPosition + pat2Len ) ;
2006-02-21 13:24:44 +01:00
}
2006-02-22 01:53:14 +01:00
}
2010-09-04 16:01:34 +02:00
//recursion if another pair of the pattern can still be found in the line
2010-09-26 14:57:07 +02:00
if ( ( ( firstPosition = input . indexOf ( pat1 ) ) > = 0 ) & & ( input . indexOf ( pat2 , firstPosition + pat1Len ) > = 0 ) ) {
input = pairReplace ( input , pat1 , pat2 , repl1 , repl2 ) ;
2007-02-20 23:07:59 +01:00
}
2006-02-21 13:24:44 +01:00
return input ;
}
2006-02-22 01:53:14 +01:00
2010-09-04 16:01:34 +02:00
/ * * Replaces wiki tags with HTML tags in one line of text .
* @param line line of text to be transformed from wiki code to HTML
* @return HTML fragment
2009-05-01 09:28:59 +02:00
* /
2010-09-04 16:01:34 +02:00
public String processLineOfWikiCode ( String line ) {
2010-10-19 01:00:43 +02:00
//If HTML has not been replaced yet (can happen if method gets called in recursion), replace now!
if ( ( ! replacedHtmlAlready | | preformattedSpanning ) & & line . indexOf ( WIKI_CLOSE_PRE_ESCAPED ) < 0 ) {
2010-09-04 16:01:34 +02:00
line = CharacterCoding . unicode2html ( line , true ) ;
replacedHtmlAlready = true ;
2006-01-18 02:48:34 +01:00
}
2006-01-16 22:15:06 +01:00
2006-04-17 21:37:09 +02:00
//check if line contains preformatted symbols or if we are in a preformatted sequence already.
2010-10-19 01:00:43 +02:00
if ( ( line . indexOf ( WIKI_OPEN_PRE_ESCAPED ) > = 0 ) | |
( line . indexOf ( WIKI_CLOSE_PRE_ESCAPED ) > = 0 ) | |
preformattedSpanning ) {
2010-09-04 16:01:34 +02:00
line = processPreformattedText ( line ) ;
2009-04-09 16:55:20 +02:00
} else {
2006-01-16 22:15:06 +01:00
2006-01-23 14:59:40 +01:00
//tables first -> wiki-tags in cells can be treated after that
2010-09-04 16:01:34 +02:00
line = processTable ( line ) ;
2006-01-23 14:59:40 +01:00
2005-08-31 16:43:55 +02:00
// format lines
2010-09-18 13:40:37 +02:00
if ( line . length ( ) > 0 & & line . charAt ( 0 ) = = WIKI_FORMATTED ) {
2010-09-04 16:01:34 +02:00
line = " <tt> " + line . substring ( 1 ) + " </tt> " ;
2009-05-01 09:28:59 +02:00
}
2010-09-18 13:40:37 +02:00
if ( line . startsWith ( WIKI_HR_LINE ) ) {
line = " <hr /> " + line . substring ( LEN_WIKI_HR_LINE ) ;
2009-05-01 09:28:59 +02:00
}
2006-01-16 22:15:06 +01:00
// citings contributed by [MN]
2010-09-18 13:40:37 +02:00
if ( line . length ( ) > 0 & & line . charAt ( 0 ) = = WIKI_INDENTION ) {
2010-09-04 16:01:34 +02:00
final StringBuilder head = new StringBuilder ( ) ;
final StringBuilder tail = new StringBuilder ( ) ;
2010-09-18 13:40:37 +02:00
while ( line . length ( ) > 0 & & line . charAt ( 0 ) = = WIKI_INDENTION ) {
2010-09-26 14:57:07 +02:00
head . append ( HTML_OPEN_BLOCKQUOTE ) ;
tail . append ( HTML_CLOSE_BLOCKQUOTE ) ;
2010-09-04 16:01:34 +02:00
line = line . substring ( 1 ) ;
2006-01-16 22:15:06 +01:00
}
2010-09-04 16:01:34 +02:00
line = head + line + tail ;
2006-01-22 15:20:38 +01:00
}
2010-10-19 01:00:43 +02:00
// end contrib [MN]
2006-01-16 22:15:06 +01:00
2006-01-22 15:20:38 +01:00
// format headers
2010-10-19 01:00:43 +02:00
line = pairReplace ( line , WIKI_HEADLINE_TAG_6 , " <h6> " , " </h6> " ) ;
line = pairReplace ( line , WIKI_HEADLINE_TAG_5 , " <h5> " , " </h5> " ) ;
line = pairReplace ( line , WIKI_HEADLINE_TAG_4 , " <h4> " , " </h4> " ) ;
line = pairReplace ( line , WIKI_HEADLINE_TAG_3 , " <h3> " , " </h3> " ) ;
line = pairReplace ( line , WIKI_HEADLINE_TAG_2 , " <h2> " , " </h2> " ) ;
line = pairReplace ( line , WIKI_HEADLINE_TAG_1 , " <h1> " , " </h1> " ) ;
2006-01-16 22:15:06 +01:00
2010-09-18 13:40:37 +02:00
line = pairReplace ( line , WIKI_EMPHASIZE_3 , " <b><i> " , " </i></b> " ) ;
line = pairReplace ( line , WIKI_EMPHASIZE_2 , " <b> " , " </b> " ) ;
line = pairReplace ( line , WIKI_EMPHASIZE_1 , " <i> " , " </i> " ) ;
2006-01-16 22:15:06 +01:00
2010-10-19 01:00:43 +02:00
line = pairReplace ( line , WIKI_OPEN_STRIKE , WIKI_CLOSE_STRIKE , " <span class= \" strike \" > " , " </span> " ) ;
2010-09-26 14:57:07 +02:00
2010-09-04 16:01:34 +02:00
line = processUnorderedList ( line ) ;
line = processOrderedList ( line ) ;
line = processDefinitionList ( line ) ;
2006-01-22 15:20:38 +01:00
2010-09-04 16:01:34 +02:00
line = processLinksAndImages ( line ) ;
2005-08-06 19:03:12 +02:00
2006-01-16 22:15:06 +01:00
}
2010-09-04 16:01:34 +02:00
if ( ! processingPreformattedText ) {
replacedHtmlAlready = false ;
2009-05-01 09:28:59 +02:00
}
2010-09-26 14:57:07 +02:00
if ( ! ( line . endsWith ( HTML_CLOSE_LIST_ELEMENT ) | | processingDefList | | escape | | processingPreformattedText | | processingTable | | processingCell ) ) {
2010-09-04 16:01:34 +02:00
line + = " <br /> " ;
2009-05-01 09:28:59 +02:00
}
2010-09-04 16:01:34 +02:00
return line ;
2005-08-06 19:03:12 +02:00
}
2010-10-19 01:00:43 +02:00
}