Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6441cca
feat: add missing dimensions detection https://github.com/Codeinwp/op…
selul Sep 16, 2025
2c8e2d0
refactor: modularize image detection and optimize background image ha…
selul Sep 16, 2025
cd9b6e2
refactor: update optimizer to run profiling instead of finding above-…
selul Sep 16, 2025
8ab7474
feat: add srcset detection and handling for images, enhancing respons…
selul Sep 17, 2025
eed8be3
feat: implement waitForViewportImages utility and enhance srcset dete…
selul Sep 17, 2025
3d71060
refactor: improve code readability by standardizing spacing and forma…
selul Sep 17, 2025
0ebc797
refactor: update lazyload logic to conditionally load profiler based …
selul Sep 17, 2025
736baf5
test: update assertions in lazyload tests to reflect changes in loadi…
selul Sep 17, 2025
c37a3f9
refactor: replace lazyload checks with profiler loading logic across …
selul Sep 18, 2025
a4cc39a
feat: enhance srcset detection to include crop status and improve log…
selul Sep 18, 2025
602d116
refactor: replace console logging with optmlLogger for improved debug…
selul Sep 22, 2025
26f3676
refactor: enhance cropping detection logic in srcset detector to incl…
selul Oct 1, 2025
3eeca78
Merge remote-tracking branch 'origin/development' into feat/improved_…
selul Oct 1, 2025
fc21f61
fix phpstan reports
selul Oct 1, 2025
722faed
Fix PHPStan errors in inc/tag_replacer.php
selul Oct 1, 2025
deb4f96
feat: add force option to URL rebuilding in tag and URL replacers
selul Oct 1, 2025
ec89c6e
Merge branch 'development' into feat/improved_scaling
selul Oct 1, 2025
c63f37b
feat: add HTML comment generation for profiling data and improve para…
selul Oct 1, 2025
c03d351
Merge branch 'refs/heads/development' into feat/improved_scaling
selul Oct 6, 2025
5cc6744
implement purge cache compatibilities https://github.com/Codeinwp/opt…
selul Oct 6, 2025
06467e1
feat: add check for user scroll position before image detection https…
selul Oct 6, 2025
29e04d9
feat: limit above fold images to 6 and set maximum preloaded links to…
selul Oct 6, 2025
ffb256d
add more bg selectors https://github.com/Codeinwp/optimole-service/i…
selul Oct 6, 2025
0b74fb7
fix placeholder width/height calculator when image is offloaded
selul Oct 7, 2025
7744c6e
feat: enhance image detection with optimized dimensions support for l…
selul Oct 7, 2025
1f00f57
fix format
selul Oct 7, 2025
2ab152b
refactor: remove redundant missing type entries from phpstan baseline…
selul Oct 7, 2025
a71ebf9
refactor: update parameter type hint formatting in dam offload utils
selul Oct 7, 2025
a207794
Merge branch 'development' into feat/improved_scaling
selul Oct 7, 2025
d42a41b
preload only lcp urls and fetch priority only on lcp
selul Oct 7, 2025
93f11a3
remove assertion for fetch priority in lazyload viewport tests
selul Oct 7, 2025
cb752e7
[skip ci] update comment
selul Oct 7, 2025
929b722
chore: update .distignore and .gitignore to include coverage and test…
selul Oct 7, 2025
4ea9d8c
Merge branch 'development' into feat/improved_scaling
selul Oct 7, 2025
71bb263
chore: remove .babelrc configuration file and update Jest transform s…
selul Oct 7, 2025
49a757f
refactor: remove unused width step size configuration and enhance res…
selul Oct 8, 2025
e564154
fix: correct indentation in Profile.php and update device type in tes…
selul Oct 8, 2025
c865ec8
feat: add 'kinsta' to the cache types
selul Oct 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .distignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ phpcs.xml
phpunit.xml
phpunit-cc.xml
phpmd.xml
jest.config.js
jest.setup.js
package.json
package-lock.json
composer.json
Expand All @@ -31,6 +33,8 @@ tests
dist
artifact
assets/src
assets/js/modules/__tests__
coverage
.wporg
.nvmrc
.github
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: ESLint
name: JavaScript Tests

on:
pull_request:
Expand All @@ -9,21 +9,36 @@ on:
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.ref }}
cancel-in-progress: true

jobs:
run:
if: github.event.pull_request.draft == false
test:
if: github.event_name == 'push' || github.event.pull_request.draft == false
runs-on: ubuntu-latest
name: ESLint
name: ESLint & Jest Tests
steps:
- uses: actions/checkout@master
- uses: actions/checkout@v3
with:
persist-credentials: false

- name: Setup Node
uses: actions/setup-node@v1
uses: actions/setup-node@v3
with:
node-version: 18
- name: Lint js files
cache: 'npm'

- name: Install dependencies
run: |
npm install -g npm
npm ci

- name: Run ESLint
run: |
npm run lint

- name: Run unit tests
run: |
npm test

- name: Run tests with coverage
run: |
npm run test:coverage

3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ build
cc-test-reporter
assets/build
test-results
tests/assets/filestash
tests/assets/filestash
coverage
14 changes: 14 additions & 0 deletions assets/js/modules/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Optimole JavaScript Modules - Agent Instructions


## Code standards
- **CRITICAL**: All functions must have JSDoc comments with `@param` and `@return` annotations
- Use ES6 modules with `import`/`export` syntax
- Follow camelCase naming for functions and variables
- Use `const`/`let` instead of `var`
- Always handle errors gracefully with try/catch blocks
- Use descriptive variable names and avoid abbreviations

## Testing instructions
- Use only unit tests

162 changes: 162 additions & 0 deletions assets/js/modules/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Optimole JavaScript Modules

This directory contains the modular JavaScript components for the Optimole image optimizer.

## Module Structure

### Core Modules

#### `logger.js`
- **Purpose**: Centralized logging functionality with debug mode support
- **Exports**: `optmlLogger` object
- **Key Features**:
- Debug mode detection via URL params or localStorage
- Structured logging with prefixes
- Table logging support
- Conditional logging based on debug state

#### `storage.js`
- **Purpose**: Session storage management for tracking processed pages
- **Exports**: `optmlStorage` object
- **Key Features**:
- Generate unique storage keys for URL/device combinations
- Check if page/device combinations have been processed
- Mark combinations as processed with timestamps
- Error handling for storage operations

#### `device.js`
- **Purpose**: Device type detection based on screen width
- **Exports**: `optmlDevice` object
- **Key Features**:
- Mobile/desktop detection using 600px breakpoint
- Device type constants (MOBILE: 1, DESKTOP: 2)
- Helper methods for device type checking
- PageSpeed Insights compatible detection logic

#### `api.js`
- **Purpose**: REST API communication with fallback mechanisms
- **Exports**: `optmlApi` object
- **Key Features**:
- Primary sendBeacon API for reliable data transmission
- Fetch API fallback for when sendBeacon fails
- Automatic storage marking on successful sends
- Error handling and logging

#### `dom-utils.js`
- **Purpose**: DOM manipulation and utility functions
- **Exports**: `optmlDomUtils` object
- **Key Features**:
- Debounce utility for performance optimization
- Unique CSS selector generation for elements
- Background image detection and URL extraction
- Page condition checking (viewport, visibility, load state)
- Promise-based waiting utilities

### Specialized Modules

#### `background.js`
- **Purpose**: Background image handling and lazy loading observation
- **Exports**: `optmlBackground` object
- **Key Features**:
- Background image lazy loading detection
- Mutation observer setup for class changes
- URL extraction from background images
- Selector processing and element observation

#### `lcp.js`
- **Purpose**: Largest Contentful Paint (LCP) element detection
- **Exports**: `optmlLcp` object
- **Key Features**:
- Performance Observer integration
- LCP element identification and processing
- Support for both image and background image LCP elements
- Timeout handling for LCP detection

#### `image-detector.js`
- **Purpose**: Image detection and dimension analysis
- **Exports**: `optmlImageDetector` object
- **Key Features**:
- Missing dimension detection for images
- Intersection Observer setup for above-fold detection
- Optimole image observation (`data-opt-id` attributes)
- Cleanup utilities for temporary attributes

#### `srcset-detector.js`
- **Purpose**: Srcset analysis and missing variation detection for eligible images
- **Exports**: `optmlSrcsetDetector` object
- **Key Features**:
- Smart image detection with improved skip logic:
- Includes images without `data-opt-src` (non-lazyload images)
- Includes images with `data-opt-src` AND `data-opt-lazy-loaded` (completed lazyload)
- Skips images with only `data-opt-src` (pending lazyload)
- **Aspect ratio detection for cropping requirements**:
- Compares natural vs. displayed aspect ratios to determine if cropping is needed
- Uses intelligent thresholds: 5% tolerance, 15% significant difference, 10% ratio change
- Prevents unnecessary cropping when aspect ratios match
- Returns separate crop status data as `imageId: cropStatus` mapping
- Calculates required srcset variations using comprehensive size ranges:
- Mobile range: 200w-500w (50w steps) for dense mobile coverage
- Tablet range: 500w-800w (100w steps) for tablet devices
- Desktop range: 800w-1200w (200w steps) for desktop screens
- High-res range: 1200w-1600w (200w steps) with strategic 2x DPR
- Configurable generation settings:
- `widthStepSize`: Step size for width variations (default: 100px)
- `minSize`: Minimum image size to consider (default: 200px)
- `maxVariations`: Maximum srcset variations per image (default: 8)
- `sizeTolerance`: Tolerance for existing sizes (default: 50px)
- Analyzes existing srcset attributes to identify missing sizes
- **Ultra-compact API payload**: Sends only essential fields with short names (w, h, d, s, b)
- **Separate crop status**: Returns crop requirements as `imageId: cropStatus` mapping instead of per-srcset flags
- **Full logging**: Complete analysis data available in console logs for debugging
- Smart selection from dense size grid for optimal responsive coverage

#### `main.js`
- **Purpose**: Main orchestrator coordinating all functionality
- **Exports**: `optmlMain` object
- **Key Features**:
- Complete above-the-fold detection workflow
- Module coordination and data aggregation
- API data preparation and submission with separate crop status
- Error handling and condition checking

## Data Structure

### API Payload Structure
The main module sends data to the REST API with the following structure:

```javascript
{
d: deviceType, // Device type (1=mobile, 2=desktop)
a: aboveTheFoldImages, // Array of above-fold image IDs
b: backgroundSelectors, // Background image selectors
u: url, // Page URL
t: timestamp, // Request timestamp
h: hmac, // Security hash
l: lcpData, // LCP (Largest Contentful Paint) data
m: missingDimensions, // Missing dimension data
s: srcsetData, // Srcset variations data
c: cropStatusData // Crop status mapping (imageId -> boolean)
}
```

### Srcset Data Structure
Individual srcset entries contain:
```javascript
{
w: width, // Image width
h: height, // Image height
d: dpr, // Device pixel ratio
s: descriptor, // Srcset descriptor (e.g., "300w")
b: breakpoint // CSS breakpoint
}
```

### Crop Status Data Structure
Crop requirements are stored separately:
```javascript
{
882936320: true, // Image ID -> requires cropping
123456789: false // Image ID -> no cropping needed
}
```

Loading
Loading