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

org.docx4j.convert.out.html.HtmlCssHelper Maven / Gradle / Ivy

Go to download

docx4j is a library which helps you to work with the Office Open XML file format as used in docx documents, pptx presentations, and xlsx spreadsheets.

There is a newer version: 11.4.11
Show newest version
/*
   Licensed to Plutext Pty Ltd under one or more contributor license agreements.  
   
 *  This file is part of docx4j.

    docx4j is licensed 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.docx4j.convert.out.html;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.docx4j.model.properties.Property;
import org.docx4j.model.properties.PropertyFactory;
import org.docx4j.model.properties.paragraph.Indent;
import org.docx4j.model.properties.paragraph.PBorderBottom;
import org.docx4j.model.properties.paragraph.PBorderTop;
import org.docx4j.model.properties.paragraph.PShading;
import org.docx4j.model.styles.StyleTree;
import org.docx4j.model.styles.StyleTree.AugmentedStyle;
import org.docx4j.model.styles.Tree;
import org.docx4j.openpackaging.packages.OpcPackage;
import org.docx4j.wml.CTShd;
import org.docx4j.wml.CTTblPrBase;
import org.docx4j.wml.CTTblStylePr;
import org.docx4j.wml.PPr;
import org.docx4j.wml.RPr;
import org.docx4j.wml.Style;
import org.docx4j.wml.TcPr;
import org.docx4j.wml.TrPr;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;

/** These is an utility class with some common functions for the 
 *  HTML-exporters and the SvgExporter.
 * 
 */
public class HtmlCssHelper {

	private static Logger log = LoggerFactory.getLogger(HtmlCssHelper.class);
	
	//Temporary maps that get used in applyAttributes, they are kept here to be able to reuse it
	private static ThreadLocal> threadLocalTempMap = new ThreadLocal>();
		
    public static void createDefaultCss(boolean hasDefaultHeader, boolean hasDefaultFooter, StringBuilder result) {
    	//TODO: This method needs to be replaced with something similar to the LayoutMasterSetBuilder of fo
		result.append("/*paged media */ div.header {display: none }");
		result.append("div.footer {display: none } /*@media print { */");
		if (hasDefaultHeader) {
			result.append("div.header {display: block; position: running(header) }");
		}
		if (hasDefaultFooter) {
			result.append("div.footer {display: block; position: running(footer) }");
		}
		
		result.append("@page { size: A4; margin: 10%; @top-center {");
		result.append("content: element(header) } @bottom-center {");
		result.append("content: element(footer) } }");

		result.append("/*element styles*/ .del  {text-decoration:line-through;color:red;} ");
		result.append(".ins {text-decoration:none;background:#c0ffc0;padding:1px;}");
    	
    }
	
    public static void createCssForStyles(OpcPackage opcPackage, StyleTree styleTree, StringBuilder result) {

		// First iteration - table styles
		result.append("\n /* TABLE STYLES */ \n");    	
		Tree tableTree = styleTree.getTableStylesTree();		
    	for (org.docx4j.model.styles.Node n : tableTree.toList() ) {
    		
    		if (n.getData()==null) {
    			if (n.equals(tableTree.getRootElement() )) {
    				// that's ok
    			} else {
    				log.error("Node unexpectedly null data" );
    			}
    			continue;
    		}
    		
    		Style s = n.getData().getStyle();

    		result.append( "table."+ s.getStyleId()  + " {display:table;" );
    		
    		// TblPr
    		if (s.getTblPr()==null) {
    		} else {
    			log.debug("Applying tblPr..");
            	createCss(s.getTblPr(), result);
            	
    		}
    		
    		// TblStylePr - STTblStyleOverrideType stuff
    		if (s.getTblStylePr()==null) {
    		} else {
    			log.debug("Applying tblStylePr.. TODO!");
    			// Its a list, created automatically
            	createCss(s.getTblStylePr(), result);
    		}
    		
    		
    		// TrPr - eg jc, trHeight, wAfter, tblCellSpacing
    		if (s.getTrPr()==null) {
    		} else {
    			log.debug("Applying trPr.. TODO!");
            	createCss( s.getTrPr(), result);
    		}
    		
    		// TcPr - includes includes TcPrInner.TcBorders, CTShd, TcMar, CTVerticalJc
    		if (s.getTcPr()==null) {
    		} else {
    			log.debug("Applying tcPr.. ");
            	createCss( s.getTcPr(), result);
    		}
    		    		
        	if (s.getPPr()==null) {
        		log.debug("null pPr for style " + s.getStyleId());
        	} else {
        		HtmlCssHelper.createCss(opcPackage, s.getPPr(), result, false, false );
        	}
        	if (s.getRPr()==null) {
        		log.debug("null rPr for style " + s.getStyleId());
        	} else {
            	HtmlCssHelper.createCss(opcPackage, s.getRPr(), result);
        	}
        	result.append( "}\n" );         	
    	}
		
		// Second iteration - paragraph level pPr *and rPr*
		result.append("\n /* PARAGRAPH STYLES */ \n");    	
		Tree pTree = styleTree.getParagraphStylesTree();		
    	for (org.docx4j.model.styles.Node n : pTree.toList() ) {
    		
    		if (n.getData()==null) {
    			if (n.equals(pTree.getRootElement() )) {
    				// shouldn't happen in paragraph case, but still, that's ok
    			} else {
    				log.error("Node unexpectedly null data" );
    			}
    			continue;
    		}
    		
    		Style s = n.getData().getStyle();

    		result.append( "."+ s.getStyleId()  + " {display:block;" );  // not just p, also inherit on ul|ol
        	if (s.getPPr()==null) {
        		log.debug("null pPr for style " + s.getStyleId());
        	} else {
        		HtmlCssHelper.createCss(opcPackage, s.getPPr(), result, false, false );
        	}
        	if (s.getRPr()==null) {
        		log.debug("null rPr for style " + s.getStyleId());
        	} else {
            	HtmlCssHelper.createCss(opcPackage, s.getRPr(), result);
        	}
        	result.append( "}\n" );        	
    	}
		    	
	    // Third iteration, character styles
		result.append("\n /* CHARACTER STYLES */ ");
		//result.append("\n /* These come last, so they have more weight than the paragraph _rPr component styles */ \n ");
		
		Tree cTree = styleTree.getCharacterStylesTree();		
    	for (org.docx4j.model.styles.Node n : cTree.toList() ) {
    		
    		if (n.getData()==null) {
    			if (n.equals(cTree.getRootElement() )) {
    				// that's ok
    			} else {
    				log.error("Node unexpectedly null data" );
    			}
    			continue;
    		}
    		
    		Style s = n.getData().getStyle();

    		result.append( "span."+ s.getStyleId()  + " {display:inline;" );
        	if (s.getRPr()==null) {
        		log.warn("! null rPr for character style " + s.getStyleId());
        	} else {
            	HtmlCssHelper.createCss(opcPackage, s.getRPr(), result);
        	}
        	result.append( "}\n" );        	
    	}	
    }
    
    protected static void createCss(CTTblPrBase  tblPr, StringBuilder result) {
    	
		if (tblPr==null) {
			return;
		}
    	
    	List properties = PropertyFactory.createProperties(tblPr);    	
    	for( Property p :  properties ) {
    		appendNonNull(result, p);
    	}    
    }
    
    protected static void createCss(List tblStylePrList, StringBuilder result) {
    	// STTblStyleOverrideType
    	
		if (tblStylePrList==null) {
			return;
		}
    	
    	List properties = PropertyFactory.createProperties(tblStylePrList);    	
    	for( Property p :  properties ) {
    		appendNonNull(result, p);
    	}    
    }
    
    protected static void createCss(TrPr trPr, StringBuilder result) {
    	// includes jc, trHeight, wAfter, tblCellSpacing
    	
		if (trPr==null) {
			return;
		}
    	
    	List properties = PropertyFactory.createProperties(trPr);    	
    	for( Property p :  properties ) {
    		appendNonNull(result, p);
    	}    
    }
    
    protected static void createCss(TcPr tcPr, StringBuilder result) {
    	// includes TcPrInner.TcBorders, CTShd, TcMar, CTVerticalJc
    	
		if (tcPr==null) {
			return;
		}
    	
    	List properties = PropertyFactory.createProperties(tcPr);    	
    	for( Property p :  properties ) {
    		appendNonNull(result, p);
    	}    
    }
    
    public static void createCss(OpcPackage opcPackage, PPr pPr, StringBuilder result, boolean ignoreBorders, boolean isListItem) {
    	
    	if (isListItem) {
    		result.append("display: list-item;");
    	}
    	
		if (pPr==null) {
			return;
		}
    	
    	List properties = PropertyFactory.createProperties(opcPackage, pPr);    	
    	for( Property p :  properties ) {
    		
			if (ignoreBorders &&
					((p instanceof PBorderTop)
							|| (p instanceof PBorderBottom))) {
				continue;
			}

	    	if (isListItem
	    			&& p instanceof Indent) {
	    		// Avoid indent settings which would overwrite the bullet 
	    		// eg "position: relative; margin-left: 0.5in;text-indent: -0.25in;
				continue;	    		
	    	}
			
			if (p instanceof PShading) {
    	    	// To close the gap between divs, we need to avoid
    	    	// CSS margin collapse.    	    	
    	    	// To do that, we add a border the same color as 
    	    	// the background color				
				String fill = ((CTShd)p.getObject()).getFill();				
				result.append("border-color: #" + fill + "; border-style:solid; border-width:1px;");
			}
    		
    		appendNonNull(result, p);
    	}    
    }
    
    public static void createCss(OpcPackage opcPackage, RPr rPr, StringBuilder result) {

    	List properties = PropertyFactory.createProperties(opcPackage, rPr);
    	
    	for( Property p :  properties ) {
    		appendNonNull(result, p);
    	}
    }

    private static void appendNonNull(StringBuilder result, Property p) {
		String prop = p.getCssProperty();
		if (prop!=null) {
			result.append(prop);
		}
    }
    
	public static void applyAttributes(List properties, Element node) {
	Map tempAttributeMap = null;
	StringBuilder buffer = null;
		if ((properties != null) && (!properties.isEmpty())) {
			tempAttributeMap = getTempMap();
			if ((properties != null) && (!properties.isEmpty())) {
				buffer = new StringBuilder();
				for (int i=0; i 0)) {
			node.setAttribute("style", style + newValue);
		}
		else {
			node.setAttribute("style", newValue);
		}
	}
	
	protected static Map getTempMap() {
	Map ret = threadLocalTempMap.get();
		if (ret == null) {
			ret = new TreeMap();
			threadLocalTempMap.set(ret);
		}
		return ret;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy