B4J Library [B4X] MiniHTML3

Version 3.00
MiniHTML library for B4X — a fluent HTML builder for B4J/B4A/B4i.

GitHub: https://github.com/pyhoon/MiniHTML3

Overview​

MiniHTML3 lets you construct HTML documents programmatically in B4X using an object-oriented, chaining API. Instead of concatenating strings, you build a tree of MiniHtml tag objects, then call build to render the final HTML string.

What's New​

  1. JSON to MiniHtml (and vice versa)
  2. Removed deprecated functions
  3. Code Snippets
    • Handler Class
    • Model Class
    • View Class
    • Cache
    • Helper
Following details are mostly copied and modified from markdown files created by DeepSeek V4 Flash Free through OpenCode.
 

Attachments

  • MiniHTML.b4xlib
    18.3 KB · Views: 7
Last edited:

aeric

Expert
Licensed User
Longtime User

Features​

  • Fluent API — Method chaining for concise, readable code
  • Automatic tag mode — Self-closing (<br>, <img>), uniline (<span>text</span>), multiline (<div> text</div>), meta (<!DOCTYPE>, <meta>), or no-tag (raw text)
  • Class & style management — addClass, removeClass, addStyle, removeStyle with auto-sync to class/style attributes
  • Attribute helpers — attr, attr2 (map), attr3 (boolean), plus convenience methods: lang, required, disabled, checked, selected, hidden, readonly
  • HTML parsing — Parse existing HTML strings into MiniHtml objects (Parse, ConvertFromBytes, ConvertToMiniHtml)
  • CDN helpers — cdn, cdn2, cdn3 for adding <script> and <link> tags with integrity/crossorigin support
  • Comments — comment (indented), comment2 (inline)
  • Text wrapping — text, text2 (overwrite), textWrap (indented)
  • Output options — build (no indent), build2 (custom indent), buildImpl (custom indent + attribute alignment)
  • Flat/minified output — Set Flat = True to suppress line breaks
  • Indentation control — Customize indent string (default: " "), control indent per-node
  • Format attributes — FormatAttributes = True aligns attributes across lines
  • Child traversal — ChildByName, ChildById, ChildByIndex with deep search
 

aeric

Expert
Licensed User
Longtime User

Quick Start​

(Using MiniHTML Helper module)
B4X:
' Build a simple HTML page
Dim doc As MiniHtml
doc.Initialize("doctype")
doc.Append(GeneratePage)
Return doc.ToString

Sub GeneratePage As String
    Dim html1 As MiniHtml = MH.Html
    Dim head1 As MiniHtml = MH.Head.up(html1)
    Dim title1 As MiniHtml = MH.Title.up(head1)
    title1.text("Hello")
    Dim body1 As MiniHtml = MH.Body.up(html1)
    Dim div1 As MiniHtml = MH.Div.up(body1)
    div1.cls("container").text("Hello World!")
    Return html1.build
End Sub

To create a MiniHTML helper module:
  1. Add a new Code Module and name it MH.
  2. Put cursor after the line Sub Process_Globals.
  3. Start typing "minihelper".
  4. Press Enter.
  5. The code will be added to the module.
1781886830093.png
 
Last edited:

aeric

Expert
Licensed User
Longtime User

API Reference​

MH.bas — Tag Factories​

MethodTag
Html<html lang="en">
Head<head>
Body<body>
Title<title>
Div<div>
Span<span>
P<p>
Anchor<a>
Button<button>
Input<input>
Label<label>
Form<form>
Table<table>
Tr<tr>
Td<td>
Th<th>
Thead<thead>
Tbody<tbody>
Ul<ul>
Li<li>
SelectTag<select>
Option<option>
Textarea<textarea>
Img<img>
Meta<meta>
Link<link>
Script<script>
Style<style>
Strong<strong>
Br<br>
Nav<nav>
Icon<i>
Svg<svg>
Path<path>
Footer<footer>
Caption<caption>
H1, H2, H3, H5, H6Heading tags

MiniHtml — Key Methods​

Construction:
  • Initialize(Name) — Create a tag with auto-detected mode
  • build — Render to string (no indent, no CRLF on first line)
  • build2(indent) — Render with custom indent
  • buildImpl(indent, AlignAttributes) — Full control
Adding children:
  • add(ChildTag) — Add child, returns child
  • up(ParentTag) — Add to parent, returns self (alias for addTo)
  • addTo(ParentTag) — Add to parent, returns self
  • text(value) — Add inner text
  • text2(value) — Clear children and set inner text
  • textWrap(value) — Add indented inner text
  • script(value) — Add <script>value</script> child
  • linebreak — Add a non-indented line break
  • comment(value) — Add <!-- value --> with indent
  • comment2(value, newline) — Add inline comment
Attributes:
  • attr(key, value) — Set attribute
  • attr2(map) — Set multiple attributes from map
  • attr3(key) — Set boolean attribute (no value)
Classes & Styles:
  • cls(value) or addClass(value) — Add class(es)
  • removeClass(value) — Remove class
  • sty(value) or addStyle(value) — Add style(s) (semicolon-separated)
  • removeStyle(key) — Remove style
Boolean attributes:
  • required, disabled, checked, selected, hidden, readonly
CDN helpers:
  • cdn(format, url) — Add <script src="..."> or <link href="...">
  • cdn2(format, url, integrity, crossorigin) — With SRI
  • cdn3(format, url, keyvals) — With extra attributes
Traversal:
  • ChildByName(value) — Deep search by tag name
  • ChildById(value) — Deep search by id attribute
  • ChildByIndex(index) — Get child by position
Parsing & JSON:
  • Parse(HtmlText) — Parse HTML string into MiniHtml
  • FromJson(JsonStr) — Parse JSON string into MiniHtml tree (shorthand format)
  • FromMap(m As Map) — Parse pre-parsed Map into MiniHtml (shorthand format)
  • ToMap — Serialize MiniHtml tree to a Map in shorthand format
  • ToJson — Serialize MiniHtml tree to a JSON string
  • ConvertFromBytes(Buffer()) — Parse from byte array
  • ConvertToBytes — Serialize to byte array
  • ConvertToMiniHtml(HtmlNode) — Convert parser node to MiniHtml
Configuration:
  • Flat — Suppress line breaks (minified output)
  • Indentation — Enable/disable per-node indent
  • LineFeed — Enable/disable CRLF
  • IndentString — Indentation string (default: " ")
  • FormatAttributes — Align multi-line attributes
  • Mode — uniline, multiline, meta, self, notext
  • SpecialTags — Tags excluded from default indentation

MiniHtmlParser — HTML Parser​

The parser (credits to Erel) converts HTML strings into a tree of HtmlNode objects.

Types:
  • HtmlNode(Name, Children, Attributes, Closed, Parent)
  • HtmlAttribute(Key, Value)
Key methods:
  • Parse(HtmlText) — Returns root HtmlNode
  • FindNode(Root, TagName, Attribute) — Recursive node search
  • FindDirectNodes(Root, TagName, Attribute) — Direct children search
  • IsNodeMatches(Node, TagName, Attribute) — Match test
  • GetTextFromNode(Node, ChildIndex) — Extract text
  • GetAttributeValue(Node, Key, Default) — Get attribute value
  • UnescapeEntities(XmlInput) — Unescape HTML entities
  • PrintNode(node) — Debug output
  • CreateHtmlAttribute(Key, Value) — Create attribute
 

aeric

Expert
Licensed User
Longtime User

JSON to MiniHtml​

Build HTML from JSON using the shorthand format.

Format​

JSON:
{"tagname": {"property": "value", ...}}

The outer key is the tag name, and its value is a map of properties. A string value is treated as inner text.

Properties​

KeyTypeDescription
classstringCSS class(es)
stylestringCSS style(s)
textstringInner text
idstringid attribute
attrsmapAdditional attributes
childrenarrayNested elements (same format)
modestringuniline, multiline, meta, self
flatboolSuppress line breaks
indentationboolEnable indentation
formatattributesboolAlign multi-line attributes
requiredboolBoolean attribute
disabledboolBoolean attribute
checkedboolBoolean attribute
selectedboolBoolean attribute
hiddenboolBoolean attribute
readonlyboolBoolean attribute
(any other)*Treated as attribute

Examples​

B4X:
Dim m As MiniHtml
m.Initialize("")
Dim root As MiniHtml = m.FromJson($"
{
  "div": {
    "class": "container",
    "style": "margin: auto",
    "attrs": {"data-id": "123"},
    "children": [
      {"h1": {"text": "Title"}},
      {"p": {"class": "lead", "text": "Paragraph text"}},
      {"button": {
        "class": "btn btn-primary",
        "disabled": true,
        "text": "Submit"
      }}
    ]
  }
}
"$)
Return root.build

Array root for multiple fragments:
JSON:
[{"div": {"class": "alert", "text": "Message"}}, {"script": {"text": "console.log('ok')"}}]

String shorthand for text-only tags:
JSON:
{"span": "hello world"}

Pre-parsed Map:
B4X:
Dim map1 As Map = CreateMap("div": CreateMap("class": "foo", "text": "bar"))
Dim root As MiniHtml = m.FromMap(map1)

Round-trip (ToMap / ToJson)​

Serialize a MiniHtml tree back to Map or JSON:
B4X:
Dim m As MiniHtml
m.Initialize("")
Dim root As MiniHtml = m.FromJson(${"div": {"class": "container", "text": "Hello"}}$)

' To Map
Dim map1 As Map = root.ToMap

' To JSON string
Dim json As String = root.ToJson

Text-only shorthand is preserved:
B4X:
Dim el As MiniHtml
el.Initialize("span")
el.text("Hello")
Log(el.ToJson) ' {"span":"Hello"}

Mixed content (text + tags) uses a children array with strings for text:
B4X:
' Produces: {"children": ["Hello ", {"strong": {"text": "world"}}, "!"]}

Boolean attributes round-trip as true:
B4X:
Dim el As MiniHtml
el.Initialize("button")
el.required
el.text("Submit")
Log(el.ToJson) ' {"button": {"text": "Submit", "required": true}}
 

aeric

Expert
Licensed User
Longtime User

Helper.bas — Higher-Level UI Helpers​


Static-code module providing tag factories, Bootstrap 5 UI components, form helpers, HTMX helpers, and custom components for the MiniHTML library.

Tag Factories​

MethodTagNotes
CreateTag(Name)anyGeneric tag factory
Html<html>With lang="en"
Head<head>
Body<body>
Title<title>
Div<div>
Span<span>
P<p>
Anchor<a>
Button<button>
Strong<strong>
Br<br>
Nav<nav>
Form<form>
H1, H2, H3, H5, H6<h1>–<h6>
Script<script>
Style<style>
Meta<meta>
Link<link>
Icon<i>
Img<img>
Svg<svg>
Path<path>
Input<input>
Label<label>
Caption<caption>
Footer<footer>
Table<table>
Thead<thead>
Tbody<tbody>
Tr<tr>
Td<td>
Th<th>
Ul<ul>
Li<li>
SelectTag<select>
Option<option>
Textarea<textarea>

Custom Components​

MethodReturnsDescription
CreateAlertInfo(Message, Status)AlertInfoCreate alert data object
CreateToastInfo(Entity, Action, Message, Status)ToastInfoCreate toast data object
Alert(info)StringRenders <div class="alert alert-{status}">{message}</div>
Toast(id, table, info)StringHTMX out-of‑band swap container + MiniJs event dispatch
NavLinkItem(text, href, icon_cls, icon_title)MiniHtml<li class="nav-item"> with anchor + icon
AnchorIcon(cls, hx_get, title_text, icon_class)MiniHtmlAnchor with hx-get for modal trigger + icon
ButtonCloseMiniHtml<button type="button" class="btn-close" data-bs-dismiss="modal">
ButtonAdd(text, cls, hx_get, hx_target, hx_trigger, data_bs_target, data_bs_toggle)MiniHtmlButton with icon + HTMX modal attributes
ButtonSubmit(text, cls)MiniHtml<button type="submit">
ButtonCancel(text, cls)MiniHtml<button type="button" data-bs-dismiss="modal">
ButtonSearch(text, cls, hx_post, hx_target)MiniHtmlSearch button with HTMX attrs
InputSearch(cls, id, name)MiniHtml<input type="text"> search field
TextLabel(text, cls, forId)MiniHtml<label for="...">
FormGroupMiniHtml<div class="form-group">
InputGroupMiniHtml<div class="input-group mb-3">
HiddenInput(id, name, value)MiniHtml<input type="hidden">
RequiredLabel(text, forId)MiniHtmlLabel with red asterisk
RequiredTextInput(id, name, value)MiniHtmlRequired text input
RequiredDropdown(id, name)MiniHtmlRequired <select class="form-select">
ContainerModalMiniHtmlBootstrap 5 modal container (fade, centered)
ContainerModalWithButton(TitleText, ParagraphText, ButtonText)MiniHtmlModal with header, body, footer + dismiss button
ContainerToastMiniHtmlFixed-position toast container (bottom‑right)

Conversion Helpers​

MethodReturnsDescription
ConvertFromBytes(Buffer())MiniHtmlParse UTF‑8 byte array into MiniHtml tree
ConvertToMiniHtml(Root)Byte()Serialize MiniHtml tree to UTF‑8 byte array

Bootstrap Layout Helpers​

MethodReturnsDescription
ContainerMiniHtml<div class="container">
ContainerFluidMiniHtml<div class="container-fluid">
RowMiniHtml<div class="row">
Col(cols)MiniHtml<div class="col-{cols}">

Form Input Helpers​

All form helpers apply form-control class and guard empty-string parameters.
MethodReturnsDescription
InputText(id, name, value, placeholder)MiniHtml<input type="text">
InputEmail(id, name, value, placeholder)MiniHtml<input type="email">
InputPassword(id, name, placeholder)MiniHtml<input type="password">
InputNumber(id, name, value, MinValue, MaxValue, StepValue)MiniHtml<input type="number">
InputDate(id, name, value)MiniHtml<input type="date">
InputFile(id, name, accept, multiple)MiniHtml<input type="file">
TextareaInput(id, name, value, rows, placeholder)MiniHtml<textarea class="form-control">
CheckboxInput(id, name, value, text, checked)MiniHtmlform-check div with label
RadioInput(name, id, value, text, checked)MiniHtmlform-check div with label
SelectInput(id, name, options, selectedValue, prompt, required)MiniHtml<select class="form-select"> with <option> children
SelectInput expects options as a List of Map items with keys "value" and "text".

Bootstrap UI Components​

MethodReturnsDescription
CardMiniHtml<div class="card">
CardHeaderMiniHtml<div class="card-header">
CardBodyMiniHtml<div class="card-body">
CardFooterMiniHtml<div class="card-footer">
CardTitleMiniHtml<h5 class="card-title">
CardTextMiniHtml<p class="card-text">
Badge(text, cls)MiniHtml<span class="badge {cls}">{text}</span>
ListGroupMiniHtml<ul class="list-group">
ListGroupItem(text, cls)MiniHtml<li class="list-group-item {cls}">{text}</li>
ListGroupButton(text, cls, active)MiniHtml<button class="list-group-item list-group-item-action {cls}[ active]">
ProgressBar(now, MinValue, MaxValue, cls, showLabel)MiniHtmlProgress bar with ARIA attrs
Spinner(cls, text)MiniHtml<div class="spinner-border {cls}"> + sr‑only text
SpinnerGrow(cls, text)MiniHtml<div class="spinner-grow {cls}"> + sr‑only text
AlertDismissible(message, status)MiniHtmlDismissible Bootstrap alert with close button

HTMX Helpers​

MethodReturnsDescription
HxGet(href, target, swap, trigger)MiniHtmlAnchor with hx-get, hx-target, hx-swap, hx-trigger
HxPost(href, target, swap)MiniHtmlButton with hx-post, hx-target, hx-swap

Navigation Helpers​

MethodReturnsDescription
Navbar(brand, expand, cls)MiniHtml<nav class="navbar navbar-expand-{expand} {cls}"> with brand
NavItem(text, href, active)MiniHtml<li class="nav-item"><a class="nav-link[ active]" href="...">

Utility Helpers​

MethodReturnsDescription
CssLink(href)MiniHtml<link rel="stylesheet" href="...">
JsScript(src)MiniHtml<script src="...">
ImgResponsive(src, alt, cls)MiniHtml<img class="img-fluid {cls}" src="..." alt="...">
PageHeading(text, tag)MiniHtmlGeneric heading tag with inner text
ButtonIcon(text, iconCls, btnCls)MiniHtmlButton with icon + text
AnchorButton(text, href, cls)MiniHtmlAnchor styled as button (class="btn {cls}")

Types​

B4X:
Type AlertInfo (Message As String, Status As String)
Type ToastInfo (Entity As String, Action As String, Message As String, Status As String)
 

aeric

Expert
Licensed User
Longtime User

Cache.bas — Page & Component Caching​

Static-code module for caching MiniHtml objects in a Map context. Supports round‑tripping through byte arrays so cached MiniHtml trees can be cloned without re-building.

Methods​

MethodReturnsDescription
ExistInCache(ctx, Key)BooleanCheck if Key exists in the cache map
WriteToCache(ctx, Key, Value)-Store Value in the cache map
ReadFromCache(ctx, Key)ObjectRead from cache; returns MiniHtml if stored as MiniHtml or byte array, otherwise raw Object
ConvertFromBytes(Buffer())MiniHtmlParse UTF‑8 byte array into a MiniHtml tree
ConvertToBytesByte()Serialize an empty MiniHtml to UTF‑8 byte array

Example​

MC is Cache code module
ProductsView.bas:
Public Sub Show As String
    Dim CacheName As String = "Products Page"
    ' Check and write
    If MC.ExistInCache(App.ctx, CacheName) = False Then
        MC.WriteToCache(App.ctx, CacheName, ProductsPage)
    End If
    ' Read back (auto-detects MiniHtml vs byte[])
    Dim page1 As MiniHtml = MC.ReadFromCache(App.ctx, CacheName)
    Dim doc As MiniHtml
    doc.Initialize("doctype")
    doc.Append(page1.build)
    Return doc.ToString
End Sub

Notes​

  • ReadFromCache transparently handles both raw MiniHtml objects and byte arrays ([B type), calling ConvertFromBytes on the latter.
  • ConvertToBytes serializes an empty tag — useful when you want to clone a MiniHtml tree by storing and re-reading it as bytes.
 
Top