From 23007099364343413b4c84338bcda78bf052ef01 Mon Sep 17 00:00:00 2001 From: Sven Luijten <11269635+svenluijten@users.noreply.github.com> Date: Mon, 10 Jul 2023 14:03:42 +0200 Subject: [PATCH] Initial commit --- .editorconfig | 19 +++ .gitattributes | 10 ++ .github/dependabot.yml | 6 + .github/workflows/run-tests.yml | 30 +++++ .gitignore | 3 + CONTRIBUTING.md | 93 +++++++++++++ LICENSE.md | 21 +++ README.md | 120 +++++++++++++++++ composer.json | 34 +++++ phpunit.xml.dist | 17 +++ src/DarkModeImagesExtension.php | 52 +++++++ src/Event/DarkModeImagesListener.php | 70 ++++++++++ src/Node/Picture.php | 9 ++ src/Node/Source.php | 29 ++++ src/Query/HasClass.php | 27 ++++ src/Renderer/PictureRenderer.php | 37 +++++ src/Renderer/SourceRenderer.php | 25 ++++ tests/DarkModeImagesExtensionTest.php | 127 ++++++++++++++++++ tests/Query/HasClassTest.php | 39 ++++++ tests/Renderer/NullRenderer.php | 32 +++++ tests/Renderer/PictureRendererTest.php | 31 +++++ tests/Renderer/SourceRendererTest.php | 19 +++ ...ages with light and dark mode class__1.txt | 2 + ...ages with only one light mode class__1.txt | 2 + ...without dark- or light mode classes__1.txt | 2 + ...es with data set 2 picture elements__1.txt | 4 + ...h have dark- and light mode classes__1.txt | 3 + ...a set an image tag without siblings__1.txt | 1 + ...n image with 2 (non-image) siblings__1.txt | 3 + ...ages with data set dark as fallback__1.txt | 2 + ...ages with data set dark image first__1.txt | 2 + ... image separated by another element__1.txt | 3 + ...tImages with data set no image tags__1.txt | 1 + ...ages with data set other dark class__1.txt | 2 + ...ta set other light and dark classes__1.txt | 2 + ...ges with data set other light class__1.txt | 2 + 36 files changed, 881 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/run-tests.yml create mode 100644 .gitignore create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 src/DarkModeImagesExtension.php create mode 100644 src/Event/DarkModeImagesListener.php create mode 100644 src/Node/Picture.php create mode 100644 src/Node/Source.php create mode 100644 src/Query/HasClass.php create mode 100644 src/Renderer/PictureRenderer.php create mode 100644 src/Renderer/SourceRenderer.php create mode 100644 tests/DarkModeImagesExtensionTest.php create mode 100644 tests/Query/HasClassTest.php create mode 100644 tests/Renderer/NullRenderer.php create mode 100644 tests/Renderer/PictureRendererTest.php create mode 100644 tests/Renderer/SourceRendererTest.php create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 images with light and dark mode class__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 images with only one light mode class__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 images without dark- or light mode classes__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 picture elements__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 3 images, 2 of which have dark- and light mode classes__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set an image tag without siblings__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set an image with 2 (non-image) siblings__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set dark as fallback__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set dark image first__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set light and dark image separated by another element__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set no image tags__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set other dark class__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set other light and dark classes__1.txt create mode 100644 tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set other light class__1.txt diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..081ec3b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at http://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_size = 4 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[composer.json] +indent_size = 4 +indent_style = space diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..24ca40c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,10 @@ +* text=auto + +/tests export-ignore +/.editorconfig export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/CONTRIBUTING.md export-ignore +/phpunit.xml.dist export-ignore + +/tests/**/__snapshots__/** binary diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..6bd86e3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: weekly diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 0000000..6db26b6 --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,30 @@ +name: Tests +on: [push, pull_request] + +jobs: + test: + name: PHP ${{ matrix.php }} on ${{ matrix.os }} (${{ matrix.dependency-version }}) + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + php: [8.1, 8.2] + dependency-version: [highest, lowest] + steps: + - uses: actions/checkout@v3.5.3 + + - name: Configure PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom + coverage: none + + - name: Install dependencies + uses: ramsey/composer-install@v2 + with: + dependency-versions: ${{ matrix.dependency-version }} + composer-options: "--prefer-dist" + + - name: Execute tests + run: vendor/bin/phpunit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2885bcd --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/composer.phar +/composer.lock +/vendor diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..4b82055 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,93 @@ +# How to contribute +Thank you for considering to contribute to this repository! This file will walk you through all the steps to ensure both +you and I have a good time submitting and reviewing your contribution. First off, some basic rules and reading material: + +- Submit your work in a new branch and make the PR to the master branch. +- [Write a short & descriptive commit message](http://chris.beams.io/posts/git-commit/). +- Rebase before committing the final change. +- Stick to [PSR-2](http://www.php-fig.org/psr/psr-2/). +- Add tests if necessary and ensure all the tests are green on the final commit. +- Make sure the CI tools used by the repository are all in order. If one fails, you should make it pass. + +## Contributing +Here are the steps to follow to contribute to this repository: + +- [Fork this repository on GitHub](#fork-this-repository). +- [Clone your fork to your local machine](#clone-your-fork). +- [Create a feature branch](#create-a-branch). +- [Add an 'upstream' remote](#add-a-remote). +- [Regularly pull & rebase from the upstream remote](#pull-and-rebase). +- [Work on feature branch](#working-on-branch). +- [Make tests pass](#make-tests-pass) +- [Submit a pull request to the master branch](#submitting-pull-request). + +### Fork this repository +Fork the repository right here on GitHub. To learn more about forking a repository, visit +[GitHub's help article](https://help.github.com/articles/fork-a-repo/). + +### Clone your fork +Clone your repository on your local machine to start work on your pull request. + +```bash +$ git clone git@github.com:/.git +# Or if you prefer HTTPS: +$ git clone https://github.com//.git + +$ cd +``` + +### Create a branch +Make your own feature branch in order not to clutter up master. + +```bash +# Think of a good name for your branch: +# fix/typo-in-readme +# feature/some-feature +# bug/some-bug-you-are-fixing +$ git checkout -b +``` + +### Add a remote +Add an 'upstream' remote to pull from and to stay up to date with the work being done in there. + +```bash +# List all current remotes +$ git remote -v +origin git@github.com//.git (fetch) +origin git@github.com//.git (push) + +# Add a new remote called 'upstream' +$ git remote add upstream git@github.com:svenluijten/.git +# Or if you prefer HTTPS: +$ git remote add upstream https://github.com/svenluijten/.git + +# The new remote should now be in the list +$ git remote -v +origin git@github.com//.git (fetch) +origin git@github.com//.git (push) +upstream git@github.com/svenluijten/.git (fetch) +upstream git@github.com/svenluijten/.git (push) +``` + +### Pull and rebase +Pull from upstream to stay up to date with what others might be doing in this repository. Any merge conflicts that arise +are your responsibility to resolve. + +```bash +$ git pull --rebase upstream master +``` + +### Working on branch +Do your magic and make your fix. I can't help you with this 😉. Once you're happy with the result and all tests pass, +go ahead and push to your feature branch. + +```bash +$ git push origin +``` + +### Make tests pass +You can run `composer check` to see if the tests & static analysis pass. Feel free to only run the static analyses at the +very end, this could take a while on bigger projects. To only run the tests, run `composer test`. + +### Submitting pull request +Now, let's head back over to this repository on GitHub and submit the pull request! diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..2951437 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# The MIT License (MIT) + +Copyright (c) Sven Luijten + +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..fd3518e --- /dev/null +++ b/README.md @@ -0,0 +1,120 @@ +# CommonMark Dark Mode Images Extension + +[![Latest Version on Packagist][ico-version]][link-packagist] +[![Total Downloads][ico-downloads]][link-downloads] +[![Software License][ico-license]](LICENSE.md) +[![Build Status][ico-build]][link-build] + +This [CommonMark](https://commonmark.thephpleague.com) extension allows you to determine what images to show in dark- or +light mode in Markdown converted using CommonMark. + +## Installation +Via [composer](http://getcomposer.org): + +```bash +composer require sven/commonmark-dark-mode-images +``` + +## Usage +To enable the extension, first make sure [the `Attributes` extension](https://commonmark.thephpleague.com/2.4/extensions/attributes/) +that ships with CommonMark is enabled. Then, add the extension to the CommonMark environment: + +```php +use Sven\CommonMark\DarkModeImages\DarkModeImagesExtension; + +$environment->addExtension(new DarkModeImagesExtension()); +``` + +You'll have to apply some classes to your Markdown images to indicate to this extension that they should be converted: + +```md +![Screenshot of a settings dialog](/images/settings-light.jpg){.light-image} +![dark](/images/settings-dark.jpg){.dark-image} +``` + +These `{.light-image}` and `{.dark-image}` tags are part of [the `Attributes` extension](https://commonmark.thephpleague.com/2.4/extensions/attributes/). +They apply classes to the converted `` elements, which this extension uses to do its magic. The resulting HTML will +look something like this: + +```html + + + Screenshot of a settings dialog + +``` + +## Configuration + +### Fallback or original +This option allows you to select either `'light'` or `'dark'`as the "original" form of the picture you're embedding. +This determines which picture will be used if the browser doesn't support the `` element. + +```php +use League\CommonMark\Environment\Environment; +use Sven\CommonMark\DarkModeImages\DarkModeImagesExtension; + +$environment = new Environment([ + 'dark_mode_images' => [ + 'fallback' => 'dark', // Default: 'light'. + ], +]); + +$environment->addExtension(new DarkModeImagesExtension()); +``` + +### Class on `` element +To change the class that is eventually applied to the rendered `` element, use the `picture_class` +configuration option: + +```php +use League\CommonMark\Environment\Environment; +use Sven\CommonMark\DarkModeImages\DarkModeImagesExtension; + +$environment = new Environment([ + 'dark_mode_images' => [ + 'picture_class' => '', // Default: 'dark-mode-images-picture'. + ], +]); + +$environment->addExtension(new DarkModeImagesExtension()); +``` + +### Light and dark classes +Use the `dark_image_class` and `light_image_class` configuration options to determine what classes to apply to your +Markdown images to indicate which is for dark mode, and which is for light mode. + +```php +use League\CommonMark\Environment\Environment; +use Sven\CommonMark\DarkModeImages\DarkModeImagesExtension; + +$environment = new Environment([ + 'dark_mode_images' => [ + 'light_image_class' => 'l', // Default: 'light-image'. + 'dark_image_class' => 'd', // Default: 'dark-image'. + ], +]); + +$environment->addExtension(new DarkModeImagesExtension()); +``` + +### Note +It is _not_ recommended to use this extension when converting to Markdown on-the-fly on every request. This is best +suited for use in a static site generator like [Jigsaw](https://jigsaw.tighten.co/). + +## Contributing +All contributions (pull requests, issues and feature requests) are welcome. Make sure to read through the +[CONTRIBUTING.md](CONTRIBUTING.md) first, though. See the [contributors page](../../graphs/contributors) for all +contributors. + +## License +`sven/commonmark-dark-mode-images` is licensed under the MIT License (MIT). Please see [the license file](LICENSE.md) +for more information. + +[ico-version]: https://img.shields.io/packagist/v/sven/commonmark-dark-mode-images.svg?style=flat-square +[ico-license]: https://img.shields.io/badge/license-MIT-green.svg?style=flat-square +[ico-downloads]: https://img.shields.io/packagist/dt/sven/commonmark-dark-mode-images.svg?style=flat-square +[ico-build]: https://img.shields.io/github/workflow/status/svenluijten/commonmark-dark-mode-images/Tests?style=flat-square + +[link-packagist]: https://packagist.org/packages/sven/commonmark-dark-mode-images +[link-downloads]: https://packagist.org/packages/sven/commonmark-dark-mode-images +[link-build]: https://github.com/svenluijten/commonmark-dark-mode-images/actions/workflows/run-tests.yml diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..06262ba --- /dev/null +++ b/composer.json @@ -0,0 +1,34 @@ +{ + "name": "sven/commonmark-dark-mode-images", + "description": "", + "keywords": [], + "license": "MIT", + "authors": [ + { + "name": "Sven Luijten", + "email": "contact@svenluijten.com", + "homepage": "https://svenluijten.com" + } + ], + "require": { + "league/commonmark": "^2.3" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0", + "spatie/phpunit-snapshot-assertions": "^5.0.1" + }, + "autoload": { + "psr-4": { + "Sven\\CommonMark\\DarkModeImages\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Sven\\CommonMark\\DarkModeImages\\Tests\\": "tests/" + } + }, + "config": { + "sort-packages": true + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..d6c1ed9 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,17 @@ + + + + + ./tests/ + + + diff --git a/src/DarkModeImagesExtension.php b/src/DarkModeImagesExtension.php new file mode 100644 index 0000000..de19995 --- /dev/null +++ b/src/DarkModeImagesExtension.php @@ -0,0 +1,52 @@ +getExtensions(); + + $this->assertArrayContainsInstanceOf(AttributesExtension::class, $extensions); + + $environment + ->addEventListener(DocumentParsedEvent::class, [new DarkModeImagesListener(), 'processDocument']) + ->addRenderer(Picture::class, new PictureRenderer()) + ->addRenderer(Source::class, new SourceRenderer()) + ; + } + + public function configureSchema(ConfigurationBuilderInterface $builder): void + { + $builder->addSchema('dark_mode_images', Expect::structure([ + 'dark_image_class' => Expect::string()->default('dark-image'), + 'light_image_class' => Expect::string()->default('light-image'), + 'picture_class' => Expect::string()->default('dark-mode-images-picture'), + 'fallback' => Expect::anyOf('light', 'dark')->default('light'), + ])); + } + + private function assertArrayContainsInstanceOf(string $class, iterable $extensions): void + { + foreach ($extensions as $extension) { + if ($extension instanceof $class) { + return; + } + } + + throw new \RuntimeException('The "'.self::class.'" extension requires the "'.$class.'" extension to loaded before it.'); + } +} diff --git a/src/Event/DarkModeImagesListener.php b/src/Event/DarkModeImagesListener.php new file mode 100644 index 0000000..9bce434 --- /dev/null +++ b/src/Event/DarkModeImagesListener.php @@ -0,0 +1,70 @@ +config->get('dark_mode_images/fallback'); + + if ($defaultScheme === 'light') { + $originalClass = $this->config->get('dark_mode_images/light_image_class'); + $otherClass = $this->config->get('dark_mode_images/dark_image_class'); + } else { + $originalClass = $this->config->get('dark_mode_images/dark_image_class'); + $otherClass = $this->config->get('dark_mode_images/light_image_class'); + } + + $originalImages = (new Query()) + ->where(Query::type(Image::class)) + ->andWhere(new HasClass($originalClass)) + ->findAll($event->getDocument()); + + foreach ($originalImages as $originalImage) { + $otherImage = (new Query()) + ->where(Query::type(Image::class)) + ->andWhere(new HasClass($otherClass)) + ->findOne($originalImage->parent()); + + if ($otherImage === null || in_array($originalImage, [$otherImage->previous(), $otherImage->next()], true)) { + continue; + } + + $otherScheme = $defaultScheme === 'light' ? 'dark' : 'light'; + + $otherSource = new Source($otherImage->getUrl(), '(prefers-color-scheme: '.$otherScheme.')'); + + $picture = new Picture(); + $picture->data->set('dark_mode_images', true); + + $picture->appendChild($otherSource); + $classes = explode(' ', $originalImage->data->get('attributes/class')); + $newClasses = array_filter($classes, fn ($cls) => $cls !== $originalClass); + + $fallbackImage = clone $originalImage; + $fallbackImage->data->set('attributes/class', implode(' ', $newClasses)); + + $picture->appendChild($fallbackImage); + + $otherImage->detach(); + $originalImage->replaceWith($picture); + } + } + + public function setConfiguration(ConfigurationInterface $configuration): void + { + $this->config = $configuration; + } +} diff --git a/src/Node/Picture.php b/src/Node/Picture.php new file mode 100644 index 0000000..8ca047e --- /dev/null +++ b/src/Node/Picture.php @@ -0,0 +1,9 @@ +url = $url; + $this->mediaQuery = $mediaQuery; + } + + public function getUrl(): string + { + return $this->url; + } + + public function getMediaQuery(): string + { + return $this->mediaQuery; + } +} diff --git a/src/Query/HasClass.php b/src/Query/HasClass.php new file mode 100644 index 0000000..907c5a7 --- /dev/null +++ b/src/Query/HasClass.php @@ -0,0 +1,27 @@ +class = $class; + } + + public function __invoke(Node $node): bool + { + if (! $node->data->has('attributes/class')) { + return false; + } + + $nodeClasses = $node->data->get('attributes/class'); + + return in_array($this->class, explode(' ', $nodeClasses), true); + } +} diff --git a/src/Renderer/PictureRenderer.php b/src/Renderer/PictureRenderer.php new file mode 100644 index 0000000..e5ba333 --- /dev/null +++ b/src/Renderer/PictureRenderer.php @@ -0,0 +1,37 @@ +data->has('dark_mode_images') && $node->data->get('dark_mode_images') === true) { + $node->data->append('attributes/class', $this->config->get('dark_mode_images/picture_class')); + } + + return new HtmlElement( + tagName: 'picture', + attributes: $node->data->get('attributes'), + contents: $childRenderer->renderNodes($node->children()), + ); + } + + public function setConfiguration(ConfigurationInterface $configuration): void + { + $this->config = $configuration; + } +} diff --git a/src/Renderer/SourceRenderer.php b/src/Renderer/SourceRenderer.php new file mode 100644 index 0000000..d6c637d --- /dev/null +++ b/src/Renderer/SourceRenderer.php @@ -0,0 +1,25 @@ +data->get('attributes'), + 'media' => $node->getMediaQuery(), + 'srcset' => $node->getUrl(), + ]; + + return new HtmlElement('source', $attributes, selfClosing: true); + } +} diff --git a/tests/DarkModeImagesExtensionTest.php b/tests/DarkModeImagesExtensionTest.php new file mode 100644 index 0000000..eff72b4 --- /dev/null +++ b/tests/DarkModeImagesExtensionTest.php @@ -0,0 +1,127 @@ +addExtension(new CommonMarkCoreExtension()); + $environment->addExtension(new DarkModeImagesExtension()); + + $converter = new MarkdownConverter($environment); + + $this->expectException(RuntimeException::class); + + $converter->convert('# test'); + } + + /** @dataProvider dataProvider */ + public function testImages(string $markdown, array $config = []): void + { + $environment = new Environment($config); + $environment->addExtension(new CommonMarkCoreExtension()); + $environment->addExtension(new AttributesExtension()); + $environment->addExtension(new DarkModeImagesExtension()); + + $converter = new MarkdownConverter($environment); + + $output = rtrim((string) $converter->convert($markdown)); + + $this->assertMatchesSnapshot($output); + } + + public static function dataProvider(): iterable + { + yield 'no image tags' => [ + 'test', + ]; + + yield 'an image tag without siblings' => [ + '![test](/example.jpg)', + ]; + + yield 'an image with 2 (non-image) siblings' => [ + << [ + << [<< [<< [<< [<< [<< [<< [<< ['fallback' => 'dark']]]; + + yield 'other light class' => [<< ['light_image_class' => 'light']]]; + + yield 'other dark class' => [<< ['dark_image_class' => 'dark']]]; + + yield 'other light and dark classes' => [<< ['dark_image_class' => 'dark', 'light_image_class' => 'light']]]; + } +} diff --git a/tests/Query/HasClassTest.php b/tests/Query/HasClassTest.php new file mode 100644 index 0000000..6e2a49a --- /dev/null +++ b/tests/Query/HasClassTest.php @@ -0,0 +1,39 @@ +data->set('attributes/class', 'test-class'); + + self::assertTrue($query($node)); + } + + public function testHasClassAmongstMany(): void + { + $query = new HasClass('test-class'); + + $node = new class extends Node {}; + $node->data->set('attributes/class', 'class-one test-class class-two'); + + self::assertTrue($query($node)); + } +} diff --git a/tests/Renderer/NullRenderer.php b/tests/Renderer/NullRenderer.php new file mode 100644 index 0000000..1b33012 --- /dev/null +++ b/tests/Renderer/NullRenderer.php @@ -0,0 +1,32 @@ +render(new Picture(), new NullRenderer()); + + self::assertEquals('', rtrim($output)); + } + + public function testRenderingAPictureElementWithAttributes(): void + { + $r = new PictureRenderer(); + + $picture = new Picture(); + $picture->data->set('attributes', ['class' => 'test-class']); + + $output = $r->render($picture, new NullRenderer()); + + self::assertEquals('', rtrim($output)); + } +} diff --git a/tests/Renderer/SourceRendererTest.php b/tests/Renderer/SourceRendererTest.php new file mode 100644 index 0000000..1274296 --- /dev/null +++ b/tests/Renderer/SourceRendererTest.php @@ -0,0 +1,19 @@ +render(new Source('https://example.com', '(prefers-color-scheme: dark)'), new NullRenderer()); + + self::assertEquals('', rtrim($output)); + } +} diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 images with light and dark mode class__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 images with light and dark mode class__1.txt new file mode 100644 index 0000000..9f82f49 --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 images with light and dark mode class__1.txt @@ -0,0 +1,2 @@ +

image one +

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 images with only one light mode class__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 images with only one light mode class__1.txt new file mode 100644 index 0000000..f47b479 --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 images with only one light mode class__1.txt @@ -0,0 +1,2 @@ +

image one +image two

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 images without dark- or light mode classes__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 images without dark- or light mode classes__1.txt new file mode 100644 index 0000000..e5c3c83 --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 images without dark- or light mode classes__1.txt @@ -0,0 +1,2 @@ +

image one +image two

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 picture elements__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 picture elements__1.txt new file mode 100644 index 0000000..9058957 --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 2 picture elements__1.txt @@ -0,0 +1,4 @@ +

image one light + +image two light +

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 3 images, 2 of which have dark- and light mode classes__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 3 images, 2 of which have dark- and light mode classes__1.txt new file mode 100644 index 0000000..bb2710f --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set 3 images, 2 of which have dark- and light mode classes__1.txt @@ -0,0 +1,3 @@ +

image one + +image three

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set an image tag without siblings__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set an image tag without siblings__1.txt new file mode 100644 index 0000000..5383bf6 --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set an image tag without siblings__1.txt @@ -0,0 +1 @@ +

test

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set an image with 2 (non-image) siblings__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set an image with 2 (non-image) siblings__1.txt new file mode 100644 index 0000000..5df3cd1 --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set an image with 2 (non-image) siblings__1.txt @@ -0,0 +1,3 @@ +

test header

+

test +test text

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set dark as fallback__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set dark as fallback__1.txt new file mode 100644 index 0000000..d625159 --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set dark as fallback__1.txt @@ -0,0 +1,2 @@ +

image one +

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set dark image first__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set dark image first__1.txt new file mode 100644 index 0000000..7571d8e --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set dark image first__1.txt @@ -0,0 +1,2 @@ +

+image two

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set light and dark image separated by another element__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set light and dark image separated by another element__1.txt new file mode 100644 index 0000000..c22b5f5 --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set light and dark image separated by another element__1.txt @@ -0,0 +1,3 @@ +

image one light

+

a bit of text here

+

image one dark

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set no image tags__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set no image tags__1.txt new file mode 100644 index 0000000..82571e1 --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set no image tags__1.txt @@ -0,0 +1 @@ +

test

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set other dark class__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set other dark class__1.txt new file mode 100644 index 0000000..7571d8e --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set other dark class__1.txt @@ -0,0 +1,2 @@ +

+image two

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set other light and dark classes__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set other light and dark classes__1.txt new file mode 100644 index 0000000..7571d8e --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set other light and dark classes__1.txt @@ -0,0 +1,2 @@ +

+image two

\ No newline at end of file diff --git a/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set other light class__1.txt b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set other light class__1.txt new file mode 100644 index 0000000..7571d8e --- /dev/null +++ b/tests/__snapshots__/DarkModeImagesExtensionTest__testImages with data set other light class__1.txt @@ -0,0 +1,2 @@ +

+image two

\ No newline at end of file