org.magicwerk.brownies.html.content.HtmlTextFormatter Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2012 by Thomas Mauch
*
* 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.
*
* $Id: HtmlTableFormatter.java 3374 2016-11-14 00:57:24Z origo $
*/
package org.magicwerk.brownies.html.content;
import java.util.List;
import org.jdom2.Attribute;
import org.magicwerk.brownies.collections.GapList;
import org.magicwerk.brownies.collections.IList;
import org.magicwerk.brownies.core.StringTools;
import org.magicwerk.brownies.core.strings.text.TextTabs;
import org.magicwerk.brownies.core.strings.text.TextTools;
import org.magicwerk.brownies.html.HtmlConst;
import org.magicwerk.brownies.html.HtmlElement;
import org.magicwerk.brownies.html.HtmlElement.HtmlElementContainer;
import org.magicwerk.brownies.html.HtmlInline;
import org.magicwerk.brownies.html.content.HtmlFormatters.Context;
import org.magicwerk.brownies.html.content.HtmlFormatters.HtmlFormatter;
import org.magicwerk.brownies.jdom.JdomTools;
/**
* Class {@link HtmlTextFormatter} formats text into HTML text elements.
*/
public class HtmlTextFormatter {
public enum Mode {
/** Use HTML element P for display */
PARAGRAPH,
/** Use HTML element PRE for display */
PREFORMATTED
}
// Configuration
/** Display mode */
Mode mode = Mode.PARAGRAPH;
/** Class attribute to add to the created elements {@literal /
} (optional, null for none) */
String elemClass;
/** Number of unbreakable spaces used to replace a tab, -1 for no replacement to be done (default is 3) */
int spacesPerTab = 3;
/** Formatter to use for each line (optional, null for none) */
HtmlFormatter lineFormatter;
/** If not null, invalid characters are replaced by this character. The default {@link StringTools#NOT_A_CHAR} removes invalid chars */
Character replaceInvalid = StringTools.NOT_A_CHAR;
// Config
/** Getter for {@link #mode} */
public Mode getMode() {
return mode;
}
/** Setter for {@link #mode} */
public HtmlTextFormatter setMode(Mode mode) {
this.mode = mode;
return this;
}
/** Getter for {@link #spacesPerTab} */
public int getSpacesPerTab() {
return spacesPerTab;
}
/** Setter for {@link #spacesPerTab} */
public HtmlTextFormatter setSpacesPerTab(int spacesPerTab) {
this.spacesPerTab = spacesPerTab;
return this;
}
/** Setter for {@link #lineFormatter} */
public HtmlTextFormatter setLineFormatter(HtmlFormatter lineFormatter) {
this.lineFormatter = lineFormatter;
return this;
}
/** Setter for {@link #elemClass} */
public HtmlTextFormatter setElemClass(String elemClass) {
this.elemClass = elemClass;
return this;
}
/**
* Replace tabs and new lines.
*
* @param text text to format
* @return HtmlFlow representing text
*/
public HtmlElement formatText(String text) {
IList strs = formatLines(text, mode);
if (mode == Mode.PARAGRAPH) {
return formatTextP(strs);
} else {
return formatTextPre(strs);
}
}
public HtmlElement formatLines(List lines) {
IList strs = GapList.create(lines);
if (mode == Mode.PARAGRAPH) {
strs.transform(TextTools::removeEol);
return formatTextP(strs);
} else {
strs.transform(TextTools::addEol);
return formatTextPre(strs);
}
}
IList formatLines(String str, Mode mode) {
boolean includeEol = (mode == Mode.PREFORMATTED);
IList lines = TextTools.splitLines(str, includeEol);
return lines;
}
HtmlElement formatTextP(IList lines) {
Context ctx = new Context();
lines.transform(this::formatWhitespaces);
HtmlElement container = new HtmlElementContainer();
for (int i = 0; i < lines.size(); i++) {
String str = lines.get(i);
HtmlElement p = createElem(HtmlConst.ELEM_P).addText(str);
container.addElem(p);
if (lineFormatter != null) {
ctx.row = i;
ctx.str = str;
Attribute attr = lineFormatter.format(ctx);
if (attr != null) {
p.getElement().setAttribute(attr.clone());
}
}
}
return container;
}
HtmlElement formatTextPre(IList lines) {
Context ctx = new Context();
lines.transform(this::formatWhitespaces);
HtmlInline pre = createElem(HtmlConst.ELEM_PRE);
for (int i = 0; i < lines.size(); i++) {
String str = lines.get(i);
Attribute attr = null;
if (lineFormatter != null) {
ctx.row = i;
ctx.str = str;
attr = lineFormatter.format(ctx);
if (attr != null) {
String eol = TextTools.getEol(str);
String line = TextTools.removeEol(str);
pre.newSpan(line).getElement().setAttribute(attr.clone());
addText(pre, eol);
}
}
if (attr == null) {
addText(pre, str);
}
}
return pre;
}
void addText(HtmlInline pre, String str) {
if (replaceInvalid != null) {
str = JdomTools.sanitizeText(str, replaceInvalid);
}
pre.addText(str);
}
HtmlInline createElem(String name) {
HtmlInline elem = new HtmlInline(name);
if (elemClass != null) {
elem.setClass(elemClass);
}
return elem;
}
String formatWhitespaces(String line) {
if (spacesPerTab != -1) {
line = TextTabs.normalizeTabs(line, spacesPerTab);
}
line = normalizeSpaces(line);
return line;
}
public static String normalizeSpaces(String line) {
StringBuilder buf = new StringBuilder();
boolean prevSpace = false;
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if (c == ' ') {
if (prevSpace) {
buf.append(TextTools.NBSP);
} else {
buf.append(TextTools.SPACE);
prevSpace = true;
}
} else {
buf.append(c);
prevSpace = false;
}
}
return buf.toString();
}
}