Class Html

All Implemented Interfaces:
AttachNotifier, DetachNotifier, HasElement, HasStyle, Serializable

public class Html extends Component
A component which encapsulates a given HTML fragment with a single root element.

Note that it is the developer's responsibility to sanitize and remove any dangerous parts of the HTML before sending it to the user through this component. Passing raw input data to the user will possibly lead to cross-site scripting attacks.

To help with sanitization, a jsoup Safelist of permitted elements and attributes can be configured through a safelist-accepting constructor. Once configured, all content applied to the component — the initial value and any value later set through setHtmlContent(String) or pushed by a bound signal — is sanitized with it, so any element or attribute that the safelist doesn't permit is removed. The safelist is fixed at construction and cannot be changed afterwards.

jsoup's Safelist is not Serializable, but a Vaadin component must be serializable (sessions can be persisted to disk or replicated across a cluster). Storing a Safelist directly would break session serialization, so the safelist is supplied through a SerializableSupplier — a serializable factory that is invoked to build the safelist — rather than as a Safelist instance.

For the supplier to be serializable, it must not capture a (non-serializable) Safelist instance. Use a method reference to a factory, or a lambda that builds a new safelist inline:


 // Method reference to a standard jsoup factory; relaxed() permits common
 // block elements such as <div>:
 new Html(untrustedHtml, Safelist::relaxed);

 // Lambda that builds a fresh safelist inline (captures nothing); basic()
 // does not permit <div>, so it is added explicitly:
 new Html(untrustedHtml, () -> Safelist.basic().addTags("div"));

 // A reusable supplier kept in a static field:
 static final SerializableSupplier<Safelist> SAFELIST = () -> Safelist
         .relaxed().addAttributes("a", "target");
 new Html(untrustedHtml, SAFELIST);
 
Do not capture an already-built Safelist in the supplier: that puts the non-serializable instance back into the component's state and fails session serialization:

 Safelist safelist = Safelist.basic();
 // BAD: captures the non-serializable Safelist instance
 new Html(untrustedHtml, () -> safelist);
 
The supplier is invoked when the component is created (and again lazily on the next sanitization after deserialization, since the cached safelist is transient), not on every sanitization, so it should return an equivalent safelist on each call and must not return null.

The safelist must permit the fragment's single root element; otherwise the root is stripped and the resulting fragment no longer has exactly one root element. Note that Safelist.basic() does not permit <div>, so a <div>-rooted fragment requires e.g. Safelist.basic().addTags("div") or Safelist.relaxed().

This component does not expand the HTML fragment into a server side DOM tree so you cannot traverse or modify the HTML on the server. The root element can be accessed through Component.getElement() and the inner HTML through getInnerHtml().

The inner content and attributes can be changed after creation through setHtmlContent(String) or by binding a signal, but the root tag cannot be changed.

Note that this component doesn't support svg element as a root node. See separate Svg component if you want to display SVG images.

Since:
1.0
Author:
Vaadin Ltd
See Also:
  • Constructor Details

    • Html

      public Html(InputStream stream)
      Creates an instance based on the HTML fragment read from the stream. The fragment must have exactly one root element.

      A best effort is done to parse broken HTML but no guarantees are given for how invalid HTML is handled.

      Any heading or trailing whitespace is removed while parsing but any whitespace inside the root tag is preserved.

      Parameters:
      stream - the input stream which provides the HTML in UTF-8
      Throws:
      UncheckedIOException - if reading the stream fails
    • Html

      public Html(InputStream stream, SerializableSupplier<org.jsoup.safety.Safelist> safelistSupplier)
      Creates an instance based on the HTML fragment read from the stream, sanitized using the safelist obtained from the given supplier. The fragment must have exactly one root element after sanitization.

      The supplier is also stored on the component, so any later content change via setHtmlContent(String) or a bound signal is sanitized with it as well. Any element or attribute that the safelist doesn't permit is removed. The safelist must permit the root element.

      A best effort is done to parse broken HTML but no guarantees are given for how invalid HTML is handled.

      Any heading or trailing whitespace is removed while parsing but any whitespace inside the root tag is preserved.

      Parameters:
      stream - the input stream which provides the HTML in UTF-8
      safelistSupplier - supplies the safelist of permitted elements and attributes, not null
      Throws:
      UncheckedIOException - if reading the stream fails
      NullPointerException - if the supplier is null
      Since:
      25.2
    • Html

      public Html(String outerHtml)
      Creates an instance based on the given HTML fragment. The fragment must have exactly one root element.

      A best effort is done to parse broken HTML but no guarantees are given for how invalid HTML is handled.

      Any heading or trailing whitespace is removed while parsing but any whitespace inside the root tag is preserved.

      Parameters:
      outerHtml - the HTML to wrap
    • Html

      public Html(String outerHtml, SerializableSupplier<org.jsoup.safety.Safelist> safelistSupplier)
      Creates an instance based on the given HTML fragment, sanitized using the safelist obtained from the given supplier. The fragment must have exactly one root element after sanitization.

      The supplier is also stored on the component, so any later content change via setHtmlContent(String) or a bound signal is sanitized with it as well. Any element or attribute that the safelist doesn't permit is removed. The safelist must permit the root element.

      A best effort is done to parse broken HTML but no guarantees are given for how invalid HTML is handled.

      Any heading or trailing whitespace is removed while parsing but any whitespace inside the root tag is preserved.

      Parameters:
      outerHtml - the HTML to wrap
      safelistSupplier - supplies the safelist of permitted elements and attributes, not null
      Throws:
      NullPointerException - if the supplier is null
      Since:
      25.2
    • Html

      public Html(Signal<String> htmlSignal)
      Creates an instance based on the given HTML fragment signal. The signal's current value must have exactly one root element. Subsequent changes to the signal will update the component's content (root tag cannot be changed after creation).
      Parameters:
      htmlSignal - the signal that provides the HTML outer content
      Throws:
      IllegalArgumentException - if the signal is null or its current value is null or empty, or doesn't have exactly one root element
      Since:
      25.1
    • Html

      public Html(Signal<String> htmlSignal, SerializableSupplier<org.jsoup.safety.Safelist> safelistSupplier)
      Creates an instance based on the given HTML fragment signal, with every value sanitized using the safelist obtained from the given supplier. The signal's current value must have exactly one root element after sanitization. Subsequent changes to the signal will update the component's content (root tag cannot be changed after creation).

      The supplier is stored on the component, so both the initial value and every subsequent value are sanitized with it. Any element or attribute that the safelist doesn't permit is removed. The safelist must permit the root element.

      Parameters:
      htmlSignal - the signal that provides the HTML outer content
      safelistSupplier - supplies the safelist of permitted elements and attributes, not null
      Throws:
      IllegalArgumentException - if the signal is null or its current value is null or empty, or doesn't have exactly one root element
      NullPointerException - if the supplier is null
      Since:
      25.2
  • Method Details

    • setHtmlContent

      public void setHtmlContent(String html)
      Sets the content based on the given HTML fragment. The fragment must have exactly one root element, which matches the existing one.

      If a safelist supplier was provided at construction, the content is sanitized with it before being used.

      A best effort is done to parse broken HTML but no guarantees are given for how invalid HTML is handled.

      Any heading or trailing whitespace is removed while parsing but any whitespace inside the root tag is preserved.

      Parameters:
      html - the HTML to wrap
      Since:
      23.3
    • getInnerHtml

      public String getInnerHtml()
      Gets the inner HTML, i.e. everything inside the root element.
      Returns:
      the inner HTML, not null
    • bindHtmlContent

      public SignalBinding<String> bindHtmlContent(Signal<String> htmlSignal)
      Binds a Signal's value to this component's HTML content (outer HTML). The content is set immediately with the current signal value when the binding is created, and is kept synchronized with any subsequent signal value changes while the component is attached. When the component is detached, signal value changes have no effect.

      If a safelist supplier was provided at construction, every value — the initial one and each subsequent change — is sanitized with it, so any element or attribute that the safelist doesn't permit is removed.

      While a Signal is bound to the HTML content, any attempt to set the HTML content manually via setHtmlContent(String) throws BindingActiveException. The same happens when trying to bind a new Signal while one is already bound.

      The first value of the signal must have exactly one root element. When updating the content, the root tag name must remain the same as the component's current root tag. A null or empty signal value is rejected with an IllegalArgumentException.

      Parameters:
      htmlSignal - the signal to bind, not null
      Throws:
      BindingActiveException - thrown when there is already an existing binding
      Since:
      25.1