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("\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("" + label + ">\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(" " +
textChunk.getContents() + " \n");
}
}
writeStream(" \n");
writeStream("
\n");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy