An example HTMLDocument

HTML in Java

Update: this technique no longer works since name reflection was removed in later versions of Java. Here is another approach. Another use of lambda parameter reflection could be to write html inline in Java. It allows us to create builders like this, in Java, where we’d previously have to use a language like Kotlin and a library like Kara.

String doc = html( head( meta(charset -> "utf-8"), link(rel->stylesheet, type->css, href->"/my.css"), script(type->javascript, src -> "/some.js") ), body( h1("Hello World", style->"font-size:200%;"), article( p("Here is an interesting paragraph"), p( "And another", small("small") ), ul( li("An"), li("unordered"), li("list") ) ) ) ).asString();

String doc = html( head( meta(charset -> «utf-8″), link(rel->stylesheet, type->css, href->»/my.css»), script(type->javascript, src -> «/some.js») ), body( h1(«Hello World», style->»font-size:200%;»), article( p(«Here is an interesting paragraph»), p( «And another», small(«small») ), ul( li(«An»), li(«unordered»), li(«list») ) ) ) ).asString();

Which generates html like

Code Generation

Why would you do this? Well we could do code generation. e.g. we can programmatically generate paragraphs.

body( asList("one","two","three") .stream() .map(number -> "Paragraph " + number) .map(content -> p(content)) )

body( asList(«one»,»two»,»three») .stream() .map(number -> «Paragraph » + number) .map(content -> p(content)) )

Help from the Type System

We can also use the Java type system to help us write valid code.

Читайте также:  Замена значения словаря питон

It will be a compile time error to specify an invalid attribute for link rel.

It’s a compile time error to omit a mandatory tag

It’s also a compile time error to have a body tag inside a p tag, because body is not phrasing content.

We can also ensure that image sizes are in pixels

Safety

We can also help reduce injection attacks when inserting content from users into our markup, by having the DSL html-encoding any content passed in.

assertEquals( "

<script src="attack.js"></script>

"
, p("").asString() );

How does it work?

See this previous blogpost that shows how to get lambda parameter names with reflection. This allows us to specify the key value pairs for html attributes quite cleanly.

I’ve created an Attribute type that converts a lambda to a html attribute.

public interface AttributeT> extends NamedValueT> { default String asString() { return name() + "=\"" + value()+"\""; } }

For the tags themselves we declare an interface per tag, with a heirarchy to allow certain tags in certain contexts. For example Small is PhrasingContent and can be inside a P tag.

public interface Small extends PhrasingContent { default Small small(String content) { return () -> tag("small", content); } }

public interface Small extends PhrasingContent < default Small small(String content) < return () ->tag(«small», content); > >

To make it easy to have all the tag names available in the context without having to static import lots of things, we can create a “mixin” interface that combines all the tags.

public interface HtmlDsl extends Html, Head, Body, Link, Meta, P, Script, H1, Li, Ul, Article, Small, Img .

public interface HtmlDsl extends Html, Head, Body, Link, Meta, P, Script, H1, Li, Ul, Article, Small, Img .

Then where we want to write html we just make our class implement HtmlDsl (Or we could staticly import the methods instead.

We can place restrictions on which tags are valid using overloaded methods for the tag names. e.g. HTML

public interface Html extends NoAttributes { default Html html(Head head, Body body) { .

public interface Html extends NoAttributes < default Html html(Head head, Body body) < .

and restrict the types of attributes using enums or other wrapper types. Here Img tag can only have measurements in pixels

public interface Img extends NoChildren { default Img img(AttributeString> src, AttributePixelMeasurement> dim1, AttributePixelMeasurement> dim2) { .

public interface Img extends NoChildren < default Img img(Attributesrc, Attribute dim1, Attribute dim2) < .

All the code is available on github to play with. Have a look at this test for executable examples. n.b. it’s just a proof of concept at this point. Only sufficient code exists to illustrate the examples in this blog post.

What other creative uses can you find for parameter reflection?

Leave a Reply

  • Do you need a Strong Leader?
  • Supporting Sustainability
  • Pondering Agile Principles
  • Cost of Attrition
  • Uncovering Better Ways
  • Don’t hire top talent; hire for weaknesses.
  • Escape the Permission Trap with Healthy Habits
  • Thinking in Questions with SQL
  • Leadership Language Lessons from Star Trek
  • Java 16 Pattern Matching Fun
  • We got lucky
  • Revisiting Html in Java
  • Meetings, ugh! Let’s change our language
  • Latency Numbers Every Team Should Know
  • Humility
  • Sealed Java State Machines
  • A little rant about talent
  • Fun with Java Records
  • The benefits of making code worse
  • Reasons to hire inexperienced engineers
  • Do you CI?
  • Learning from Pain
  • The unsung upsides of staying put
  • Hack Days; Removing the Rules
  • End to End Tests

Источник

How to Use HTML in Swing Components

Many Swing components display a text string as part of their GUI. By default, a component’s text is displayed in a single font and color, all on one line. You can determine the font and color of a component’s text by invoking the component’s setFont and setForeground methods, respectively. For example, the following code creates a label and then sets its font and color:

label = new JLabel("A label"); label.setFont(new Font("Serif", Font.PLAIN, 14)); label.setForeground(new Color(0xffffdd));

If you want to mix fonts or colors within the text, or if you want formatting such as multiple lines, you can use HTML. HTML formatting can be used in all Swing buttons, menu items, labels, tool tips, and tabbed panes, as well as in components such as trees and tables that use labels to render text.

To specify that a component’s text has HTML formatting, just put the tag at the beginning of the text, then use any valid HTML in the remainder. Here is an example of using HTML in a button’s text:

button = new JButton("Two
lines");

Here is the resulting button.

An Example: HtmlDemo

An application called HtmlDemo lets you play with HTML formatting by setting the text on a label. You can find the entire code for this program in HtmlDemo.java . Here is a picture of the HtmlDemo example.

Screenshot of HtmlDemo in the Metal look and feel.

Try This:

  1. Click the Launch button to run HtmlDemo using Java™ Web Start (download JDK 7 or later). Alternatively, to compile and run the example yourself, consult the example index.
  2. Edit the HTML formatting in the text area at the left and click the «Change the label» button. The label at the right shows the result.
  3. Remove the tag from the text area on the left. The label’s text is no longer parsed as HTML.

Example 2: ButtonHtmlDemo

Let us look at another example that uses HTML. ButtonHtmlDemo adds font, color, and other text formatting to three buttons. You can find the entire code for this program in ButtonHtmlDemo.java . Here is a picture of the ButtonHtmlDemo example.

Screenshot of ButtonHtmlDemo in the Metal look and feel.

Click the Launch button to run ButtonHtmlDemo using Java™ Web Start (download JDK 7 or later). Alternatively, to compile and run the example yourself, consult the example index.

The left and right buttons have multiple lines and text styles and are implemented using HTML. The middle button, on the other hand, uses just one line, font, and color, so it does not require HTML. Here is the code that specifies the text formatting for these three buttons:

b1 = new JButton("Disable
" + "middle button", leftButtonIcon); Font font = b1.getFont().deriveFont(Font.PLAIN); b1.setFont(font); . b2 = new JButton("middle button", middleButtonIcon); b2.setFont(font); b2.setForeground(new Color(0xffffdd)); . b3 = new JButton("Enable
" + "middle button", rightButtonIcon); b3.setFont(font);

Note that we have to use a tag to cause the mnemonic characters «D» and «E» to be underlined in the buttons that use HTML. Note also that when a button is disabled, its HTML text unfortunately remains black, instead of becoming gray. (Refer to bug #4783068 to see if this situation changes.)

This section discussed how to use HTML in ordinary, non-text components. For information on components whose primary purpose is formatting text, see Using Text Components.

If you are programming in JavaFX, see HTML Editor.

Источник

Java вставка html кода

A document that models HTML. The purpose of this model is to support both browsing and editing. As a result, the structure described by an HTML document is not exactly replicated by default. The element structure that is modeled by default, is built by the class HTMLDocument.HTMLReader , which implements the HTMLEditorKit.ParserCallback protocol that the parser expects. To change the structure one can subclass HTMLReader , and reimplement the method getReader(int) to return the new reader implementation. The documentation for HTMLReader should be consulted for the details of the default structure created. The intent is that the document be non-lossy (although reproducing the HTML format may result in a different format). The document models only HTML, and makes no attempt to store view attributes in it. The elements are identified by the StyleContext.NameAttribute attribute, which should always have a value of type HTML.Tag that identifies the kind of element. Some of the elements (such as comments) are synthesized. The HTMLFactory uses this attribute to determine what kind of view to build. This document supports incremental loading. The TokenThreshold property controls how much of the parse is buffered before trying to update the element structure of the document. This property is set by the EditorKit so that subclasses can disable it. The Base property determines the URL against which relative URLs are resolved. By default, this will be the Document.StreamDescriptionProperty if the value of the property is a URL. If a tag is encountered, the base will become the URL specified by that tag. Because the base URL is a property, it can of course be set directly. The default content storage mechanism for this document is a gap buffer ( GapContent ). Alternatives can be supplied by using the constructor that takes a Content implementation.

Modifying HTMLDocument

The following examples illustrate using these methods. Each example assumes the HTML document is initialized in the following way:

JEditorPane p = new JEditorPane(); p.setContentType("text/html"); p.setText(". "); // Document text is provided below. HTMLDocument d = (HTMLDocument) p.getDocument();

With the following HTML content:

   div < background-color: silver; >ul  

Paragraph 1

Paragraph 2

All the methods for modifying an HTML document require an Element . Elements can be obtained from an HTML document by using the method getElement(Element e, Object attribute, Object value) . It returns the first descendant element that contains the specified attribute with the given value, in depth-first order. For example, d.getElement(d.getDefaultRootElement(), StyleConstants.NameAttribute, HTML.Tag.P) returns the first paragraph element.

A convenient shortcut for locating elements is the method getElement(String) ; returns an element whose ID attribute matches the specified value. For example, d.getElement(«BOX») returns the DIV element.

The getIterator(HTML.Tag t) method can also be used for finding all occurrences of the specified HTML tag in the document.

Inserting elements

Replacing elements

Summary

The following table shows the example document and the results of various methods described above.

Источник

Оцените статью