001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.html; 018 019import static org.apache.juneau.common.utils.StringUtils.*; 020 021import java.io.*; 022 023import org.apache.juneau.*; 024import org.apache.juneau.xml.*; 025 026/** 027 * Specialized writer for serializing HTML. 028 * 029 * <h5 class='section'>See Also:</h5><ul> 030 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HtmlBasics">HTML Basics</a> 031 032 * </ul> 033 */ 034public class HtmlWriter extends XmlWriter { 035 036 /** 037 * Constructor. 038 * 039 * @param out The writer being wrapped. 040 * @param useWhitespace If <jk>true</jk>, tabs will be used in output. 041 * @param maxIndent The maximum indentation level. 042 * @param trimStrings If <jk>true</jk>, strings should be trimmed before they're serialized. 043 * @param quoteChar The quote character to use (i.e. <js>'\''</js> or <js>'"'</js>) 044 * @param uriResolver The URI resolver for resolving URIs to absolute or root-relative form. 045 */ 046 public HtmlWriter(Writer out, boolean useWhitespace, int maxIndent, boolean trimStrings, char quoteChar, 047 UriResolver uriResolver) { 048 super(out, useWhitespace, maxIndent, trimStrings, quoteChar, uriResolver, false, null); 049 } 050 051 /** 052 * Copy constructor. 053 * 054 * @param w Writer being copied. 055 */ 056 public HtmlWriter(HtmlWriter w) { 057 super(w); 058 } 059 060 //----------------------------------------------------------------------------------------------------------------- 061 // Overridden methods 062 //----------------------------------------------------------------------------------------------------------------- 063 064 @Override /* XmlSerializerWriter */ 065 public HtmlWriter text(Object o, boolean preserveWhitespace) { 066 067 if (o == null) { 068 append("<null/>"); 069 return this; 070 } 071 String s = o.toString(); 072 if (s.isEmpty()) { 073 append("<sp/>"); 074 return this; 075 } 076 077 for (int i = 0; i < s.length(); i++) { 078 char test = s.charAt(i); 079 if (test == '&') 080 append("&"); 081 else if (test == '<') 082 append("<"); 083 else if (test == '>') 084 append(">"); 085 else if (test == '\n') 086 append(preserveWhitespace ? "\n" : "<br/>"); 087 else if (test == '\f') // XML 1.0 doesn't support form feeds or backslashes, so we have to invent something. 088 append(preserveWhitespace ? "\f" : "<ff/>"); 089 else if (test == '\b') 090 append(preserveWhitespace ? "\b" : "<bs/>"); 091 else if (test == '\t') 092 append(preserveWhitespace ? "\t" : "<sp> </sp>"); 093 else if ((i == 0 || i == s.length()-1) && Character.isWhitespace(test)) { 094 if (preserveWhitespace) 095 w(test); 096 else if (test == ' ') 097 append("<sp> </sp>"); 098 else 099 append("<sp>&#x").append(toHex4(test)).append(";</sp>"); 100 } 101 else if (Character.isISOControl(test)) 102 append("&#" + (int) test + ";"); 103 else 104 w(test); 105 } 106 107 return this; 108 } 109 110 @Override /* XmlSerializerWriter */ 111 public HtmlWriter oTag(String ns, String name, boolean needsEncoding) { 112 super.oTag(ns, name, needsEncoding); 113 return this; 114 } 115 @Override /* XmlSerializerWriter */ 116 public HtmlWriter oTag(String ns, String name) { 117 super.oTag(ns, name); 118 return this; 119 } 120 @Override /* XmlSerializerWriter */ 121 public HtmlWriter oTag(String name) { 122 super.oTag(name); 123 return this; 124 } 125 @Override /* XmlSerializerWriter */ 126 public HtmlWriter oTag(int indent, String ns, String name, boolean needsEncoding) { 127 super.oTag(indent, ns, name, needsEncoding); 128 return this; 129 } 130 @Override /* XmlSerializerWriter */ 131 public HtmlWriter oTag(int indent, String ns, String name) { 132 super.oTag(indent, ns, name); 133 return this; 134 } 135 @Override /* XmlSerializerWriter */ 136 public HtmlWriter oTag(int indent, String name) { 137 super.oTag(indent, name); 138 return this; 139 } 140 @Override /* XmlSerializerWriter */ 141 public HtmlWriter tag(String ns, String name, boolean needsEncoding) { 142 super.tag(ns, name, needsEncoding); 143 return this; 144 } 145 @Override /* XmlSerializerWriter */ 146 public HtmlWriter tag(String ns, String name) { 147 super.tag(ns, name); 148 return this; 149 } 150 @Override /* XmlSerializerWriter */ 151 public HtmlWriter tag(String name) { 152 super.tag(name); 153 return this; 154 } 155 @Override /* XmlSerializerWriter */ 156 public HtmlWriter tag(int indent, String name) { 157 super.tag(indent, name); 158 return this; 159 } 160 @Override /* XmlSerializerWriter */ 161 public HtmlWriter tag(int indent, String ns, String name, boolean needsEncoding) { 162 super.tag(indent, ns, name, needsEncoding); 163 return this; 164 } 165 @Override /* XmlSerializerWriter */ 166 public HtmlWriter tag(int indent, String ns, String name) { 167 super.tag(indent, ns, name); 168 return this; 169 } 170 @Override /* XmlSerializerWriter */ 171 public HtmlWriter sTag(String ns, String name) { 172 super.sTag(ns, name); 173 return this; 174 } 175 @Override /* XmlSerializerWriter */ 176 public HtmlWriter sTag(String ns, String name, boolean needsEncoding) { 177 super.sTag(ns, name, needsEncoding); 178 return this; 179 } 180 @Override /* XmlSerializerWriter */ 181 public HtmlWriter sTag(int indent, String ns, String name) { 182 super.sTag(indent, ns, name); 183 return this; 184 } 185 @Override /* XmlSerializerWriter */ 186 public HtmlWriter sTag(int indent, String name) { 187 super.sTag(indent, name); 188 return this; 189 } 190 @Override /* XmlSerializerWriter */ 191 public HtmlWriter sTag(String name) { 192 super.sTag(name); 193 return this; 194 } 195 @Override /* XmlSerializerWriter */ 196 public HtmlWriter sTag(int indent, String ns, String name, boolean needsEncoding) { 197 super.sTag(indent, ns, name, needsEncoding); 198 return this; 199 } 200 @Override /* XmlSerializerWriter */ 201 public HtmlWriter eTag(String ns, String name) { 202 super.eTag(ns, name); 203 return this; 204 } 205 @Override /* XmlSerializerWriter */ 206 public HtmlWriter eTag(String ns, String name, boolean needsEncoding) { 207 super.eTag(ns, name, needsEncoding); 208 return this; 209 } 210 @Override /* XmlSerializerWriter */ 211 public HtmlWriter eTag(int indent, String ns, String name) { 212 super.eTag(indent, ns, name); 213 return this; 214 } 215 @Override /* XmlSerializerWriter */ 216 public HtmlWriter eTag(int indent, String name) { 217 super.eTag(indent, name); 218 return this; 219 } 220 @Override /* XmlSerializerWriter */ 221 public HtmlWriter eTag(String name) { 222 super.eTag(name); 223 return this; 224 } 225 @Override /* XmlSerializerWriter */ 226 public HtmlWriter eTag(int indent, String ns, String name, boolean needsEncoding) { 227 super.eTag(indent, ns, name, needsEncoding); 228 return this; 229 } 230 @Override /* XmlSerializerWriter */ 231 public HtmlWriter attr(String name, Object value) { 232 super.attr(name, value); 233 return this; 234 } 235 @Override /* XmlSerializerWriter */ 236 public HtmlWriter attr(String ns, String name, Object value) { 237 super.attr(ns, name, value); 238 return this; 239 } 240 @Override /* XmlSerializerWriter */ 241 public HtmlWriter attr(String ns, String name, Object value, boolean valNeedsEncoding) { 242 super.attr(ns, name, value, valNeedsEncoding); 243 return this; 244 } 245 @Override /* XmlSerializerWriter */ 246 public HtmlWriter attr(String name, Object value, boolean valNeedsEncoding) { 247 super.attr(null, name, value, valNeedsEncoding); 248 return this; 249 } 250 @Override /* XmlSerializerWriter */ 251 public HtmlWriter oAttr(String ns, String name) { 252 super.oAttr(ns, name); 253 return this; 254 } 255 @Override /* SerializerWriter */ 256 public HtmlWriter cr(int depth) { 257 if (depth > 0) 258 super.cr(depth); 259 return this; 260 } 261 @Override /* SerializerWriter */ 262 public HtmlWriter cre(int depth) { 263 if (depth > 0) 264 super.cre(depth); 265 return this; 266 } 267 @Override /* SerializerWriter */ 268 public HtmlWriter appendln(int indent, String text) { 269 super.appendln(indent, text); 270 return this; 271 } 272 @Override /* SerializerWriter */ 273 public HtmlWriter appendln(String text) { 274 super.appendln(text); 275 return this; 276 } 277 @Override /* SerializerWriter */ 278 public HtmlWriter append(int indent, String text) { 279 super.append(indent, text); 280 return this; 281 } 282 @Override /* SerializerWriter */ 283 public HtmlWriter append(int indent, char c) { 284 super.append(indent, c); 285 return this; 286 } 287 @Override /* SerializerWriter */ 288 public HtmlWriter s() { 289 super.s(); 290 return this; 291 } 292 @Override /* SerializerWriter */ 293 public HtmlWriter q() { 294 super.q(); 295 return this; 296 } 297 @Override /* SerializerWriter */ 298 public HtmlWriter i(int indent) { 299 super.i(indent); 300 return this; 301 } 302 @Override /* SerializerWriter */ 303 public HtmlWriter nl(int indent) { 304 super.nl(indent); 305 return this; 306 } 307 @Override /* SerializerWriter */ 308 public HtmlWriter append(Object text) { 309 super.append(text); 310 return this; 311 } 312 @Override /* SerializerWriter */ 313 public HtmlWriter append(String text) { 314 super.append(text); 315 return this; 316 } 317 @Override /* SerializerWriter */ 318 public HtmlWriter append(char c) { 319 super.append(c); 320 return this; 321 } 322}