Skip to content

Latest commit

 

History

History
193 lines (162 loc) · 15.9 KB

File metadata and controls

193 lines (162 loc) · 15.9 KB

HTML element index — full coverage tracker

Every standard HTML element (per the MDN HTML elements reference), with its status in the Tina4Pascal renderer. Companion to CSS-PROPERTY-INDEX.md. Goal: every rendered element ✅.

Re-audited 2026-09-06 against the source (every ✅ spot-checked in code; added the <search> landmark found missing). Corrections are flagged inline.

Status: ✅ Rendered correctly · 🟡 Partial · ⬜ Intentionally not rendered (metadata/scripting) · ❌ Missing (should render, doesn't).

Main root & metadata

Element Status Note
html, body layout roots
head, meta, base not rendered
title ignored (inner text can leak as a stray node — minor)
link[rel=stylesheet] inline <style> and external <link href> both applied. Relative hrefs load from beside the HTML; remote URLs are fetched once through the shell (FetchToFile) into a local csscache/ and reused. Cascade order preserved (links before inline <style>)
style parsed into the stylesheet

Content sectioning

Element Status Note
header, footer, main, section, article, aside, nav block
search block landmark (wraps a search form) — added to the block-tag set
h1–h6 UA sizes + weight + margins
hgroup block; heading children stack
address block + italic UA

Text content

Element Status Note
div, p block + margins
ul, ol block + indent + markers
menu renders as a list (block + indent + disc markers), like ul
li list-item + marker
dl, dt, dd bold term, indented def
blockquote indent + left border
pre monospace, whitespace preserved
hr UA thin grey rule line (1px block) + 8px margins
figure, figcaption block; figure has UA 1em/40px margins

Inline text semantics

Element Status Note
a, span inline. A click on <a href> with no onclick/control fires the core link hook (Tina4InvokeLink) with the href + target; the shell's registered opener (Tina4LinkOpenopen/ShellExecute/xdg-open) hands it to the OS by scheme: tel:→dialer, mailto:→mail, sms:→messages, http(s):→browser, geo:/maps:→maps. Verified all four schemes dispatch with exact URLs. App wires it once via Tina4InstallLinkOpener (no-op until then)
b, strong, i, em, u, ins bold/italic/underline
s, del line-through
strike line-through (legacy alias of s/del)
small, mark, code, kbd, samp, var mark = yellow bg; code/kbd/samp mono
sub, sup baseline shift + smaller
abbr, cite, dfn, q, br q = auto quotes; nested <q> switch to the inner ‘ ’ pair (reftest css-q-nested)
wbr zero-width break opportunity (line wraps there when needed)
bdi, bdo <bdo dir> overrides direction (characters reverse + mirror); <bdi> isolates content with auto-detected direction. Built on the bidi reorder; verified matching Chrome. Reftest bdo-override
time, data inline text (no visual difference required; value/datetime are metadata)
ruby, rt, rp stacked annotation: the <rt> renders centred above its base in a smaller font (furigana); the ruby flows inline and reserves space above the line; <rp> fallback parens hidden. Whole base treated as one annotation pair (no per-character split). Reftest ruby-basic

Image & multimedia

Element Status Note
img remote fetch + decode + cache + aspect (all platforms)
svg pure-Pascal vector painter (Tina4SVG) — shapes, paths, text, transforms, fill gradients (<linearGradient>/<radialGradient> via url(#id)), clip-path (<clipPath> first shape, incl. on a <g> subtree) and <use> (href reference + x/y, from <defs>); no mask/filters yet
qrcode Tina4 custom — pure-Pascal QR encoder
camera Tina4 custom — "Take Photo" → shell capture
recorder ✅ macOS · 🟡 iOS/Android degrade Tina4 custom — mic capture, the stateful audio analogue of <camera>. Classified ckFile; a tap toggles a recording attribute that drives the chrome (🎙 Record → ⏹ Stop → 🎙 filename) and the start/stop path. TinaTouch returns TINA_RECORD_START/TINA_RECORD_STOP; the shell contract adds StartAudioCapture/StopAudioCapture (safe defaults → a shell with no mic just never arms). On stop the host calls TinaSetRecording(path), which stamps the control value, routes the clip into an <audio id="rec"> player if present, and fires the element's onrecord action. macOS ✅ real AVAudioRecorder → AAC .m4a in the temp dir (bundled app needs NSMicrophoneUsageDescription). iOS/Android degrade like <camera> there (no shell override yet — iOS AVAudioRecorder+AVAudioSession, Android MediaRecorder+RECORD_AUDIO are the follow-up). State machine covered by tests/test_interact.pas
picture, source, srcset responsive selection (media/type/density/width/sizes)
video ✅ iOS · ✅ Android · 🟡 macOS core lays out a poster box + exposes rect/src/flags/poster via tina4_embed_*. Attributes honored per shell: controls, autoplay, loop, muted (bitmask), and poster (painted as the box background by the core). iOSAVPlayerViewController. AndroidVideoView+MediaController in a host FrameLayout. macOS 🟡 Cocoa AVPlayerView (AVKit; loop TODO) — compiles, verify pending a GUI run
audio <audio controls> is an engine-drawn control (ckAudio) — a light bar with a round ▶/⏸ button and a progress track, painted by the core (PaintAudioControl) so it looks identical on every platform (no black video surface). A bare <audio> is display:none. It is not a native overlay: a tap returns TINA_AUDIO_TOGGLE and the shell reads TinaAudioSrc/TinaAudioWantPlay, drives an audio player, and pushes the elapsed fraction + sounding state back with TinaSetAudioProgress each frame (playing/progress attributes drive the glyph + bar). Shell contract: AudioPlay/AudioPause/AudioProgress (safe defaults → a shell with no audio out draws an idle bar). iOS/macOS AVAudioPlayer, Android MediaPlayer (relative src resolved against the asset base), desktop the htmlviewer harness — engine-drawn control verified on macOS render + live on Android (tap ▶ plays, bar advances, ⏸ pauses, resets at end)
canvas pure-Pascal Canvas 2D (Tina4Canvas2D) — an app registers a painter for <canvas id>; draws with the familiar methods (rects, paths, arc/bezier/quadratic, fill/stroke, text, transforms, globalAlpha, drawImage). drawImage honours the context matrix — scale/flip on every backend, rotation/skew through the CTM (Cocoa/iOS). Core-rendered → every shell + snapshot-testable. No JS, no Skia
barcode-scanner 🟡 core+decode · ❌ camera Tina4 custom — a live camera scanner. The core lays out a placeholder box and surfaces it through the embed pipeline as kind 2 (tina4_embed_*), capturing the formats attr (e.g. "qr,ean13") and boolean torch; a decode reported by a shell via TinaScanResult fires the element's onscan action with the exact decoded value (by-name dispatch — never parsed as call syntax). Desktop decoding done: Tina4Barcode binds libzbar, loaded dynamically by soname (no build/link dep) — decodes a grayscale frame → value + symbology; round-trip-tested (tests/test_barcode.pas: Tina4QR → zbar). Still per-shell: the camera preview + frame capture (AVFoundation built-in metadata on iOS/macOS, CameraX+MLKit on Android, MediaCapture/V4L2 on desktop feeding Tina4Barcode). Element/dispatch covered by tests/test_scanner.pas
camera-view ✅ core box · ❌ preview Tina4 custom — a live camera preview (the un-decoded sibling of <barcode-scanner>, for a monitor/feed rather than QR). The core lays out a black inline-block placeholder box (HTML default intrinsic 300×150, shell overlays a native preview over it — same model as <video>); reftest camera-view-test/-ref matches at 0.00%. Shell contract added (Tina4RenderBackend, safe defaults): StartCameraPreview(elementId, facing) / StopCameraPreview / GrabCameraFrame → JPEG (for streaming/motion/detection). Still per-shell: the native preview + frame grab (reuse the scanner's AVCaptureSession/Camera2 session minus the metadata output; add AVCaptureVideoDataOutput/ImageReader for the JPEG). Companion contract StartAudioMeter/AudioLevel (RMS 0..1) + BeginBackgroundCapture land alongside for the monitor use case
iframe intentionally not supported — Tina4 composes pages with <include src> (native HTML splice into the same render tree), not a foreign web view
object, map legacy embed / image maps — not planned
track, area, embed void children / not applicable

Tina4 custom tags

Custom-element registry (src/Tina4Elements.pas) — invent a tag once and it works everywhere, no core SameText edits. Two tiers, both proven by tests/test_elements.pas and rendered live on Cocoa (see the demo <nicebutton> / <ratingstars> in examples/htmlviewer):

  • Tier 1 — RegisterElement(name, template, css): a template element expands at Build time (next to InjectPseudo) into plain HTML — brace-attr placeholders filled from attributes, a children placeholder from the element's inner HTML. The host tag is consumed (its id carries to the first expanded node); the downstream engine sees only standard elements. Idempotent/stable across rebuilds. Registered default CSS is folded into the sheet (UA-like).
  • Tier 2 — RegisterNativeElement(name, paint, ontap, css): the element keeps its own tag and draws itself through the canvas contract (Paint hook in PaintBox, clipped like <canvas>) and responds to a tap (OnTap hook in Tina4Interact + the macOS host), sized by its registered CSS. Portable to every shell by construction.
Element Status Note
include[src] fetches HTML + splices in place, caches, nested, per-tag auth headers
secure redacted under capture-protection (see TinaSetCaptureProtected)
lottie Tina4 custom — pure-Pascal Lottie/Bodymovin player (Tina4Lottie) rendering inline JSON via Canvas 2D; shape layers, bezier paths, fills/strokes, keyframed transforms + parenting, cubic-bezier easing; animates off the ticker. No Skia/JS. Verified on iPhone

Table content

Element Status Note
table auto/explicit column sizing, border attr
thead, tbody, tfoot tfoot rows moved to the bottom regardless of source order; no sticky/repeat
tr, td
th UA bold + center
colspan (attr) both layout passes
rowspan (attr) cell reserves its columns downward; following rows shift correctly
caption full-table-width block above (default) or below rows; caption-side honored
col, colgroup per-column width via width attr or style; span honored

Forms

Element Status Note
form block; submit collects name=value
input[text/email/password/search/number] all accept text + focus/caret; password masks (•). number paints a right-edge ▴/▾ spinner; clicking it steps value by step (default 1), clamped to min/max, firing change. (numeric/email soft-keyboard still pending a keyboard-type shell contract)
input[checkbox] draw + toggle, :checked stylable
input[radio] draw + group exclusivity by name
input[submit/button] drawn button + press feedback
input[file] "Choose File" → shell picker; shows filename
input[date] native calendar picker — formatted display (format attr), month nav, today, ISO value (see examples/datepicker)
input[color/range/tel/url/…] ✅/🟡 color swatch + range slider drawn; tel/url as text
textarea multi-line editing: click positions the caret (line by Y, column by X); type/backspace/delete at the caret; Enter splits the line; ←/→ and ↑/↓ navigate (↑/↓ keep the column across lines)
select, option drawn dropdown overlay with ✓
optgroup label row + indented options in the dropdown; nested options selectable and resolved when closed
button drawn; submit
label for=/wrapping/sibling all wired to focus+toggle
fieldset, legend bordered group; the legend straddles the top border and notches it (masks the segment behind its background)
datalist inert (display:none UA); options never painted
output <output formula="a * 2 + b"> recomputes from named field values via a built-in arithmetic evaluator (+ − × ÷, parens); recalculated on oninput="output.recalc()" and seeded at load. No JS engine
progress, meter drawn bars (progress accent, meter green) from value/max

Interactive & scripting

Element Status Note
details, summary draws ▸/▾ + honors open; tapping the summary toggles open/closed (mobile TinaTouch + desktop MouseUp)
dialog dialog.show(id)/dialog.close(id) open/close it in flow; dialog.showModal(id) centres it over a dimmed backdrop (top layer). Driven by the built-in event actions from a plain onclick — no JS engine
script content skipped (not rendered)
noscript 🟡 children render (non-spec, harmless)
template inert (display:none UA); content never painted
slot 🟡 passthrough (no shadow DOM)

Misc

Element/Attr Status Note
onclick (any element) semantic obj:method(args) + :active feedback
id / class / style selectors + inline styles (inline wins)
hidden attribute ⇒ display:none
<!-- comments --> stripped by the parser (SkipComment) — content and any tag-like text inside are dropped, never a stray node
<!DOCTYPE> skipped (SkipDoctype)

Outstanding (verified against source 2026-09-05)

Everything not listed here is ✅ or ⬜ in the tables above. Each row is corrected in the same commit that changes its behaviour — this list is the truth, not a wishlist.

Core-renderable, still open: none — the element inventory is complete. A minimal event hook (Tina4Builtins: dialog.show/showModal/close, output.recalc + a tiny arithmetic evaluator, dispatched from plain onclick/ oninput via Tina4Events) unblocked the last two (<output>, <dialog> modal) without a JS engine. Anything richer (arbitrary scripting) stays out of scope by design — native apps consume APIs built elsewhere.

Done recently: <output> formula binding + <dialog> show/close/modal (event hook); <textarea> mid-text editing; input[number] steppers; <fieldset> notch; external <link href> CSS fetch (FetchToFilecsscache/).

Media — all done: video (iOS AVPlayerViewController + Android VideoView; macOS Cocoa AVPlayerView 🟡 loop TODO), audio (engine-drawn ckAudio control + AudioPlay/AudioProgress contract, not a native overlay), canvas (pure-Pascal Tina4Canvas2D), lottie (pure-Pascal Tina4Lottie). iframe/object/map intentionally not rendered (use <include src>).

Deferred (need a larger subsystem, intentionally later):

Done since the previous audit: whole tables set (rowspan, caption+side, col/colgroup, tfoot, th); template/datalist inert; <optgroup>; <dialog> open/closed; details/summary tap-toggle (was already wired — doc was stale); menu list, strike, hgroup, figure margins, address italic, hr rule line, wbr, time/data.