blocks and tags outside a small allow list go. */ public function html(string $value): string { if ($this->unfiltered) { return $value; } $value = (string) preg_replace('#]*>.*?#is', '', str_replace(chr(0), '', $value)); return (string) preg_replace( '#]*>#i', '', $value ); } public function code(string $value): string { return $value; } /** * Like esc_url_raw: spaces become %20, characters outside its allow list (tags, quotes, * braces, NUL) go, %0d/%0a are removed repeatedly, javascript: gives ''. */ public function url(string $value): string { $value = str_replace(' ', '%20', trim($value)); $value = (string) preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\x80-\xff]|i', '', $value); do { $before = $value; $value = str_replace(['%0d', '%0a', '%0D', '%0A'], '', $value); } while ($value !== $before); return str_starts_with(strtolower($value), 'javascript:') ? '' : $value; } public function allowsUnfilteredHtml(): bool { return $this->unfiltered; } }; } public static function media(): MediaResolver { return new class implements MediaResolver { public function image(int $id): ?array { return match ($id) { 33 => ['url' => 'https://kunde.test/wp-content/uploads/team.jpg', 'alt' => 'Unser Team'], 12 => ['url' => 'https://kunde.test/wp-content/uploads/halle.jpg', 'alt' => ''], default => null, }; } }; } public static function placeholders(): Placeholders { return new Placeholders(DesignSystemTest::sample()); } public static function attrWriter(bool $unfiltered = false): AttrWriter { return new AttrWriter(ModuleCatalogTest::sampleCatalog(), self::placeholders(), self::sanitizer($unfiltered)); } /** * @param array>>|null $modules Short form per * type instead of ShortformMap (to reach paths the curated map never names). */ public static function shortform(bool $unfiltered = false, ?array $modules = null): ShortformWriter { return new ShortformWriter(self::placeholders(), self::media(), self::attrWriter($unfiltered), $modules); } }