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

com.janeluo.easypdf.HTMLDoc Maven / Gradle / Ivy

The newest version!
/* Copyright (c) 2021 janeluo
 * easy-pdf is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package com.janeluo.easypdf;

import com.alibaba.fastjson.JSONObject;
import org.xml.sax.Attributes;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 输出 HTML 文档
 */
public class HTMLDoc extends TextDoc {
    static public final int TYPE_INPUT = 1;
    static public final int TYPE_COMBO = 2;

    private boolean isOpen = false;
    private JSONObject jsonObject;
    private List cssPaths;
    private List jsPaths;
    private String declare = null;
    private String extra = null;
    private int type = TYPE_INPUT;

    private String htmlOpen = ""
            + "\n"
            + "\n"
            + "  \n"
            + "    __TITLE__\n"
            + "    \n"
            + "    \n"
            + "    \n"
            + "    \n"
            + "    \n"
            + "    __CSS_URL__\n"
            + "    __JS_URL__\n"
            + "  \n"
            + "  \n";

    private final String htmlClose = "  \n\n";


    public HTMLDoc(OutputStream outputStream) {
        super(outputStream);
    }

    public void setJSONObject(JSONObject jsonObject) {
        this.jsonObject = jsonObject;
    }

    public void setLinkPaths(List css_paths, List js_paths) {
        this.cssPaths = css_paths;
        this.jsPaths = js_paths;
    }

    public void setDeclare(String declare) {
        this.declare = declare;
    }

    public void setExtra(String extra) {
        this.extra = extra;
    }

    public void setType(int type) {
        this.type = type;
    }

    private boolean writeStream(String string) {
        try {
            outputStream.write(string.getBytes(encoding));
            return true;
        } catch (UnsupportedEncodingException e) {
            System.err.println("Unsupported encoding.");
            return false;
        } catch (IOException e) {
            System.err.println("Write to html stream failed.");
            return false;
        }
    }

    private void substituteDeclare() {
        if (declare != null) {
            htmlOpen = htmlOpen.replace("", declare);
        }
    }

    private void substituteTitle() {
        if (jsonObject != null) {
            if (jsonObject.containsKey("title")) {
                Object value = jsonObject.get("title");
                if (value instanceof String) {
                    htmlOpen = htmlOpen.replace("__TITLE__",
                            Util.escapeHtmlString((String) value));
                }
            }
        }
        htmlOpen = htmlOpen.replace("__TITLE__", "");
    }

    private void substituteCSSLinks() {
        if (cssPaths != null) {
            StringBuilder builder = new StringBuilder();
            for (String path : cssPaths) {
                builder.append("\n");
            }
            htmlOpen = htmlOpen.replace("__CSS_URL__",
                    builder.toString().trim());
        } else {
            htmlOpen = htmlOpen.replace("__CSS_URL__", "");
        }
    }

    private void substituteJSLinks() {
        if (jsPaths != null) {
            StringBuilder builder = new StringBuilder();
            for (String path : jsPaths) {
                builder.append("    \n");
            }
            htmlOpen = htmlOpen.replace("__JS_URL__",
                    builder.toString().trim());
        } else {
            htmlOpen = htmlOpen.replace("__JS_URL__", "");
        }
    }

    @Override
    public boolean open() {
        if (outputStream == null) {
            return false;
        }

        substituteDeclare();
        substituteTitle();
        htmlOpen = htmlOpen.replace("__ENCODING__", encoding);
        substituteCSSLinks();
        substituteJSLinks();

        isOpen = true;
        return writeStream(htmlOpen);
    }

    @Override
    public void close() {
        if (isOpen && outputStream != null) {
            if (extra != null) {
                writeStream(extra);
            }
            writeStream(htmlClose);
        }
    }

    @Override
    public boolean isOpen() {
        return isOpen;
    }

    private final Map block_labels = new HashMap() {
        {
            put("title", "h1");
            put("chapter", "h2");
            put("section", "h3");
            put("para", "p");
        }
    };

    private String getHtmlLabel(String blockName) {

        return block_labels.get(blockName.toLowerCase());
    }

    private Map getHtmlAttrs(TextChunk chunk,
                                             boolean blockElement) {
        Map chunkAttrs = chunk.getAttrs();
        Map htmlAttrs = new HashMap<>();
        StringBuilder styleString = new StringBuilder();

        for (String key : chunkAttrs.keySet()) {
            if ("font-style".equalsIgnoreCase(key)) {
                String[] styles = chunkAttrs.get(key).split(",");
                for (String style : styles) {
                    String styleName = style.trim();
                    if ("bold".equalsIgnoreCase(styleName)) {
                        styleString.append("font-weight: bold; ");
                    } else if ("italic".equalsIgnoreCase(styleName)) {
                        styleString.append("font-style: italic; ");
                    } else if ("underline".equalsIgnoreCase(styleName)) {
                        styleString.append("font-decoration: underline; ");
                    }
                }
            } else if (blockElement && "indent".equalsIgnoreCase(key)) {
                styleString.append("text-indent: ").append(chunkAttrs.get(key)).append("px; ");
            } else if (blockElement && "align".equalsIgnoreCase(key)) {
                styleString.append("text-align: ").append(chunkAttrs.get(key)).append("; ");
            }
        }
        if (styleString.toString().length() > 0) {
            htmlAttrs.put("style", styleString.toString());
        }
        return htmlAttrs;
    }

    private String htmlCharEscape(String contents) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < contents.length(); i++) {
            char ch = contents.charAt(i);
            if (ch == '\n') {
                builder.append("
"); } else { String escape = Util.escapeHtmlChars(ch); if (escape != null) { builder.append(escape); } else { builder.append(ch); } } } return builder.toString(); } private void writeValue(TextChunk chunk) { Map attrs = chunk.getAttrs(); String id = attrs.get("id"); String minlen = attrs.get("minlen"); switch (type) { case TYPE_INPUT: writeStream(" 0) { writeStream(" id=\"" + id + "\" name=\"" + id + "\""); } if (minlen != null && minlen.length() > 0) { writeStream(" size=\"" + minlen + "\""); } writeStream(" />"); break; case TYPE_COMBO: writeStream(" 0) { writeStream(" size=\"" + minlen + "\""); } writeStream(" readonly=\"readonly\""); writeStream(" />"); writeStream(" 0) { writeStream(" id=\"" + id + "\" name=\"" + id + "\""); } writeStream(">\n"); writeStream("\n"); writeStream("\n"); writeStream("\n"); break; default: break; } } @Override public void writeBlock(String blockName, List chunkList) throws IOException { if (outputStream == null || chunkList.size() == 0) { return; } String label = getHtmlLabel(blockName); if (label == null) { System.err.println("unable map block name '" + blockName + "'to html label."); return; } for (int i = 0; i < chunkList.size(); i++) { TextChunk chunk = chunkList.get(i); if (chunk.isValue()) { writeValue(chunk); continue; } if (i == 0) { writeStream(" <" + label + " class=\"" + blockName + "\""); } else { writeStream(" htmlAttrs = getHtmlAttrs(chunk, i == 0); for (String key : htmlAttrs.keySet()) { writeStream(" " + key + "=\"" + htmlAttrs.get(key) + "\""); } writeStream(">"); writeStream(htmlCharEscape(chunk.getContents())); if (i > 0) { writeStream(""); } } writeStream("\n"); } @Override public void newPage() { writeStream("
\n"); } @Override public void addHrule(Attributes attrs) { writeStream("
\n"); } @Override public void addImage(Attributes attrs) { String value = attrs.getValue("src"); if (value == null) { System.err.println("img missing src attribute."); return; } writeStream(""); } @Override public void writeTable(TextTable table) { if (!isOpen() || table == null) { return; } Map attrs = table.getAttrs(); int[] columns = null; String value = attrs.get("columns"); if (value != null) { try { String[] array = value.split(","); columns = new int[array.length]; int total = 0; for (int i = 0; i < array.length; i++) { columns[i] = Integer.parseInt(array[i]); total += columns[i]; } for (int i = 0; i < columns.length; i++) { columns[i] = columns[i] * 100 / total; } } catch (Exception ex) { System.err.println("column must has a integer value"); } } if (columns == null) { return; } writeStream(" \n"); for (int i = 0; i < table.getCells().size(); i++) { int colno = i % columns.length; if (colno == 0) { if (i > 0) { writeStream(" \n"); } writeStream(" \n"); } if (columns[colno] > 0) { TextChunk textChunk = table.getCells().get(i); writeStream(" \n"); } } writeStream(" \n"); writeStream("
" + textChunk.getContents() + "
\n"); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy