Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Design Pattern for generating HTML Tags

For a small system that can get a String and output an HTML, what design pattern would be suitable?

This is a small example:

public String makeStrong(String in) {

    return "<strong>" + in + "</strong>";
}

Of course it needs to model some hierarchical structure so that it can fit <ul> and <ol> and their children. I'm thinking of Decorator but Composite pattern sounds good too. What should I consider?

like image 340
Mikael S. Avatar asked Feb 08 '14 20:02

Mikael S.


People also ask

What is design pattern in HTML?

Design patterns are common in programming, such as in object-oriented programming. In HTML / CSS , design patterns are those that work across browsers and devices. They manage complexity, mitigate code bloat, and improve productivity.

Which design pattern is best for Web application?

The Singleton Design Pattern That prevents multiple instances from being active at the same time which could cause weird bugs. Most of the time this gets implemented in the constructor. The goal of the singleton pattern is typically to regulate the global state of an application.

What are design patterns with examples?

Design patterns provide a standard terminology and are specific to particular scenario. For example, a singleton design pattern signifies use of single object so all developers familiar with single design pattern will make use of single object and they can tell each other that program is following a singleton pattern.


2 Answers

On first glance I thought of a Builder pattern or better a fluent API. A bit more compact is the following:

import static a.b.c.HTML.*;

    String html = p(
                ol(
                    li(),
                    li(
                        _("Hello, "),
                        strong(_("World")),
                        _("!")
                    ),
                    li()
                )
            ).toString();


public class HTML {

    protected final String tag;
    private final HTML[] items;

    public HTML(String tag, final HTML... items) {
        this.tag = tag;
        this.items = items;
    }

    public static HTML _(String text) {
        return new HTML(text) {

            @Override
            public String toString() {
                return tag;
            }

            @Override
            protected void buildString(StringBuilder sb) {
                sb.append(tag);
            }
       };
    }

    public static HTML li(final HTML... items) {
        return new HTML("li", items);
    }

    public static HTML ol(final HTML... items) {
        return new HTML("ol", items);
    }

    public static HTML p(final HTML... items) {
        return new HTML("p", items);
    }

    public static HTML strong(final HTML... items) {
        return new HTML("strong", items);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        buildString(sb);
        return sb.toString();
    }

    protected void buildString(StringBuilder sb) {
        sb.append('<').append(tag);
        if (items.length == 0) {
            sb.append(" />"); 
        } else {
            sb.append('>');
            for (HTML item : items) {
                item.buildString(sb);
            }
            sb.append("</").append(tag).append('>');
        }

    }
}
like image 168
Joop Eggen Avatar answered Oct 20 '22 01:10

Joop Eggen


Consider the builder pattern for building validated HTML fragments. I wrote something similar to validate HTML for use in Swing app components, e.g. tooltips. Here's a rough skeleton of something you could build on:

public final class HtmlBuilder()
{
  private final StringBuilder sb = new StringBuilder();
  private final Deque tagStack = new ArrayDeque();  

  public HtmlBuilder()
  {
    startTag("html");
  }

  // Consider using an enum of valid tags and extending to support attributes
  public HtmlBuilder startTag( String tag )
  {
    // TODO preconditions
    tagStack.push( tag );
    sb.append('<').append(tag).append('>');
    return this;
  }

  public HtmlBuilder endTag( String tag )
  {
    // TODO preconditions,
    // e.g. check "!tagStack.isEmpty() && tagStack.peek().equals( tag )
    tagStack.pop();
    sb.append('<').append('/').append(tag).append('>');
    return this;
  }

  public HtmlBuilder append( String text )
  {
    // TODO Preconditions, check for/escape special characters etc
    sb.append( text );
    return this;
  }

  @Override
  public String toString()
  {
    endTag("html")
    return sb.toString();
  }
}

Simple use case:

String html = new HtmlBuilder()
    .startTag( "strong" ).append( "text" ).endTag( "strong" )
    .toString();

You could add as much validation as you like, e.g. defining "tr" as only being allowed inside a "table". I suspect there is something like this out there already.

like image 21
nicktalbot Avatar answered Oct 20 '22 01:10

nicktalbot