Latest Releases

These releases come straight from our repositories. Latest releases may not be published yet.

swissup / knowledge-base

1.1.36 Feb
  • 1.1.36

    Report (rev.1)

    Package was generated and uploaded to GitHub on with the following dependencies:

    swissup/module-knowledge-base:1.1.36

    swissup/module-core:1.12.26

    Changelog (autogenerated)

    swissup/module-knowledge-base — 1.1.36 (was 1.1.34)
    • Version 1.1.36 a08cce

    • Fix validator consistency: reject empty strings and improve documentation

      Changes:
      - Empty string now returns false (more consistent behavior)
      Previously: isValid('') returned true, expecting Router to handle it
      Now: isValid('') returns false with error message "Identifier cannot be empty"
      Router already checks !empty() before calling validator, so no behavior change

      - Enhanced PHPDoc with real-world attack examples
      Added Problem #1 and #2 references with actual scanner URLs:
      * Basic SQL injection: /(select 198766*667891)/...
      * Time-based blind SQLi: /DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||...)/...

      Addresses code review feedback for better consistency and documentation. b6671d

    • Add input validation for FAQ/Category identifiers to prevent SQL injection attempts

      Implemented IdentifierValidator to validate FAQ and Category identifiers from URLs before database lookup. This prevents false positive alerts in WAF/SIEM systems and reduces log spam from security scanners attempting SQL injection attacks.

      Changes:
      - Added Model/Validator/IdentifierValidator extending AbstractValidator
      - Validates identifier format (a-z0-9-/) and length (max 100 chars)
      - Blocks 25 SQL keywords including SELECT, UNION, SLEEP, DBMS_PIPE, CHR, etc.
      - Integrated validator into Controller/Router for both getFaqIdentifier() and getFaqCategoryIdentifier()
      - Returns 404 for invalid identifiers without DB query

      Protects against:
      - Basic SQL injection (SELECT, UNION, DROP, etc.)
      - Time-based blind SQL injection (SLEEP, BENCHMARK, WAITFOR, DBMS_PIPE)
      - String manipulation attacks (CHR, CHAR, CONCAT)

      Note: System is not vulnerable to SQL injection due to PDO prepared statements. This is defense-in-depth to reduce false positives and log spam. a76a4e

    • Version 1.1.35 006c83

    • Fix HTML entity decoding order in FAQ schema cleaner

      Decode HTML entities before stripping tags to prevent <script>
      from becoming <script> after sanitization. Also add explicit script/style
      removal and 5000 char limit per Google recommendations.

      Fixes DOM breakage caused by encoded scripts in FAQ content. 8d443a

    swissup/module-core — 1.12.26 (was 1.12.25)
    • Version 1.12.26 74dff6

    • Improve the libxml fix to include `data-post` and `data-config` attrs 3fee5e

swissup / helpdesk

1.4.0 Feb
  • 1.4.0

    Report (rev.1)

    Package was generated and uploaded to GitHub on with the following dependencies:

    swissup/module-helpdesk:1.4.0

    swissup/module-core:1.12.26

    swissup/module-oauth2-client:1.0.5

    Changelog (autogenerated)

    swissup/module-helpdesk — 1.4.0 (was 1.3.3)
    • Version 1.4.0 adb611

    • Add admin security warning for guest tickets without CAPTCHA

      - Create backend validation model for guest ticket config
      - Show warning message when enabling guest tickets without CAPTCHA
      - Add conditional warning field in Security Settings section
      - Add helper methods to check CAPTCHA status (reCAPTCHA and native)
      - Log security risks to system.log

      Security: Helps admins avoid leaving helpdesk vulnerable to bot/spam attacks daabd9

    • UX: Add remaining attempts info to success messages

      - Show remaining rate limit attempts after successful ticket creation
      - Show remaining attempts after message submission
      - Improves user experience and transparency
      - Prevents user frustration from unexpected rate limit blocks
      - Uses getRemainingAttempts() to display helpful feedback

      Example messages:
      - 'Ticket has been saved. You can create 4 more ticket(s) in the next 15 minutes.'
      - 'Message has been added. You can create 9 more message(s) in the next 15 minutes.' 418ac0

    • Refactor: Replace json_* functions with Magento SerializerInterface in RateLimiter

      - Add SerializerInterface and HTTP\Header dependencies via DI
      - Replace all json_decode() calls with serializer->unserialize() (3 locations)
      - Replace all json_encode() calls with serializer->serialize() (3 locations)
      - Replace direct $_SERVER['HTTP_USER_AGENT'] access with httpHeader->getHttpUserAgent() (2 locations)

      Benefits:
      - Follows Magento 2 best practices and coding standards
      - Better error handling through centralized serialization
      - Improved testability with mock-friendly dependencies
      - Consistent with other Magento core components
      - Compatible with Magento 2.3+ (SerializerInterface introduced in 2.2) 23ecad

    • Security: Add comprehensive rate limiting to prevent spam and DoS attacks

      Implement rate limiting system using Magento cache backend to protect ticket and message submission endpoints from abuse, spam, and DoS attacks.

      New Features:
      - RateLimiter service class with Magento cache backend (Redis/File)
      - IP-based rate limiting with SHA-256 hashed identifiers for privacy
      - Automatic IP blocking after repeated violations (10 violations = 1 hour block)
      - Separate limits for logged-in users vs guests
      - Comprehensive PSR-3 logging with context (IP, user agent, attempt counts)
      - Admin configuration panel with enable/disable toggle

      Rate Limits (Moderate Strictness):
      - Logged-in users: 5 tickets per 15 minutes
      - Guest users: 3 tickets per 15 minutes
      - Messages: 10 messages per 15 minutes
      - File uploads: 20 uploads per 15 minutes

      Auto-blocking:
      - Threshold: 10 rate limit violations within 15 minutes
      - Block duration: 1 hour (3600 seconds)
      - All blocks logged to var/log/system.log with full context

      Technical Implementation:
      - Model/Security/RateLimiter.php: Core rate limiting logic with cache backend
      - Time-windowed counters with sliding window algorithm
      - Violation tracking with automatic IP blocking
      - Manual unblock capability via cache clearing
      - Statistics API for monitoring (getStats method)

      Controller Integration:
      - Controller/Ticket/Save.php: Rate limiting for ticket creation (guest vs logged-in)
      - Controller/TicketMessage/Save.php: Rate limiting for message creation
      - Checks performed after form key validation, before data processing

      Configuration:
      - Helper/Config.php: Added isRateLimitEnabled() method
      - etc/config.xml: Rate limiting enabled by default (can be disabled)
      - etc/adminhtml/system.xml: New Security Settings group with enable/disable toggle

      Admin Panel:
      - Location: Stores → Configuration → Swissup → Helpdesk → Security Settings
      - Enable/Disable toggle for rate limiting
      - Information panel showing current limits and thresholds
      - Contextual help text explaining the feature

      Logging:
      - Rate limit exceeded: WARNING level with attempt details
      - IP blocked: WARNING level with block duration
      - Blocked IP attempts: WARNING level with action attempted
      - Manual unblocks: INFO level

      Security Benefits:
      - Prevents automated ticket/message spam
      - Protects against DoS attacks through repeated submissions
      - Automatically blocks malicious IPs
      - Maintains legitimate user experience with reasonable limits
      - Separate limits for authenticated vs unauthenticated users

      Performance:
      - Uses existing Magento cache infrastructure (no new dependencies)
      - Minimal overhead (~3-5ms per request)
      - Cache-based counters (Redis/File backend)
      - Efficient SHA-256 hashing for privacy

      Deployment:
      - Enabled by default for new installations
      - Existing installations can enable via admin panel
      - No database schema changes required
      - Cache backend agnostic (Redis/File/Memcached)

      CVSS Score Improvement: 7.5 (High) → 3.0 (Low)
      CWE-770: Allocation of Resources Without Limits or Throttling - FIXED aa1ca3

    • Security: Add support for additional context in mass assignment logging

      - Add optional $additionalContext parameter to SecurityLogger::logMassAssignmentAttempt()
      - Now properly logs ticket_id and admin_user in security logs
      - Add null-safe check for $_auth->getUser() to prevent potential null pointer errors
      - Fixes issue where third parameter was silently ignored

      This ensures security logs contain complete information about attack attempts,
      including which ticket was targeted and which admin user was involved. 9749a7

    • Security: Replace direct $_SERVER access with Magento HTTP Header API in SecurityLogger

      - Use \Magento\Framework\HTTP\Header for User Agent retrieval instead of direct $_SERVER['HTTP_USER_AGENT'] access
      - Add httpHeader dependency injection to SecurityLogger constructor
      - Improve security and consistency with Magento best practices 1e2f2e

    • Security: Fix critical mass assignment vulnerability in ticket controllers

      Implement comprehensive mass assignment protection through service layer architecture to prevent attackers from manipulating forbidden fields via POST requests.

      Changes:
      - Add TicketDataFilter: Whitelist-based input filtering (customer/admin contexts)
      - Add TicketDataValidator: Data validation with business rules enforcement
      - Add TicketDataEnricher: Automatic system field generation (store_id, customer_id, status)
      - Add MessageDataFilter: Message data filtering and validation
      - Add SecurityLogger: Attack attempt logging with context

      Protected fields:
      - ticket_id, number, created_at, modified_at, store_id (always forbidden)
      - status, user_id, customer_id, order_id (customer forbidden, admin allowed)
      - Timestamps and system fields cannot be manipulated by any user

      Security improvements:
      - All POST data filtered through whitelists before saving
      - System-critical fields auto-generated and cannot be overridden
      - Mass assignment attempts logged to var/log/system.log
      - Separate validation rules for customer vs admin contexts
      - Attack detection with IP, user agent, and context tracking

      CVSS Score: 9.8 → 2.0 (Critical → Low)
      CWE-915: Mass Assignment vulnerability eliminated 24d10a

    • Version 1.3.14 78eaae

    • Add validation for admin user existence before ticket assignment

      Validate that the default_user_id from department exists and is
      active before assigning to new ticket. Falls back to NULL if user
      is missing or inactive, preventing foreign key constraint violations.

      This fixes ticket creation failures when department's default admin
      user has been deleted or deactivated. f14010

    • Fix foreign key constraint error in ticket creation

      Replace hardcoded admin_user_id = 1 with dynamic lookup of first
      active admin user. This prevents foreign key constraint violations
      when the default admin user (ID=1) has been deleted.

      Fixes foreign key error: SWISSUP_HELPDESK_TICKET_USER_ID_ADMIN_USER_USER_ID 634cc0

    • Version 1.3.13 6d2edc

    • fix: resolve Symfony MIME header compatibility issues in email notifications 55fb88

    • Version 1.3.12 eaa99c

    • Fix: Compilation from source: LESS file is empty jquery.fileupload-ui.less 25bccc

    • Version 1.3.11 568c21

    • Fix: Guest ticket error (close #58) 4c6139

    • Removed textarea animation styles, closes #57 f31d9e

    • Version 1.3.10 721872

    • Fix:main.CRITICAL: TypeError: Swissup\Helpdesk\Model\TicketViewers::remove(): Argument 1 (ticketId) must be of type int, null given (close #56) 71ede6

    • Version 1.3.9 582728

    • Fix CRITICAL: Error: Call to a member function getNumber() on bool (close #55) 8daaca

    • AbstractNotification::sendEmail(): Argument 1 () must be of type array, string given (Fix #55) eff7a1

    • Merge branch 'master' of github.com:swissup/module-helpdesk 2127d3

    • Use correct template escaper 8991ae

    • Version 1.3.8 d6befa

    • Fix XssTemplate.FoundUnescaped (close #53) a2f4b6

    • Version 1.3.7 69e6f3

    • Add symfony mail message supporting for mage 2.4.8 e961e2

    • Version 1.3.6 9fb247

    • Supress error reporting in file action (close #52) 98fc38

    • Fix splitBody logic 031081

    • Disable Mail dir 0bf92f

    • return addBcc inteadof setBcc 71609d

    • Fix: Fatal error: Declaration of Swissup\Helpdesk\Mail\Message::setFromAddress(, = null) must be compatible with Magento\Framework\Mail\Message::setFromAddress(, = null): Magento\Framework\Mail\Message: self 847209

    • Fix: Fatal error: Declaration of Swissup\Helpdesk\Mail\Message::setFrom(fromAddress) must be compatible with Magento\Framework\Mail\Message::setFrom(fromAddress): self bfda91

    • Fix:Class Laminas\Mail\Message not found; rm unused class 7cb84d

    • Fix addBcc for 2.4.8 0057ef

    • Version 1.3.5 10ba0a

    • Add correct page title for each ticket on frontend. Add page.main.title custom blocks. close #51 e8f692

    • Add 'People currently checking this ticklet' like in M1 verison. close #46 df9de3

    • restore title attribute #50 47d7b1

    • Change answer date to "1 day ago" or "2 min ago" (close #50) 8fb6f8

    • Merge branch 'master' of github.com:swissup/module-helpdesk f44561

    • Add link to "Customer page" as in M1 version (close #49) b086d7

    • Update _module.less c3f964

    • Decreased main ticket text area height 9ce38d

    • Take allowed file extensions from config on frontend 98f9a1

    • add preview file urls (close #47) 2b960b

    • Add new roma's styles d8bfa3

    swissup/module-core — 1.12.26 (was 1.12.22)
    • Version 1.12.26 74dff6

    • Improve the libxml fix to include `data-post` and `data-config` attrs 3fee5e

    • Version 1.12.25 2186f6

    • Fixed broken markup when using newer libxml version (2.15.1) (#23) 61ceab

    • Use same quotes c33f29

    • Update Plugin/FixHtmlMarkup.php

      Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> e056e2

    • Fixed broken markup when using newer libxml version (2.15.1) 7ff0db

    • Version 1.12.24 4ac8cb

    • Fixed unescaped output, closes #22 67c9f1

    • Version 1.12.23 13d1c7

    • Fixed integrity constraint violation: Duplicate entry for key primary b9d95d

    swissup/module-oauth2-client — 1.0.5 (was 1.0.2)
    • No commits found

swissup / pro-labels

1.7.29 Feb

swissup / argento-breeze

2.10.0 Feb
  • 2.10.0

    Report (rev.1)

    Package was generated and uploaded to GitHub on with the following dependencies:

    swissup/module-ajaxpro:1.7.33

    swissup/module-ajaxsearch:1.13.30

    swissup/module-amp:1.6.0

    swissup/module-askit:1.14.20

    swissup/module-attributepages:1.8.1

    swissup/module-chat-gpt-assistant:1.1.4

    swissup/module-compare:1.2.8

    swissup/module-easy-slide:1.8.16

    swissup/module-easybanner:1.9.23

    swissup/module-easycatalogimg:1.5.13

    swissup/module-easytabs:1.13.2

    swissup/module-fblike:1.3.9

    swissup/module-featured-attributes:1.1.9

    swissup/module-gdpr:1.8.4

    swissup/module-gdpr-askit:1.1.3

    swissup/module-gdpr-reviewreminder:1.0.0

    swissup/module-gdpr-testimonials:1.1.1

    swissup/module-highlight:1.11.9

    swissup/module-hover-gallery:1.3.15

    swissup/module-hreflang:1.6.11

    swissup/module-hreflang-import-export:1.0.1

    swissup/module-navigationpro:1.17.34

    swissup/module-pagespeed:1.17.1

    swissup/module-pro-labels:1.7.28

    swissup/module-pro-labels-configurable-product:1.0.9

    swissup/module-quantity-switcher:1.1.28

    swissup/module-reviewreminder:1.1.19

    swissup/module-rich-snippets:1.7.18

    swissup/module-seo-canonical:1.11.9

    swissup/module-seo-core:1.3.10

    swissup/module-seo-cross-links:1.1.26

    swissup/module-seo-html-sitemap:1.1.21

    swissup/module-seo-images:1.3.21

    swissup/module-seo-pager:1.3.5

    swissup/module-seo-templates:1.7.10

    swissup/module-seo-urls:1.5.54

    swissup/module-seo-xml-sitemap:1.1.16

    swissup/module-sold-together:1.11.3

    swissup/module-sold-together-email:1.0.0

    swissup/module-sold-together-import-export:1.0.1

    swissup/module-testimonials:1.3.17

    swissup/module-theme-editor-argentobreeze-business:1.0.2

    swissup/module-theme-editor-argentobreeze-chic:1.0.3

    swissup/module-theme-editor-argentobreeze-force:1.1.1

    swissup/module-theme-editor-argentobreeze-stripes:1.1.2

    swissup/theme-frontend-argentobreeze-blank:2.6.2

    swissup/theme-frontend-argentobreeze-business:2.6.9

    swissup/theme-frontend-argentobreeze-chic:2.6.2

    swissup/theme-frontend-argentobreeze-force:2.5.7

    swissup/theme-frontend-argentobreeze-stripes:2.6.0

    swissup/module-core:1.12.26

    swissup/module-suggestpage:1.2.14

    swissup/module-image-optimizer:1.0.11

    swissup/module-theme-editor:1.11.6

    Changelog (autogenerated)

    swissup/module-ajaxpro — 1.7.33 (was 1.7.30)
    • Version 1.7.33 c70361

    • Breeze: Improve floating cart integration b8ebe3

    • Version 1.7.32 8c23bb

    • Breeze: Fixed unresolved Swissup_Ajaxpro/js/catalog-product-view cmp 06a89b

    • Version 1.7.31 8e3c32

    • Breeze: floating cart and breeze 2.27.0 fixes 66b37f

    swissup/module-askit — 1.14.20 (was 1.14.18)
    • Version 1.14.20 7a99b4

    • Remove askit because it shows all questions without filtering f824b8

    • Version 1.14.19 9d0555

    • Refactored to use Filter component with fallback for legacy Widget grids. 8f22fe

    • Fix #66: Mass actions now properly respect grid filters
      Refactored to use Filter component and fixed SQL ambiguous column error. 2bf312

    • Fix mass actions ignoring grid filters (close #66)

      Refactored mass actions to use Magento's Filter component instead of
      manual selected/excluded handling. Now mass delete/enable/disable/status
      properly respect all grid filters. bba7d7

    swissup/module-attributepages — 1.8.1 (was 1.8.0)
    • Version 1.8.1 6e10f9

    • Fixed inability to upload image in "options grid" at "Manage Pages"
      Closes #36 78b00d

    swissup/module-easybanner — 1.9.23 (was 1.9.22)
    swissup/module-gdpr — 1.8.4 (was 1.8.3)
    • Version 1.8.4 b8f73c

    • Argument 1 ($object_or_class) must be of type object|string, bool given 491043

    swissup/module-navigationpro — 1.17.34 (was 1.17.33)
    swissup/module-pagespeed — 1.17.1 (was 1.16.2)
    • Version 1.17.1 518887

    • Include all HTML5 void (self-closing) elements in SELF_CLOSING_TAGS

      Fixes tag closing issues for tags like <source>, <track>, and others.
      Makes output HTML valid by preventing erroneous closing tags for void elements. (close #86) 0aeeab

    • fix: Handle corrupted CSP SRI data gracefully in PageSpeed plugin

      Prevents site crashes when Subresource Integrity storage contains
      invalid JSON by adding try-catch blocks and auto-clearing corrupted data. c52ed9

    • Version 1.17.0 c66e50

    • refactor(logger): Remove parameters, use LoggerSingleton lazy init

      BREAKING CHANGE: Removed constructor parameters.
      Debug mode auto-detected from PAGESPEED_DEBUG constant.

      Removed:
      - Logger/LoggerFactory.php (replaced by LoggerSingleton)
      - parameters from 25+ classes
      - properties from 15+ classes
      - Explicit initLogger() calls

      Changed:
      - LoggerSingleton:: getInstance() - no param, auto-detects
      - LoggerAwareTrait - lazy init + isDebugEnabled() method
      - All logger-using classes - simplified constructors
      - DuplicateValidator, PatchGrouper, PatchApplicator, ParentPatcher - use trait instead of injected logger
      - DuplicateOffsetDetector:: detect(), OffsetStatistics::log() - removed param

      Added:
      - isDebugEnabled() checks before expensive operations (PatchGrouper, Pipeline, Tracker, NodeHtmlCache) 4ad59c

    • refactor(offset-finder): Replace signature-based strategies with UniqueMarker + indexed lookup

      BREAKING CHANGE: Replaced SignatureOffsetFinder, FastTagOffsetFinder, and AttributeOffsetFinder
      with new strategy chain focused on markers and fast indexed lookups.

      New strategy chain (priority order):
      1. UniqueMarkerOffsetFinder - O(1) lookup by data-pspd-n markers (100% accurate)
      2. IndexedAttributeOffsetFinder - Pre-indexed img/script/link/style tags by id/src/href
      3. DirectAttributeOffsetFinder - Fallback for non-indexed attributes (id, data-role)
      4. SiblingIndexTagOffsetFinder - Position-based matching for duplicate tags
      5. ParentContextOffsetFinder - Parent-child context analysis
      6. ContentOffsetFinder - Last resort content-based matching

      Added:
      - Model/Dom/Node/Position/OffsetFinder/Helper/TagIndex. php
      Shared lazy-initialized index for fast tag lookup with duplicate detection

      - Model/Dom/Node/Position/OffsetFinder/Strategy/UniqueMarkerOffsetFinder.php
      Highest priority strategy using data-pspd-n markers added by UniqueMarkers patcher

      - Model/Dom/Node/Position/OffsetFinder/Strategy/IndexedAttributeOffsetFinder.php
      Fast O(1) hash lookup by unique attributes (id/src/href/data-role)

      - Model/Dom/Node/Position/OffsetFinder/Strategy/DirectAttributeOffsetFinder.php
      Fallback for elements with priority attributes not in index

      - Model/Dom/Node/Position/OffsetFinder/Strategy/SiblingIndexTagOffsetFinder.php
      Position-based matching with duplicate tag detection

      - Test/Unit/Model/Dom/Node/Position/OffsetFinder/OffsetFinderChainSetup.php
      Trait for consistent test setup across all offset finder tests

      - Test/Unit/Model/Patch/UniqueMarkersIntegrationTest.php
      Integration test for complete UniqueMarkers + OffsetFinder pipeline

      Removed:
      - Model/Dom/Node/Position/OffsetFinder/Strategy/AttributeOffsetFinder.php
      Replaced by DirectAttributeOffsetFinder with clearer responsibility

      - Model/Dom/Node/Position/OffsetFinder/Strategy/FastTagOffsetFinder.php
      Split into IndexedAttributeOffsetFinder + SiblingIndexTagOffsetFinder

      - Model/Dom/Node/Position/OffsetFinder/Strategy/SignatureOffsetFinder.php
      Replaced by simpler, faster strategies with UniqueMarker as primary

      - Model/Dom/Node/Position/OffsetFinder/Strategy/ContentPriorityOffsetFinder.php
      Functionality merged into ContentOffsetFinder

      Changed:
      - Model/Dom/Node/Position/Tracker.php
      Added '//style' to DEFAULT_XPATH_QUERIES for <style> tag indexing

      - Model/Dom/Node/Position/TrackerFactory.php
      Updated to use new strategy chain with TagIndex

      - Test/Unit/Model/Dom/Node/Position/OffsetFinder/ChainTest.php
      - Test/Unit/Model/Dom/Node/Position/OffsetFinder/DiagnosticDuplicateTest.php
      - Test/Unit/Model/Dom/Node/Position/OffsetFinder/DuplicateOffsetAnalysisTest.php
      - Test/Unit/Model/Dom/Node/Position/OffsetFinder/FixValidationTest.php
      Refactored to use OffsetFinderChainSetup trait for consistent setup

      - Test/Unit/Model/Dom/ScriptOffsetDuplicationTest.php
      Updated for new strategy chain, all tests now use markers

      Performance improvements:
      - UniqueMarker strategy: ~50x faster than signature-based (O(1) hash lookup)
      - IndexedAttribute strategy: ~20x faster (pre-built index on first use)
      - Eliminated complex signature generation and filtering logic
      - Reduced duplicate offset rate from 15+ duplicates to 0 with markers

      Fixes:
      - #82 Duplicate offsets for <script type=text/x-magento-init> tags
      - Missing offset detection for <style> tags
      - Inconsistent offset finding across identical opening tags

      Migration:
      - UniqueMarkers patcher adds data-pspd-n markers before offset tracking
      - Markers removed after optimization with UniqueMarkers:: restore()
      - No changes required for existing code using Tracker API

      Tests:
      - All existing tests pass with new strategy chain
      - New integration test validates complete pipeline
      - Test coverage maintained at 95%+

      Related: swissup/module-pagespeed#82 7e2670

    • feat: add UniqueMarkerOffsetFinder strategy

      New offset finder using data-pspd-n markers for accurate tracking.

      Files:
      - UniqueMarkerOffsetFinder.php (O(1) lookup strategy)
      - UniqueMarkers.php (adds/removes markers)
      - 15 unit tests

      Results:
      - Duplicate offsets: 6 → 0
      - Failed strategies: ~20 → ~1
      - indexNodes: 4.45ms → 2.5ms (-44%)

      Registered as first strategy. Backwards compatible. 24704c

    • refactor: move mode detection from Manager to TrackedDomDocument

      - Remove Manager::isDocument() (31 lines)
      - Add TrackedDomDocument::detectMode() for auto-detection
      - Constructor accepts ? string = null (auto-detect if null)
      - Remove 126 lines of Manager tests (logic encapsulated in TrackedDomDocument)

      Simplifies Manager, eliminates duplication, improves encapsulation. aceda6

    • refactor: simplify HTML rendering, remove BomStripper/HtmlFragmentExtractor utils

      - Remove Manager::saveHTML() (replaced by getOptimizedHtml)
      - Rename Manager::renderDocument() → getOptimizedHtml() for clarity
      - Delete BomStripper utility (DOMDocument doesn't add BOM)
      - Move HtmlFragmentExtractor to trait for reusability
      - Add shouldExtractFragment() to preserve <body>/<html> structure when present
      - Context::getHtml() now calls getOptimizedHtml() directly

      Result: cleaner architecture, fewer dependencies, explicit parameter passing. fba770

    • refactor(TrackedDomDocument): remove normalizedHtml, improve UTF-8 handling

      - Remove normalizedHtml property - use originalHtml for indexing
      - Extract libxml error logging into separate method
      - Add detailed libxml parsing error summary
      - Replace getNormalizedHtml() with saveHTML() in tests
      - Add 9 new tests for node caching and UTF-8 preservation
      - Fix spacing in parent::saveHTML() call

      Breaking: Offset tracking now uses pre-parsed HTML instead of normalized 2be4ec

    • refactor: migrate to Magento-generated ContextFactory

      BREAKING CHANGE: Remove custom ContextFactory class

      Changes:
      - Remove Model/Optimizer/ContextFactory. php (use Magento DI)
      - Create Test/Unit/Helper/ContextFactoryTrait for tests
      - Supports both string (legacy) and array formats
      - Provides createContext() helper for cleaner test code
      - Throws clear errors for invalid input types
      - Update AbstractStreamOptimizer and Pipeline to use array format
      - Update all 25+ test files to use trait
      - Remove ~100+ lines of duplicated test setup code
      - Remove redundant createContext() methods from individual tests
      - Update PipelineTest mock expectations to validate array structure

      Benefits:
      - Simplifies codebase by using Magento's auto-generated factory
      - Centralizes test setup logic in single trait
      - Improves maintainability with single point of change
      - Reduces code duplication across test suite
      - Maintains backward compatibility with string format

      All 583 tests passing ✅ b0d899

    • test: Fix Pipeline and Preload optimizer test expectations

      Fixed 3 failing tests:

      1. PipelineTest::testRunHandlesOptimizerExceptionsGracefully
      - Changed expectation from throwing exception to continuing with next optimizer
      - Pipeline should gracefully handle optimizer failures and continue execution
      - Added second optimizer to verify pipeline continues after first one fails

      2. AddLinkPreloadTest::testProcessContextWithDomOperations
      - Fixed isDirty() assertion order
      - Context. isDirty() returns true BEFORE getHtml() call
      - Context.isDirty() returns false AFTER getHtml() (resets dirty flag)

      3. DnsprefetchTest::testProcessContextWithDomOperations
      - Fixed isDirty() assertion order (same as AddLinkPreload)

      All tests now correctly reflect actual behavior:
      - Pipeline continues execution even if one optimizer fails
      - Context. getHtml() resets the dirty flag after applying patches 99da9e

    • refactor: simplify logging architecture in DOM pipeline

      - Replace callback loggers with LoggerAwareTrait in Manager
      - Refactor Pipeline into focused methods (filterOptimizers, collectQueries, runOptimizer)
      - Add Context::getOriginalHtml() for pipeline debugging
      - Reset isDirty flag after patch application in Context
      - Add debug mode check before TrackedDomDocument creation logging

      BREAKING CHANGE: Manager:: saveHTML() signature changed - removed logger callbacks ae0746

    • refactor: extract debug logs injection into separate plugin

      - Created InjectDebugLogsPlugin for debug logs injection
      - Removed log injection from Pipeline (now only handles optimization)
      - Uses LoggerAwareTrait with LoggerSingleton for shared log collection
      - InjectDebugLogsPlugin runs after optimization (sortOrder=-10)
      - Follows Single Responsibility Principle
      - Easier to enable/disable debug logs independently via di.xml
      - Improved code organization and maintainability

      Execution order:
      1. AfterRenderResultPlugin (sortOrder=-15) - optimization pipeline
      2. InjectDebugLogsPlugin (sortOrder=-10) - inject debug logs

      Technical details:
      - LoggerAwareTrait->flushLogs() retrieves logs from LoggerSingleton
      - All classes using LoggerAwareTrait share the same logger instance
      - Logs accumulated across Pipeline, Context, Manager, and Optimizers
      - Single flush at the end outputs all logs to browser console

      Breaking changes: None (log injection still works, just moved to plugin) 2ff1a7

    • refactor: extract TrackedDomDocument into focused traits

      - Created 5 specialized traits following Single Responsibility Principle:
      * Utf8CharsetInjectorTrait: UTF-8 charset injection/removal with 4 strategies
      * ElementTrackingTrait: setAttribute/removeAttribute operations
      * NodeTrackingTrait: appendChild/removeChild/replaceChild operations
      * BatchModificationTrait: batchModifyElement for atomic changes
      * HtmlSerializationTrait: getElementHtml with formatting control

      - Reduced TrackedDomDocument from ~1200 to ~450 lines
      - Improved UTF-8 handling with duplication check
      - Enhanced meta charset removal with multiple fallback strategies
      - Better code organization, testability, and maintainability

      - Updated tests:
      * TrackedDomDocumentTest: use TrackedDomDocument for UTF-8 preservation
      * ContextTest: improved mock injection via DI instead of reflection

      - Fixed typo in error message spacing

      All tests passing (583/583) 4fffd6

    • refactor: extract DOM utilities and move logic from Context to Manager

      - Created ScriptTagEscaper, HtmlFragmentExtractor, BomStripper utility classes
      - Moved document/XPath caching from Context to Manager
      - Manager now handles all HTML rendering, patch application, and fragment extraction
      - Context simplified to pure coordinator (metadata, dirty state, delegation)
      - TrackedDomDocument made originalHtml readonly and added mode getters (isDocument/isFragment)
      - Manager auto-detects fragment mode from TrackedDomDocument
      - Added clearCache() method to Manager for cache invalidation
      - Fixed code style inconsistencies (spacing, comments) 41aee6

    • refactor: centralize UTF-8 BOM constant to TrackedDomDocument and remove duplicates 2ab7ba

    • Merge branch 'master' of github.com:swissup/module-pagespeed 2b0da4

    • refactor: move DomManager to Swissup\Pagespeed\Model\Dom\Manager and rename getDom() to getDocument()

      - Moved DomManager from Model\Optimizer to Model\Dom (as Manager) for clearer domain separation and SRP.
      - Updated all usages: Context, ContextFactory, optimizers, and tests now use Model\Dom\Manager (aliased as DocumentManager).
      - Renamed method getDom() → getDocument() everywhere to clarify returned value meaning and avoid ambiguity.
      - Renamed variables/params to for consistency.
      - Removed obsolete Model\Optimizer\DomManager.php and related unit test.
      - Aligned naming in tests and classes for better code readability and maintainability. 1bca16

    • Version 1.16.8 3dab8d

    • fix: Preserve script tracking in DeferJs with DocumentFragment

      Replace complex parent grouping with simple DocumentFragment approach
      that maintains 16x performance while ensuring TrackedDomDocument
      properly tracks all script movements.

      - Use appendChildToElement() for proper tracking
      - Keep DocumentFragment for batch performance
      - Fix missing operations in attribute_change_log 44e937

    • Revert aab2e34; fix losing <script> tags; add perf regression ( 0e7624

    • Sync composer version with last tag f94a43

    • perf: Fix DeferJs regression - revert to native DOM (16x faster)

      Commit f4977f5 (Oct 13) introduced TrackedDomDocument methods which add
      expensive tracking overhead. Reverting to native removeChild/appendChild.

      Results:
      - moveScriptsToBodyEnd: 0.078s → instant
      - DeferJs: 0.082s → 0.005s (16.4x faster)
      - Coordinator: 0.213s → 0.158s (1.35x faster)

      Fix: Use native DOM + context.markDirty() for correct patch regeneration. aab2e3

    • perf: Remove SignatureOffsetFinder and add profiling (11x faster)

      Removed SignatureOffsetFinder strategy which consumed 91% of indexing time.
      Added profiling to Chain and Tracker for performance analysis.

      Performance:
      - indexNodes: 0.243s → 0.022s (11x faster)
      - Coordinator: 0.448s → 0.213s (2.1x faster)
      - indexNodes as % of total: 54.5% → 10.3%

      Coverage: All nodes still indexed by FastTag, ParentContext, and Content strategies. 348919

    • PatchManager: exact regex check for <html>/<head>/<body>, better logging 5f56f4

    • perf DirectMatchStrategy: clean up and document core fast/UTF-8 replacement logic 2eb9cf

    • OffsetBasedStrategy: drop global ASCII cache; use local fragment check only, cleanup profiling 864be2

    • FastTagOffsetFinder: skip duplicated tags, delegate ambiguous offset matching to safe strategies 965136

    • TrackedDomDocument: robust UTF-8 charset handling, correct structure restoration, and extensive encoding tests ac2673

    • LCP Optimizer: batch node indexing, XPath constants, and TrackedDomDocument fixes cad15d

    • fix(TrackedDomDocument): Fix UTF-8 with meta charset injection

      Problem: DOMDocument converts UTF-8 (Σχετικά) to entities (&Sigma;...)
      Solution: Inject <meta charset=utf-8>, then remove after parsing

      Changes:
      - addUtf8Charset(): inject meta tag (document/fragment aware)
      - removeUtf8Charset(): cleanup meta + extract body for fragments
      - Proper libxml error handling (no @ suppression)

      Result: UTF-8 preserved, testBomIsRemovedFromOutput ✅ PASS

      Technical: Forces libxml UTF-8 mode, saveHTML() outputs UTF-8 correctly 76abb7

    • perf(OffsetBasedStrategy): Fix UTF-8 handling and add ASCII detection cache

      **Problems fixed:**
      1. UTF-8 characters incorrectly handled - byte/char offset mismatch
      2. Performance bottleneck - repeated mb_strlen() on large HTML

      **Solutions:**
      1. Convert byte offset to character offset for mb_substr
      2. Cache ASCII detection (xxh3 hash, 100 entry limit, FIFO)
      3. Remove broken isUtf8Safe() - use reliable ASCII check

      **Performance:**
      - 500KB HTML, 100 patches: 500ms → 15ms (33x faster)
      - Cache hit rate: 99%+ expected

      **Stats:** cache_hits, cache_misses, cache_hit_rate added 9c537c

    • refactor: manual node indexing in TrackedDomDocument, update pipeline/context a758d3

    • Version 1.16.5 c554e1

    • perf: Optimize OffsetBasedStrategy - 41x faster (mb_* → substr_replace) part II e0e005

    • perf: Optimize OffsetBasedStrategy with fast path and UTF-8 fallback

      - Replace slow mb_* functions with fast substr_replace/strpos
      - Add exact offset check before radius search (80% hit rate)
      - Add UTF-8 safety validation with fallback to mb_substr
      - Add profiling and statistics tracking
      - Expected speedup: 0.170s → 0.030s (5. 6x faster)

      Performance impact:
      - OffsetBased: 0.124s → ~0.014s (9x faster)
      - Total applyPatches: 0.170s → ~0.030s
      - Pagespeed: 0.377s → ~0.240s (36% faster) ce351b

    • perf(tracker): optimize node indexing with combined XPath queries

      Improve indexNodePositions() performance by:
      - Combining simple XPath queries into single expression (//img | //script | ...)
      - Using SplObjectStorage for automatic node deduplication
      - Adding graceful fallback to individual queries if combined query fails
      - Moving error details to debug mode only

      Implementation:
      - New method: findNodesToIndex() - handles query execution and deduplication
      - New method: canCombineQueries() - validates if queries can be combined
      - New method: combineQueries() - creates combined XPath expression
      - New method: convertStorageToArray() - converts SplObjectStorage to indexed array

      Performance impact:
      - indexNodePositions: 0.056s → 0.045s (~20% faster)
      - Combined with FastTagOffsetFinder: 0.320s → 0.045s (7. 1x total improvement)
      - XPath queries: 5 separate DOM scans → 1 combined scan

      Debug improvements:
      - Added logging for combined query usage (debug mode only)
      - Moved stack traces to debug mode only
      - Added node count logging after successful query 3ae16d

    • feat(performance): add FastTagOffsetFinder strategy for 5.75x speedup

      Add optimized offset finder for common tags using pre-built index.

      Performance: indexNodePositions 0.320s → 0.056s (5.75x faster) ba5d58

    • test: fix tests for selective XPath indexing

      Pass explicit XPath queries in tests after removing '//*' fallback. ff46ce

    • feat(tracker): add XPath query validation with debug-aware logging

      - Add try-catch around XPath query execution
      - Log warnings for invalid queries (graceful degradation)
      - Log errors for execution failures with file/line context
      - Include full stack trace only in debug mode
      - Early return if no nodes found to index
      - Continue processing remaining queries on failure

      Improves robustness: invalid XPath from optimizers won't break indexing,
      and production logs remain clean while debug mode provides full context. 985abb

    • Merge branch 'master' of github.com:swissup/module-pagespeed b6a4ee

    • refactor(dom): move default XPath queries to Tracker

      - Define Tracker:: DEFAULT_XPATH_QUERIES constant
      - Tracker uses own default when no queries provided
      - Pipeline references Tracker's default instead of duplicating
      - Remove hardcoded defaults from TrackedDomDocument
      - Eliminate '//*' fallback to avoid performance issues

      Single source of truth: Tracker owns indexing logic and default queries. 1d81d0

    • Version 1.16.3 f688ab

    • perf: optimize DOM indexing with XPath query batching

      Collect XPath queries from optimizers and index only required nodes
      instead of all elements, reducing overhead for large HTML documents. 5bfd08

    • Merge branch 'master' of github.com:swissup/module-pagespeed 19ae9a

    • Refactor: centralize profiler usage with ProfilerLoggingTrait

      - Introduced ProfilerLoggingTrait to encapsulate Magento Profiler start/stop logic.
      - Replaced all direct \Magento\Framework\Profiler calls in DOM/optimizer classes with trait methods.
      - Applied profiling wrappers to indexNodePositions, patch application, and optimizer processContext sections.
      - Removed duplicated profiler code and cleaned up profiler labels.
      - Improved profiling coverage and readability; makes maintaining performance tuning and debug info easier. 0a2072

    swissup/module-pro-labels — 1.7.28 (was 1.7.26)
    • Version 1.7.28 f67742

    • Fix: Allow text labels without digits, validate stock_item instead

      - Remove regex check that blocked text-only labels
      - Add stock_item validation when variable is used in label text
      - Use optional chaining for safer property access

      Fixes #38 429bf7

    • Version 1.7.27 de840f

    • Fixed not initialized labels in preview at Magento 2 system config. 842f92

    • Fixed issue when uploaded image doesn't showup in preview for manula labesl. 9a84cd

    • Enhancement: Update getBackgroundImageUrl ( use parent selector instead of href); modify getControlName to support Uppy input 4613ff

    • Fixed poorly positioned labes in preview in admin. 3e03de

    swissup/module-rich-snippets — 1.7.18 (was 1.7.16)
    • Version 1.7.18 d95bbd

    • Skip home breadcrumb in JSON-LD output and enforce minimum items for valid BreadcrumbList 6da95a

    • Add reeze integration for product breadcrumbs created via JS. ea00c7

    • Improve product page breadcrumbs snippet. Generate it via JS. d907f6

    • Refactor FAQPage and QAPage to use PageContext ViewModel for page context resolving. Remove copy/paste error. 5d2ca6

    • Update schema.org URLs to use HTTPS e31276

    • Version 1.7.17 03007e

    • Rich snippet Organization is rendered on Home page only (Google recommendation) ce9bfc

    • Do not add richsnippets to attributepage because it shown all questions ca0069

    swissup/module-seo-cross-links — 1.1.26 (was 1.1.21)
    • Version 1.1.26 873900

    • Fixed failed compilation when Attribute Pages is not installed. (#8) 4cc63c

    • Version 1.1.25 46465b

    • Fixed not working seosuite without the attribute pages module. (https://github.com/swissup/module-seo-cross-links/issues/8) 7b3d16

    • Fix variable name casing for skipCrossLinksProcessing in afterProductAttribute method 3c0a7f

    • Add skipCrosslinksProcessing parameter to afterProductAttribute method (close #10) 24e491

    • Version 1.1.24 3c5dd6

    • Fixed broken column layout. 465ce5

    • Version 1.1.23 08f161

    • Serialize only body child nodes when get the HTML back. 61c56c

    • Version 1.1.22 294494

    • Assign priority to the longest key available in the description. (for example, two links: X-Max and X-Max V3 Pro. The shortest link will use the longest link canonical url)(https://github.com/swissup/module-seo-cross-links/issues/5) fd3d69

    • Support attribute pages. (part1 -https://github.com/swissup/module-seo-cross-links/issues/8) 35416e

    swissup/theme-frontend-argentobreeze-business — 2.6.9 (was 2.6.8)
    • Version 2.6.9 185684

    • Added missing `requires` to sizing chart block 52e7be

    • Fixed less compilation error when ajaxsearch is disabled 4c1151

    swissup/theme-frontend-argentobreeze-chic — 2.6.2 (was 2.6.1)
    swissup/theme-frontend-argentobreeze-force — 2.5.7 (was 2.5.6)
    swissup/module-core — 1.12.26 (was 1.12.25)
    • Version 1.12.26 74dff6

    • Improve the libxml fix to include `data-post` and `data-config` attrs 3fee5e

    swissup/module-theme-editor — 1.11.6 (was 1.11.5)
    • Version 1.11.6 b13cdb

    • use Magento filesystem API for file operations on remote server

      replace native PHP file functions with Magento filesystem abstraction

      - Replace file_exists() with getMediaDirectory()->isExist()
      - Replace filemtime() with getMediaDirectory()->stat()['mtime'] daf7f1

swissup / argento-m2

1.52.0 Feb
  • 1.52.0

    Report (rev.1)

    Package was generated and uploaded to GitHub on with the following dependencies:

    swissup/module-ajaxpro:1.7.33

    swissup/module-ajaxsearch:1.13.30

    swissup/module-amp:1.6.0

    swissup/module-askit:1.14.20

    swissup/module-attributepages:1.8.1

    swissup/module-chat-gpt-assistant:1.1.4

    swissup/module-compare:1.2.8

    swissup/module-easy-slide:1.8.16

    swissup/module-easybanner:1.9.23

    swissup/module-easycatalogimg:1.5.13

    swissup/module-easytabs:1.13.2

    swissup/module-fblike:1.3.9

    swissup/module-featured-attributes:1.1.9

    swissup/module-font-awesome:1.4.4

    swissup/module-gdpr:1.8.4

    swissup/module-gdpr-askit:1.1.3

    swissup/module-gdpr-reviewreminder:1.0.0

    swissup/module-gdpr-testimonials:1.1.1

    swissup/module-highlight:1.11.9

    swissup/module-hover-gallery:1.3.15

    swissup/module-hreflang:1.6.11

    swissup/module-hreflang-import-export:1.0.1

    swissup/module-lightboxpro:1.3.9

    swissup/module-navigationpro:1.17.34

    swissup/module-pagespeed:1.17.1

    swissup/module-pro-labels:1.7.28

    swissup/module-pro-labels-configurable-product:1.0.9

    swissup/module-quantity-switcher:1.1.28

    swissup/module-reviewreminder:1.1.19

    swissup/module-rich-snippets:1.7.18

    swissup/module-seo-canonical:1.11.9

    swissup/module-seo-core:1.3.10

    swissup/module-seo-cross-links:1.1.26

    swissup/module-seo-html-sitemap:1.1.21

    swissup/module-seo-images:1.3.21

    swissup/module-seo-pager:1.3.5

    swissup/module-seo-templates:1.7.10

    swissup/module-seo-urls:1.5.54

    swissup/module-seo-xml-sitemap:1.1.16

    swissup/module-sold-together:1.11.3

    swissup/module-sold-together-custom-options:1.0.2

    swissup/module-sold-together-email:1.0.0

    swissup/module-sold-together-import-export:1.0.1

    swissup/module-testimonials:1.3.17

    swissup/module-theme-editor-argento-chic:1.7.4

    swissup/module-theme-editor-argento-essence:1.7.3

    swissup/module-theme-editor-argento-flat:1.7.3

    swissup/module-theme-editor-argento-force:1.4.2

    swissup/module-theme-editor-argento-home:1.2.3

    swissup/module-theme-editor-argento-luxury:1.7.2

    swissup/module-theme-editor-argento-mall:1.7.3

    swissup/module-theme-editor-argento-marketplace:1.7.3

    swissup/module-theme-editor-argento-pure2:1.6.4

    swissup/module-theme-editor-argento-stripes:1.7.5

    swissup/theme-frontend-argento-blank:1.49.4

    swissup/theme-frontend-argento-chic:1.48.2

    swissup/theme-frontend-argento-essence:1.46.3

    swissup/theme-frontend-argento-flat:1.46.5

    swissup/theme-frontend-argento-force:1.48.2

    swissup/theme-frontend-argento-home:1.48.3

    swissup/theme-frontend-argento-luxury:1.48.1

    swissup/theme-frontend-argento-mall:1.48.1

    swissup/theme-frontend-argento-marketplace:1.48.3

    swissup/theme-frontend-argento-pure2:1.46.5

    swissup/theme-frontend-argento-stripes:1.48.2

    swissup/module-core:1.12.26

    swissup/module-suggestpage:1.2.14

    swissup/module-image-optimizer:1.0.11

    swissup/module-theme-editor:1.11.6

    Changelog (autogenerated)

    swissup/module-ajaxpro — 1.7.33 (was 1.7.30)
    • Version 1.7.33 c70361

    • Breeze: Improve floating cart integration b8ebe3

    • Version 1.7.32 8c23bb

    • Breeze: Fixed unresolved Swissup_Ajaxpro/js/catalog-product-view cmp 06a89b

    • Version 1.7.31 8e3c32

    • Breeze: floating cart and breeze 2.27.0 fixes 66b37f

    swissup/module-askit — 1.14.20 (was 1.14.18)
    • Version 1.14.20 7a99b4

    • Remove askit because it shows all questions without filtering f824b8

    • Version 1.14.19 9d0555

    • Refactored to use Filter component with fallback for legacy Widget grids. 8f22fe

    • Fix #66: Mass actions now properly respect grid filters
      Refactored to use Filter component and fixed SQL ambiguous column error. 2bf312

    • Fix mass actions ignoring grid filters (close #66)

      Refactored mass actions to use Magento's Filter component instead of
      manual selected/excluded handling. Now mass delete/enable/disable/status
      properly respect all grid filters. bba7d7

    swissup/module-attributepages — 1.8.1 (was 1.8.0)
    • Version 1.8.1 6e10f9

    • Fixed inability to upload image in "options grid" at "Manage Pages"
      Closes #36 78b00d

    swissup/module-easybanner — 1.9.23 (was 1.9.22)
    swissup/module-gdpr — 1.8.4 (was 1.8.3)
    • Version 1.8.4 b8f73c

    • Argument 1 ($object_or_class) must be of type object|string, bool given 491043

    swissup/module-navigationpro — 1.17.34 (was 1.17.33)
    swissup/module-pagespeed — 1.17.1 (was 1.16.2)
    • Version 1.17.1 518887

    • Include all HTML5 void (self-closing) elements in SELF_CLOSING_TAGS

      Fixes tag closing issues for tags like <source>, <track>, and others.
      Makes output HTML valid by preventing erroneous closing tags for void elements. (close #86) 0aeeab

    • fix: Handle corrupted CSP SRI data gracefully in PageSpeed plugin

      Prevents site crashes when Subresource Integrity storage contains
      invalid JSON by adding try-catch blocks and auto-clearing corrupted data. c52ed9

    • Version 1.17.0 c66e50

    • refactor(logger): Remove parameters, use LoggerSingleton lazy init

      BREAKING CHANGE: Removed constructor parameters.
      Debug mode auto-detected from PAGESPEED_DEBUG constant.

      Removed:
      - Logger/LoggerFactory.php (replaced by LoggerSingleton)
      - parameters from 25+ classes
      - properties from 15+ classes
      - Explicit initLogger() calls

      Changed:
      - LoggerSingleton:: getInstance() - no param, auto-detects
      - LoggerAwareTrait - lazy init + isDebugEnabled() method
      - All logger-using classes - simplified constructors
      - DuplicateValidator, PatchGrouper, PatchApplicator, ParentPatcher - use trait instead of injected logger
      - DuplicateOffsetDetector:: detect(), OffsetStatistics::log() - removed param

      Added:
      - isDebugEnabled() checks before expensive operations (PatchGrouper, Pipeline, Tracker, NodeHtmlCache) 4ad59c

    • refactor(offset-finder): Replace signature-based strategies with UniqueMarker + indexed lookup

      BREAKING CHANGE: Replaced SignatureOffsetFinder, FastTagOffsetFinder, and AttributeOffsetFinder
      with new strategy chain focused on markers and fast indexed lookups.

      New strategy chain (priority order):
      1. UniqueMarkerOffsetFinder - O(1) lookup by data-pspd-n markers (100% accurate)
      2. IndexedAttributeOffsetFinder - Pre-indexed img/script/link/style tags by id/src/href
      3. DirectAttributeOffsetFinder - Fallback for non-indexed attributes (id, data-role)
      4. SiblingIndexTagOffsetFinder - Position-based matching for duplicate tags
      5. ParentContextOffsetFinder - Parent-child context analysis
      6. ContentOffsetFinder - Last resort content-based matching

      Added:
      - Model/Dom/Node/Position/OffsetFinder/Helper/TagIndex. php
      Shared lazy-initialized index for fast tag lookup with duplicate detection

      - Model/Dom/Node/Position/OffsetFinder/Strategy/UniqueMarkerOffsetFinder.php
      Highest priority strategy using data-pspd-n markers added by UniqueMarkers patcher

      - Model/Dom/Node/Position/OffsetFinder/Strategy/IndexedAttributeOffsetFinder.php
      Fast O(1) hash lookup by unique attributes (id/src/href/data-role)

      - Model/Dom/Node/Position/OffsetFinder/Strategy/DirectAttributeOffsetFinder.php
      Fallback for elements with priority attributes not in index

      - Model/Dom/Node/Position/OffsetFinder/Strategy/SiblingIndexTagOffsetFinder.php
      Position-based matching with duplicate tag detection

      - Test/Unit/Model/Dom/Node/Position/OffsetFinder/OffsetFinderChainSetup.php
      Trait for consistent test setup across all offset finder tests

      - Test/Unit/Model/Patch/UniqueMarkersIntegrationTest.php
      Integration test for complete UniqueMarkers + OffsetFinder pipeline

      Removed:
      - Model/Dom/Node/Position/OffsetFinder/Strategy/AttributeOffsetFinder.php
      Replaced by DirectAttributeOffsetFinder with clearer responsibility

      - Model/Dom/Node/Position/OffsetFinder/Strategy/FastTagOffsetFinder.php
      Split into IndexedAttributeOffsetFinder + SiblingIndexTagOffsetFinder

      - Model/Dom/Node/Position/OffsetFinder/Strategy/SignatureOffsetFinder.php
      Replaced by simpler, faster strategies with UniqueMarker as primary

      - Model/Dom/Node/Position/OffsetFinder/Strategy/ContentPriorityOffsetFinder.php
      Functionality merged into ContentOffsetFinder

      Changed:
      - Model/Dom/Node/Position/Tracker.php
      Added '//style' to DEFAULT_XPATH_QUERIES for <style> tag indexing

      - Model/Dom/Node/Position/TrackerFactory.php
      Updated to use new strategy chain with TagIndex

      - Test/Unit/Model/Dom/Node/Position/OffsetFinder/ChainTest.php
      - Test/Unit/Model/Dom/Node/Position/OffsetFinder/DiagnosticDuplicateTest.php
      - Test/Unit/Model/Dom/Node/Position/OffsetFinder/DuplicateOffsetAnalysisTest.php
      - Test/Unit/Model/Dom/Node/Position/OffsetFinder/FixValidationTest.php
      Refactored to use OffsetFinderChainSetup trait for consistent setup

      - Test/Unit/Model/Dom/ScriptOffsetDuplicationTest.php
      Updated for new strategy chain, all tests now use markers

      Performance improvements:
      - UniqueMarker strategy: ~50x faster than signature-based (O(1) hash lookup)
      - IndexedAttribute strategy: ~20x faster (pre-built index on first use)
      - Eliminated complex signature generation and filtering logic
      - Reduced duplicate offset rate from 15+ duplicates to 0 with markers

      Fixes:
      - #82 Duplicate offsets for <script type=text/x-magento-init> tags
      - Missing offset detection for <style> tags
      - Inconsistent offset finding across identical opening tags

      Migration:
      - UniqueMarkers patcher adds data-pspd-n markers before offset tracking
      - Markers removed after optimization with UniqueMarkers:: restore()
      - No changes required for existing code using Tracker API

      Tests:
      - All existing tests pass with new strategy chain
      - New integration test validates complete pipeline
      - Test coverage maintained at 95%+

      Related: swissup/module-pagespeed#82 7e2670

    • feat: add UniqueMarkerOffsetFinder strategy

      New offset finder using data-pspd-n markers for accurate tracking.

      Files:
      - UniqueMarkerOffsetFinder.php (O(1) lookup strategy)
      - UniqueMarkers.php (adds/removes markers)
      - 15 unit tests

      Results:
      - Duplicate offsets: 6 → 0
      - Failed strategies: ~20 → ~1
      - indexNodes: 4.45ms → 2.5ms (-44%)

      Registered as first strategy. Backwards compatible. 24704c

    • refactor: move mode detection from Manager to TrackedDomDocument

      - Remove Manager::isDocument() (31 lines)
      - Add TrackedDomDocument::detectMode() for auto-detection
      - Constructor accepts ? string = null (auto-detect if null)
      - Remove 126 lines of Manager tests (logic encapsulated in TrackedDomDocument)

      Simplifies Manager, eliminates duplication, improves encapsulation. aceda6

    • refactor: simplify HTML rendering, remove BomStripper/HtmlFragmentExtractor utils

      - Remove Manager::saveHTML() (replaced by getOptimizedHtml)
      - Rename Manager::renderDocument() → getOptimizedHtml() for clarity
      - Delete BomStripper utility (DOMDocument doesn't add BOM)
      - Move HtmlFragmentExtractor to trait for reusability
      - Add shouldExtractFragment() to preserve <body>/<html> structure when present
      - Context::getHtml() now calls getOptimizedHtml() directly

      Result: cleaner architecture, fewer dependencies, explicit parameter passing. fba770

    • refactor(TrackedDomDocument): remove normalizedHtml, improve UTF-8 handling

      - Remove normalizedHtml property - use originalHtml for indexing
      - Extract libxml error logging into separate method
      - Add detailed libxml parsing error summary
      - Replace getNormalizedHtml() with saveHTML() in tests
      - Add 9 new tests for node caching and UTF-8 preservation
      - Fix spacing in parent::saveHTML() call

      Breaking: Offset tracking now uses pre-parsed HTML instead of normalized 2be4ec

    • refactor: migrate to Magento-generated ContextFactory

      BREAKING CHANGE: Remove custom ContextFactory class

      Changes:
      - Remove Model/Optimizer/ContextFactory. php (use Magento DI)
      - Create Test/Unit/Helper/ContextFactoryTrait for tests
      - Supports both string (legacy) and array formats
      - Provides createContext() helper for cleaner test code
      - Throws clear errors for invalid input types
      - Update AbstractStreamOptimizer and Pipeline to use array format
      - Update all 25+ test files to use trait
      - Remove ~100+ lines of duplicated test setup code
      - Remove redundant createContext() methods from individual tests
      - Update PipelineTest mock expectations to validate array structure

      Benefits:
      - Simplifies codebase by using Magento's auto-generated factory
      - Centralizes test setup logic in single trait
      - Improves maintainability with single point of change
      - Reduces code duplication across test suite
      - Maintains backward compatibility with string format

      All 583 tests passing ✅ b0d899

    • test: Fix Pipeline and Preload optimizer test expectations

      Fixed 3 failing tests:

      1. PipelineTest::testRunHandlesOptimizerExceptionsGracefully
      - Changed expectation from throwing exception to continuing with next optimizer
      - Pipeline should gracefully handle optimizer failures and continue execution
      - Added second optimizer to verify pipeline continues after first one fails

      2. AddLinkPreloadTest::testProcessContextWithDomOperations
      - Fixed isDirty() assertion order
      - Context. isDirty() returns true BEFORE getHtml() call
      - Context.isDirty() returns false AFTER getHtml() (resets dirty flag)

      3. DnsprefetchTest::testProcessContextWithDomOperations
      - Fixed isDirty() assertion order (same as AddLinkPreload)

      All tests now correctly reflect actual behavior:
      - Pipeline continues execution even if one optimizer fails
      - Context. getHtml() resets the dirty flag after applying patches 99da9e

    • refactor: simplify logging architecture in DOM pipeline

      - Replace callback loggers with LoggerAwareTrait in Manager
      - Refactor Pipeline into focused methods (filterOptimizers, collectQueries, runOptimizer)
      - Add Context::getOriginalHtml() for pipeline debugging
      - Reset isDirty flag after patch application in Context
      - Add debug mode check before TrackedDomDocument creation logging

      BREAKING CHANGE: Manager:: saveHTML() signature changed - removed logger callbacks ae0746

    • refactor: extract debug logs injection into separate plugin

      - Created InjectDebugLogsPlugin for debug logs injection
      - Removed log injection from Pipeline (now only handles optimization)
      - Uses LoggerAwareTrait with LoggerSingleton for shared log collection
      - InjectDebugLogsPlugin runs after optimization (sortOrder=-10)
      - Follows Single Responsibility Principle
      - Easier to enable/disable debug logs independently via di.xml
      - Improved code organization and maintainability

      Execution order:
      1. AfterRenderResultPlugin (sortOrder=-15) - optimization pipeline
      2. InjectDebugLogsPlugin (sortOrder=-10) - inject debug logs

      Technical details:
      - LoggerAwareTrait->flushLogs() retrieves logs from LoggerSingleton
      - All classes using LoggerAwareTrait share the same logger instance
      - Logs accumulated across Pipeline, Context, Manager, and Optimizers
      - Single flush at the end outputs all logs to browser console

      Breaking changes: None (log injection still works, just moved to plugin) 2ff1a7

    • refactor: extract TrackedDomDocument into focused traits

      - Created 5 specialized traits following Single Responsibility Principle:
      * Utf8CharsetInjectorTrait: UTF-8 charset injection/removal with 4 strategies
      * ElementTrackingTrait: setAttribute/removeAttribute operations
      * NodeTrackingTrait: appendChild/removeChild/replaceChild operations
      * BatchModificationTrait: batchModifyElement for atomic changes
      * HtmlSerializationTrait: getElementHtml with formatting control

      - Reduced TrackedDomDocument from ~1200 to ~450 lines
      - Improved UTF-8 handling with duplication check
      - Enhanced meta charset removal with multiple fallback strategies
      - Better code organization, testability, and maintainability

      - Updated tests:
      * TrackedDomDocumentTest: use TrackedDomDocument for UTF-8 preservation
      * ContextTest: improved mock injection via DI instead of reflection

      - Fixed typo in error message spacing

      All tests passing (583/583) 4fffd6

    • refactor: extract DOM utilities and move logic from Context to Manager

      - Created ScriptTagEscaper, HtmlFragmentExtractor, BomStripper utility classes
      - Moved document/XPath caching from Context to Manager
      - Manager now handles all HTML rendering, patch application, and fragment extraction
      - Context simplified to pure coordinator (metadata, dirty state, delegation)
      - TrackedDomDocument made originalHtml readonly and added mode getters (isDocument/isFragment)
      - Manager auto-detects fragment mode from TrackedDomDocument
      - Added clearCache() method to Manager for cache invalidation
      - Fixed code style inconsistencies (spacing, comments) 41aee6

    • refactor: centralize UTF-8 BOM constant to TrackedDomDocument and remove duplicates 2ab7ba

    • Merge branch 'master' of github.com:swissup/module-pagespeed 2b0da4

    • refactor: move DomManager to Swissup\Pagespeed\Model\Dom\Manager and rename getDom() to getDocument()

      - Moved DomManager from Model\Optimizer to Model\Dom (as Manager) for clearer domain separation and SRP.
      - Updated all usages: Context, ContextFactory, optimizers, and tests now use Model\Dom\Manager (aliased as DocumentManager).
      - Renamed method getDom() → getDocument() everywhere to clarify returned value meaning and avoid ambiguity.
      - Renamed variables/params to for consistency.
      - Removed obsolete Model\Optimizer\DomManager.php and related unit test.
      - Aligned naming in tests and classes for better code readability and maintainability. 1bca16

    • Version 1.16.8 3dab8d

    • fix: Preserve script tracking in DeferJs with DocumentFragment

      Replace complex parent grouping with simple DocumentFragment approach
      that maintains 16x performance while ensuring TrackedDomDocument
      properly tracks all script movements.

      - Use appendChildToElement() for proper tracking
      - Keep DocumentFragment for batch performance
      - Fix missing operations in attribute_change_log 44e937

    • Revert aab2e34; fix losing <script> tags; add perf regression ( 0e7624

    • Sync composer version with last tag f94a43

    • perf: Fix DeferJs regression - revert to native DOM (16x faster)

      Commit f4977f5 (Oct 13) introduced TrackedDomDocument methods which add
      expensive tracking overhead. Reverting to native removeChild/appendChild.

      Results:
      - moveScriptsToBodyEnd: 0.078s → instant
      - DeferJs: 0.082s → 0.005s (16.4x faster)
      - Coordinator: 0.213s → 0.158s (1.35x faster)

      Fix: Use native DOM + context.markDirty() for correct patch regeneration. aab2e3

    • perf: Remove SignatureOffsetFinder and add profiling (11x faster)

      Removed SignatureOffsetFinder strategy which consumed 91% of indexing time.
      Added profiling to Chain and Tracker for performance analysis.

      Performance:
      - indexNodes: 0.243s → 0.022s (11x faster)
      - Coordinator: 0.448s → 0.213s (2.1x faster)
      - indexNodes as % of total: 54.5% → 10.3%

      Coverage: All nodes still indexed by FastTag, ParentContext, and Content strategies. 348919

    • PatchManager: exact regex check for <html>/<head>/<body>, better logging 5f56f4

    • perf DirectMatchStrategy: clean up and document core fast/UTF-8 replacement logic 2eb9cf

    • OffsetBasedStrategy: drop global ASCII cache; use local fragment check only, cleanup profiling 864be2

    • FastTagOffsetFinder: skip duplicated tags, delegate ambiguous offset matching to safe strategies 965136

    • TrackedDomDocument: robust UTF-8 charset handling, correct structure restoration, and extensive encoding tests ac2673

    • LCP Optimizer: batch node indexing, XPath constants, and TrackedDomDocument fixes cad15d

    • fix(TrackedDomDocument): Fix UTF-8 with meta charset injection

      Problem: DOMDocument converts UTF-8 (Σχετικά) to entities (&Sigma;...)
      Solution: Inject <meta charset=utf-8>, then remove after parsing

      Changes:
      - addUtf8Charset(): inject meta tag (document/fragment aware)
      - removeUtf8Charset(): cleanup meta + extract body for fragments
      - Proper libxml error handling (no @ suppression)

      Result: UTF-8 preserved, testBomIsRemovedFromOutput ✅ PASS

      Technical: Forces libxml UTF-8 mode, saveHTML() outputs UTF-8 correctly 76abb7

    • perf(OffsetBasedStrategy): Fix UTF-8 handling and add ASCII detection cache

      **Problems fixed:**
      1. UTF-8 characters incorrectly handled - byte/char offset mismatch
      2. Performance bottleneck - repeated mb_strlen() on large HTML

      **Solutions:**
      1. Convert byte offset to character offset for mb_substr
      2. Cache ASCII detection (xxh3 hash, 100 entry limit, FIFO)
      3. Remove broken isUtf8Safe() - use reliable ASCII check

      **Performance:**
      - 500KB HTML, 100 patches: 500ms → 15ms (33x faster)
      - Cache hit rate: 99%+ expected

      **Stats:** cache_hits, cache_misses, cache_hit_rate added 9c537c

    • refactor: manual node indexing in TrackedDomDocument, update pipeline/context a758d3

    • Version 1.16.5 c554e1

    • perf: Optimize OffsetBasedStrategy - 41x faster (mb_* → substr_replace) part II e0e005

    • perf: Optimize OffsetBasedStrategy with fast path and UTF-8 fallback

      - Replace slow mb_* functions with fast substr_replace/strpos
      - Add exact offset check before radius search (80% hit rate)
      - Add UTF-8 safety validation with fallback to mb_substr
      - Add profiling and statistics tracking
      - Expected speedup: 0.170s → 0.030s (5. 6x faster)

      Performance impact:
      - OffsetBased: 0.124s → ~0.014s (9x faster)
      - Total applyPatches: 0.170s → ~0.030s
      - Pagespeed: 0.377s → ~0.240s (36% faster) ce351b

    • perf(tracker): optimize node indexing with combined XPath queries

      Improve indexNodePositions() performance by:
      - Combining simple XPath queries into single expression (//img | //script | ...)
      - Using SplObjectStorage for automatic node deduplication
      - Adding graceful fallback to individual queries if combined query fails
      - Moving error details to debug mode only

      Implementation:
      - New method: findNodesToIndex() - handles query execution and deduplication
      - New method: canCombineQueries() - validates if queries can be combined
      - New method: combineQueries() - creates combined XPath expression
      - New method: convertStorageToArray() - converts SplObjectStorage to indexed array

      Performance impact:
      - indexNodePositions: 0.056s → 0.045s (~20% faster)
      - Combined with FastTagOffsetFinder: 0.320s → 0.045s (7. 1x total improvement)
      - XPath queries: 5 separate DOM scans → 1 combined scan

      Debug improvements:
      - Added logging for combined query usage (debug mode only)
      - Moved stack traces to debug mode only
      - Added node count logging after successful query 3ae16d

    • feat(performance): add FastTagOffsetFinder strategy for 5.75x speedup

      Add optimized offset finder for common tags using pre-built index.

      Performance: indexNodePositions 0.320s → 0.056s (5.75x faster) ba5d58

    • test: fix tests for selective XPath indexing

      Pass explicit XPath queries in tests after removing '//*' fallback. ff46ce

    • feat(tracker): add XPath query validation with debug-aware logging

      - Add try-catch around XPath query execution
      - Log warnings for invalid queries (graceful degradation)
      - Log errors for execution failures with file/line context
      - Include full stack trace only in debug mode
      - Early return if no nodes found to index
      - Continue processing remaining queries on failure

      Improves robustness: invalid XPath from optimizers won't break indexing,
      and production logs remain clean while debug mode provides full context. 985abb

    • Merge branch 'master' of github.com:swissup/module-pagespeed b6a4ee

    • refactor(dom): move default XPath queries to Tracker

      - Define Tracker:: DEFAULT_XPATH_QUERIES constant
      - Tracker uses own default when no queries provided
      - Pipeline references Tracker's default instead of duplicating
      - Remove hardcoded defaults from TrackedDomDocument
      - Eliminate '//*' fallback to avoid performance issues

      Single source of truth: Tracker owns indexing logic and default queries. 1d81d0

    • Version 1.16.3 f688ab

    • perf: optimize DOM indexing with XPath query batching

      Collect XPath queries from optimizers and index only required nodes
      instead of all elements, reducing overhead for large HTML documents. 5bfd08

    • Merge branch 'master' of github.com:swissup/module-pagespeed 19ae9a

    • Refactor: centralize profiler usage with ProfilerLoggingTrait

      - Introduced ProfilerLoggingTrait to encapsulate Magento Profiler start/stop logic.
      - Replaced all direct \Magento\Framework\Profiler calls in DOM/optimizer classes with trait methods.
      - Applied profiling wrappers to indexNodePositions, patch application, and optimizer processContext sections.
      - Removed duplicated profiler code and cleaned up profiler labels.
      - Improved profiling coverage and readability; makes maintaining performance tuning and debug info easier. 0a2072

    swissup/module-pro-labels — 1.7.28 (was 1.7.26)
    • Version 1.7.28 f67742

    • Fix: Allow text labels without digits, validate stock_item instead

      - Remove regex check that blocked text-only labels
      - Add stock_item validation when variable is used in label text
      - Use optional chaining for safer property access

      Fixes #38 429bf7

    • Version 1.7.27 de840f

    • Fixed not initialized labels in preview at Magento 2 system config. 842f92

    • Fixed issue when uploaded image doesn't showup in preview for manula labesl. 9a84cd

    • Enhancement: Update getBackgroundImageUrl ( use parent selector instead of href); modify getControlName to support Uppy input 4613ff

    • Fixed poorly positioned labes in preview in admin. 3e03de

    swissup/module-rich-snippets — 1.7.18 (was 1.7.16)
    • Version 1.7.18 d95bbd

    • Skip home breadcrumb in JSON-LD output and enforce minimum items for valid BreadcrumbList 6da95a

    • Add reeze integration for product breadcrumbs created via JS. ea00c7

    • Improve product page breadcrumbs snippet. Generate it via JS. d907f6

    • Refactor FAQPage and QAPage to use PageContext ViewModel for page context resolving. Remove copy/paste error. 5d2ca6

    • Update schema.org URLs to use HTTPS e31276

    • Version 1.7.17 03007e

    • Rich snippet Organization is rendered on Home page only (Google recommendation) ce9bfc

    • Do not add richsnippets to attributepage because it shown all questions ca0069

    swissup/module-seo-cross-links — 1.1.26 (was 1.1.21)
    • Version 1.1.26 873900

    • Fixed failed compilation when Attribute Pages is not installed. (#8) 4cc63c

    • Version 1.1.25 46465b

    • Fixed not working seosuite without the attribute pages module. (https://github.com/swissup/module-seo-cross-links/issues/8) 7b3d16

    • Fix variable name casing for skipCrossLinksProcessing in afterProductAttribute method 3c0a7f

    • Add skipCrosslinksProcessing parameter to afterProductAttribute method (close #10) 24e491

    • Version 1.1.24 3c5dd6

    • Fixed broken column layout. 465ce5

    • Version 1.1.23 08f161

    • Serialize only body child nodes when get the HTML back. 61c56c

    • Version 1.1.22 294494

    • Assign priority to the longest key available in the description. (for example, two links: X-Max and X-Max V3 Pro. The shortest link will use the longest link canonical url)(https://github.com/swissup/module-seo-cross-links/issues/5) fd3d69

    • Support attribute pages. (part1 -https://github.com/swissup/module-seo-cross-links/issues/8) 35416e

    swissup/module-core — 1.12.26 (was 1.12.25)
    • Version 1.12.26 74dff6

    • Improve the libxml fix to include `data-post` and `data-config` attrs 3fee5e

    swissup/module-theme-editor — 1.11.6 (was 1.11.5)
    • Version 1.11.6 b13cdb

    • use Magento filesystem API for file operations on remote server

      replace native PHP file functions with Magento filesystem abstraction

      - Replace file_exists() with getMediaDirectory()->isExist()
      - Replace filemtime() with getMediaDirectory()->stat()['mtime'] daf7f1

swissup / gdpr

1.8.4 Feb

swissup / ajaxpro

1.7.33 Feb

swissup / askit

1.14.20 Feb

swissup / easybanner

1.9.23 Feb