Skip to content

release: merge dev into main#83

Merged
usernane merged 26 commits into
mainfrom
dev
Jun 10, 2026
Merged

release: merge dev into main#83
usernane merged 26 commits into
mainfrom
dev

Conversation

@usernane

Copy link
Copy Markdown
Member

Summary

Merge all development work from dev into main for release.

Changes Included

Testing

All tests pass (362 tests, 1083 assertions) across PHP 8.1–8.5.

Breaking Changes

  • children() returns Vector instead of LinkedList
  • setAttribute() throws InvalidArgumentException for invalid names
  • Attribute values with & now render as &, " as "
  • HTMLTable::rows()/cols() derive from DOM state, not counters

Ibrahim BinAlshikh and others added 25 commits June 10, 2026 15:16
…63, #71, #74, #75, #76, #77

Add tests that verify the existence of bugs reported in the listed
issues. Tests for #57, #74, and #75 already pass as those bugs were
fixed alongside the test additions.
Replace str_replace('"', '\"', $val) with proper encoding of & and
" characters in quoted attribute values. This produces valid HTML output
where & is rendered as & and " as ".

Update existing test expectations to match the corrected output.

Closes #77
…ames

setAttribute() now throws InvalidArgumentException when a structurally
invalid attribute name is passed (e.g., names with spaces, quotes, =).
Previously these were silently discarded.

The TemplateCompiler uses a safeSetAttribute() helper to gracefully
skip invalid names encountered during HTML parsing.

Closes #76
Wrap the ob_start/require/ob_get_clean sequence in a try-catch block.
If the template throws, ob_end_clean() is called before re-throwing
the exception, preventing a permanently leaked output buffer.

Closes #59
Use a static closure to execute the template require, preventing
templates from accessing the TemplateCompiler instance via $this.
Also eliminates variable name collisions by using __ prefixed names
for internal variables.

Closes #62
Replace manual $rows and $cols counters with methods that read from
the actual DOM state. rows() returns childrenCount() and cols() returns
the first row's child count. This eliminates desync when rows are
added or removed via addRow() or inherited methods.

Closes #71
Extend the existing <?php escaping to also handle <?= (short echo)
and <? (short open tag) before splitting on <. This prevents
InvalidNodeNameException when these sequences appear in parsed text.

Closes #60
Copy attributes from parsed <html> and <body> elements to the
HTMLDoc instance in parseHTMLDoc(). Previously these attributes
(lang, dir, class, id, etc.) were silently discarded.

Closes #56
Change the script content extraction regex from a fixed lookbehind
(?<=<script>) to a capturing group <script[^>]*>(.*?)</script>.
This correctly handles script tags with attributes like type or src,
preventing their content from being corrupted by the HTML parser.

Closes #55
Replace restricted ASCII character class [\t-!#-~] in attribute value
regex with [^"]* (and [^']* for single quotes). This correctly
matches UTF-8 multibyte characters and prevents > inside quoted
attribute values from being interpreted as the tag closing delimiter.

Closes #58
Extract comment bodies that contain < into placeholders before the
explode('<', ...) split, preserving the <!-- --> wrapper so the parser
still recognizes them as comment nodes. Only comments with < are
replaced to avoid disrupting normal comment parsing.

Closes #63
Fix array_indentation rule in php_cs.php.dist (was passed empty array
instead of true). Run php-cs-fixer on all source files.
fix: resolve 10 bugs in HTMLNode, HTMLTable, and TemplateCompiler
Replace LinkedList (O(n) index access) with Vector (O(1) index access)
for the internal children list. This eliminates O(n²) patterns in
rendering, ID searches, and tag searches.

Benchmarks with 1000 children:
- toHTML(): 9x faster (134ms → 15ms)
- getChildByID(): 35x faster (239ms → 7ms)
- index-based loop: 363x faster (105ms → 0.3ms)

BREAKING CHANGE: children() now returns Vector instead of LinkedList.
Code that type-hints LinkedList for children() return must update.

Closes #66
perf!: replace LinkedList with Vector for child node storage
Add HtmlRenderer class with per-instance rendering configuration
(formatted, quoted, useForwardSlash). This eliminates shared mutable
static state in the rendering path, making it safe for concurrent use
in async contexts (Swoole, ReactPHP, RoadRunner).

The renderer can be used standalone:
  $renderer = new HtmlRenderer(formatted: true, quoted: true);
  echo $renderer->render($node);

Existing toHTML()/toXML() methods on HTMLNode remain unchanged for
backward compatibility.

100% test coverage on HtmlRenderer (92 lines, 11 methods).

Closes #64
Closes #61
refactor: extract rendering logic into dedicated HtmlRenderer class
Add three new static methods that wrap fromFile() with explicit return
types and fail-fast validation:

- fromFileAsDocument(): returns HTMLDoc, throws if not a full document
- fromFileAsNode(): returns HTMLNode, throws if multiple roots or empty
- fromFileAsArray(): returns array, always succeeds by normalizing

The existing fromFile() remains unchanged for backward compatibility.

Closes #65
feat(HTMLNode): add type-specific factory methods for template loading
Align README with the WebFiori ecosystem standard (webfiori/collections):
- Plain markdown headers (no emoji)
- Centered badges with PHP 8.1+ badge
- Table of Contents
- Supported PHP Versions table
- Key Features bullet list
- Quick Start with working example
- Testing, Contributing, License, Support, Changelog sections

Closes #54
Add self-contained, runnable examples following the webfiori/database
pattern (folder per example with README.md and example.php):

- 01-basic-document: Complete HTML5 document creation
- 02-elements-and-attributes: Chaining, styles, iteration
- 03-forms-and-input: Form building with various input types
- 04-tables: Table creation and dynamic columns
- 05-html-templates: Slot-based HTML templates
- 06-php-templates: PHP templates with logic
- 07-standalone-renderer: HtmlRenderer per-instance config
- 08-xml-output: XML generation
When an HTMLNode instance is passed as a slot value, render it as raw
HTML instead of escaping it. String values remain escaped via
htmlspecialchars() for XSS safety.

Usage:
  $badge = new HTMLNode('span', ['class' => 'badge']);
  $badge->text('New');
  $card = HTMLNode::fromFileAsNode('card.html', ['title' => $badge]);
docs: standardize README.md structure
@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.88476% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 98.48%. Comparing base (cf3dfe1) to head (a9833d5).
⚠️ Report is 30 commits behind head on main.

Files with missing lines Patch % Lines
WebFiori/Ui/TemplateCompiler.php 97.10% 2 Missing ⚠️
WebFiori/Ui/HTMLNode.php 98.55% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main      #83      +/-   ##
============================================
+ Coverage     98.44%   98.48%   +0.04%     
- Complexity      898      979      +81     
============================================
  Files             6        7       +1     
  Lines          1799     1981     +182     
============================================
+ Hits           1771     1951     +180     
- Misses           28       30       +2     
Flag Coverage Δ
php-8.1 98.48% <98.88%> (+0.04%) ⬆️
php-8.2 98.38% <98.86%> (+0.04%) ⬆️
php-8.3 98.38% <98.86%> (+0.04%) ⬆️
php-8.4 98.38% <98.86%> (+0.04%) ⬆️
php-8.5 97.62% <98.86%> (+0.12%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@usernane usernane merged commit 9ba3f2a into main Jun 10, 2026
9 checks passed
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant