All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.myfaces.custom.inputHtml.InputHtml Maven / Gradle / Ivy

Go to download

JSF components and utilities that can be used with any JSF implementation. This library is based on the JSF1.1 version of Tomahawk, but with minor source code and build changes to take advantage of JSF2.1 features. A JSF2.1 implementation is required to use this version of the Tomahawk library.

The newest version!
/*
 * 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.myfaces.custom.inputHtml;

import javax.faces.FacesException;
import javax.faces.application.Resource;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIViewRoot;
import javax.faces.component.UniqueIdVendor;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.event.ListenerFor;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
import org.apache.myfaces.component.html.ext.HtmlInputText;
import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
import org.apache.myfaces.shared_tomahawk.renderkit.html.util.FormInfo;
import org.apache.myfaces.shared_tomahawk.renderkit.html.util.JavascriptUtils;
import org.apache.myfaces.tomahawk.application.PreRenderViewAddResourceEvent;
import org.apache.myfaces.tomahawk.util.TomahawkResourceUtils;

/**
 * HTML Editor using the kupu library.
 * http://kupu.oscom.org/
 *
 * An inline HTML based word processor based on the Kupu library. 
 * 
 * See http://kupu.oscom.org 
 * 
 * Right now, the support is limited to one editor per page 
 * (but you can use tabs to have multiple editors, but only 
 * one rendered at a time). 
 * 
 * Unless otherwise specified, all attributes accept static values or EL expressions.
 *
 * @author Sylvain Vieujot (latest modification by $Author: skitching $)
 * @version $Revision: 673833 $ $Date: 2008-07-03 16:58:05 -0500 (jue, 03 jul 2008) $
 */
@JSFComponent(
   name = "t:inputHtml",
   tagClass = "org.apache.myfaces.custom.inputHtml.InputHtmlTag",
   composite=true)
@ListenerFor(systemEventClass=PreRenderViewAddResourceEvent.class)
public class InputHtml extends HtmlInputText implements NamingContainer, UniqueIdVendor {
    public static final String COMPONENT_TYPE = "org.apache.myfaces.InputHtml";

    public static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.InputHtml";

    private static final String INPUT_HTML_LIBRARY = "oam.custom.inputHtml";
    private static final String INPUT_HTML_LIBRARY_KUPU_DRAWERS = "oam.custom.inputHtml.kupudrawers";

    private static final Log log = LogFactory.getLog(HtmlInputText.class);

    public InputHtml() {
        setRendererType(DEFAULT_RENDERER_TYPE);
    }
    
    @Override
    public void setRendererType(String rendererType)
    {
        if (!"javax.faces.Composite".equals(rendererType))
        {
            super.setRendererType(rendererType);
        }
    }
    
    public void processEvent(ComponentSystemEvent event)
    {
        super.processEvent(event);
        if (event instanceof PreRenderViewAddResourceEvent)
        {
            InputHtml editor = (InputHtml) event.getComponent();
            if( !HtmlRendererUtils.isDisplayValueOnly(editor) && !useFallback(editor))
            {
                FacesContext facesContext = FacesContext.getCurrentInstance();
                //AddResource addResource = AddResourceFactory.getInstance(facesContext);
                //addResource.addStyleSheet(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupustyles.css");
                TomahawkResourceUtils.addOutputStylesheetResource(facesContext, INPUT_HTML_LIBRARY, "myFacesKupustyles.css");
                //addResource.addStyleSheet(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupudrawerstyles.css");
                TomahawkResourceUtils.addOutputStylesheetResource(facesContext, INPUT_HTML_LIBRARY, "kupudrawerstyles.css");
                //addResource.addStyleSheet(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "myFaces.css");
                TomahawkResourceUtils.addOutputStylesheetResource(facesContext, INPUT_HTML_LIBRARY, "myFaces.css");
    
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "sarissa.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "sarissa.js");
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "sarissa_ieemu_xpath.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "sarissa_ieemu_xpath.js");
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupuhelpers.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupuhelpers.js");
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupueditor.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupueditor.js");
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupubasetools.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupubasetools.js");
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupuloggers.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupuloggers.js");
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupunoi18n.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupunoi18n.js");
                //addResource.addJavaScriptAtPosition(context, InputHtmlRenderer.class, "i18n/i18n.js"); //NO
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupucleanupexpressions.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupucleanupexpressions.js");
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupucontentfilters.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupucontentfilters.js");
    
                if (editor.isShowAnyToolBox())
                {
                    //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kuputoolcollapser.js");
                    TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kuputoolcollapser.js");
                }
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupucontextmenu.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupucontextmenu.js");
    
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupuinit.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupuinit.js");
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupustart.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupustart.js");
    
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupusourceedit.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupusourceedit.js");
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupuspellchecker.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupuspellchecker.js");
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupudrawers.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupudrawers.js");
    
                //addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "kupuundo.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "kupuundo.js");
                //addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "diff_match_patch.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "diff_match_patch.js");
    
                //addResource.addJavaScriptAtPosition(facesContext, AddResource.HEADER_BEGIN, InputHtmlRenderer.class, "myFacesUtils.js");
                TomahawkResourceUtils.addOutputScriptResource(facesContext, INPUT_HTML_LIBRARY, "myFacesUtils.js");
                
                if( editor.getStyle()!=null ){
                    // Convert the style into an style declaration so that it doesn't preempt the Zoom works as it's relying on changing the class
                    //addResource.addInlineStyleAtPosition(
                    //        context, AddResource.HEADER_BEGIN,
                    //        "#kupu-editor{height: inherit;}\n"+
                    //        "div.kupu-fulleditor{"+editor.getStyle()+"}");
                    TomahawkResourceUtils.addInlineOutputStylesheetResource(facesContext, 
                            "#kupu-editor{height: inherit;}\n"+
                            "div.kupu-fulleditor{"+editor.getStyle()+"}");
                }
            }
        }
    }
    
    private static boolean useFallback(InputHtml editor){
        // TODO : Handle fallback="auto"
        return editor.getFallback().equals("true");
    }
    /*
    
      
        
  #{resource['oam.custom.inputHtml:fulldoc.html']}
  1
  0
  1
  application/xhtml+xml
  1
  
    plain
    listing
    grid
    data
  

  
    
      Convert single quotes to curly ones
      
        
          (\W)'
        
        
          \1‘
        
      
      
        
          '
        
        
      
    
    
      Reduce whitespace
      
        
          [\n\r\t]
        
        
          \x20
        
      
      
        
          [ ]{2}
        
        
          \x20
        
      
    
  

  #{resource['oam.custom.inputHtml.kupudrawers:drawer.xsl']}
  #{resource['oam.custom.inputHtml.kupudrawers:drawer.xsl']}
  #{resource['oam.custom.inputHtml.kupudrawers:imagelibrary.xml']}
  #{resource['oam.custom.inputHtml.kupudrawers:linklibrary.xml']}
   
   

      
    
   */
    public String getKupuConfig()
    {
        StringBuilder builder = new StringBuilder();
        builder.append("");
        builder.append("");
        builder.append("fulldoc.html");
        builder.append("1");
        builder.append("0");
        builder.append("1");
        builder.append("application/xhtml+xml");
        builder.append("1");
        builder.append("");
        builder.append("plain");
        builder.append("listing");
        builder.append("grid");
        builder.append("data");
        builder.append("");

        builder.append("");
        builder.append("");
        builder.append("Convert single quotes to curly ones");
        builder.append("");
        builder.append("");
        builder.append("(\\W)'");
        builder.append("");
        builder.append("");
        builder.append("\1‘");
        builder.append("");
        builder.append("");
        builder.append("");
        builder.append("");
        builder.append("'");
        builder.append("");
        builder.append("");
        builder.append("’");
        builder.append("");
        builder.append("");
        builder.append("");
        builder.append("");
        builder.append("Reduce whitespace");
        builder.append("");
        builder.append("");
        builder.append("[\n\r\t]");
        builder.append("");
        builder.append("");
        builder.append("\\x20");
        builder.append("");
        builder.append("");
        builder.append("");
        builder.append("");
        builder.append("[ ]{2}");
        builder.append("");
        builder.append("");
        builder.append("\\x20");
        builder.append("");
        builder.append("");
        builder.append("");
        builder.append("");

        FacesContext context = getFacesContext();
        Resource resource = context.getApplication().getResourceHandler()
                .createResource("drawer.xsl",
                        INPUT_HTML_LIBRARY_KUPU_DRAWERS);
        builder.append("" + resource.getRequestPath()
                + "");
        builder.append("" + resource.getRequestPath()
                + "");

        resource = context.getApplication().getResourceHandler()
                .createResource("imagelibrary.xml",
                        INPUT_HTML_LIBRARY_KUPU_DRAWERS);
        builder.append("" + resource.getRequestPath()
                + "");

        resource = context.getApplication().getResourceHandler()
                .createResource("linklibrary.xml",
                        INPUT_HTML_LIBRARY_KUPU_DRAWERS);
        builder.append("" + resource.getRequestPath()
                + "");

        builder.append(" ");
        builder.append(" ");

        builder.append("");
        builder.append("");
        return builder.toString();
    }
    
    
    public String getDisplayValueOnlyText()
    {
        return getHtmlBody(RendererUtils.getStringValue(getFacesContext(), this));
    }
    
    public String getFallbackText()
    {
        String text = RendererUtils.getStringValue(getFacesContext(), this);
        return htmlToPlainText(text, this);
    }
    
    public String getHiddenText()
    {
        return RendererUtils.getStringValue(getFacesContext(), this);
    }
    
    private static String htmlToPlainText(String html, InputHtml editor){
        return editor.getHtmlBody( html )
                .replaceAll("","\n")
                .replaceAll("<.+?>", "");
    }
    
    
    public String getFormId()
    {
        FormInfo parentFormInfo = RendererUtils.findNestingForm(this, getFacesContext());
        if(parentFormInfo == null)
            throw new FacesException("InputHtml must be embedded in a form.");
        return parentFormInfo.getFormName(); 
    }
    
    public String getEncodedText()
    {
        String text = this.getValueAsHtmlDocument(getFacesContext());
        return (text == null) ? "" : JavascriptUtils.encodeString( text );

    }
    
    /**
     * 
     * {@inheritDoc}
     * 
     * @since 2.0
     */
    public String createUniqueId(FacesContext context, String seed)
    {
        StringBuilder bld = new StringBuilder();

        // Generate an identifier for a component. The identifier will be prefixed with UNIQUE_ID_PREFIX, and will be unique within this UIViewRoot. 
        if(seed==null)
        {
            Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
            uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
            getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
            return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(uniqueIdCounter).toString();    
        }
        // Optionally, a unique seed value can be supplied by component creators which should be included in the generated unique id.
        else
        {
            return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(seed).toString();
        }
    }    
    
    /**
     * Use a text area instead of the javascript HTML editor. 
     * 
     * Default is false. Use with caution.
     * 
     * @JSFProperty
     */
    public String getFallback(){
        return (String) getStateHelper().eval(PropertyKeys.fallback, "false");
    }
    public void setFallback(String _fallback){
        getStateHelper().put(PropertyKeys.fallback, _fallback);
    }

    /**
     * The type of the value. It can be either fragment for an HTML 
     * fragment (default) or document for a full HTML document, with 
     * head, title, body, ... tags.
     * 
     * @JSFProperty
     */
    public String getType(){
        return (String) getStateHelper().eval(PropertyKeys.type, "fragment");
    }
    public void setType(String _type){
        getStateHelper().put(PropertyKeys.type, _type);
    }
    public boolean isTypeDocument(){
        return getType().equals("document");
    }

    /**
     * Allows the user to edit the HTML source code. Default is true.
     * 
     * @JSFProperty
     */
    public boolean isAllowEditSource(){
        return (Boolean) getStateHelper().eval(PropertyKeys.allowEditSource, Boolean.TRUE);
    }
    public void setAllowEditSource(boolean allowEditSource){
        getStateHelper().put(PropertyKeys.allowEditSource, allowEditSource);
    }

    /**
     * Allows the user to insert external links. Default is true.
     * 
     * @JSFProperty
     */
    public boolean isAllowExternalLinks(){
        return (Boolean) getStateHelper().eval(PropertyKeys.allowExternalLinks, Boolean.TRUE);
    }
    public void setAllowExternalLinks(boolean allowExternalLinks){
        getStateHelper().put(PropertyKeys.allowExternalLinks, allowExternalLinks);
    }

    /**
     * Show the Kupu Logo in the buttons bar. Default is true.
     * 
     * @JSFProperty
     */
    public boolean isAddKupuLogo(){
        return (Boolean) getStateHelper().eval(PropertyKeys.addKupuLogo, Boolean.TRUE);
    }
    public void setAddKupuLogo(boolean addKupuLogo){
        getStateHelper().put(PropertyKeys.addKupuLogo, addKupuLogo);
    }

    /**
     * Shortcut to avoid setting all the showXXToolBox to true. Default is false.
     * 
     * @JSFProperty
     */
    public boolean isShowAllToolBoxes(){
        return (Boolean) getStateHelper().eval(PropertyKeys.showAllToolBoxes, Boolean.FALSE);
    }
    public void setShowAllToolBoxes(boolean showAllToolBoxes){
        getStateHelper().put(PropertyKeys.showAllToolBoxes, showAllToolBoxes);
    }

    /**
     * Show the Properties tool box next to the text. Default is false.
     * 
     * @JSFProperty
     */
    public boolean isShowPropertiesToolBox(){
        if( isShowAllToolBoxes() )
            return true;

        return (Boolean) getStateHelper().eval(PropertyKeys.showPropertiesToolBox, Boolean.FALSE);
    }

    public void setShowPropertiesToolBox(boolean showPropertiesToolBox){
        getStateHelper().put(PropertyKeys.showPropertiesToolBox, showPropertiesToolBox);
    }

    /**
     * Show the Links tool box next to the text. Default is false.
     * 
     * @JSFProperty
     */
    public boolean isShowLinksToolBox(){
        if( isShowAllToolBoxes() )
            return true;

        return (Boolean) getStateHelper().eval(PropertyKeys.showLinksToolBox, Boolean.FALSE);
    }
    
    public void setShowLinksToolBox(boolean showLinksToolBox){
        getStateHelper().put(PropertyKeys.showLinksToolBox, showLinksToolBox);
    }

    /**
     * Show the Images tool box next to the text. Default is false.
     * 
     * @JSFProperty
     */
    public boolean isShowImagesToolBox(){
        if( isShowAllToolBoxes() )
            return true;

        return (Boolean) getStateHelper().eval(PropertyKeys.showImagesToolBox, Boolean.FALSE);
    }
    public void setShowImagesToolBox(boolean showImagesToolBox){
        getStateHelper().put(PropertyKeys.showImagesToolBox, showImagesToolBox);
    }

    /**
     * Show the Tables tool box next to the text. Default is false.
     * 
     * @JSFProperty
     */
    public boolean isShowTablesToolBox(){
        if( isShowAllToolBoxes() )
            return true;

        return (Boolean) getStateHelper().eval(PropertyKeys.showTablesToolBox, Boolean.FALSE);
    }
    public void setShowTablesToolBox(boolean showTablesToolBox){
        getStateHelper().put(PropertyKeys.showTablesToolBox, showTablesToolBox);
    }

    /**
     * Show the Cleanup Expressions tool box next to the text. Default is false.
     * 
     * @JSFProperty
     */
    public boolean isShowCleanupExpressionsToolBox(){
        if( isShowAllToolBoxes() )
            return true;

        return (Boolean) getStateHelper().eval(PropertyKeys.showCleanupExpressionsToolBox, Boolean.FALSE);
    }
    public void setShowCleanupExpressionsToolBox(boolean showCleanupExpressionsToolBox){
        getStateHelper().put(PropertyKeys.showCleanupExpressionsToolBox, showCleanupExpressionsToolBox);
    }

    /**
     * Show the Debug tool box next to the text. Default is false.
     * 
     * @JSFProperty
     */
    public boolean isShowDebugToolBox(){
        if( isShowAllToolBoxes() )
            return true;

        return (Boolean) getStateHelper().eval(PropertyKeys.showDebugToolBox, Boolean.FALSE);
    }
    public void setShowDebugToolBox(boolean showTablesToolBox){        
        getStateHelper().put(PropertyKeys.showDebugToolBox, showTablesToolBox);
    }

    public boolean isShowAnyToolBox(){
           return isShowAllToolBoxes()
               || isShowPropertiesToolBox()
               || isShowLinksToolBox()
               || isShowImagesToolBox()
               || isShowTablesToolBox()
               || isShowCleanupExpressionsToolBox()
               || isShowDebugToolBox();
    }

    public String getValueAsHtmlDocument(FacesContext context){
        String val = RendererUtils.getStringValue(context, this);
        if( isHtmlDocument( val ) )
            return val;

        return ""+(val==null ? "" : val)+"";
    }

    private static boolean isHtmlDocument(String text){
        if( text == null )
            return false;

        if( text.indexOf("")!=-1 || text.indexOf("")!=-1 || text.indexOf("") )
            return fragment.substring(0, fragment.length()-6);
        return fragment;
    }
    
    String getHtmlBody(String html){
        html = html.trim();
        if( html.length() == 0 )
            return "";

        String lcText = html.toLowerCase();
        int textLength = lcText.length();
        int bodyStartIndex = -1;
        while(bodyStartIndex < textLength){
            bodyStartIndex++;
            bodyStartIndex = lcText.indexOf("' )
                break;

            if( c!=' ' && c!='\t' )
                continue;

            bodyStartIndex = lcText.indexOf('>', bodyStartIndex);
            break;
        }
        bodyStartIndex++;

        int bodyEndIndex = lcText.lastIndexOf("")-1;
        
        if( bodyStartIndex<0 || bodyEndIndex<0
           || bodyStartIndex > bodyEndIndex
           || bodyStartIndex>=textLength || bodyEndIndex>=textLength ){

            if( lcText.indexOf("")!=-1 || lcText.indexOf("")!=-1 )
                return "";
            
            int htmlStartIndex = lcText.indexOf("");
            int htmlEndIndex = lcText.indexOf("");
            if( htmlStartIndex != -1 && htmlEndIndex > htmlStartIndex )
                return html.substring(htmlStartIndex+6, htmlEndIndex);
            
            if( isTypeDocument() )
                log.warn("Couldn't extract HTML body from :\n"+html);
            return html.trim();
        }

        return html.substring(bodyStartIndex, bodyEndIndex+1).trim();
    }
    
    protected enum PropertyKeys
    {
        fallback,
        type,
        allowEditSource,
        allowExternalLinks,
        addKupuLogo,
        showAllToolBoxes,
        showPropertiesToolBox,
        showLinksToolBox,
        showImagesToolBox,
        showTablesToolBox,
        showCleanupExpressionsToolBox,
        showDebugToolBox,
        uniqueIdCounter
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy