Cleanup some build/quality check stuff

This commit is contained in:
Timothy Warren 2020-03-13 09:53:31 -04:00
parent c60b821bca
commit 39f672b35f
26 changed files with 232 additions and 258 deletions

1
Jenkinsfile vendored
View File

@ -5,6 +5,7 @@ pipeline {
agent any
steps {
sh 'curl -sS https://getcomposer.org/installer | php'
sh 'rm -rf ./vendor'
sh 'rm -f composer.lock'
sh 'php composer.phar install --ignore-platform-reqs'
}

View File

@ -60,6 +60,7 @@ class RoboFile extends Tasks {
$this->lint();
$this->phploc(TRUE);
$this->phpcs(TRUE);
$this->phpmd(TRUE);
$this->dependencyReport();
$this->phpcpdReport();
}
@ -157,6 +158,30 @@ class RoboFile extends Tasks {
$this->_run($cmd_parts);
}
public function phpmd($report = FALSE): void
{
$report_cmd_parts = [
'vendor/bin/phpmd',
'./src',
'xml',
'cleancode,codesize,controversial,design,naming,unusedcode',
'--exclude ParallelAPIRequest',
'--reportfile ./build/logs/phpmd.xml'
];
$normal_cmd_parts = [
'vendor/bin/phpmd',
'./src',
'ansi',
'cleancode,codesize,controversial,design,naming,unusedcode',
'--exclude ParallelAPIRequest'
];
$cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
$this->_run($cmd_parts);
}
/**
* Run the phploc tool
*
@ -236,6 +261,10 @@ class RoboFile extends Tasks {
glob('*.php')
);
$files = array_filter($files, static function(string $value) {
return strpos($value, '__snapshots__') === FALSE;
});
sort($files);
return $files;

View File

@ -1,81 +0,0 @@
<?php
/**
* CodeIgniter_Sniffs_Operators_LogicalOperatorAndSniff.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2006 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
/**
* CodeIgniter_Sniffs_Operators_LogicalOperatorAndSniff.
*
* Ensures that the logical operator 'AND' is in upper case and suggest the use of its symbolic equivalent.
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2006 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
namespace CodeIgniter\Sniffs\Operators;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
class LogicalOperatorAndSniff implements Sniff
{
/**
* Returns an array of tokens this test wants to listen for: symbolic and literal operators and.
*
* @return array
*/
public function register()
{
return array(
T_LOGICAL_AND,
);
}//end register()
/**
* Processes this test, when one of its tokens is encountered.
*
* @param File $phpcsFile The current file being scanned.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
*
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$operator_token = $tokens[$stackPtr];
$operator_string = $operator_token['content'];
$operator_code = $operator_token['code'];
if ($operator_string !== strtoupper($operator_string)) {
$error_message = 'Logical operator should be in upper case;'
. ' use "' . strtoupper($operator_string)
. '" instead of "' . $operator_string . '"';
$phpcsFile->addError($error_message, $stackPtr, 'LowercaseLogicalOperator');
}
$warning_message = 'The symbolic form "&&" is preferred over the literal form "AND"';
$phpcsFile->addWarning($warning_message, $stackPtr, 'UseOfLiteralAndOperator');
}//end process()
}//end class
?>

View File

@ -1,84 +0,0 @@
<?php
/**
* CodeIgniter_Sniffs_Operators_UppercaseLogicalOperatorOrSniff.
*
* PHP version 5
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2006 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
/**
* CodeIgniter_Sniffs_Operators_UppercaseLogicalOperatorOrSniff.
*
* Ensures that the logical operator 'OR' is in upper cases and its symbolic equivalent.
*
* @category PHP
* @package PHP_CodeSniffer
* @author Thomas Ernest <thomas.ernest@baobaz.com>
* @copyright 2006 Thomas Ernest
* @license http://thomas.ernest.fr/developement/php_cs/licence GNU General Public License
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
namespace CodeIgniter\Sniffs\Operators;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Files\File;
class UppercaseLogicalOperatorOrSniff implements Sniff
{
/**
* Returns an array of tokens this test wants to listen for: literal and symbolic operators or.
*
* @return array
*/
public function register()
{
return array(
T_BOOLEAN_OR,
T_LOGICAL_OR,
);
}//end register()
/**
* Processes this test, when one of its tokens is encountered.
*
* @param File $phpcsFile The current file being scanned.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
*
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$operator_token = $tokens[$stackPtr];
$operator_string = $operator_token['content'];
$operator_code = $operator_token['code'];
if ($operator_code == T_BOOLEAN_OR) {
$error_message = 'Logical operator "' . $operator_string
. '" is prohibited; use "OR" instead';
$phpcsFile->addError($error_message, $stackPtr, 'UseOf||InsteadOfOR');
}
// it is literal, if it is not symbolic
else if ($operator_string !== strtoupper($operator_string)) {
$error_message = 'Logical operator should be in upper case;'
. ' use "' . strtoupper($operator_string)
. '" instead of "' . $operator_string . '"';
$phpcsFile->addError($error_message, $stackPtr, 'UseOfLowercaseOr');
}
}//end process()
}//end class
?>

View File

@ -23,7 +23,7 @@
<!-- Classes and functions should be commented -->
<rule ref="PEAR.Commenting.ClassComment"/>
<rule ref="PEAR.Commenting.FunctionComment"/>
<rule ref="Squiz.Commenting.FunctionCommentThrowTag"/>
<!-- <rule ref="Squiz.Commenting.FunctionCommentThrowTag"/>-->
<!-- Use warnings for docblock comments for files and variables, since nothing is cleary explained -->
<rule ref="PEAR.Commenting.FileComment">
<properties>

View File

@ -46,15 +46,15 @@
"filp/whoops": "^2.1",
"pdepend/pdepend": "^2.2",
"phploc/phploc": "^5.0",
"phpmd/phpmd": "^2.4",
"phpmd/phpmd": "^2.8",
"phpstan/phpstan": "^0.12.0",
"phpunit/phpunit": "^8.4.3",
"roave/security-advisories": "dev-master",
"robmorgan/phinx": "^0.10.6",
"sebastian/phpcpd": "^4.1.0",
"spatie/phpunit-snapshot-assertions": "^2.2.1",
"spatie/phpunit-snapshot-assertions": "^4",
"squizlabs/php_codesniffer": "^3.2.2",
"symfony/var-dumper": "^4.4.1",
"symfony/var-dumper": "^5",
"theseer/phpdox": "*"
},
"scripts": {

View File

@ -78,10 +78,10 @@
</source>
<!-- git vcs information -->
<source type="git">
<!-- <source type="git">
<git binary="/usr/bin/git" />
<history enabled="true" limit="15" cache="${phpDox.project.workdir}/gitlog.xml" />
</source>
</source> -->
<!-- PHP Code Sniffer findings -->
<source type="checkstyle">
@ -89,24 +89,18 @@
</source>
<!-- PHPMessDetector -->
<!--
<source type="pmd">
<file name="pmd.xml" />
<file name="phpmd.xml" />
</source>
-->
<!-- PHPUnit Coverage XML -->
<source type="phpunit">
<coverage path="coverage/clover.xml" />
<!-- <source type="phpunit"> -->
<!-- <coverage path="coverage" /> -->
<!-- <coverage path="clover.xml" />-->
<!-- @path - the directory where the xml code coverage report can be found -->
<!--<filter directory="${phpDox.project.source}" />-->
<!-- @directory - path of the phpunit config whitelist filter directory -->
</source>
<source type="phpunit">
<filter directory="${phpDox.project.source}" />
</source>
<!-- </source> -->
</enrich>
<!-- <build engine="..." enabled="true" output="..." /> -->

View File

@ -1,55 +0,0 @@
<?xml version="1.0"?>
<psalm
totallyTyped="false"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="src" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
<issueHandlers>
<LessSpecificReturnType errorLevel="info" />
<!-- level 3 issues - slightly lazy code writing, but provably low false-negatives -->
<DeprecatedMethod errorLevel="info" />
<DeprecatedProperty errorLevel="info" />
<DeprecatedClass errorLevel="info" />
<DeprecatedConstant errorLevel="info" />
<DeprecatedFunction errorLevel="info" />
<DeprecatedInterface errorLevel="info" />
<DeprecatedTrait errorLevel="info" />
<InternalMethod errorLevel="info" />
<InternalProperty errorLevel="info" />
<InternalClass errorLevel="info" />
<MissingClosureReturnType errorLevel="info" />
<MissingReturnType errorLevel="info" />
<MissingPropertyType errorLevel="info" />
<InvalidDocblock errorLevel="info" />
<MisplacedRequiredParam errorLevel="info" />
<PropertyNotSetInConstructor errorLevel="info" />
<MissingConstructor errorLevel="info" />
<MissingClosureParamType errorLevel="info" />
<MissingParamType errorLevel="info" />
<RedundantCondition errorLevel="info" />
<DocblockTypeContradiction errorLevel="info" />
<RedundantConditionGivenDocblockType errorLevel="info" />
<UnresolvableInclude errorLevel="info" />
<RawObjectIteration errorLevel="info" />
<InvalidStringClass errorLevel="info" />
</issueHandlers>
</psalm>

View File

@ -161,7 +161,7 @@ class Controller {
return;
}
if (null === $url)
if (NULL === $url)
{
$url = $util->isViewPage()
? (string) $this->request->getUri()
@ -201,7 +201,6 @@ class Controller {
'Forbidden',
'You must <a href="/login">log in</a> to perform this action.'
);
die();
}
}
@ -297,18 +296,18 @@ class Controller {
* @param int $httpCode
* @param string $title
* @param string $message
* @param string $long_message
* @param string $longMessage
* @throws InvalidArgumentException
* @throws ContainerException
* @throws NotFoundException
* @return void
*/
public function errorPage(int $httpCode, string $title, string $message, string $long_message = ''): void
public function errorPage(int $httpCode, string $title, string $message, string $longMessage = ''): void
{
$this->outputHTML('error', [
'title' => $title,
'message' => $message,
'long_message' => $long_message
'long_message' => $longMessage
], NULL, $httpCode);
}
@ -384,7 +383,7 @@ class Controller {
*
* @param string $template
* @param array $data
* @param HtmlView|null $view
* @param HtmlView|NULL $view
* @param int $code
* @throws InvalidArgumentException
* @throws ContainerException
@ -393,7 +392,7 @@ class Controller {
*/
protected function outputHTML(string $template, array $data = [], $view = NULL, int $code = 200): void
{
if (null === $view)
if (NULL === $view)
{
$view = new HtmlView($this->container);
}

View File

@ -133,11 +133,6 @@ const SETTINGS_MAP = [
],
],
],
/* 'options' => [
'type' => 'subfield',
'title' => 'Options',
'fields' => [],
] */
],
'config' => [
'kitsu_username' => [

View File

@ -0,0 +1,28 @@
empty: false
id: '15839442'
mal_id: '33206'
episodes:
watched: '-'
total: '-'
length: null
airing:
status: 'Currently Airing'
started: '2017-01-12'
ended: null
anime:
empty: false
age_rating: null
cover_image: 'https://media.kitsu.io/anime/poster_images/12243/small.jpg?1481144116'
genres: [Comedy, Fantasy, 'Slice of Life']
id: '12243'
show_type: TV
slug: kobayashi-san-chi-no-maid-dragon
streaming_links: { }
title: 'Kobayashi-san Chi no Maid Dragon'
titles: ['Miss Kobayashi''s Dragon Maid', 小林さんちのメイドラゴン]
notes: null
private: false
rewatching: false
rewatched: 0
user_rating: '-'
watching_status: current

View File

@ -0,0 +1,13 @@
empty: false
id: 14047981
anilist_item_id: null
mal_id: null
data:
empty: false
notes: 'Very formulaic.'
private: false
progress: 38
ratingTwenty: 16
reconsumeCount: 0
reconsuming: false
status: current

View File

@ -0,0 +1,13 @@
empty: false
id: 14047981
anilist_item_id: null
mal_id: '12345'
data:
empty: false
notes: 'Very formulaic.'
private: true
progress: 38
ratingTwenty: 16
reconsumeCount: 0
reconsuming: true
status: current

View File

@ -0,0 +1,12 @@
empty: false
id: 14047983
anilist_item_id: null
mal_id: '12347'
data:
empty: false
notes: ''
private: true
progress: 12
reconsumeCount: 0
reconsuming: true
status: current

View File

@ -0,0 +1,33 @@
empty: false
characters: { }
staff: { }
age_rating: R
age_rating_guide: 'Violence, Profanity'
cover_image: 'https://media.kitsu.io/anime/poster_images/7442/small.jpg?1418580054'
episode_count: 25
episode_length: 24
genres: { }
id: 32344
included:
categories: { 23: { name: 'Super Power', slug: super-power, description: null }, 11: { name: Fantasy, slug: fantasy, description: '' }, 4: { name: Drama, slug: drama, description: '' }, 1: { name: Action, slug: action, description: '' } }
mappings: { 5686: { externalSite: myanimelist/anime, externalId: '16498', relationships: { media: { links: { self: 'https://kitsu.io/api/edge/mappings/5686/relationships/media', related: 'https://kitsu.io/api/edge/mappings/5686/media' } } } }, 14153: { externalSite: thetvdb/series, externalId: '267440', relationships: { media: { links: { self: 'https://kitsu.io/api/edge/mappings/14153/relationships/media', related: 'https://kitsu.io/api/edge/mappings/14153/media' } } } }, 15073: { externalSite: thetvdb/season, externalId: '514060', relationships: { media: { links: { self: 'https://kitsu.io/api/edge/mappings/15073/relationships/media', related: 'https://kitsu.io/api/edge/mappings/15073/media' } } } } }
streamingLinks: { 103: { url: 'http://www.crunchyroll.com/attack-on-titan', subs: [en], dubs: [ja], relationships: { streamer: { links: { self: 'https://kitsu.io/api/edge/streaming-links/103/relationships/streamer', related: 'https://kitsu.io/api/edge/streaming-links/103/streamer' } }, media: { links: { self: 'https://kitsu.io/api/edge/streaming-links/103/relationships/media', related: 'https://kitsu.io/api/edge/streaming-links/103/media' } } } }, 102: { url: 'http://www.hulu.com/attack-on-titan', subs: [en], dubs: [ja], relationships: { streamer: { links: { self: 'https://kitsu.io/api/edge/streaming-links/102/relationships/streamer', related: 'https://kitsu.io/api/edge/streaming-links/102/streamer' } }, media: { links: { self: 'https://kitsu.io/api/edge/streaming-links/102/relationships/media', related: 'https://kitsu.io/api/edge/streaming-links/102/media' } } } }, 101: { url: 'http://www.funimation.com/shows/attack-on-titan/videos/episodes', subs: [en], dubs: [ja], relationships: { streamer: { links: { self: 'https://kitsu.io/api/edge/streaming-links/101/relationships/streamer', related: 'https://kitsu.io/api/edge/streaming-links/101/streamer' } }, media: { links: { self: 'https://kitsu.io/api/edge/streaming-links/101/relationships/media', related: 'https://kitsu.io/api/edge/streaming-links/101/media' } } } }, 100: { url: t, subs: [en], dubs: [ja], relationships: { streamer: { links: { self: 'https://kitsu.io/api/edge/streaming-links/100/relationships/streamer', related: 'https://kitsu.io/api/edge/streaming-links/100/streamer' } }, media: { links: { self: 'https://kitsu.io/api/edge/streaming-links/100/relationships/media', related: 'https://kitsu.io/api/edge/streaming-links/100/media' } } } } }
show_type: TV
slug: attack-on-titan
status: 'Finished Airing'
streaming_links:
- { meta: { name: Crunchyroll, link: true, image: streaming-logos/crunchyroll.svg }, link: 'http://www.crunchyroll.com/attack-on-titan', subs: [en], dubs: [ja] }
- { meta: { name: Funimation, link: true, image: streaming-logos/funimation.svg }, link: 'http://www.funimation.com/shows/attack-on-titan/videos/episodes', subs: [en], dubs: [ja] }
- { meta: { name: Hulu, link: true, image: streaming-logos/hulu.svg }, link: 'http://www.hulu.com/attack-on-titan', subs: [en], dubs: [ja] }
- { meta: { name: Netflix, link: false, image: streaming-logos/netflix.svg }, link: t, subs: [en], dubs: [ja] }
synopsis: |
Several hundred years ago, humans were nearly exterminated by titans. Titans are typically several stories tall, seem to have no intelligence, devour human beings and, worst of all, seem to do it for the pleasure rather than as a food source. A small percentage of humanity survived by enclosing themselves in a city protected by extremely high walls, even taller than the biggest of titans. Flash forward to the present and the city has not seen a titan in over 100 years. Teenage boy Eren and his foster sister Mikasa witness something horrific as the city walls are destroyed by a colossal titan that appears out of thin air. As the smaller titans flood the city, the two kids watch in horror as their mother is eaten alive. Eren vows that he will murder every single titan and take revenge for all of mankind.
(Source: ANN)
title: 'Attack on Titan'
titles:
- 'Attack on Titan'
- 'Shingeki no Kyojin'
- 進撃の巨人
trailer_id: n4Nj6Y_SNYI
url: 'https://kitsu.io/anime/attack-on-titan'

View File

@ -1,5 +1,60 @@
- null
- null
- null
- null
- null
-
empty: false
id: '15084773'
mal_id: '26769'
chapters: { read: 67, total: '-' }
volumes: { read: '-', total: '-' }
manga: { empty: false, genres: [Comedy, Romance, School, 'Slice of Life', Thriller], id: '20286', image: 'https://media.kitsu.io/manga/poster_images/20286/small.jpg?1434293999', slug: bokura-wa-minna-kawaisou, title: 'Bokura wa Minna Kawaisou', titles: { }, type: Manga, url: 'https://kitsu.io/manga/bokura-wa-minna-kawaisou' }
reading_status: current
notes: ''
rereading: false
reread: 0
user_rating: 9
-
empty: false
id: '15085607'
mal_id: '16'
chapters: { read: 17, total: 120 }
volumes: { read: '-', total: 14 }
manga: { empty: false, genres: [Comedy, Ecchi, Harem, Romance, Sports], id: '47', image: 'https://media.kitsu.io/manga/poster_images/47/small.jpg?1434249493', slug: love-hina, title: 'Love Hina', titles: { }, type: Manga, url: 'https://kitsu.io/manga/love-hina' }
reading_status: current
notes: ''
rereading: false
reread: 0
user_rating: 7
-
empty: false
id: '15084529'
mal_id: '35003'
chapters: { read: 16, total: '-' }
volumes: { read: '-', total: '-' }
manga: { empty: false, genres: [Comedy, Ecchi, 'Gender Bender', Romance, School, Sports, Supernatural], id: '11777', image: 'https://media.kitsu.io/manga/poster_images/11777/small.jpg?1438784325', slug: yamada-kun-to-7-nin-no-majo, title: 'Yamada-kun to 7-nin no Majo', titles: ['Yamada-kun and the Seven Witches'], type: Manga, url: 'https://kitsu.io/manga/yamada-kun-to-7-nin-no-majo' }
reading_status: current
notes: ''
rereading: false
reread: 0
user_rating: 9
-
empty: false
id: '15312827'
mal_id: '78523'
chapters: { read: 68, total: '-' }
volumes: { read: '-', total: '-' }
manga: { empty: false, genres: [Romance, School, 'Slice of Life'], id: '27175', image: 'https://media.kitsu.io/manga/poster_images/27175/small.jpg?1464379411', slug: relife, title: ReLIFE, titles: { }, type: Manga, url: 'https://kitsu.io/manga/relife' }
reading_status: current
notes: ''
rereading: false
reread: 0
user_rating: '-'
-
empty: false
id: '15084769'
mal_id: '60815'
chapters: { read: 43, total: '-' }
volumes: { read: '-', total: '-' }
manga: { empty: false, genres: [Comedy, School, 'Slice of Life'], id: '25491', image: 'https://media.kitsu.io/manga/poster_images/25491/small.jpg?1434305043', slug: joshikausei, title: Joshikausei, titles: { }, type: Manga, url: 'https://kitsu.io/manga/joshikausei' }
reading_status: current
notes: ''
rereading: false
reread: 0
user_rating: 8

View File

@ -0,0 +1,19 @@
empty: false
characters: { }
chapter_count: '-'
cover_image: 'https://media.kitsu.io/manga/poster_images/20286/small.jpg?1434293999'
genres: { }
id: '20286'
included:
genres: { 3: { attributes: { name: Comedy, slug: comedy, description: null } }, 24: { attributes: { name: School, slug: school, description: null } }, 16: { attributes: { name: 'Slice of Life', slug: slice-of-life, description: '' } }, 14: { attributes: { name: Romance, slug: romance, description: '' } }, 18: { attributes: { name: Thriller, slug: thriller, description: null } } }
mappings: { 48014: { attributes: { externalSite: myanimelist/manga, externalId: '26769' } } }
manga_type: manga
staff: { }
synopsis: |
Usa, a high-school student aspiring to begin a bachelor lifestyle, moves into a new apartment only to discover that he not only shares a room with a perverted roommate that has an obsession for underaged girls, but also that another girl, Ritsu, a love-at-first-sight, is living in the same building as well!
(Source: Kirei Cake)
title: 'Bokura wa Minna Kawaisou'
titles:
- null
url: 'https://kitsu.io/manga/bokura-wa-minna-kawaisou'
volume_count: '-'

View File

@ -124,11 +124,6 @@ const SETTINGS_MAP = [
],
],
],
/* 'options' => [
'type' => 'subfield',
'title' => 'Options',
'fields' => [],
] */
],
'config' => [
'kitsu_username' => [

View File

@ -0,0 +1 @@
<picture><source srcset="https://www.example.com/image.webp" type="image/webp" /><source srcset="https://www.example.com/image.jpg" type="image/jpeg" /><img src="https://www.example.com/image.jpg" alt="" /></picture>

View File

@ -0,0 +1 @@
<picture><source srcset="https://localhost/assets/images/anime/15424.webp" type="image/webp" /><source srcset="https://localhost/assets/images/anime/15424.jpg" type="image/jpeg" /><img src="https://localhost/assets/images/anime/15424.jpg" alt="" /></picture>

View File

@ -0,0 +1 @@
<picture><source srcset="https://localhost/assets/images/avatar/25.bmp" type="image/bmp" /><source srcset="https://localhost/assets/images/avatar/25.gif" type="image/gif" /><img src="https://localhost/assets/images/avatar/25.gif" alt="" /></picture>

View File

@ -0,0 +1 @@
<picture><source srcset="https://localhost/assets/images/foo.jpf" type="image/jpx" /><source srcset="https://localhost/assets/images/foo.jpg" type="image/jpeg" /><img src="https://localhost/assets/images/foo.jpg" alt="" /></picture>

View File

@ -0,0 +1 @@
<img src="https://localhost/assets/images/placeholder.png" alt="placeholder.png" />

View File

@ -0,0 +1 @@
<img src="https://localhost/assets/images/foo.jpg" alt="should exist" width="200" height="200" />

View File

@ -0,0 +1 @@
<picture width="200" height="300"><source srcset="https://localhost/assets/images/example.svg" type="image/svg+xml" /><source srcset="https://localhost/assets/images/example.png" type="image/png" /><img src="https://localhost/assets/images/example.png" alt="Example text" /></picture>

View File

@ -0,0 +1 @@
<picture><source srcset="https://localhost/assets/images/placeholder.webp" type="image/webp" /><source srcset="https://localhost/assets/images/placeholder.png" type="image/png" /><img src="https://localhost/assets/images/placeholder.png" alt="" /></picture>