diff --git a/.github/workflows/deploy-web.yaml b/.github/workflows/deploy-web.yaml new file mode 100644 index 0000000..9c43054 --- /dev/null +++ b/.github/workflows/deploy-web.yaml @@ -0,0 +1,23 @@ +name: Build and deploy docs to GitHub Pages +on: + push: + branches: + - master + - main +permissions: + contents: write +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - uses: actions/cache@v2 + with: + key: ${{ github.ref }} + path: .cache + - run: pip install 'mkdocs-resize-images[dev]' + - run: make fixRelativeLinkDocs + - run: mkdocs gh-deploy --force \ No newline at end of file diff --git a/.github/workflows/mkdoxy-build-test.yaml b/.github/workflows/mkdoxy-build-test.yaml new file mode 100644 index 0000000..6899a79 --- /dev/null +++ b/.github/workflows/mkdoxy-build-test.yaml @@ -0,0 +1,28 @@ +name: MkDoxy build all supported Python versions + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + # You can use PyPy versions in python-version. + matrix: + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + # You can test your matrix by printing the current Python version + - name: Display Python version + run: python -c "import sys; print(sys.version)" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install 'mkdocs-resize-images[dev]' + - name: Build docs + run: mkdocs build --clean --strict --verbose \ No newline at end of file diff --git a/.gitignore b/.gitignore index 68bc17f..a0f0c68 100644 --- a/.gitignore +++ b/.gitignore @@ -158,3 +158,5 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ + +.resize-hash diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..31216a1 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,22 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..a971a2c --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/mkdocs-resize-images.iml b/.idea/mkdocs-resize-images.iml new file mode 100644 index 0000000..909438d --- /dev/null +++ b/.idea/mkdocs-resize-images.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..4176176 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..b97f815 --- /dev/null +++ b/Makefile @@ -0,0 +1,40 @@ +.PHONY: package release release-test clean reviewCode docs-serve docs-build + +# Packaging +package: + rm -f dist/* + python3 setup.py sdist bdist_wheel + +install: package + python3 -m pip install --no-deps --force dist/*.whl + +install-dev: package + python3 -m pip install --force --editable . + +release: package + twine upload --repository pypi dist/* + +release-test: package + twine upload --repository testpypi dist/* + +clean: + rm -rf dist build + + +fixRelativeLinkDocs: + # change ./docs/ to ./ + sed 's/\.\/docs\//\.\//g' README.md > docs/README.md + +# Testing +reviewCode: + sourcery review mkdoxy --in-place + +install-dev: + python3 -m pip install --force --editable . + +# Documentation +docs-serve: fixRelativeLinkDocs + mkdocs serve + +docs-build: fixRelativeLinkDocs + mkdocs build \ No newline at end of file diff --git a/README.md b/README.md index c7e9c11..bdfdcb3 100644 --- a/README.md +++ b/README.md @@ -1 +1,67 @@ -# mkdocs-resize-images \ No newline at end of file +# MkDocs Resize Images Plugin + +

+ + + + + + + +

+ +This MkDocs plugin finds all folders with a certain name, by default `assets-large`, resizes all images in those folders according to the plugin configuration. +Then saves the resized images in a different folder, by default `assets`. +The plugin also supports caching: if a file has not changed since the last time the plugin ran, it won't be processed again. + +## Installation + +Install the plugin using pip from [PyPI](https://pypi.org/project/mkdocs-resize-images/): + +```bash +pip install mkdocs-resize-images +``` + +Activate the plugin in `mkdocs.yml`: + +```yaml +plugins: + - search + - resize-images +``` + +Create `.gitignore` file in your project root directory and add the following line to it: + +```bash +assets-large # or whatever you have set as source-dir + +.resize-hash # if you have enabled caching +``` + + +## Usage + +By default, the plugin will look for images in all directories named assets-large, resize them to 800x600 pixels, and then save the resized images in assets directories in the same parent directories as the assets-large directories. + +You can configure the plugin in your mkdocs.yml: + +```yaml +plugins: + - search + - resize-images: + source-dir: assets-large + target-dir: assets + enable_cache: True + size: [800, 600] + extensions: ['.jpg', '.jpeg', '.png', '.gif', '.svg'] +``` + +`source-dir`: The name of the directories to search for images to resize. Default is `assets-large`. + +`target-dir`: The name of the directories to save the resized images in. Default is `assets`. + +`size`: The size to resize the images to, specified as [width, height]. Default is `[800, 600]`. + +`extensions`: List of image file extensions to consider for resizing. The plugin will look for images with these extensions in both lower and upper case. Default is `['.jpg', '.jpeg', '.png', '.gif', '.svg']`. + +`enable_cache`: Whether to enable caching. If enabled, the plugin will check if a file has changed since the last time the plugin ran, and if not, it won't process the file again. Default is `True`. \ No newline at end of file diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 0000000..7fe3f8a --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +resize.kubaandrysek.cz \ No newline at end of file diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..bdfdcb3 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,67 @@ +# MkDocs Resize Images Plugin + +

+ + + + + + + +

+ +This MkDocs plugin finds all folders with a certain name, by default `assets-large`, resizes all images in those folders according to the plugin configuration. +Then saves the resized images in a different folder, by default `assets`. +The plugin also supports caching: if a file has not changed since the last time the plugin ran, it won't be processed again. + +## Installation + +Install the plugin using pip from [PyPI](https://pypi.org/project/mkdocs-resize-images/): + +```bash +pip install mkdocs-resize-images +``` + +Activate the plugin in `mkdocs.yml`: + +```yaml +plugins: + - search + - resize-images +``` + +Create `.gitignore` file in your project root directory and add the following line to it: + +```bash +assets-large # or whatever you have set as source-dir + +.resize-hash # if you have enabled caching +``` + + +## Usage + +By default, the plugin will look for images in all directories named assets-large, resize them to 800x600 pixels, and then save the resized images in assets directories in the same parent directories as the assets-large directories. + +You can configure the plugin in your mkdocs.yml: + +```yaml +plugins: + - search + - resize-images: + source-dir: assets-large + target-dir: assets + enable_cache: True + size: [800, 600] + extensions: ['.jpg', '.jpeg', '.png', '.gif', '.svg'] +``` + +`source-dir`: The name of the directories to search for images to resize. Default is `assets-large`. + +`target-dir`: The name of the directories to save the resized images in. Default is `assets`. + +`size`: The size to resize the images to, specified as [width, height]. Default is `[800, 600]`. + +`extensions`: List of image file extensions to consider for resizing. The plugin will look for images with these extensions in both lower and upper case. Default is `['.jpg', '.jpeg', '.png', '.gif', '.svg']`. + +`enable_cache`: Whether to enable caching. If enabled, the plugin will check if a file has changed since the last time the plugin ran, and if not, it won't process the file again. Default is `True`. \ No newline at end of file diff --git a/docs/assets-large/002.jpg b/docs/assets-large/002.jpg new file mode 100644 index 0000000..225e618 Binary files /dev/null and b/docs/assets-large/002.jpg differ diff --git a/docs/assets-large/004.jpg b/docs/assets-large/004.jpg new file mode 100644 index 0000000..dd6a28e Binary files /dev/null and b/docs/assets-large/004.jpg differ diff --git a/docs/assets-large/005.jpg b/docs/assets-large/005.jpg new file mode 100644 index 0000000..b5290d3 Binary files /dev/null and b/docs/assets-large/005.jpg differ diff --git a/docs/assets-large/index.md b/docs/assets-large/index.md new file mode 100644 index 0000000..7acf737 --- /dev/null +++ b/docs/assets-large/index.md @@ -0,0 +1 @@ +Image source: https://roboruka.robotickytabor.cz/ \ No newline at end of file diff --git a/docs/assets/logo.png b/docs/assets/logo.png new file mode 100755 index 0000000..b9745c4 Binary files /dev/null and b/docs/assets/logo.png differ diff --git a/docs/example.md b/docs/example.md new file mode 100644 index 0000000..d3a092d --- /dev/null +++ b/docs/example.md @@ -0,0 +1,9 @@ +# Example + +This is large image in `assets-large` folder: +![Large image](assets-large/002.jpg) + + +This is resized image in `assets` folder: +![If you see this message, it means the plugin does not work, please check your configuration.](assets/002.jpg) + diff --git a/docs/project1/assets-large/002.jpg b/docs/project1/assets-large/002.jpg new file mode 100644 index 0000000..225e618 Binary files /dev/null and b/docs/project1/assets-large/002.jpg differ diff --git a/docs/project1/assets-large/004.jpg b/docs/project1/assets-large/004.jpg new file mode 100644 index 0000000..dd6a28e Binary files /dev/null and b/docs/project1/assets-large/004.jpg differ diff --git a/docs/project1/assets-large/005.jpg b/docs/project1/assets-large/005.jpg new file mode 100644 index 0000000..b5290d3 Binary files /dev/null and b/docs/project1/assets-large/005.jpg differ diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..462fbca --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,101 @@ +site_name: MkDocs - Resize images plugin +site_url: https://resize.kubaandrysek.cz/ +site_author: Jakub Andrýsek +site_description: >- + MkDocs plugin to resize images according to the configuration. + +# Repository +repo_name: JakubAndrysek/mkdocs-resize-images +repo_url: https://github.com/JakubAndrysek/mkdocs-resize-images +edit_uri: edit/main/docs/ + +# Copyright +copyright: Copyright © 2023 Jakub Andrýsek + +theme: + name: material + language: en + logo: assets/logo.png + favicon: assets/logo.png + features: + - navigation.tabs + - navigation.indexes + - navigation.top + - content.action.edit + - content.action.view + - navigation.tracking + - navigation.tabs + - navigation.expand + icon: + repo: fontawesome/brands/github + + + palette: + # Palette toggle for dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + primary: grey + accent: grey + toggle: + icon: material/brightness-4 + name: Switch to light mode + + # Palette toggle for light mode + - media: "(prefers-color-scheme: light)" + scheme: default + primary: grey + accent: grey + toggle: + icon: material/brightness-7 + name: Switch to dark mode + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/JakubAndrysek + - icon: fontawesome/brands/twitter + link: https://twitter.com/KubaAndrysek + - icon: fontawesome/brands/linkedin + link: https://www.linkedin.com/in/jakub-andrysek/ + analytics: + provider: google +# property: G-FC199H98G7 + feedback: + title: Was this page helpful? + ratings: + - icon: material/emoticon-happy-outline + name: This page was helpful + data: 1 + note: >- + Thanks for your feedback! + - icon: material/emoticon-sad-outline + name: This page could be improved + data: 0 + note: >- + Thanks for your feedback! + + +use_directory_urls: True + +plugins: + - search + - open-in-new-tab + - glightbox + - resize-images: + source-dir: assets-large + target-dir: assets + size: [800, 600] + enable_cache: True + + +markdown_extensions: + - pymdownx.highlight + - pymdownx.superfences + - admonition + - pymdownx.details + - pymdownx.superfences + - attr_list + +nav: + - Home: 'README.md' + - Example: 'example.md' diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5873a22 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +Pillow \ No newline at end of file diff --git a/resize_images/__init__.py b/resize_images/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/resize_images/plugin.py b/resize_images/plugin.py new file mode 100644 index 0000000..5a6e20e --- /dev/null +++ b/resize_images/plugin.py @@ -0,0 +1,78 @@ +# Author: Jakub Andrýsek +# Email: email@kubaandrysek.cz +# Website: https://kubaandrysek.cz +# License: MIT +# GitHub: https://github.com/JakubAndrysek/mkdocs-resize-images +# PyPI: https://pypi.org/project/mkdocs-resize-images/ + +from pathlib import Path +from itertools import chain +from PIL import Image +import hashlib +import logging + +from mkdocs.plugins import BasePlugin +from mkdocs.config import config_options + +log: logging.Logger = logging.getLogger("mkdocs") + +class ResizeImagesPlugin(BasePlugin): + + config_scheme = ( + ('size', config_options.Type(list, default=(800, 600), required=False)), + ('source-dir', config_options.Type(str, default='assets-large', required=False)), + ('target-dir', config_options.Type(str, default='assets', required=False)), + ('extensions', config_options.Type(list, default=['.jpg', '.jpeg', '.png', '.gif', '.svg'], required=False)), + ('enable_cache', config_options.Type(bool, default=True, required=False)), + ) + + def on_post_build(self, config): + base_dir = Path(config['docs_dir']) + for source_dir in base_dir.rglob(self.config['source-dir']): + content_changed = False + target_dir = source_dir.parent / self.config['target-dir'] + target_dir.mkdir(parents=True, exist_ok=True) + + hash_file_path = source_dir / '.resize-hash' + existing_hashes = self.get_existing_hashes(hash_file_path) + + for ext in self.config['extensions']: + for file in chain(source_dir.glob(f'*{ext.lower()}'), source_dir.glob(f'*{ext.upper()}')): + file_hash = self.get_file_hash(file) + if not self.config['enable_cache'] or file_hash not in existing_hashes: + content_changed = True + self.resize_image(file, target_dir) + existing_hashes.append(file_hash) + + if content_changed: + self.write_hashes(existing_hashes, hash_file_path) + + log.info(f'Resized images from `{self.config["source-dir"]}` to `{self.config["target-dir"]} with size {self.config["size"]}`') + return config + + def resize_image(self, file, target_dir): + try: + with Image.open(file) as img: + tuple_size = tuple(self.config['size']) + img.thumbnail(tuple_size) + base_filename = file.name + img.save(target_dir / base_filename) + except Exception as e: + log.error(f'Error resizing image {file}: {e}') + + def get_file_hash(self, filepath): + with open(filepath, "rb") as f: + bytes = f.read() + readable_hash = hashlib.md5(bytes).hexdigest() + return readable_hash + + def get_existing_hashes(self, hash_file_path): + if hash_file_path.exists(): + with open(hash_file_path, 'r') as file: + return file.read().splitlines() + return [] + + def write_hashes(self, hashes, hash_file_path): + with open(hash_file_path, 'w') as file: + for hash in hashes: + file.write(f'{hash}\n') diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..ef7e8d7 --- /dev/null +++ b/setup.py @@ -0,0 +1,46 @@ +from setuptools import setup, find_packages + +def readme(): + with open('README.md') as f: + return f.read() + + +# https://pypi.org/project/mkdocs-resize-images/ +setup( + name='mkdocs-resize-images', + version='1.0.0', + description='MkDocs plugin to resize images according to the configuration.', + long_description=readme(), + long_description_content_type='text/markdown', + keywords='mkdocs plugin, resize images, mkdocs, plugin, images, resize', + url='https://github.com/JakubAndrysek/mkdocs-resize-images', + author='Jakub Andrýsek', + author_email='email@kubaandrysek.cz', + license='MIT', + python_requires='>=3.7', + install_requires=['mkdocs', 'Pillow'], + extras_require={ + 'dev': [ + 'mkdocs-material', + 'mkdocs-open-in-new-tab', + 'mkdocs-glightbox', + 'mkdocs-git-revision-date-localized-plugin', + ] + }, + classifiers=[ + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Operating System :: OS Independent', + ], + packages=find_packages(), + include_package_data=True, + entry_points={ + 'mkdocs.plugins': [ + 'resize-images = resize_images.plugin:ResizeImagesPlugin' + ] + }, +)