This repository has been archived by the owner on Feb 13, 2022. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- renamed kirbytag and filemethod to: lazysrcset
- refac with focus on lazyloading, kirbytag (inheriting core image kirbytag) and core srcset - removed picture element - unittests, travis ci, coveralls - new readme Signed-off-by: Bruno Meilick <b@bnomei.com>
- Loading branch information
Showing
16 changed files
with
627 additions
and
289 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,107 +1,216 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Bnomei; | ||
|
||
class Srcset | ||
use Kirby\Cms\KirbyTag; | ||
use Kirby\Toolkit\A; | ||
|
||
final class Srcset | ||
{ | ||
public static function srcset(\Kirby\Cms\File $file, $preset = 'default', $lazy = null, $prefix = null, $class = null, $imgclass = null, $snippet = 'plugin-srcset-img') | ||
/* | ||
* @var array | ||
*/ | ||
private $options; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
private $data; | ||
|
||
/* | ||
* @var string | ||
*/ | ||
private $text; | ||
|
||
/* | ||
* @var misc | ||
*/ | ||
private $parent; | ||
|
||
/* | ||
* @var string | ||
*/ | ||
public const PLACEHOLDER = 'https://srcset.net/placeholder.jpg'; | ||
|
||
/** | ||
* SrcsetTag constructor. | ||
* @param null $data | ||
*/ | ||
public function __construct($data = null, array $options = []) | ||
{ | ||
if (!$file || !is_a($file, 'Kirby\Cms\File')) { | ||
return null; | ||
if (is_a($data, 'Kirby\Cms\KirbyTag')) { | ||
$this->parent = $data->parent(); | ||
$options = $this->dataFromTag($data); | ||
} elseif (is_a($data, 'Kirby\Cms\File') || is_a($data, 'Kirby\Cms\FileVersion')) { | ||
$this->parent = $data->parent(); | ||
$options['value'] = $data->filename(); | ||
} elseif (is_array($data)) { | ||
$this->parent = A::get($data, 'parent'); | ||
$options = $data; | ||
} | ||
|
||
$lazy = !is_null($lazy) ? $lazy : option('bnomei.srcset.lazy', false); | ||
$isLazy = $lazy !== null && $lazy !== false; | ||
$defaults = [ | ||
'lazy' => option('bnomei.srcset.lazy'), | ||
'prefix' => option('bnomei.srcset.prefix'), | ||
'autosizes' => option('bnomei.srcset.autosizes'), | ||
'figure' => option('bnomei.srcset.figure') === true, | ||
'quality' => intval(option('thumbs.quality', 80)), | ||
]; | ||
$this->options = $this->normalizeData(array_merge($defaults, $options)); | ||
|
||
$img = $file; | ||
if ($fallbackType = option('bnomei.srcset.fallback.type')) { | ||
$img = $file->parent()->file(str_replace($img->extension(), $fallbackType, $img->filename())); | ||
if ($this->parent) { | ||
$this->options['file'] = $this->parent->file((string)A::get($this->options, 'value')); | ||
} | ||
|
||
return snippet($snippet, [ | ||
'file' => $file, | ||
'lazy' => (is_string($lazy) ? $lazy : ($lazy ? 'lazyload' : '')), | ||
'isLazy' => $isLazy, | ||
'preset' => is_array($preset) ? implode(', ', $preset) : $preset, | ||
'img' => \Bnomei\Srcset::img($img, $preset, $lazy), | ||
'sources' => \Bnomei\Srcset::sources($file, $preset, $lazy), | ||
'autoSizes' => option('bnomei.srcset.autosizes'), | ||
'prefix' => $prefix ? $prefix : option('bnomei.srcset.prefix'), | ||
'class' => $class ? $class : option('bnomei.srcset.class', ''), | ||
'imgclass' => $imgclass ? $imgclass : option('bnomei.srcset.imgclass', ''), | ||
], true); | ||
$this->text = $this->imageKirbytagFromData($this->options); | ||
$this->text = $this->applySrcset($this->text, $this->options); | ||
} | ||
|
||
public static function resizeWithType(\Kirby\Cms\File $file, int $width, string $type) | ||
/** | ||
* @param null $key | ||
* @return array|mixed | ||
*/ | ||
public function option($key = null) | ||
{ | ||
if (!$file || !is_a($file, 'Kirby\Cms\File')) { | ||
return null; | ||
if ($key) { | ||
return A::get($this->options, $key); | ||
} | ||
|
||
$resize = option('bnomei.srcset.resize', null); | ||
if ($resize && is_callable($resize)) { | ||
return $resize($file, $width, $type); | ||
} else { | ||
return $file->resize($width); | ||
} | ||
return $this->options; | ||
} | ||
|
||
/** | ||
* @return array | ||
*/ | ||
public function attrKeys(): array | ||
{ | ||
return array_merge( | ||
['value'], | ||
KirbyTag::$types['image']['attr'], | ||
['sizes', 'lazy', 'prefix', 'autosizes'] | ||
); | ||
} | ||
|
||
public static function presetWidthsForFile($file, $preset = 'default') | ||
/** | ||
* @param array $data | ||
* @return array | ||
*/ | ||
public function normalizeData(array $data) | ||
{ | ||
$presets = option('bnomei.srcset.presets'); | ||
$presetWidths = is_array($preset) ? $preset : \Kirby\Toolkit\A::get($presets, $preset, []); | ||
if (in_array(0, $presetWidths) || count($presetWidths) == 0) { | ||
$presetWidths[] = intval($file->width()); | ||
$norm = []; | ||
foreach ($data as $key => $val) { | ||
if (is_string($val) && $val === 'true') { | ||
$val = true; | ||
} | ||
if (is_string($val) && $val === 'false') { | ||
$val = false; | ||
} | ||
if (is_string($val) && $val === 'null') { | ||
$val = null; | ||
} | ||
if (is_null($val)) { | ||
continue; | ||
} | ||
$norm[$key] = $val; | ||
} | ||
sort($presetWidths, SORT_NUMERIC); | ||
$presetWidths = array_unique($presetWidths); | ||
return $presetWidths; | ||
return $norm; | ||
} | ||
|
||
public static function img(\Kirby\Cms\File $file, $preset = 'default', $lazy = false) | ||
/** | ||
* @param KirbyTag $tag | ||
* @return array | ||
*/ | ||
public function dataFromTag(KirbyTag $tag) | ||
{ | ||
if (!$file && !is_a($file, 'Kirby\Cms\File')) { | ||
return null; | ||
$data = []; | ||
foreach ($this->attrKeys() as $attr) { | ||
$val = $tag->$attr; | ||
if (is_null($val)) { | ||
continue; | ||
} | ||
$data[$attr] = $tag->$attr; | ||
} | ||
$captionFieldname = option('bnomei.srcset.img.alt.fieldname', 'caption'); | ||
$presetWidths = self::presetWidthsForFile($file, $preset); | ||
return [ | ||
'src' => $file->resize($presetWidths[count($presetWidths) - 1])->url(), // trigger thumb if needed | ||
'alt' => $file->$captionFieldname()->isNotEmpty() ? $file->$captionFieldname()->value() : $file->filename(), | ||
]; | ||
return $data; | ||
} | ||
|
||
public static function sources(\Kirby\Cms\File $file, $preset = 'default', $lazy = false) | ||
/** | ||
* @param array $data | ||
* @return string | ||
*/ | ||
public function imageKirbytagFromData(array $data = []): string | ||
{ | ||
if (!$file && !is_a($file, 'Kirby\Cms\File')) { | ||
return null; | ||
$attrs = ['(image: ' . self::PLACEHOLDER]; // A::get($data, 'value') | ||
$lazy = A::get($data, 'lazy'); | ||
if ($lazy) { | ||
$data['imgclass'] = trim(A::get($data, 'imgclass', '') . ' ' . $lazy); | ||
} | ||
foreach (KirbyTag::$types['image']['attr'] as $attr) { | ||
$val = A::get($data, $attr); | ||
if (!$val || strlen(strval($val)) === 0) { | ||
continue; | ||
} | ||
$attrs[] = $attr . ': ' . $val; | ||
} | ||
$attrs[] = ')'; | ||
$text = implode(' ', $attrs); | ||
|
||
$presetWidths = self::presetWidthsForFile($file, $preset); | ||
$text = kirby()->kirbytags($text, $data); | ||
if (!A::get($data, 'figure')) { | ||
$text = str_replace(['<figure>', '</figure>'], ['', ''], $text); | ||
} | ||
return $text; | ||
} | ||
|
||
/** | ||
* @param string $text | ||
* @param array $data | ||
* @return string | ||
*/ | ||
public function applySrcset(string $text, array $data = []): string | ||
{ | ||
$srcfile = new SrcsetFile( | ||
A::get($data, 'file'), | ||
A::get($data, 'sizes'), | ||
A::get($data, 'width'), | ||
A::get($data, 'heigth'), | ||
A::get($data, 'quality') | ||
); | ||
|
||
$types = option('bnomei.srcset.types', []); | ||
if (count($types) == 0 || option('bnomei.srcset.types.addsource', false)) { | ||
$types[] = $file->mime(); | ||
$srcset = [ | ||
A::get($data, 'prefix') . 'src' => $srcfile->src(), | ||
A::get($data, 'prefix') . 'srcset' => $srcfile->srcset(), | ||
]; | ||
if ($this->option('debug')) { | ||
$srcset['data-thumb-srcset'] = $srcfile->sizes(); | ||
} | ||
$autosizes = A::get($data, 'autosizes'); | ||
if ($autosizes === true) { | ||
$autosizes = 'auto'; | ||
} | ||
if ($autosizes) { | ||
$srcset['data-sizes'] = $autosizes; | ||
} | ||
|
||
$sources = []; | ||
foreach ($types as $t) { | ||
$srcset = []; | ||
foreach ($presetWidths as $p) { | ||
if ($p <= 0) { | ||
continue; | ||
} | ||
$img = static::resizeWithType($file, intval($p), strval($t)); | ||
if ($img && (is_a($img, 'Kirby\CMS\FileVersion') || is_a($img, 'Kirby\CMS\File'))) { | ||
$srcset[] = $img->url() . ' ' . $p . 'w'; | ||
} | ||
} | ||
$sources[] = [ | ||
'srcset' => implode(', ', $srcset), | ||
'type' => $t, | ||
]; | ||
$attrs = []; | ||
foreach ($srcset as $key => $value) { | ||
$attrs[] = '' . $key . '="' . $value . '"'; | ||
} | ||
|
||
return $sources; | ||
$text = str_replace( | ||
'src="' . self::PLACEHOLDER . '"', | ||
implode(' ', $attrs), | ||
$text | ||
); | ||
|
||
return $text; | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function html(): string | ||
{ | ||
return trim(strval($this->text)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Bnomei; | ||
|
||
use Kirby\Cms\File; | ||
use Kirby\Toolkit\Str; | ||
|
||
final class SrcsetFile | ||
{ | ||
/* | ||
* @var File | ||
*/ | ||
private $file; | ||
|
||
/* | ||
* @var array|string|null | ||
*/ | ||
private $sizes; | ||
|
||
/* | ||
* @var int | ||
*/ | ||
private $width; | ||
|
||
/* | ||
* @var int | ||
*/ | ||
private $height; | ||
|
||
/* | ||
* @var int | ||
*/ | ||
private $quality; | ||
|
||
/** | ||
* SrcsetFile constructor. | ||
* @param File $file | ||
* @param null $sizes | ||
* @param int|null $width | ||
* @param int|null $height | ||
* @param int|null $quality | ||
*/ | ||
public function __construct(File $file, $sizes = null, ?int $width = null, ?int $height = null, ?int $quality = null) | ||
{ | ||
$this->file = $file; | ||
|
||
if (is_callable($sizes)) { | ||
$sizes = $sizes(); | ||
} | ||
if (is_string($sizes) && (Str::contains($sizes, ' ') || Str::contains($sizes, ','))) { | ||
$sizes = str_replace(['[', ']', ',', ' ', 'px'], ['', '', ' ', ' ', ''], $sizes); | ||
$sizes = array_map(function ($v) { | ||
return intval(trim($v)); | ||
}, explode(' ', $sizes)); | ||
} | ||
$this->sizes = $sizes; | ||
|
||
$this->width = $width; | ||
$this->height = $height; | ||
$this->quality = $quality; | ||
} | ||
|
||
/** | ||
* @return string|null | ||
*/ | ||
public function src(): ?string | ||
{ | ||
// NOTE: call to trigger thumb component | ||
return $this->file->resize($this->width, $this->height, $this->quality)->url(); | ||
} | ||
|
||
/** | ||
* @return string|null | ||
*/ | ||
public function srcset(): ?string | ||
{ | ||
return $this->file->srcset($this->sizes); | ||
} | ||
|
||
/** | ||
* @return string | ||
*/ | ||
public function sizes(): string | ||
{ | ||
if (is_array($this->sizes)) { | ||
return json_encode($this->sizes, JSON_FORCE_OBJECT); | ||
} | ||
return strval($this->sizes); | ||
} | ||
} |
Oops, something went wrong.