| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| package org.apache.wiki.markdown.extensions.jspwikilinks.postprocessor; |
| |
| import com.vladsch.flexmark.ast.HtmlInline; |
| import com.vladsch.flexmark.ext.toc.TocBlock; |
| import com.vladsch.flexmark.util.ast.Node; |
| import com.vladsch.flexmark.util.ast.NodeTracker; |
| import com.vladsch.flexmark.util.sequence.CharSubSequence; |
| import org.apache.log4j.Logger; |
| import org.apache.wiki.api.core.Context; |
| import org.apache.wiki.api.exceptions.PluginException; |
| import org.apache.wiki.api.plugin.Plugin; |
| import org.apache.wiki.markdown.nodes.JSPWikiLink; |
| import org.apache.wiki.parser.PluginContent; |
| import org.apache.wiki.preferences.Preferences; |
| |
| import java.text.MessageFormat; |
| import java.util.ResourceBundle; |
| |
| |
| /** |
| * {@link NodePostProcessorState} which further post processes plugin links. |
| */ |
| public class PluginLinkNodePostProcessorState implements NodePostProcessorState< JSPWikiLink > { |
| |
| private static final Logger LOG = Logger.getLogger( PluginLinkNodePostProcessorState.class ); |
| private final Context wikiContext; |
| private final boolean m_wysiwygEditorMode; |
| |
| public PluginLinkNodePostProcessorState( final Context wikiContext ) { |
| this.wikiContext = wikiContext; |
| final Boolean wysiwygVariable = wikiContext.getVariable( Context.VAR_WYSIWYG_EDITOR_MODE ); |
| m_wysiwygEditorMode = wysiwygVariable != null ? wysiwygVariable : false; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see NodePostProcessorState#process(NodeTracker, Node) |
| */ |
| @Override |
| public void process( final NodeTracker state, final JSPWikiLink link ) { |
| if( link.getText().toString().startsWith( "{TableOfContents" ) ) { |
| handleTableOfContentsPlugin( state, link ); |
| return; |
| } |
| PluginContent pluginContent = null; |
| try { |
| pluginContent = PluginContent.parsePluginLine( wikiContext, link.getUrl().toString(), -1 ); // -1 == do not generate _bounds parameter |
| // |
| // This might sometimes fail, especially if there is something which looks |
| // like a plugin invocation but is really not. |
| // |
| if( pluginContent != null ) { |
| final String pluginInvocation = pluginInvocation( link.getText().toString(), pluginContent ); |
| final HtmlInline content = new HtmlInline( CharSubSequence.of( pluginInvocation ) ); |
| pluginContent.executeParse( wikiContext ); |
| NodePostProcessorStateCommonOperations.addContent( state, link, content ); |
| } |
| } catch( final PluginException e ) { |
| LOG.info( wikiContext.getRealPage().getWiki() + " : " + wikiContext.getRealPage().getName() + " - Failed to insert plugin: " + e.getMessage() ); |
| if( !m_wysiwygEditorMode ) { |
| final ResourceBundle rbPlugin = Preferences.getBundle( wikiContext, Plugin.CORE_PLUGINS_RESOURCEBUNDLE ); |
| NodePostProcessorStateCommonOperations.makeError( state, link, MessageFormat.format( rbPlugin.getString( "plugin.error.insertionfailed" ), |
| wikiContext.getRealPage().getWiki(), |
| wikiContext.getRealPage().getName(), |
| e.getMessage() ) ); |
| } |
| } finally { |
| if( pluginContent != null ) { |
| removeLink( state, link ); |
| } |
| } |
| } |
| |
| /** |
| * Return plugin execution. As plugin execution may not fire the plugin (i.e., on WYSIWYG editors), on those cases, the plugin line is returned. |
| * |
| * @param pluginMarkup plugin markup line |
| * @param pluginContent the plugin content. |
| * @return plugin execution, or plugin markup line if it wasn't executed. |
| */ |
| String pluginInvocation( final String pluginMarkup, final PluginContent pluginContent ) { |
| final String pluginInvocation = pluginContent.invoke( wikiContext ); |
| if( pluginMarkup.equals( pluginInvocation + "()" ) ) { // plugin line markup == plugin execution + "()" -> hasn't been executed |
| return pluginMarkup; |
| } else { |
| return pluginInvocation; |
| } |
| } |
| |
| void handleTableOfContentsPlugin(final NodeTracker state, final JSPWikiLink link) { |
| if( !m_wysiwygEditorMode ) { |
| final ResourceBundle rb = Preferences.getBundle( wikiContext, Plugin.CORE_PLUGINS_RESOURCEBUNDLE ); |
| final HtmlInline divToc = new HtmlInline( CharSubSequence.of( "<div class=\"toc\">\n" ) ); |
| final HtmlInline divCollapseBox = new HtmlInline( CharSubSequence.of( "<div class=\"collapsebox\">\n" ) ); |
| final HtmlInline divsClosing = new HtmlInline( CharSubSequence.of( "</div>\n</div>\n" ) ); |
| final HtmlInline h4Title = new HtmlInline( CharSubSequence.of( "<h4 id=\"section-TOC\">" + // FIXME proper plugin parameters handling |
| rb.getString( "tableofcontents.title" ) + |
| "</h4>\n" ) ); |
| final TocBlock toc = new TocBlock( CharSubSequence.of( "[TOC]" ), CharSubSequence.of( "levels=1-3" ) ); |
| |
| link.insertAfter( divToc ); |
| divToc.insertAfter( divCollapseBox ); |
| divCollapseBox.insertAfter( h4Title ); |
| h4Title.insertAfter( toc ); |
| toc.insertAfter( divsClosing ); |
| |
| } else { |
| NodePostProcessorStateCommonOperations.inlineLinkTextOnWysiwyg( state, link, m_wysiwygEditorMode ); |
| } |
| removeLink( state, link ); |
| } |
| |
| void removeLink(final NodeTracker state, final JSPWikiLink link) { |
| link.unlink(); |
| state.nodeRemoved( link ); |
| } |
| |
| } |