001package ball.xml;
002/*-
003 * ##########################################################################
004 * Utilities
005 * %%
006 * Copyright (C) 2008 - 2022 Allen D. Ball
007 * %%
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *      http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 * ##########################################################################
020 */
021import java.net.URI;
022import java.util.stream.Stream;
023import org.w3c.dom.Node;
024
025/**
026 * Common HTML templates.
027 *
028 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball}
029 */
030public interface HTMLTemplates extends XMLServices {
031
032    /**
033     * {@code <a href="}{@link URI#toASCIIString() href.toASCIIString()}{@code ">}{@link URI#toString() href.toString()}{@code </a>}
034     *
035     * @param   href            {@link URI}
036     *
037     * @return  {@link org.w3c.dom.Element}
038     */
039    default FluentNode a(URI href) { return a(href, (String) null); }
040
041    /**
042     * {@code <a href="}{@link URI#toASCIIString() href.toASCIIString()}{@code ">}{@link Node node}{@code </a>}
043     *
044     * @param   href            {@link URI}
045     * @param   node            {@link Node}
046     *
047     * @return  {@link org.w3c.dom.Element}
048     */
049    default FluentNode a(URI href, Node node) {
050        FluentNode a = element("a", node);
051
052        if (href != null) {
053            a.add(attr("href", href.toASCIIString()));
054        }
055
056        return a;
057    }
058
059    /**
060     * {@code <a href="}{@link URI#toASCIIString() href.toASCIIString()}{@code ">}{@link #text(String) text(content)}{@code </a>}
061     *
062     * @param   href            {@link URI}
063     * @param   content         {@link org.w3c.dom.Text} content
064     *
065     * @return  {@code <a/>} {@link org.w3c.dom.Element}
066     */
067    default FluentNode a(URI href, String content) {
068        return a(href, text((content != null) ? content : href.toString()));
069    }
070
071    /**
072     * {@code <b>}{@link Node node}{@code </b>}
073     *
074     * @param   node            {@link Node}
075     *
076     * @return  {@code <b/>} {@link org.w3c.dom.Element}
077     */
078    default FluentNode b(Node node) { return element("b", node); }
079
080    /**
081     * {@code <b>}{@link #text(String) text(content)}{@code </b>}
082     *
083     * @param   content         {@link org.w3c.dom.Text} content
084     *
085     * @return  {@link org.w3c.dom.Element}
086     */
087    default FluentNode b(String content) { return b(text(content)); }
088
089    /**
090     * {@code <code>}{@link String content}{@code </code>}
091     *
092     * @param   content         {@link org.w3c.dom.Text} content
093     *
094     * @return  {@link org.w3c.dom.Element}
095     */
096    default FluentNode code(String content) {
097        return element("code").content(content);
098    }
099
100    /**
101     * {@code <code>}{@link String#valueOf(boolean) String.valueOf(content)}{@code </code>}
102     *
103     * @param   content         {@link org.w3c.dom.Text} content
104     *
105     * @return  {@link org.w3c.dom.Element}
106     */
107    default FluentNode code(boolean content) {
108        return code(String.valueOf(content));
109    }
110
111    /**
112     * {@code <div>}{@link Node nodes...}{@code </div>}
113     *
114     * @param   stream          The {@link Stream} of {@link Node}s to
115     *                          append to the newly created
116     *                          {@link org.w3c.dom.Element}.
117     *
118     * @return  {@link org.w3c.dom.Element}
119     */
120    default FluentNode div(Stream<Node> stream) {
121        return div(stream.toArray(Node[]::new));
122    }
123
124    /**
125     * {@code <div>}{@link Node nodes...}{@code </div>}
126     *
127     * @param   nodes           The {@link Node}s to append to the newly
128     *                          created {@link org.w3c.dom.Element}.
129     *
130     * @return  {@link org.w3c.dom.Element}
131     */
132    default FluentNode div(Node... nodes) { return element("div", nodes); }
133
134    /**
135     * {@code <h1>}{@link Node nodes...}{@code </h1>}
136     *
137     * @param   stream          The {@link Stream} of {@link Node}s to
138     *                          append to the newly created
139     *                          {@link org.w3c.dom.Element}.
140     *
141     * @return  {@link org.w3c.dom.Element}
142     */
143    default FluentNode h1(Stream<Node> stream) {
144        return h1(stream.toArray(Node[]::new));
145    }
146
147    /**
148     * {@code <h1>}{@link Node nodes...}{@code </h1>}
149     *
150     * @param   nodes           The {@link Node}s to append to the newly
151     *                          created {@link org.w3c.dom.Element}.
152     *
153     * @return  {@link org.w3c.dom.Element}
154     */
155    default FluentNode h1(Node... nodes) { return element("h1", nodes); }
156
157    /**
158     * {@code <h1>}{@link #text(String) text(content)}{@code </h1>}
159     *
160     * @param   content         {@link org.w3c.dom.Text} content
161     *
162     * @return  {@link org.w3c.dom.Element}
163     */
164    default FluentNode h1(String content) { return h1(text(content)); }
165
166    /**
167     * {@code <h2>}{@link Node nodes...}{@code </h2>}
168     *
169     * @param   stream          The {@link Stream} of {@link Node}s to
170     *                          append to the newly created
171     *                          {@link org.w3c.dom.Element}.
172     *
173     * @return  {@link org.w3c.dom.Element}
174     */
175    default FluentNode h2(Stream<Node> stream) {
176        return h2(stream.toArray(Node[]::new));
177    }
178
179    /**
180     * {@code <h2>}{@link Node nodes...}{@code </h2>}
181     *
182     * @param   nodes           The {@link Node}s to append to the newly
183     *                          created {@link org.w3c.dom.Element}.
184     *
185     * @return  {@link org.w3c.dom.Element}
186     */
187    default FluentNode h2(Node... nodes) { return element("h2", nodes); }
188
189    /**
190     * {@code <h2>}{@link #text(String) text(content)}{@code </h2>}
191     *
192     * @param   content         {@link org.w3c.dom.Text} content
193     *
194     * @return  {@link org.w3c.dom.Element}
195     */
196    default FluentNode h2(String content) { return h2(text(content)); }
197
198    /**
199     * {@code <h3>}{@link Node nodes...}{@code </h3>}
200     *
201     * @param   stream          The {@link Stream} of {@link Node}s to
202     *                          append to the newly created
203     *                          {@link org.w3c.dom.Element}.
204     *
205     * @return  {@link org.w3c.dom.Element}
206     */
207    default FluentNode h3(Stream<Node> stream) {
208        return h3(stream.toArray(Node[]::new));
209    }
210
211    /**
212     * {@code <h3>}{@link Node nodes...}{@code </h3>}
213     *
214     * @param   nodes           The {@link Node}s to append to the newly
215     *                          created {@link org.w3c.dom.Element}.
216     *
217     * @return  {@link org.w3c.dom.Element}
218     */
219    default FluentNode h3(Node... nodes) { return element("h3", nodes); }
220
221    /**
222     * {@code <h3>}{@link #text(String) text(content)}{@code </h3>}
223     *
224     * @param   content         {@link org.w3c.dom.Text} content
225     *
226     * @return  {@link org.w3c.dom.Element}
227     */
228    default FluentNode h3(String content) { return h3(text(content)); }
229
230    /**
231     * {@code <h4>}{@link Node nodes...}{@code </h4>}
232     *
233     * @param   stream          The {@link Stream} of {@link Node}s to
234     *                          append to the newly created
235     *                          {@link org.w3c.dom.Element}.
236     *
237     * @return  {@link org.w3c.dom.Element}
238     */
239    default FluentNode h4(Stream<Node> stream) {
240        return h4(stream.toArray(Node[]::new));
241    }
242
243    /**
244     * {@code <h4>}{@link Node nodes...}{@code </h4>}
245     *
246     * @param   nodes           The {@link Node}s to append to the newly
247     *                          created {@link org.w3c.dom.Element}.
248     *
249     * @return  {@link org.w3c.dom.Element}
250     */
251    default FluentNode h4(Node... nodes) { return element("h4", nodes); }
252
253    /**
254     * {@code <h4>}{@link #text(String) text(content)}{@code </h4>}
255     *
256     * @param   content         {@link org.w3c.dom.Text} content
257     *
258     * @return  {@link org.w3c.dom.Element}
259     */
260    default FluentNode h4(String content) { return h4(text(content)); }
261
262    /**
263     * {@code <h5>}{@link Node nodes...}{@code </h5>}
264     *
265     * @param   stream          The {@link Stream} of {@link Node}s to
266     *                          append to the newly created
267     *                          {@link org.w3c.dom.Element}.
268     *
269     * @return  {@link org.w3c.dom.Element}
270     */
271    default FluentNode h5(Stream<Node> stream) {
272        return h5(stream.toArray(Node[]::new));
273    }
274
275    /**
276     * {@code <h5>}{@link Node nodes...}{@code </h5>}
277     *
278     * @param   nodes           The {@link Node}s to append to the newly
279     *                          created {@link org.w3c.dom.Element}.
280     *
281     * @return  {@link org.w3c.dom.Element}
282     */
283    default FluentNode h5(Node... nodes) { return element("h5", nodes); }
284
285    /**
286     * {@code <h5>}{@link #text(String) text(content)}{@code </h5>}
287     *
288     * @param   content         {@link org.w3c.dom.Text} content
289     *
290     * @return  {@link org.w3c.dom.Element}
291     */
292    default FluentNode h5(String content) { return h5(text(content)); }
293
294    /**
295     * {@code <h6>}{@link Node nodes...}{@code </h6>}
296     *
297     * @param   stream          The {@link Stream} of {@link Node}s to
298     *                          append to the newly created
299     *                          {@link org.w3c.dom.Element}.
300     *
301     * @return  {@link org.w3c.dom.Element}
302     */
303    default FluentNode h6(Stream<Node> stream) {
304        return h6(stream.toArray(Node[]::new));
305    }
306
307    /**
308     * {@code <h6>}{@link Node nodes...}{@code </h6>}
309     *
310     * @param   nodes           The {@link Node}s to append to the newly
311     *                          created {@link org.w3c.dom.Element}.
312     *
313     * @return  {@link org.w3c.dom.Element}
314     */
315    default FluentNode h6(Node... nodes) { return element("h6", nodes); }
316
317    /**
318     * {@code <h6>}{@link #text(String) text(content)}{@code </h6>}
319     *
320     * @param   content         {@link org.w3c.dom.Text} content
321     *
322     * @return  {@link org.w3c.dom.Element}
323     */
324    default FluentNode h6(String content) { return h6(text(content)); }
325
326    /**
327     * {@code <ol>}{@link Node nodes...}{@code </ol>}
328     *
329     * @param   stream          The {@link Stream} of {@link Node}s to
330     *                          append to the newly created
331     *                          {@link org.w3c.dom.Element}.
332     *
333     * @return  {@link org.w3c.dom.Element}
334     */
335    default FluentNode ol(Stream<Node> stream) {
336        return ol(stream.toArray(Node[]::new));
337    }
338
339    /**
340     * {@code <ol>}{@link Node nodes...}{@code </ol>}
341     *
342     * @param   nodes           The {@link Node}s to append to the newly
343     *                          created {@link org.w3c.dom.Element}.
344     *
345     * @return  {@link org.w3c.dom.Element}
346     */
347    default FluentNode ol(Node... nodes) { return element("ol", nodes); }
348
349    /**
350     * {@code <ul>}{@link Node nodes...}{@code </ul>}
351     *
352     * @param   stream          The {@link Stream} of {@link Node}s to
353     *                          append to the newly created
354     *                          {@link org.w3c.dom.Element}.
355     *
356     * @return  {@link org.w3c.dom.Element}
357     */
358    default FluentNode ul(Stream<Node> stream) {
359        return ul(stream.toArray(Node[]::new));
360    }
361
362    /**
363     * {@code <ul>}{@link Node nodes...}{@code </ul>}
364     *
365     * @param   nodes           The {@link Node}s to append to the newly
366     *                          created {@link org.w3c.dom.Element}.
367     *
368     * @return  {@link org.w3c.dom.Element}
369     */
370    default FluentNode ul(Node... nodes) { return element("ul", nodes); }
371
372    /**
373     * {@code <li>}{@link Node nodes...}{@code </li>}
374     *
375     * @param   stream          The {@link Stream} of {@link Node}s to
376     *                          append to the newly created
377     *                          {@link org.w3c.dom.Element}.
378     *
379     * @return  {@link org.w3c.dom.Element}
380     */
381    default FluentNode li(Stream<Node> stream) {
382        return li(stream.toArray(Node[]::new));
383    }
384
385    /**
386     * {@code <li>}{@link Node nodes...}{@code </li>}
387     *
388     * @param   nodes           The {@link Node}s to append to the newly
389     *                          created {@link org.w3c.dom.Element}.
390     *
391     * @return  {@link org.w3c.dom.Element}
392     */
393    default FluentNode li(Node... nodes) { return element("li", nodes); }
394
395    /**
396     * {@code <li>}{@link #text(String) text(content)}{@code </li>}
397     *
398     * @param   content         {@link org.w3c.dom.Text} content
399     *
400     * @return  {@link org.w3c.dom.Element}
401     */
402    default FluentNode li(String content) { return li(text(content)); }
403
404    /**
405     * {@code <p>}{@link Node nodes...}{@code </p>}
406     *
407     * @param   stream          The {@link Stream} of {@link Node}s to
408     *                          append to the newly created
409     *                          {@link org.w3c.dom.Element}.
410     *
411     * @return  {@link org.w3c.dom.Element}
412     */
413    default FluentNode p(Stream<Node> stream) {
414        return p(stream.toArray(Node[]::new));
415    }
416
417    /**
418     * {@code <p>}{@link Node nodes...}{@code </p>}
419     *
420     * @param   nodes           The {@link Node}s to append to the newly
421     *                          created {@link org.w3c.dom.Element}.
422     *
423     * @return  {@link org.w3c.dom.Element}
424     */
425    default FluentNode p(Node... nodes) { return element("p", nodes); }
426
427    /**
428     * {@code <p>}{@link #text(String) text(content)}{@code </p>}
429     *
430     * @param   content         {@link org.w3c.dom.Text} content
431     *
432     * @return  {@link org.w3c.dom.Element}
433     */
434    default FluentNode p(String content) { return p(text(content)); }
435
436    /**
437     * {@code <pre}{@code >}{@link String content}{@code <}{@code /pre>}
438     *
439     * @param   content         {@link org.w3c.dom.Text} content
440     *
441     * @return  {@link org.w3c.dom.Element}
442     */
443    default FluentNode pre(String content) {
444        return element("pre").content(content);
445    }
446
447    /**
448     * {@code <pre lang="lang"}{@code >}{@link String content}{@code <}{@code /pre>}
449     *
450     * @param   lang            {@link org.w3c.dom.Attr} {@code lang} value
451     * @param   content         {@link org.w3c.dom.Text} content
452     *
453     * @return  {@link org.w3c.dom.Element}
454     */
455    default FluentNode pre(String lang, String content) {
456        return pre(content).add(attr("lang", lang));
457    }
458
459    /**
460     * {@code <table>}{@link Node nodes...}{@code </table>}
461     *
462     * @param   stream          The {@link Stream} of {@link Node}s to
463     *                          append to the newly created
464     *                          {@link org.w3c.dom.Element}.
465     *
466     * @return  {@link org.w3c.dom.Element}
467     */
468    default FluentNode table(Stream<Node> stream) {
469        return table(stream.toArray(Node[]::new));
470    }
471
472    /**
473     * {@code <table>}{@link Node nodes...}{@code </table>}
474     *
475     * @param   nodes           The {@link Node}s to append to the newly
476     *                          created {@link org.w3c.dom.Element}.
477     *
478     * @return  {@link org.w3c.dom.Element}
479     */
480    default FluentNode table(Node... nodes) { return element("table", nodes); }
481
482    /**
483     * {@code <caption>}{@link String content}{@code </caption>}
484     *
485     * @param   content         {@link org.w3c.dom.Text} content
486     *
487     * @return  {@link org.w3c.dom.Element}
488     */
489    default FluentNode caption(String content) {
490        return element("caption").content(content);
491    }
492
493    /**
494     * {@code <thead>}{@link Node nodes...}{@code </thead>}
495     *
496     * @param   stream          The {@link Stream} of {@link Node}s to
497     *                          append to the newly created
498     *                          {@link org.w3c.dom.Element}.
499     *
500     * @return  {@link org.w3c.dom.Element}
501     */
502    default FluentNode thead(Stream<Node> stream) {
503        return thead(stream.toArray(Node[]::new));
504    }
505
506    /**
507     * {@code <thead>}{@link Node nodes...}{@code </thead>}
508     *
509     * @param   nodes           The {@link Node}s to append to the newly
510     *                          created {@link org.w3c.dom.Element}.
511     *
512     * @return  {@link org.w3c.dom.Element}
513     */
514    default FluentNode thead(Node... nodes) { return element("thead", nodes); }
515
516    /**
517     * {@code <tbody>}{@link Node nodes...}{@code </tbody>}
518     *
519     * @param   stream          The {@link Stream} of {@link Node}s to
520     *                          append to the newly created
521     *                          {@link org.w3c.dom.Element}.
522     *
523     * @return  {@link org.w3c.dom.Element}
524     */
525    default FluentNode tbody(Stream<Node> stream) {
526        return tbody(stream.toArray(Node[]::new));
527    }
528
529    /**
530     * {@code <tbody>}{@link Node nodes...}{@code </tbody>}
531     *
532     * @param   nodes           The {@link Node}s to append to the newly
533     *                          created {@link org.w3c.dom.Element}.
534     *
535     * @return  {@link org.w3c.dom.Element}
536     */
537    default FluentNode tbody(Node... nodes) { return element("tbody", nodes); }
538
539    /**
540     * {@code <tfoot>}{@link Node nodes...}{@code </tfoot>}
541     *
542     * @param   stream          The {@link Stream} of {@link Node}s to
543     *                          append to the newly created
544     *                          {@link org.w3c.dom.Element}.
545     *
546     * @return  {@link org.w3c.dom.Element}
547     */
548    default FluentNode tfoot(Stream<Node> stream) {
549        return tfoot(stream.toArray(Node[]::new));
550    }
551
552    /**
553     * {@code <tfoot>}{@link Node nodes...}{@code </tfoot>}
554     *
555     * @param   nodes           The {@link Node}s to append to the newly
556     *                          created {@link org.w3c.dom.Element}.
557     *
558     * @return  {@link org.w3c.dom.Element}
559     */
560    default FluentNode tfoot(Node... nodes) { return element("tfoot", nodes); }
561
562    /**
563     * {@code <tr>}{@link Node nodes...}{@code </tr>}
564     *
565     * @param   stream          The {@link Stream} of {@link Node}s to
566     *                          append to the newly created
567     *                          {@link org.w3c.dom.Element}.
568     *
569     * @return  {@link org.w3c.dom.Element}
570     */
571    default FluentNode tr(Stream<Node> stream) {
572        return tr(stream.toArray(Node[]::new));
573    }
574
575    /**
576     * {@code <tr>}{@link Node nodes...}{@code </tr>}
577     *
578     * @param   nodes           The {@link Node}s to append to the newly
579     *                          created {@link org.w3c.dom.Element}.
580     *
581     * @return  {@link org.w3c.dom.Element}
582     */
583    default FluentNode tr(Node... nodes) { return element("tr", nodes); }
584
585    /**
586     * {@code <th>}{@link Node node}{@code </th>}
587     *
588     * @param   node            {@link Node}
589     *
590     * @return  {@link org.w3c.dom.Element}
591     */
592    default FluentNode th(Node node) { return element("th", node); }
593
594    /**
595     * {@code <th>}{@link #text(String) text(content)}{@code </th>}
596     *
597     * @param   content         {@link org.w3c.dom.Text} content
598     *
599     * @return  {@link org.w3c.dom.Element}
600     */
601    default FluentNode th(String content) { return th(text(content)); }
602
603    /**
604     * {@code <td>}{@link Node node}{@code </td>}
605     *
606     * @param   node            {@link Node}
607     *
608     * @return  {@link org.w3c.dom.Element}
609     */
610    default FluentNode td(Node node) { return element("td", node); }
611
612    /**
613     * {@code <td>content</td>}
614     *
615     * @param   content         {@link org.w3c.dom.Text} content
616     *
617     * @return  {@code <td/>} {@link org.w3c.dom.Element}
618     */
619    default FluentNode td(String content) { return td(text(content)); }
620
621    /**
622     * {@code <u>}{@link Node node}{@code </u>}
623     *
624     * @param   node            {@link Node}
625     *
626     * @return  {@link org.w3c.dom.Element}
627     */
628    default FluentNode u(Node node) { return element("u", node); }
629
630    /**
631     * {@code <u>}{@link #text(String) text(content)}{@code </u>}
632     *
633     * @param   content         {@link org.w3c.dom.Text} content
634     *
635     * @return  {@link org.w3c.dom.Element}
636     */
637    default FluentNode u(String content) { return u(text(content)); }
638}