Složitější vytváření maker

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Oli
Člen | 1215
+
0
-

Ahoj,
hledal jsem, ale nikde jsem nenašel žádný článek, který by makra rozebral dopodrobna. Např. jaký proměnný jsou dostupný v šabloně (_control, _presenter, …), jak si vybrat konkrétní atribut a pracovat s ním (viz divoký parsování atributů níže) atd…

Chtěl bych za použití nette-webimages vytvořit makro, který by udělalo hezčí syntax pro picturefill a zároveň by pak (třeba jednou) jen zahodilo picturefill a používalo nativní podporu srcset. To makro se mě nějak povedlo splácnout, ale přijde mě to takový dost divoký.

Oproti defaultnímu použití webimages tam přidávám nepovinné atributy path a type. Mělo by to fungovat tak, že se uvede nejmenší fotka jako první atribut (src). Srcset potom obsahuje jen ty části cesty, které se liší od obrázku ze src.

Šlo by to nějak učesat nebo to je uplně blbě (kde, proč, jak to udělat správně)? Je to můj první pokus o trochu komplexnější makro, tak prosím o shovívavost :-). (vím že to nepokrývá všechny stavy a není to blbuvzodrný, ale je to jen první nástřel/funkční prototyp)

Díky za připomínky/názory.

{picture src => "P1030303.jpg, 160, 120, path => test, type => photos",
	srcset => "(width => 380, height => 240) 600w, (width => 1600, height => 1200) 1600w"}
$me->addMacro('picture', 'echo %modify(My\Macro::prepareArguments([%node.args], $_presenter))');

// ...

public static function prepareArguments(array $arguments, Presenter $presenter)
	{
		$string = '<span data-picture>';
		$src = NULL;
		$image = NULL;

		foreach ($arguments as $key => $value) {
			if ($key === 'src' || (!array_key_exists('src', $arguments) && $key === 0))
			{
				$value = self::clearData($value);
				foreach ($value as $valueKey => $item)
				{
					if (Strings::contains($item, '=>'))
					{
						$splited = explode('=>', $item);
						$splited[1] = str_replace('"', '', $splited[1]);
						$splited[1] = str_replace('\'', '', $splited[1]);
						$value[$splited[0]] = $splited[1];
						unset($value[$valueKey]);
					}
				}
				$src = \DotBlue\WebImages\Macros::prepareArguments($value);
				$link = $presenter->link("//:Nette:Micro:", $src);
				$string .= "<span data-src=\"" . $link . "\"></span>";
				$image = $link;
			} elseif ($key === 'srcset')
			{
				foreach (Strings::matchAll($value, '~\((.*?)\) [0-9]+w~') as $item)
				{
					$args = NULL;
					$width = explode(') ', $item[0]);
					$viewport =  (int) substr($width[1], 0, -1);

					foreach (self::clearData($item[1]) as $key => $photoArgs)
					{
						$photo = explode('=>', $photoArgs);
						$args[$photo[0]] = $photo[1];
					}
					$args = $args + $src;
					$link = $presenter->link("//:Nette:Micro:", $args);
					$string .= "<span data-src=\"" . $link . "\" data-media=\"(min-width: " . $viewport . "px)\"></span>";
				}
			}
		}

		if (!is_null($image))
		{
			$string .= '<noscript><img src="' . $image . '"></noscript>';
		}

		$string .= '</span>';

		return $string;
	}


	private static function clearData($data)
	{
		$data = str_replace([', ', ' => '], [',', '=>'], $data);
		$data = explode(',', $data);
		return $data;
	}

Výstup to vygeneruje

<span data-picture>
	<span data-src="http://localhost/projekt/photos/test/160x120/P1030303.jpg"></span>
	<span data-src="http://localhost/projekt/photos/test/380x240/P1030303.jpg" data-media="(min-width: 600px)"></span>
	<span data-src="http://localhost/projekt/photos/test/1600x1200/P1030303.jpg" data-media="(min-width: 1600px)"></span>

	<noscript>
		<img src="http://localhost/projekt/photos/test/160x120/P1030303.jpg">
	</noscript>
</span>