diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..b1bb799 --- /dev/null +++ b/TODO.md @@ -0,0 +1,93 @@ +# TODO + +Concrete, code-level roadmap for theBrowser, ordered by priority: rendering correctness first (make real pages and Acid1 render better), long-term fronts (JS) last. High-level status lives in [README.md](README.md); this list tracks the actual gaps found in the code. + +## 1. Quick fixes / known bugs + +High impact, small effort — mostly straight-up bugs. + +- [x] `computed_style` percentage font-size with a parent falls through and returns nothing — the `%` branch only handles the no-parent path (`web/css/utils.py:19-34`) +- [x] `raise NotImplemented` uses the non-exception constant, so it never actually raises (`web/html/parser/utils.py:136`) +- [x] rem/em handling assigns a `str` to `font_size` and then multiplies with it (`browser/layouts/Layout.py:151-212`, `browser/layouts/ImageLayout.py:74,112`) +- [x] `convert_absolute_size_to_pixels` is a stub that always returns 16 — keyword font sizes (`small`/`medium`/`large`/...) are ignored (`browser/styling/font/utils.py:7`) +- [x] `scroll_down` uses window *width* instead of height for max scroll (`browser/Browser.py:294`) +- [x] Border and padding both write `internal_padding` and clobber each other (`browser/layouts/Layout.py:293,308`) +- [x] `DrawBorder.calculate_offset` body is commented out (always returns `(0, 0)`), so per-side borders with differing widths misalign at corners (`browser/elements/elements.py:143-165`) +- [x] `raster()` writes debug files `rules.txt` and `document.html` to CWD on every page load (`browser/Browser.py:262-267`); stray debug prints (`browser/layouts/ImageLayout.py:102`, `browser/styling/color/utils.py:185`) +- [x] Bare `except: pass` hides all page-load errors (`browser/Browser.py:98`) +- [x] `EventInit` trailing commas turn `bubbles`/`cancelable` into tuples (`web/dom/events/Event.py:10-11`) +- [x] `DomException` subclasses `BaseException` — should be `Exception`, and should actually be raised from DOM mutation code (`web/dom/exceptions/DomException.py`) + +## 2. CSS correctness + +The biggest rendering-correctness lever: cascade and selector matching. + +- [ ] Correct specificity — `(id, class, tag)` tuple instead of hardcoded `priority = 1` (`web/css/TagSelector.py:6`, `web/css/DescendantSelector.py:9`, `cascade_priority` in `web/css/utils.py`) +- [ ] Honor `!important` — it's parsed but the flag is discarded (`web/css/CSSParser.py:66-69`) +- [ ] Shorthand property expansion: `margin`, `padding`, `border`, `font`, `background` +- [ ] More selectors: universal `*`, child `>`, sibling `+`/`~`, attribute `[attr]`, basic pseudo-classes +- [ ] Broaden inherited properties beyond the current 4 (`web/css/utils.py:7-12`) and unit resolution beyond font-size px/% (proper `em`/`rem`/`pt`) +- [ ] `@media` blocks are currently swallowed and their rules discarded — parse and evaluate (`web/css/CSSParser.py:122-136`) +- [ ] Colors: `#RRGGBBAA` hex, `hsl()`/`hsla()`, `currentColor`; `initial` shouldn't hardcode black (`browser/styling/color/utils.py:161,189`) + +## 3. Layout + +Acid1 lives or dies here. + +- [ ] Proper float support: `clear`, a shared float context instead of copy-pasted left/right branches across BlockLayout/InlineLayout/TableLayout/dl (`browser/layouts/Layout.py:121`) +- [ ] Margins: `auto` centering, margin collapsing, negative margins (`browser/layouts/Layout.py:337-383`) +- [ ] `min-width`/`max-width`/`min-height`/`max-height` (commented out in `browser/layouts/InputLayout.py:48-53`), `calc()` (currently dropped, `browser/layouts/Layout.py:163`), `max-content` (`browser/layouts/Layout.py:222`) +- [ ] Units: `vh`, proper `em` vs `rem` distinction, `ch`/`ex`/`cm`/`mm`/`in` +- [ ] `display: inline-block`; `position: relative/absolute/fixed` and `z-index` — nothing reads `position` today +- [ ] Table: colspan/rowspan, `thead`/`tfoot`/`caption`, `border-collapse`, a real width algorithm instead of the current heuristic (`browser/layouts/table/TableLayout.py:196-218,261-271`) +- [ ] `dl`: distinguish `dt` vs `dd` (indentation) (`browser/layouts/dl/`) +- [ ] Remove BlockLayout hacks: default `height = 10` and the body re-layout loop (`browser/layouts/BlockLayout.py:13,45-48`) + +## 4. Painting / rendering + +- [ ] `border-style` (only solid supported) and `border-radius` (`browser/layouts/Layout.py:289`) +- [ ] `text-decoration` (underline/line-through), `text-align`, `white-space` handling +- [ ] `font-family` — currently ignored, tkinter default is always used (`browser/layouts/utils.py`) +- [ ] Re-enable emoji image rendering — the code path is commented out, emojis render as plain text (`browser/Browser.py:335-350`, `browser/elements/elements.py:42-54`) +- [ ] `background-image`; proper rgba rendering instead of the per-rect PIL image workaround (`browser/elements/elements.py:106,232`) + +## 5. HTML parsing (spec completeness) + +- [ ] Adoption-agency algorithm, reconstruct-active-formatting-elements, generate-implied-end-tags (`web/html/parser/HTMLDocumentParser.py:201,534-694,743`) +- [ ] Table insertion modes — InTable/InTableText/InCaption/InColumnGroup/InTableBody/InRow/InCell/InSelect are empty stubs (`web/html/parser/HTMLDocumentParser.py:875-900`) +- [ ] Frameset / after-body / after-after modes (`web/html/parser/HTMLDocumentParser.py:939-949`) +- [ ] Missing tokenizer states: DOCTYPE public/system identifiers, CDATA sections, PLAINTEXT, script-data-double-escaped, after-attribute-name, comment-end-bang (`web/html/parser/HTMLTokenizerRefactored.py:277,719-731,776,1012,1041-1086`) +- [ ] Named character reference state-switch TODO (`web/html/parser/HTMLTokenizerRefactored.py:1122`) and numeric noncharacter fix-up (~1211) +- [ ] Quirks-mode detection (`web/html/parser/HTMLDocumentParser.py:311`) and charset handling (`372,568`) +- [ ] Delete dead code: old `web/html/parser/HTMLTokenizer.py` (imported nowhere — parser uses `HTMLTokenizerRefactored`) and the `libs/JSlib/JavaScript.py` stub + +## 6. Networking & forms + +- [ ] Real POST form submission — `submit_form` always builds a GET query string, ignoring `method`/`enctype` (`browser/Browser.py:197-214`) +- [ ] Serialize `select`/`textarea`/checkbox semantics in form data; radio buttons don't deselect their group siblings (`browser/Browser.py:177-182`) +- [ ] `data:` URLs; handle `request()` returning `None` for unsupported schemes without crashing (`browser/utils/networking.py:37`) +- [ ] Replace hand-rolled `resolve_url` with `urllib.parse.urljoin` (`browser/utils/networking.py:16-35`) +- [ ] Cookies, explicit redirect handling, request timeouts; `REQUEST_CACHE` never invalidates and ignores Cache-Control (`browser/utils/networking.py:10,40,54`) + +## 7. Browser chrome + +- [ ] History with back/forward buttons +- [ ] Tabs +- [ ] Bookmarks +- [ ] Text input: caret positioning, selection, clipboard, tab between fields; `textarea` and `select` support +- [ ] Inspector: computed-styles panel; network view appends without clearing so rows duplicate (`browser/Inspector.py:100-102`); scrollbar created twice and wired to the wrong tree (`browser/Inspector.py:88-93`) + +## 8. JavaScript (long-term) + +- [ ] Lexer/parser for JS source — none exists, the AST can't be built from text +- [ ] Interpreter scope handling — `__enter_scope`/`__exit_scope` raise `NotImplementedError`, so `run()` always throws (`web/js/Interpreter.py:26-29`) +- [ ] Fix `ASTNode.execute` signature mismatches and implement the missing `execute` methods (`web/js/ASTNode.py`) +- [ ] DOM events: listener storage, `dispatchEvent`, propagation, `preventDefault`/`stopPropagation` — `EventTarget.add_event_listener` raises today (`web/dom/events/EventTarget.py:14`) +- [ ] Wire `