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.commons.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 */ 034@SuppressWarnings("resource") 035public class HtmlWriter extends XmlWriter { 036 037 /** 038 * Copy constructor. 039 * 040 * @param w Writer being copied. 041 */ 042 public HtmlWriter(HtmlWriter w) { 043 super(w); 044 } 045 046 /** 047 * Constructor. 048 * 049 * @param out The writer being wrapped. 050 * @param useWhitespace If <jk>true</jk>, tabs will be used in output. 051 * @param maxIndent The maximum indentation level. 052 * @param trimStrings If <jk>true</jk>, strings should be trimmed before they're serialized. 053 * @param quoteChar The quote character to use (i.e. <js>'\''</js> or <js>'"'</js>) 054 * @param uriResolver The URI resolver for resolving URIs to absolute or root-relative form. 055 */ 056 public HtmlWriter(Writer out, boolean useWhitespace, int maxIndent, boolean trimStrings, char quoteChar, UriResolver uriResolver) { 057 super(out, useWhitespace, maxIndent, trimStrings, quoteChar, uriResolver, false, null); 058 } 059 060 @Override /* Overridden from SerializerWriter */ 061 public HtmlWriter append(char c) { 062 super.append(c); 063 return this; 064 } 065 066 @Override /* Overridden from XmlWriter */ 067 public HtmlWriter append(char[] value) { 068 super.append(value); 069 return this; 070 } 071 072 @Override /* Overridden from SerializerWriter */ 073 public HtmlWriter append(int indent, char c) { 074 super.append(indent, c); 075 return this; 076 } 077 078 @Override /* Overridden from SerializerWriter */ 079 public HtmlWriter append(int indent, String text) { 080 super.append(indent, text); 081 return this; 082 } 083 084 @Override /* Overridden from SerializerWriter */ 085 public HtmlWriter append(Object text) { 086 super.append(text); 087 return this; 088 } 089 090 @Override /* Overridden from SerializerWriter */ 091 public HtmlWriter append(String text) { 092 super.append(text); 093 return this; 094 } 095 096 @Override /* Overridden from XmlWriter */ 097 public HtmlWriter appendIf(boolean flag, char value) { 098 super.appendIf(flag, value); 099 return this; 100 } 101 102 @Override /* Overridden from XmlWriter */ 103 public HtmlWriter appendIf(boolean flag, String value) { 104 super.appendIf(flag, value); 105 return this; 106 } 107 108 @Override /* Overridden from SerializerWriter */ 109 public HtmlWriter appendln(int indent, String text) { 110 super.appendln(indent, text); 111 return this; 112 } 113 114 @Override /* Overridden from SerializerWriter */ 115 public HtmlWriter appendln(String text) { 116 super.appendln(text); 117 return this; 118 } 119 120 @Override /* Overridden from XmlWriter */ 121 public HtmlWriter appendUri(Object value) { 122 super.appendUri(value); 123 return this; 124 } 125 126 @Override /* Overridden from XmlSerializerWriter */ 127 public HtmlWriter attr(String name, Object value) { 128 super.attr(name, value); 129 return this; 130 } 131 132 @Override /* Overridden from XmlSerializerWriter */ 133 public HtmlWriter attr(String name, Object value, boolean valNeedsEncoding) { 134 super.attr(null, name, value, valNeedsEncoding); 135 return this; 136 } 137 138 @Override /* Overridden from XmlSerializerWriter */ 139 public HtmlWriter attr(String ns, String name, Object value) { 140 super.attr(ns, name, value); 141 return this; 142 } 143 144 @Override /* Overridden from XmlSerializerWriter */ 145 public HtmlWriter attr(String ns, String name, Object value, boolean valNeedsEncoding) { 146 super.attr(ns, name, value, valNeedsEncoding); 147 return this; 148 } 149 150 @Override /* Overridden from XmlWriter */ 151 public HtmlWriter attrUri(String name, Object value) { 152 super.attrUri(name, value); 153 return this; 154 } 155 156 @Override /* Overridden from XmlWriter */ 157 public HtmlWriter ceTag() { 158 super.ceTag(); 159 return this; 160 } 161 162 @Override /* Overridden from SerializerWriter */ 163 public HtmlWriter cr(int depth) { 164 if (depth > 0) 165 super.cr(depth); 166 return this; 167 } 168 169 @Override /* Overridden from SerializerWriter */ 170 public HtmlWriter cre(int depth) { 171 if (depth > 0) 172 super.cre(depth); 173 return this; 174 } 175 176 @Override /* Overridden from XmlWriter */ 177 public HtmlWriter cTag() { 178 super.cTag(); 179 return this; 180 } 181 182 @Override /* Overridden from XmlSerializerWriter */ 183 public HtmlWriter eTag(int indent, String name) { 184 super.eTag(indent, name); 185 return this; 186 } 187 188 @Override /* Overridden from XmlSerializerWriter */ 189 public HtmlWriter eTag(int indent, String ns, String name) { 190 super.eTag(indent, ns, name); 191 return this; 192 } 193 194 @Override /* Overridden from XmlSerializerWriter */ 195 public HtmlWriter eTag(int indent, String ns, String name, boolean needsEncoding) { 196 super.eTag(indent, ns, name, needsEncoding); 197 return this; 198 } 199 200 @Override /* Overridden from XmlSerializerWriter */ 201 public HtmlWriter eTag(String name) { 202 super.eTag(name); 203 return this; 204 } 205 206 @Override /* Overridden from XmlSerializerWriter */ 207 public HtmlWriter eTag(String ns, String name) { 208 super.eTag(ns, name); 209 return this; 210 } 211 212 @Override /* Overridden from XmlSerializerWriter */ 213 public HtmlWriter eTag(String ns, String name, boolean needsEncoding) { 214 super.eTag(ns, name, needsEncoding); 215 return this; 216 } 217 218 @Override /* Overridden from SerializerWriter */ 219 public HtmlWriter i(int indent) { 220 super.i(indent); 221 return this; 222 } 223 224 @Override /* Overridden from XmlWriter */ 225 public HtmlWriter ie(int indent) { 226 super.ie(indent); 227 return this; 228 } 229 230 @Override /* Overridden from SerializerWriter */ 231 public HtmlWriter nl(int indent) { 232 super.nl(indent); 233 return this; 234 } 235 236 @Override /* Overridden from XmlWriter */ 237 public HtmlWriter nlIf(boolean flag, int indent) { 238 super.nlIf(flag, indent); 239 return this; 240 } 241 242 @Override /* Overridden from XmlSerializerWriter */ 243 public HtmlWriter oAttr(String ns, String name) { 244 super.oAttr(ns, name); 245 return this; 246 } 247 248 @Override /* Overridden from XmlSerializerWriter */ 249 public HtmlWriter oTag(int indent, String name) { 250 super.oTag(indent, name); 251 return this; 252 } 253 254 @Override /* Overridden from XmlSerializerWriter */ 255 public HtmlWriter oTag(int indent, String ns, String name) { 256 super.oTag(indent, ns, name); 257 return this; 258 } 259 260 @Override /* Overridden from XmlSerializerWriter */ 261 public HtmlWriter oTag(int indent, String ns, String name, boolean needsEncoding) { 262 super.oTag(indent, ns, name, needsEncoding); 263 return this; 264 } 265 266 @Override /* Overridden from XmlSerializerWriter */ 267 public HtmlWriter oTag(String name) { 268 super.oTag(name); 269 return this; 270 } 271 272 @Override /* Overridden from XmlSerializerWriter */ 273 public HtmlWriter oTag(String ns, String name) { 274 super.oTag(ns, name); 275 return this; 276 } 277 278 @Override /* Overridden from XmlSerializerWriter */ 279 public HtmlWriter oTag(String ns, String name, boolean needsEncoding) { 280 super.oTag(ns, name, needsEncoding); 281 return this; 282 } 283 284 @Override /* Overridden from SerializerWriter */ 285 public HtmlWriter q() { 286 super.q(); 287 return this; 288 } 289 290 @Override /* Overridden from SerializerWriter */ 291 public HtmlWriter s() { 292 super.s(); 293 return this; 294 } 295 296 @Override /* Overridden from XmlWriter */ 297 public HtmlWriter sIf(boolean flag) { 298 super.sIf(flag); 299 return this; 300 } 301 302 @Override /* Overridden from XmlSerializerWriter */ 303 public HtmlWriter sTag(int indent, String name) { 304 super.sTag(indent, name); 305 return this; 306 } 307 308 @Override /* Overridden from XmlSerializerWriter */ 309 public HtmlWriter sTag(int indent, String ns, String name) { 310 super.sTag(indent, ns, name); 311 return this; 312 } 313 314 @Override /* Overridden from XmlSerializerWriter */ 315 public HtmlWriter sTag(int indent, String ns, String name, boolean needsEncoding) { 316 super.sTag(indent, ns, name, needsEncoding); 317 return this; 318 } 319 320 @Override /* Overridden from XmlSerializerWriter */ 321 public HtmlWriter sTag(String name) { 322 super.sTag(name); 323 return this; 324 } 325 326 @Override /* Overridden from XmlSerializerWriter */ 327 public HtmlWriter sTag(String ns, String name) { 328 super.sTag(ns, name); 329 return this; 330 } 331 332 @Override /* Overridden from XmlSerializerWriter */ 333 public HtmlWriter sTag(String ns, String name, boolean needsEncoding) { 334 super.sTag(ns, name, needsEncoding); 335 return this; 336 } 337 338 @Override /* Overridden from XmlSerializerWriter */ 339 public HtmlWriter tag(int indent, String name) { 340 super.tag(indent, name); 341 return this; 342 } 343 344 @Override /* Overridden from XmlSerializerWriter */ 345 public HtmlWriter tag(int indent, String ns, String name) { 346 super.tag(indent, ns, name); 347 return this; 348 } 349 350 @Override /* Overridden from XmlSerializerWriter */ 351 public HtmlWriter tag(int indent, String ns, String name, boolean needsEncoding) { 352 super.tag(indent, ns, name, needsEncoding); 353 return this; 354 } 355 356 @Override /* Overridden from XmlSerializerWriter */ 357 public HtmlWriter tag(String name) { 358 super.tag(name); 359 return this; 360 } 361 362 @Override /* Overridden from XmlSerializerWriter */ 363 public HtmlWriter tag(String ns, String name) { 364 super.tag(ns, name); 365 return this; 366 } 367 368 @Override /* Overridden from XmlSerializerWriter */ 369 public HtmlWriter tag(String ns, String name, boolean needsEncoding) { 370 super.tag(ns, name, needsEncoding); 371 return this; 372 } 373 374 @Override /* Overridden from XmlWriter */ 375 public HtmlWriter text(Object value) { 376 super.text(value); 377 return this; 378 } 379 380 @Override /* Overridden from XmlSerializerWriter */ 381 public HtmlWriter text(Object o, boolean preserveWhitespace) { 382 383 if (o == null) { 384 append("<null/>"); 385 return this; 386 } 387 var s = o.toString(); 388 if (s.isEmpty()) { 389 append("<sp/>"); 390 return this; 391 } 392 393 for (var i = 0; i < s.length(); i++) { 394 var test = s.charAt(i); 395 if (test == '&') 396 append("&"); 397 else if (test == '<') 398 append("<"); 399 else if (test == '>') 400 append(">"); 401 else if (test == '\n') 402 append(preserveWhitespace ? "\n" : "<br/>"); 403 else if (test == '\f') // XML 1.0 doesn't support form feeds or backslashes, so we have to invent something. 404 append(preserveWhitespace ? "\f" : "<ff/>"); 405 else if (test == '\b') 406 append(preserveWhitespace ? "\b" : "<bs/>"); 407 else if (test == '\t') 408 append(preserveWhitespace ? "\t" : "<sp> </sp>"); 409 else if ((i == 0 || i == s.length() - 1) && Character.isWhitespace(test)) { 410 if (preserveWhitespace) 411 w(test); 412 else if (test == ' ') 413 append("<sp> </sp>"); 414 else 415 append("<sp>&#x").append(toHex4(test)).append(";</sp>"); 416 } else if (Character.isISOControl(test)) 417 append("&#" + (int)test + ";"); 418 else 419 w(test); 420 } 421 422 return this; 423 } 424 425 @Override /* Overridden from XmlWriter */ 426 public HtmlWriter textUri(Object value) { 427 super.textUri(value); 428 return this; 429 } 430 431 @Override /* Overridden from XmlWriter */ 432 public HtmlWriter w(char c) { 433 super.w(c); 434 return this; 435 } 436 437 @Override /* Overridden from XmlWriter */ 438 public HtmlWriter w(String s) { 439 super.w(s); 440 return this; 441 } 442}