From afe3df06507cf09c332621128925832e228fabd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sun, 17 May 2026 03:19:08 -0300 Subject: [PATCH] Improve baseline aligment in inline-blocks. Improved html architecture documentation. --- .agent/rules/html-layout-architecture.md | 158 ++++++++++++++++---- include/eepp/graphics/richtext.hpp | 3 +- src/eepp/graphics/richtext.cpp | 29 +++- src/eepp/ui/blocklayouter.cpp | 20 ++- src/eepp/ui/uirichtext.cpp | 35 ++++- src/tests/unit_tests/richtext_tests.cpp | 31 ++++ src/tests/unit_tests/uihtml_tests.cpp | 181 +++++++++++++++++++++++ 7 files changed, 416 insertions(+), 41 deletions(-) diff --git a/.agent/rules/html-layout-architecture.md b/.agent/rules/html-layout-architecture.md index e1d9db8e6..8c1288448 100644 --- a/.agent/rules/html-layout-architecture.md +++ b/.agent/rules/html-layout-architecture.md @@ -1,36 +1,144 @@ # HTML Layout Architecture -This document describes the decoupled HTML/CSS layout engine architecture implemented in `eepp` for `UIHTMLWidget` and related classes. +This document describes the eepp GUI HTML compatibility layer: the subset of HTML/CSS layout implemented through `UIHTMLWidget`, `UIRichText`, `RichText`, and the `UILayouter` family. + +The goal is browser-compatible behavior where implemented, not a parallel eepp-specific layout language. When adding HTML/CSS features, start from the relevant specification and then map that behavior onto the existing architecture. + +## Spec-First Requirement + +Agents must implement HTML/CSS features by following the official specifications first. Do not add element-specific hacks just to match one fixture if the behavior belongs to a generic CSS concept. + +Primary references: + +- HTML Living Standard: https://html.spec.whatwg.org/ +- CSS specifications index: https://www.w3.org/Style/CSS/specs.en.html +- CSS Display: https://www.w3.org/TR/css-display-3/ +- CSS Visual Formatting Model, including inline formatting and positioning: https://www.w3.org/TR/CSS22/visuren.html +- CSS line height and inline-block baseline rules: https://www.w3.org/TR/CSS22/visudet.html#line-height +- CSS Lists and Counters: https://www.w3.org/TR/css-lists-3/ + +Required workflow for new HTML/CSS behavior: + +- Identify the spec section that defines the behavior. +- Implement the behavior at the correct abstraction level, usually display/layout/formatting/list/positioning, not by tag name. +- Preserve HTML element defaults from the spec, such as `summary { display: list-item; }`. +- Add focused tests that encode the generic behavior and, when useful, a real HTML fixture that triggered the issue. +- If eepp intentionally supports only a subset of a spec, document the limitation close to the implementation or in this file. ## Core Concepts -### 1. UIHTMLWidget -`UIHTMLWidget` is the base class for all HTML-like elements. It holds parsed CSS properties (Display, Position, Float, Clear, etc.). Instead of implementing complex layout math directly, it queries a `UILayouterManager` to instantiate the appropriate `UILayouter` based on its `CSSDisplay` property. +### UIHTMLWidget -### 2. Layouters -Layout math has been extracted from widgets into stateless (or locally stateful) "Layouters": -- **BlockLayouter:** Handles `CSSDisplay::Block`. It positions block-level children vertically. For rich text, it delegates text shaping to the `RichText` engine and simply maps physical coordinates for custom inline widgets. -- **TableLayouter:** Handles `CSSDisplay::Table`. Encapsulates HTML table column width distribution and row positioning. -- **InlineLayouter:** Handles `CSSDisplay::Inline`. *This layouter is empty by design.* Inline formatting (like `` or ``) is completely managed by the nearest Block container (via the `RichText` engine). It acts as a no-op so standard linear layout logic doesn't override text flows. -- **NoneLayouter:** Handles `CSSDisplay::None`. Skips all layout and rendering. +`UIHTMLWidget` is the base class for HTML-like elements. It stores parsed CSS layout state such as `display`, `position`, `float`, `clear`, list style, and data attributes. It does not own all layout math directly. Instead, it uses `UILayouterManager` to instantiate the appropriate `UILayouter` for its `CSSDisplay`. -### 3. The UIRichText Engine Integration -`UIRichText` acts as the primary block container for mixed text and widget content. -- It uses `rebuildRichText()` to recursively traverse its children. -- Pure text nodes (`UITextSpan`, `
`) are appended to the core `RichText` engine via `RichText::addSpan()`. -- Arbitrary inline widgets (e.g., ``, `