LuteceWikiParser.java
/*
* Copyright (c) 2002-2023, City of Paris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice
* and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* License 1.0
*/
package fr.paris.lutece.plugins.wiki.service.parser;
import fr.paris.lutece.plugins.wiki.business.Image;
import fr.paris.lutece.plugins.wiki.business.ImageHome;
import fr.paris.lutece.plugins.wiki.business.Topic;
import fr.paris.lutece.plugins.wiki.business.TopicHome;
import fr.paris.lutece.plugins.wiki.business.TopicVersion;
import fr.paris.lutece.plugins.wiki.business.TopicVersionHome;
import fr.paris.lutece.plugins.wiki.business.WikiContent;
import fr.paris.lutece.plugins.wiki.service.PathService;
import fr.paris.lutece.portal.service.spring.SpringContextService;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.portal.service.util.AppPathService;
import static ys.wikiparser.Utils.*;
import fr.paris.lutece.plugins.wiki.web.Constants;
import ys.wikiparser.WikiParser;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.List;
/**
* Lutece Wiki Parser
*/
public class LuteceWikiParser extends WikiParser
{
private static final String BEAN_PARSER_OPTIONS = "wiki.parser.options";
private String _strPageName;
private String _strPageUrl;
private String _strLanguage;
private static WikiMacroService _macroService = new WikiMacroService( );
private static ParserOptions _options = SpringContextService.getBean( BEAN_PARSER_OPTIONS );
/**
* Constructor
*
* @param strWikiText
* The wiki text
* @param strPageUrl
* The page URL
* @param strLanguage
* The language
*/
public LuteceWikiParser( String strWikiText, String strPageName, String strPageUrl, String strLanguage )
{
super( );
_strPageName = strPageName;
_strPageUrl = strPageUrl;
_strLanguage = strLanguage;
setTableClass( _options.getTableClass( ) );
setParentTableClass( _options.getParentTableClass( ) );
setTocClass( _options.getTocClass( ) );
parse( SpecialChar.renderWiki( strWikiText ) );
}
/**
* Render specific HTML entities
*
* @param strHTML
* The HTML code to transform
* @return The transformed HTML
*/
private String renderSpecific( String strHTML )
{
String strRender = strHTML;
if ( _strPageUrl != null )
{
strRender = strRender.replaceAll( "#page_url", _strPageUrl );
}
return strRender;
}
/**
* {@inheritDoc }
*/
@Override
public String toString( )
{
return renderSpecific( super.toString( ) );
}
/**
* {@inheritDoc }
*/
@Override
protected void appendImage( String strText )
{
try
{
String [ ] link = split( strText, '|' );
String strAlt = "illustration";
String strWidth = null;
String strHeight = null;
String strAlign = null;
int nImageId = Integer.parseInt( link [0].trim( ) );
Topic topic = TopicHome.findByPageName( _strPageName );
Image image = ImageHome.findByPrimaryKey( nImageId );
if ( image == null || image.getTopicId( ) != topic.getIdTopic( ) )
{
return;
}
switch( link.length )
{
case 5:
strAlign = link [4].trim( );
case 4:
strHeight = link [3].trim( );
case 3:
strWidth = link [2].trim( );
case 2:
strAlt = link [1].trim( );
}
sb.append( "<img src=\"image?resource_type=wiki_image&id=" ).append( nImageId ).append( "\" alt=\"" );
sb.append( strAlt ).append( "\" title=\"" ).append( strAlt ).append( "\" " );
if ( link.length < 3 )
{
sb.append( " class=\"" ).append( _options.getImageClass( ) ).append( "\" " );
}
else
{
sb.append( " class=\"" ).append( _options.getSizedImageClass( ) ).append( "\" " );
}
if ( strWidth != null )
{
sb.append( " width=\"" ).append( strWidth ).append( "\" " );
}
if ( strHeight != null )
{
sb.append( " height=\"" ).append( strHeight ).append( "\" " );
}
if ( strAlign != null )
{
sb.append( " align=\"" ).append( strAlign ).append( "\" " );
}
sb.append( " />" );
}
catch( NumberFormatException e )
{
super.appendImage( strText );
}
}
/**
* {@inheritDoc }
*/
@Override
protected void appendLink( String strText )
{
String [ ] link = split( strText, '|' );
URI uri = null;
try
{ // validate URI
uri = new URI( link [0].trim( ) );
}
catch( URISyntaxException e )
{
AppLogService.error( "LuteceWikiParser : Error appenlink : " + e.getMessage( ), e );
}
if ( ( uri != null ) && uri.isAbsolute( ) )
{
sb.append( "<a href=\"" );
sb.append( escapeHTML( uri.toString( ) ) );
sb.append( "\" rel=\"nofollow\">" );
sb.append( escapeHTML( unescapeHTML( ( ( link.length >= 2 ) && !isEmpty( link [1].trim( ) ) ) ? link [1] : link [0] ) ) );
sb.append( "</a>" );
}
else
{
Topic topic = TopicHome.findByPageName( escapeHTML( escapeURL( link [0] ) ) );
String strAction;
String strAdditionalParameter = "";
String strColorBegin = "";
String strColorEnd = "";
String strTopicName = link [0];
if ( topic == null )
{
strAction = "&action=" + Constants.PARAMETER_ACTION_CREATE;
strAdditionalParameter = "&parent_page_name=" + _strPageName;
strColorBegin = "<font color=red>";
strColorEnd = "</font>";
}
else
{
TopicVersion version = TopicVersionHome.findLastVersion( topic.getIdTopic( ) );
strAction = "&view=page";
if ( version != null )
{
WikiContent content = version.getWikiContent( _strLanguage );
if ( content != null && !content.getPageTitle( ).trim( ).isEmpty( ) )
{
strTopicName = content.getPageTitle( );
}
}
}
sb.append( "<a href=\"" ).append( AppPathService.getPortalUrl( ) ).append( "?page=wiki" ).append( strAction ).append( strAdditionalParameter )
.append( "&page_name=" ).append( escapeHTML( unescapeHTML( link [0] ) ) ).append( " \" title=\"Wikipedia link\">" ).append( strColorBegin )
.append( escapeHTML( unescapeHTML( ( ( link.length >= 2 ) && !isEmpty( link [1].trim( ) ) ) ? link [1] : strTopicName ) ) )
.append( strColorEnd ).append( "</a>" );
}
}
/**
* {@inheritDoc }
*/
@Override
protected void appendMacro( String strText )
{
if ( "TOC".equals( strText ) )
{
super.appendMacro( strText ); // use default
}
else
if ( "My-macro".equals( strText ) )
{
sb.append( "{{ My macro output }}" );
}
else
if ( "breadcrumb".equals( strText.trim( ) ) )
{
sb.append( "<p>" );
Topic topic = TopicHome.findByPageName( _strPageName );
List<Topic> topicList = PathService.getParentTopics( topic );
for ( Topic item : topicList )
{
appendLink( item.getPageName( ) );
sb.append( " > " );
}
TopicVersion version = TopicVersionHome.findLastVersion( topic.getIdTopic( ) );
WikiContent content = version.getWikiContent( _strLanguage );
String strTopicName = content.getPageTitle( ).trim( );
sb.append( escapeHTML( unescapeHTML( strTopicName.isEmpty( ) ? topic.getPageName( ) : strTopicName ) ) );
sb.append( "</p>\n" );
}
else
{
super.appendMacro( strText );
}
}
/**
* Encode URL
*
* @param strURL
* the URL
* @return The encoded URL
*/
private static String escapeURL( String strURL )
{
try
{
return URLEncoder.encode( strURL, "utf-8" );
}
catch( UnsupportedEncodingException e )
{
AppLogService.error( "LuteceWikiParser : Error escaping Url : " + e.getMessage( ), e );
return null;
}
}
/**
* {@inheritDoc }
*/
@Override
protected void appendNowiki( String strText )
{
String strMacro = escapeHTML( replaceString( replaceString( strText, "~{{{", "{{{" ), "~}}}", "}}}" ) );
sb.append( _macroService.processMacro( strMacro ) );
}
}