Skip to content

chore(deps): update dependency akankov/html-min to v2.11.0 - #4

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/akankov-html-min-2.x-lockfile
Open

chore(deps): update dependency akankov/html-min to v2.11.0#4
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/akankov-html-min-2.x-lockfile

Conversation

@renovate

@renovate renovate Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
akankov/html-min 2.5.12.11.0 age confidence

Release Notes

akankov/html-min (akankov/html-min)

v2.11.0

Compare Source

Hardening release: a re-entrancy guard on the shared parser state and a
CPU-exhaustion cap on the opt-in keepBrokenHtml mode, plus supply-chain
tooling. The MinifierOptions constructor surface is unchanged and normal
minification is unaffected.

Added
  • Re-entrancy guard. Internal\HtmlParser keeps per-run placeholder state
    in static fields shared by every HtmlMin instance in the process. A nested
    minify() — e.g. from a setInlineCssMinifier() / setInlineJsMinifier()
    callback or a DOM observer — would reset that state mid-run and leave
    placeholder tokens in the output. Nesting now throws a LogicException, and
    the lock is released in a finally so a throwing callback cannot wedge a
    persistent worker (Octane / RoadRunner / Swoole). The misleading "static/pure"
    docblock is corrected accordingly.
  • Supply-chain tooling. Weekly Dependabot (composer + github-actions, with
    a 7-day new-release cooldown) and a non-blocking composer audit CI job.
Security
  • CPU-exhaustion cap on keepBrokenHtml. The broken-HTML rewrite is
    super-linear in input size, so large input could burn seconds of CPU. Input
    over 128 KB now skips the rewrite — the document is still minified, just
    without broken-HTML preservation — and logs a warning when a logger is
    attached. useKeepBrokenHtml() is now documented as trusted-input-only.

v2.10.0

Compare Source

Presets, a WHATWG omission audit, and docs. Default output gets a little
smaller (more optional end tags dropped) and a little more correct (structural
end tags are kept in front of preserved comments). No API breakage; the
MinifierOptions constructor surface is unchanged.

Added
  • MinifierOptions presets. MinifierOptions::aggressive() (maximum
    spec-valid byte savings: block-tag whitespace trimming, whitespace-only
    text-node removal, start-tag omission, spec-default attribute removal,
    inline CSS/JS minification — URL scheme stripping deliberately stays off)
    and MinifierOptions::conservative() (shape-preserving: keeps optional
    end tags, attribute quotes, attribute/class order, and empty attributes;
    only collapses whitespace, strips comments, and drops deprecated
    attributes). Both sit alongside the existing defaults(); a new README
    "Presets" section documents the trade-offs. The constructor surface is
    unchanged, so binding config keys are unaffected.
  • WHATWG omission audit: more optional end tags omitted. removeOmittedHtmlTags
    now also drops </option>/</optgroup> before an <hr> (the <select>
    separator addition), </rt> (previously only rp was handled; same
    followed-by-rt/rp-or-end rule), and </p> before the post-HTML4 block
    elements the spec lists (details, dialog, figcaption, figure,
    main, search). Smaller output; meaning unchanged.
  • Placeholder-nonce property tests. A 50-iteration sweep proves input that
    mimics the real nonce-bearing placeholder format round-trips verbatim, and
    the nonce itself is pinned: 10 lowercase hex chars, stable within a run,
    fresh on every HtmlParser::reset().
Fixed
  • html/head/body end tags are no longer omitted before a comment.
    Per WHATWG §13.1.2.4, omitting them there would pull the (preserved or
    conditional) comment inside the element on reparse — a real DOM change.
    Deliberate, documented deviation: the spec also blocks head omission
    before ASCII whitespace, but the reparse difference is a rendering-
    irrelevant whitespace node, and honoring it would keep </head> on
    virtually every real-world page — so whitespace does not block.

  • Mutation-testing droppings in the repo root. CliTest now runs each
    test from a scratch directory under the system temp dir. Under Infection,
    the TrueValue mutator on the --output= str_starts_with() check turned
    an input path /tmp/htmlminXYZ into a CWD-relative minXYZ via
    substr($arg, 9), so every make infection run left a 0-byte min* file
    in the repository root. The mutant was killed either way; the side effect
    now lands in the scratch dir instead. The /min* .gitignore entry that
    papered over this is gone.

v2.9.0

Compare Source

Completes the HTML5 tag-omission rule set and finishes decomposing the
minifier core. Default output gets a little smaller (more optional end tags
dropped); the more aggressive start-tag omission is opt-in. No API breakage.

Added
  • More optional end tags omitted. removeOmittedHtmlTags now also drops the
    end tags of <thead> (when followed by <tbody>/<tfoot>), <tbody> and
    <tfoot> (per the spec's "followed by / end of section" rules), and
    <caption>/<colgroup> (unless immediately followed by ASCII whitespace or a
    comment). Smaller table markup; well-formed output is unchanged in meaning.
  • Opt-in <html>/<head>/<body> start-tag omission. New
    removeOmittedHtmlStartTags option (MinifierOptions /
    doRemoveOmittedHtmlStartTags()), off by default, also omits the
    structural start tags where the HTML5 spec allows (never when the element
    has attributes). It is deliberately opt-in: far more aggressive than end-tag
    omission and, on an effectively-empty document, can reduce output to an empty
    string. Existing output is unchanged unless you enable it.
Changed
  • Internal: ProtectedContentManager extraction. The protected-content
    machinery (<nocompress>/<code> subtrees, inline <script>/<style>
    bodies, conditional / special comments) and its state — the saved-node map,
    counter, and placeholder token — move out of HtmlMin into a dedicated
    Internal\ProtectedContentManager. HtmlMin drops ~165 lines (1218 → 1053).
    No behaviour or API change.
  • Internal: OptionalTagOmission rule-dispatch refactor. The ~280-line
    conditional end-tag boolean is replaced by a per-tag dispatch with small,
    independently-readable rule helpers. No behaviour change — the per-tag truth
    table (quirks included, e.g. dt grouped with dd) is locked by new
    characterization tests in OptionalTagOmissionTest.

v2.8.1

Compare Source

Internal hardening of the libxml entity-preserving placeholder layer. No change
to public API or to the minified output of any input.

Changed
  • Per-run placeholder nonce. HtmlParser::reset() now regenerates the
    random placeholder nonce (and every cache derived from it) at the start of each
    minify() run instead of reusing one nonce for the whole process. This keeps the
    unguessable tokens from being reused across calls — defence-in-depth for
    long-lived / worker runtimes (Swoole, FrankenPHP, ReactPHP). All five
    nonce-derived caches are cleared together so masking and restoration never
    mismatch.
  • HtmlParser::$brokenHtmlMap is now private. It was public static but is
    only used internally; encapsulating it prevents external code from corrupting
    the cross-call replacement table.

v2.8.0

Compare Source

Test-effectiveness and parser-cleanup release. Mutation score is raised to
77.4% (line coverage stays 100%) by pinning the scoping of the
attribute-removal rules, and a redundant </html>-trim preprocessing step is
removed from the parser. The version is a minor bump rather than a patch
because that cleanup changes observable output for one class of malformed
input (multiple </html> markers) — well-formed documents are unaffected.
Released from PRs
#​35#​36.

Changed
  • Mutation score raised to ~77% (MSI 76.3% → 76.8%) by adding behavioral
    tests that pin the scoping of the deprecated/default-attribute removals —
    e.g. type=text/css is stripped only on rel=stylesheet links (not
    rel=preload), and value="" only on <input type=text> (not other input
    types). The Infection floor is ratcheted 74 → 75 to match (a ~1.75pp buffer is
    kept for timeout jitter). Audit note: the bulk of the remaining surviving
    mutants are genuinely equivalent — internal cache keys, performance
    short-circuits, (string) casts that never see null, and regex changes made
    unreachable by upstream stripos() guards — so they are intentionally not
    chased. No public API or runtime behaviour change.
  • Removed a redundant </html>-trim preprocessing step in HtmlParser::parse().
    libxml already pulls content after a closing </html> back into the body, so
    the explicit regex + str_replace was a no-op for every well-formed and
    single-</html> input (verified byte-identical on PHP 8.3/8.4/8.5). The only
    observable difference is on pathological input with multiple </html>
    markers (</html>mid</html>end), which now flattens to a single paragraph
    (<p>midend) instead of two — both are arbitrary handling of malformed HTML;
    the new behaviour is pinned by a characterization test. This also deletes a
    cluster of equivalent mutants and a confusing regex. (The sibling
    pre-<!DOCTYPE> junk strip was investigated too and is not redundant —
    libxml keeps element junk before the doctype — so it stays.)

v2.7.1

Compare Source

Test-hardening and robustness release. The library test suite now covers 100%
of lines
(up from ~93%) with the CI floors ratcheted to match, and two small
warning-suppression / dead-guard touches fell out of the coverage work. No
public API or runtime behaviour change. Released from PRs
#​31#​33.

Changed
  • HtmlParser::findAll() no longer leaks a PHP warning for an unsupported
    selector (e.g. a CSS class like .foo, which has no XPath translation). The
    malformed-query case already returned an empty array; the raw DOMXPath
    warning is now suppressed so it stays a clean empty result.
  • CLI input reading simplified. Cli::readInput() now relies on a single
    @file_get_contents() (which already reports missing / unreadable / directory
    paths via false) instead of a redundant is_file()/is_readable()
    pre-check. Behaviour is unchanged — same stderr message and exit code 1 on
    failure. Raw PHP warnings on I/O failure are suppressed (the clean stderr line
    is the signal).
  • Test suite now covers 100% of library lines (up from ~93%). Reaching the
    last few percent surfaced two small robustness touches (the findAll()
    warning suppression and the Cli read simplification above) and several
    defensive-guard simplifications; remaining unreachable type-guards were
    restructured rather than ignored. The CI floors are ratcheted to match:
    MIN_LINE_COVERAGE 90 → 100, and the Infection MSI / Covered-MSI floors
    72 → 74. No public API or runtime behaviour change.

v2.7.0

Compare Source

Extensibility and internal-architecture release. Every library class is now open
for subclassing, and the ~2,000-line HtmlMin god class is decomposed into five
focused Internal collaborators — all behaviour-preserving, no public API
change. Also fixes an adversarial-input placeholder collision and adds a
test-effectiveness toolchain (line-coverage gate + Infection mutation testing,
with Codecov and Stryker badges). Released from PRs
#​24#​29.

Fixed
  • Adversarial input that collides with internal placeholders no longer
    corrupts output.
    The parser masks libxml-hostile characters (&|+%@[]{})
    with placeholder tokens and reverses them after serialization; caller content
    that literally contained a token (e.g. ____HTMLMIN_AMP____) was rewritten by
    the restore pass (→ &). Placeholders now embed a per-process random nonce,
    so input cannot collide with them. Internal — entity/AMP/template round-trips
    are unchanged; only the obscure collision case is fixed.
Changed
  • Library classes are no longer final. Every class is now open for
    extension (final and the final readonly class form are removed throughout),
    since consumers of a library legitimately need to subclass. Value objects
    (MinifierOptions, Cli, MinifierMiddleware, DomSerializer) keep
    property-level readonly — they stay immutable but are freely
    subclassable (unlike a readonly class, which only accepts readonly
    subclasses). Rector's ReadOnlyClassRector is disabled to preserve this.
  • Decomposing the HtmlMin god class (2,023 → 1,220 lines so far), in
    behaviour-preserving slices:
    • HTML5 optional-end-tag rules — the 280-line domNodeClosingTagOptional()
      plus its tag lists and memo cache → Internal\OptionalTagOmission.
    • DOM → HTML5 serialization — domNodeToString() / attribute-string
      building / whitespace helpers → Internal\DomSerializer, which reads its
      flags through the existing HtmlMinInterface config contract.
    • Opt-in inline CSS/JS minification — the <style>/<script> coordination,
      pluggable-override storage, and bundled-minifier fallback →
      Internal\InlineContentMinifier.
    • Whitespace-collapsing passes — removeWhitespaceAroundTags() /
      sumUpWhitespace() and their tag tables → Internal\WhitespaceNormalizer
      (config-free static transforms; the toggles still gate them at the call site).
    • Doctype string building — getDoctype()Internal\Doctype::serialize(),
      sitting next to the Internal\DoctypeKind classifier.
      The protected getNextSiblingOfTypeDOMElement() and domNodeToString() are
      kept as delegating shims so existing subclasses do not break. Internal — no
      public surface change.
  • CI now measures test effectiveness. Added a coverage gate (line coverage
    floor, enforced via bin/coverage-check.php) and mutation testing with
    Infection (MSI floor). Both run in make ci and a new CI job, backed by a
    pcov Docker image (docker/coverage.Dockerfile). Dev-only — no change to the
    published package or its runtime dependencies.
  • Hardened the inline-minifier test assertions. Added boundary-exact
    characterization tests for the CSS/JS scanners (comment separation, url(
    lookahead, regex-vs-division at each character boundary, template
    interpolation). Test-only — no runtime behaviour change.
  • Hardened the attribute-removal test assertions. Added the negative
    complement of the default-attribute rules — near-misses (wrong value, or the
    right attribute on the wrong tag) that must be kept — plus the media/type
    CSS-default removals, pinning every rule's tag && attr && value conjunction.
    Test-only — no runtime behaviour change.
  • Data-driven default-attribute removals. Replaced the 13 repetitive
    if ($tag === … && $attrName === … && $attrValue === …) blocks in
    OptimizeAttributes with two declarative lookup tables. Behaviour is
    identical (guarded by the rule matrix above); ~50 lines of branching become a
    table plus two lookups. The mutation floor moves to 72% MSI — collapsing the
    if-chain removes ~90 thoroughly-killed mutants, which mechanically lowers the
    score even though the code is simpler. Internal — no public surface change.
  • Coverage and mutation badges. CI uploads line coverage to Codecov and the
    MSI to the Stryker Mutator dashboard; the README shows both badges. Reporting
    only — gated behind repository secrets and a no-op without them.

v2.6.1

Compare Source

Bug-fix release hardening the v2.6.0 bundled inline minifiers against three
edge cases that could corrupt output. All three are narrow but real; the
default-off toggles mean only opted-in callers were affected.

Fixed
  • Inline CSS: a literal ;} inside a string is no longer mangled. The
    trailing-semicolon optimisation ran as a blanket str_replace(';}', '}')
    over the whole output, reaching into verbatim-preserved strings — e.g.
    content:"x;}y" became content:"x}y". The ; is now deferred and dropped
    only when it is genuinely structural (immediately before }).
  • Inline JS: / after a postfix ++/-- is treated as division, not a
    regex.
    a++ / b was scanned as a regex literal, swallowing the rest of the
    line and suppressing whitespace collapse. a + /re/ remains a regex.
  • Inline JS: braces inside strings/nested templates within a ${…}
    interpolation no longer break template scanning.
    A construct like
    `${ obj["}"] }` previously miscounted interpolation depth, missed the
    closing backtick, and ran past the template. Strings and nested templates are
    now skipped while counting interpolation braces.

v2.6.0

Compare Source

Inline CSS and JS minification lands as an opt-in feature. The contents of
inline <style> and <script> blocks — previously passed through untouched —
can now be minified by bundled, zero-dependency, conservative minifiers, with
pluggable backends for aggressive tools. Both toggles default to off, so
existing output is unchanged. Released from PR
#​17.

Added
  • Inline CSS and JS minification (opt-in). Two new toggles minify the
    contents of inline <style> and <script> blocks, which previously
    round-tripped untouched:
    • HtmlMin::doMinifyInlineCss(bool $on = true) — strips CSS comments and
      collapses whitespace. String and url(...) contents are preserved.
    • HtmlMin::doMinifyInlineJs(bool $on = true) — conservative, ASI-safe
      minification: removes comments and collapses horizontal whitespace while
      preserving newlines, strings, regex literals, and template literals.
      <script> elements whose type is not a JavaScript type (e.g.
      application/ld+json, text/x-template) pass through untouched, as do
      <script src="..."> references.
    • Both default to off, so existing output is unchanged.
  • Pluggable minifier backends. HtmlMin::setInlineCssMinifier(?callable)
    and HtmlMin::setInlineJsMinifier(?callable) replace the bundled minifiers
    with any callable(string): string (e.g. wrap matthiasmullie/minify or
    shell out to terser). Pass null to restore the bundled default. A buggy
    bundled minifier is logged via the PSR-3 logger and falls back to the
    original source so the page is never corrupted.
  • MinifierOptions gains minifyInlineCss and minifyInlineJs fields
    (both default false).
  • CLI flags --minify-inline-css and --minify-inline-js.

Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate
renovate Bot force-pushed the renovate/akankov-html-min-2.x-lockfile branch from 3c128e7 to 5381c14 Compare May 29, 2026 17:27
@renovate renovate Bot changed the title chore(deps): update dependency akankov/html-min to v2.6.0 chore(deps): update dependency akankov/html-min to v2.6.1 May 29, 2026
@renovate
renovate Bot force-pushed the renovate/akankov-html-min-2.x-lockfile branch from 5381c14 to 6d312b3 Compare May 31, 2026 02:29
@renovate renovate Bot changed the title chore(deps): update dependency akankov/html-min to v2.6.1 chore(deps): update dependency akankov/html-min to v2.7.0 May 31, 2026
@renovate
renovate Bot force-pushed the renovate/akankov-html-min-2.x-lockfile branch from 6d312b3 to 86a3138 Compare May 31, 2026 17:58
@renovate renovate Bot changed the title chore(deps): update dependency akankov/html-min to v2.7.0 chore(deps): update dependency akankov/html-min to v2.8.0 May 31, 2026
@renovate
renovate Bot force-pushed the renovate/akankov-html-min-2.x-lockfile branch from 86a3138 to c118a13 Compare July 26, 2026 02:27
@renovate renovate Bot changed the title chore(deps): update dependency akankov/html-min to v2.8.0 chore(deps): update dependency akankov/html-min to v2.11.0 Jul 26, 2026
@renovate
renovate Bot force-pushed the renovate/akankov-html-min-2.x-lockfile branch from c118a13 to c6038b4 Compare August 7, 2026 03:47
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.

0 participants