Skip to content

Commit 63ea923

Browse files
committed
feat: improve/transform json output
1 parent 4507981 commit 63ea923

File tree

6 files changed

+58
-15
lines changed

6 files changed

+58
-15
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ $options = [
144144

145145

146146
### JSON Output
147-
If you need JSON output instead of HTML markup (for headless CMS setups, API endpoints, or JavaScript-driven rendering), use the `imagex-picture.json.php` snippet:
147+
If you need JSON output instead of HTML markup (for headless CMS setups, API endpoints, or JavaScript-driven rendering), use the `imagex-picture-json.php` snippet:
148148

149149
```php
150150
<?php
@@ -155,7 +155,7 @@ $options = [
155155
// ... all other options work the same
156156
];
157157

158-
$json = snippet('imagex-picture.json', $options, true);
158+
$json = snippet('imagex-picture-json', $options, true);
159159
echo $json;
160160
?>
161161
```

docs/examples/json-output.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# Example: JSON Output
22

3-
The `imagex-picture.json` snippet provides JSON output instead of HTML markup. This is useful for:
3+
The `imagex-picture-json` snippet provides JSON output instead of HTML markup. This is useful for:
44
- Headless CMS setups
55
- API endpoints
66
- JavaScript-driven rendering (SPA, React, Vue, etc.)
77
- Custom client-side image handling
88

99
## Usage
1010

11-
The `imagex-picture.json` snippet accepts the same options as `imagex-picture` but returns JSON data instead of HTML.
11+
The `imagex-picture-json` snippet accepts the same options as `imagex-picture` but returns JSON data instead of HTML.
1212

1313
### Global Plugin Config
1414
```php
@@ -48,7 +48,7 @@ $options = [
4848
];
4949

5050
// Important: Pass `true` as third parameter to return the snippet output
51-
$json = snippet('imagex-picture.json', $options, true);
51+
$json = snippet('imagex-picture-json', $options, true);
5252

5353
// Output JSON
5454
header('Content-Type: application/json');
@@ -96,8 +96,8 @@ $data = json_decode($json, true);
9696

9797
## Notes
9898

99-
- All options from `imagex-picture` work with `imagex-picture.json`
100-
- The third parameter (`true`) in `snippet('imagex-picture.json', $options, true)` is required to return the output instead of echoing it
99+
- All options from `imagex-picture` work with `imagex-picture-json`
100+
- The third parameter (`true`) in `snippet('imagex-picture-json', $options, true)` is required to return the output instead of echoing it
101101
- The JSON includes all calculated attributes, srcsets, and URLs
102102
- Art-directed sources are also included in the `sources` array with their media queries
103103
- Combine with Kirby's routing system to create custom API endpoints

helpers/attributes.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,18 @@ function validateAttributeTypes(array $options): void
4242
* Merges HTML attributes for different loading modes with optional default values.
4343
*
4444
* User attributes always override default attributes. Defaults are used as fallback.
45-
* Extend 'shared' by 'eager' or 'lazy' loading mode attributes.
45+
* Extends 'shared' attributes with 'eager' or 'lazy' loading mode-specific attributes.
46+
*
47+
* For 'class' and 'style' attributes: Arrays are merged and duplicates removed.
48+
* For other attributes: New values override existing values.
49+
*
50+
* Note: Returns attributes with 'class' and 'style' as arrays. Use transformForJson()
51+
* to convert them to strings for JSON output.
4652
*
4753
* @param array $attributes User-defined attributes structured by loading modes.
48-
* @param string $loadingMode The loading mode to merge attributes for.
54+
* @param string $loadingMode The loading mode to merge attributes for ('shared', 'eager', or 'lazy').
4955
* @param array $defaultAttributes Optional default attributes to apply as fallback.
50-
* @return array Merged array of HTML attributes for specified loading mode.
56+
* @return array Merged array of HTML attributes for specified loading mode (class/style as arrays).
5157
* @throws InvalidArgumentException If $loadingMode is invalid or missing.
5258
*/
5359
function mergeHTMLAttributes(array $attributes, string $loadingMode, array $defaultAttributes = ['shared' => [], 'eager' => [], 'lazy' => []]): array
@@ -72,8 +78,11 @@ function mergeHTMLAttributes(array $attributes, string $loadingMode, array $defa
7278
// Ensure both values are arrays
7379
$currentValues = is_array($currentValue) ? $currentValue : explode(' ', $currentValue);
7480
$newValues = is_array($newValue) ? $newValue : explode(' ', $newValue);
75-
// Merge, remove duplicates, re-index and remove empty values
76-
$mergedValues = array_filter(array_values(array_unique(array_merge($currentValues, $newValues))));
81+
// Merge, remove duplicates, and remove empty strings (but keep null values)
82+
$merged = array_unique(array_merge($currentValues, $newValues));
83+
$filtered = array_filter($merged, fn ($val) => $val !== '' && $val !== null && $val !== false);
84+
// Re-index array to ensure sequential keys starting from 0
85+
$mergedValues = array_values($filtered);
7786

7887
return $mergedValues;
7988
} else {

helpers/misc.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,35 @@ function srcHandler(string $src, array $srcAttributes, string $loadingMode): str
141141
return null;
142142
}
143143
}
144+
145+
/**
146+
* Transforms data for JSON output by converting class/style arrays to strings
147+
* and removing null values and empty strings.
148+
*
149+
* @param mixed $data The data to transform.
150+
* @return mixed The transformed data.
151+
*/
152+
function transformForJson(mixed $data): mixed
153+
{
154+
if (is_array($data)) {
155+
$result = [];
156+
foreach ($data as $key => $value) {
157+
// Convert class and style arrays to strings
158+
if (($key === 'class' || $key === 'style') && is_array($value)) {
159+
$value = implode(' ', $value);
160+
}
161+
162+
// Recursively transform nested arrays
163+
$transformed = transformForJson($value);
164+
165+
// Skip null values and empty strings
166+
if ($transformed !== null && $transformed !== '') {
167+
$result[$key] = $transformed;
168+
}
169+
}
170+
171+
return $result;
172+
}
173+
174+
return $data;
175+
}

index.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@
1313
],
1414
'snippets' => [
1515
'imagex-picture' => __DIR__ . '/snippets/imagex-picture.php',
16-
'imagex-picture-json' => __DIR__ . '/snippets/imagex-picture.json.php',
16+
'imagex-picture-json' => __DIR__ . '/snippets/imagex-picture-json.php',
1717
],
1818
]);

snippets/imagex-picture.json.php renamed to snippets/imagex-picture-json.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
use TimNarr\Imagex;
3+
namespace TimNarr;
44

55
$imagex = new Imagex([
66
'critical' => $critical ?? false,
@@ -20,4 +20,6 @@
2020
'imgAttributes' => $imagex->getImgAttributes(),
2121
];
2222

23-
return json_encode($data, JSON_PRETTY_PRINT);
23+
$data = transformForJson($data);
24+
25+
echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);

0 commit comments

Comments
 (0)