html
This library provides predicates for generating HTML content using either HTML 5 or XHTML 1.1 formats from a term representation. The library performs minimal validation, checking only that all elements are valid. No attempt is made to generate nicely indented output.
Normal elements are represented using a compound term with one argument
(the element content) or two arguments (the element attributes
represented by a list of Key=Value or Key-Value pairs and the
element content). The element content can be another element or a list
of elements. For example:
ol([type-a], [li(foo), li(bar), li(baz)])
The two exceptions are the pre or code elements whose content is
never interpreted as an element or a list of elements. For example, the
fragment:
pre([foo,bar,baz])
is translated to:
<pre>
[foo,bar,baz]
</pre>
Void elements are represented using a compound term with one argument,
the (possibly empty) list of attributes represented by a list of
Key=Value or Key-Value pairs. For example:
hr([class-separator])
Atomic arguments of the compound terms are interpreted as element
content. Non-atomic element content can be represented as a quoted atom
or by using the pre or code elements as explained above.
This library is a work in progress.
API documentation
Open the ../../apis/library_index.html#html link in a web browser.
Loading
To load all entities in this library, load the loader.lgt file:
| ?- logtalk_load(html(loader)).
Testing
To test this library predicates, load the tester.lgt file:
| ?- logtalk_load(html(tester)).
Generating a HTML document
HTML documents can be generated from a compound term representation and written to a file or a stream. For example, assuming we want to generate a HTML 5 file:
| ?- html5::generate(
file('hello.html'),
html([lang=en], [head(title('Hello world!')), body(p('Bye!'))])
).
When the second argument is a html/1 or html/2 compound term, a
doctype is automatically written. If we prefer instead e.g. a XHTML
1.1 document, we use the xhtml11 object:
| ?- xhtml11::generate(
file('hello.html'),
html([lang=en], [head(title('Hello world!')), body(p('Bye!'))])
).
Generating a HTML fragment
It’s also possible to generate just a fragment of a (X)HTML document by
using a list of compound terms or a compound term for an element other
than html. For example:
| ?- current_output(Stream),
html5::generate(stream(Stream), ul([li(foo), li(bar), li(baz)])).
<ul>
<li>
foo</li>
<li>
bar</li>
<li>
baz</li>
</ul>
Stream = ...
Working with callbacks to generate content
Often we need to programmatically generate HTML content from queries. In
other cases, we may have fixed content that we don’t want to keep
repeating (e.g., a navigation bar). The library supports a (::)/2
pseudo-element that sends a message to an object to retrieve content. As
an example, assume the following predicate definition in user:
content(strong('Hello world!')).
This predicate can then be called from the HTML term representation. For example:
| ?- current_output(Stream),
html5::generate(stream(Stream), span(user::content)).
<span><strong>Hello world!</strong></span>
Stream = ...
Note that the callback always takes the form Object::Closure where
Closure is extended with a single argument (to be bound to the
generated content). More complex callbacks are possible by using lambda
expressions.
Working with resource declarations
The renderer accepts explicit resource declarations in addition to the usual HTML elements. The supported resource declarations are:
resource(Type, Target)resource(Type, Target, Attributes)css(Href)js(Src)resources(Declarations)dependency(Dependent, Required)
Here, Type is css or js, Target is the stylesheet or
script location, Attributes is an optional list of HTML attributes
added to the generated <link> or <script> element, Href and
Src are shorthand forms for the corresponding stylesheet or script
target, Declarations is a list of resource specifications to
aggregate, and dependency(Dependent, Required) expresses that the
resource Dependent must be emitted after Required when ordering
the generated output.
The atom stylesheet can also be used as an alternative to css.
The atoms javascript and script can also be used as an
alternative to js.
For example, the following term renders standard stylesheet and JavaScript links directly:
| ?- current_output(Stream),
html5::generate(stream(Stream),
resources([
css('base.css'),
resource(js, 'app.js', [defer-true])
])).
This produces <link rel="stylesheet" href="base.css" /> and
<script defer src="app.js"></script>-style output.
Aggregating and ordering resources
A list of resource declarations can be wrapped with resources/1 to
normalize and aggregate them into a deterministic output order. Repeated
entries are removed automatically, and
dependency(Dependent, Required) can be used to force a resource to
be emitted after its prerequisite.
For example:
| ?- current_output(Stream),
html5::generate(stream(Stream),
resources([
dependency(resource(css, 'theme.css'), resource(css, 'base.css')),
css('theme.css'),
css('base.css'),
css('theme.css')
])).
This renders the base.css stylesheet before theme.css, while
also removing the duplicated theme.css entry from the final output.
Working with custom elements
The html5 and xhtml11 objects recognize the same set of standard
HTML 5 normal and void elements and generate an error for non-standard
elements. If you need to generate HTML content containing custom
elements, define a new object that extends one of the library objects.
For example:
:- object(html5custom,
extends(html5)).
normal_element(foo, inline).
normal_element(bar, block).
normal_element(Name, Display) :-
^^normal_element(Name, Display).
:- end_object.