From dc2ac7be537ee1dce2ad6e07e47c287784feb6de Mon Sep 17 00:00:00 2001 From: John Franey <1728528+johnfraney@users.noreply.github.com> Date: Sun, 28 Apr 2024 11:20:04 -0300 Subject: [PATCH] feat: add blurry_image Jinja extension (#75) Adds blurry_image extension to insert an tag with width & height into a Jinja template. Optionally inserts an image of a specific size. Usage: ``` {% blurry_image page.image, width=250 %} ``` --- blurry/__init__.py | 4 + blurry/cli.py | 6 +- blurry/plugins/__init__.py | 1 + blurry/plugins/jinja_plugins/__init__.py | 0 .../jinja_plugins/blurry_image_extension.py | 75 +++++++++++++++++++ .../plugins/write-a-jinja-extension-plugin.md | 30 ++++++++ docs/content/templates/syntax.md | 28 +++++++ docs/poetry.lock | 51 ++++++++++++- docs/templates/base.html | 1 + poetry.lock | 75 ++++++++++++++++++- pyproject.toml | 4 + 11 files changed, 270 insertions(+), 5 deletions(-) create mode 100644 blurry/plugins/jinja_plugins/__init__.py create mode 100644 blurry/plugins/jinja_plugins/blurry_image_extension.py create mode 100644 docs/content/plugins/write-a-jinja-extension-plugin.md diff --git a/blurry/__init__.py b/blurry/__init__.py index a3fedc6..7cbebe1 100644 --- a/blurry/__init__.py +++ b/blurry/__init__.py @@ -25,6 +25,7 @@ from blurry.markdown import convert_markdown_file_to_html from blurry.open_graph import open_graph_meta_tags from blurry.plugins import discovered_html_plugins +from blurry.plugins import discovered_jinja_extensions from blurry.plugins import discovered_jinja_filter_plugins from blurry.schema_validation import validate_front_matter_as_schema from blurry.settings import get_build_directory @@ -69,6 +70,9 @@ def get_jinja_env(): } ) ), + extensions=[ + jinja_extension.load() for jinja_extension in discovered_jinja_extensions + ], ) for filter_plugin in discovered_jinja_filter_plugins: try: diff --git a/blurry/cli.py b/blurry/cli.py index ef689b1..84e25c3 100644 --- a/blurry/cli.py +++ b/blurry/cli.py @@ -2,6 +2,7 @@ from rich.table import Table from blurry.plugins import discovered_html_plugins +from blurry.plugins import discovered_jinja_extensions from blurry.plugins import discovered_jinja_filter_plugins from blurry.plugins import discovered_markdown_plugins @@ -27,7 +28,10 @@ def print_plugin_table(): plugin_table.add_row( "\n".join([p.name for p in discovered_markdown_plugins]), "\n".join([p.name for p in discovered_html_plugins]), - "\n".join([p.name for p in discovered_jinja_filter_plugins]), + "\n".join( + [p.name for p in discovered_jinja_filter_plugins] + + [p.name for p in discovered_jinja_extensions] + ), ) console.print(plugin_table) diff --git a/blurry/plugins/__init__.py b/blurry/plugins/__init__.py index d17b6b1..cb26555 100644 --- a/blurry/plugins/__init__.py +++ b/blurry/plugins/__init__.py @@ -3,3 +3,4 @@ discovered_markdown_plugins = entry_points(group="blurry.markdown_plugins") discovered_html_plugins = entry_points(group="blurry.html_plugins") discovered_jinja_filter_plugins = entry_points(group="blurry.jinja_filter_plugins") +discovered_jinja_extensions = entry_points(group="blurry.jinja_extensions") diff --git a/blurry/plugins/jinja_plugins/__init__.py b/blurry/plugins/jinja_plugins/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/blurry/plugins/jinja_plugins/blurry_image_extension.py b/blurry/plugins/jinja_plugins/blurry_image_extension.py new file mode 100644 index 0000000..041716f --- /dev/null +++ b/blurry/plugins/jinja_plugins/blurry_image_extension.py @@ -0,0 +1,75 @@ +import mimetypes +from pathlib import Path +from urllib.parse import urlparse + +from jinja2_simple_tags import StandaloneTag +from rich.console import Console +from wand.exceptions import BlobError +from wand.image import Image + +from blurry.images import add_image_width_to_path +from blurry.settings import get_build_directory +from blurry.utils import build_path_to_url + +warning_console = Console(stderr=True, style="bold yellow") + + +class BlurryImage(StandaloneTag): + safe_output = True + tags = {"blurry_image"} + + def render(self, *args, **kwargs): + (image_url, width) = args + image_content_path: str = "." + urlparse(image_url).path + image_path = get_build_directory() / image_content_path + + try: + with Image(filename=str(image_path)) as image: + image_width = image.width + image_height = image.height + image_mimetype = image.mimetype + except BlobError: + warning_console.print(f"Could not find image: {image_path}") + return "" + + attributes = { + "width": image_width, + "height": image_height, + } + for attribute_key in kwargs: + if attribute_key in ["width", "height"]: + warning_console.print( + f"blurry_image: Received {attribute_key} in template {self.template} but this attribute is dynamic. Skipping." + ) + continue + attributes[attribute_key] = kwargs.get(attribute_key) + + if width: + image_path = add_image_width_to_path(image_path, width) + + if image_mimetype in [ + mimetypes.types_map[".jpg"], + mimetypes.types_map[".png"], + ]: + image_path = Path(str(image_path).replace(image_path.suffix, ".avif")) + + if not image_path.exists(): + warning_console.print( + f"blurry_image: Could not find {image_path}. Skipping." + ) + return "" + + attributes["src"] = build_path_to_url(image_path) + + if "alt" not in attributes: + warning_console.print( + f"blurry_image: alt attribute missing for image in {self.template}. " + "This can negatively affect accessibility. " + "Use an empty alt tag if an image is only for show." + ) + + attributes_str = " ".join( + f'{name}="{value}"' for name, value in attributes.items() + ) + + return f"" diff --git a/docs/content/plugins/write-a-jinja-extension-plugin.md b/docs/content/plugins/write-a-jinja-extension-plugin.md new file mode 100644 index 0000000..64ff30d --- /dev/null +++ b/docs/content/plugins/write-a-jinja-extension-plugin.md @@ -0,0 +1,30 @@ ++++ +"@type" = "WebPage" +name = "Plugins: write a Jinja extension plugin" +abstract = "Documentation for Blurry's Jinja extension plugins" +datePublished = 2024-04-28 ++++ + +# Plugins: write an Jinja extension plugin + +Blurry makes it easy to add [custom Jinja extensions](https://jinja.palletsprojects.com/en/3.1.x/extensions/) to your site. +What is a Jinja extension? +From the Jinja docs: + +> Jinja supports extensions that can add extra filters, tests, globals or even extend the parser. The main motivation of extensions is to move often used code into a reusable class like adding support for internationalization. + +With [custom extensions](https://jinja.palletsprojects.com/en/3.1.x/extensions/#module-jinja2.ext) you can add custom tags to Jinja, like Blurry's `{% blurry_image %}` tag. + +## Example: `{% blurry_image %}` + +This tag finds the optimized version of an image at the specified URL, and optionally of the specified size. +You can find it in Blurry's source code in `blurry/plugins/jinja_plugins/blurry_image_extension.py`. + +Under the hood the extension uses [`jinja2-simple-tags`](https://github.com/dldevinc/jinja2-simple-tags) to simplify the process of writing a custom extension. + +To use a custom Jinja extension you've developed, add the appropriate plugin syntax to your project's `pyproject.toml` file: + +```toml +[tool.poetry.plugins."blurry.jinja_extensions"] +stars = "{{ yourproject.your_extension_file }}:YourExtension" +``` diff --git a/docs/content/templates/syntax.md b/docs/content/templates/syntax.md index 150b0fe..9b07fb2 100644 --- a/docs/content/templates/syntax.md +++ b/docs/content/templates/syntax.md @@ -3,6 +3,7 @@ name = "Templates: syntax" abstract = "Documentation for Blurry's template files and Jinja syntax" datePublished = 2023-04-09 +dateModified = 2023-04-28 image = {contentUrl = "../images/schema.org-logo.png"} +++ @@ -42,3 +43,30 @@ If your templates require more granularity than the Schema.org types, you can wr [blurry.template_schema_types] ContextWebPage = 'WebPage' ``` + +## Blurry-included plugins + +Blurry ships with some plugins to simplify writing templates. + +### `{% blurry_image %}` + +This extension adds the `{% blurry_image %}` tag to simplify including images reference in [Markdown front matter](../content/markdown.md) in your templates. +It does a few things: + +- Finds the image in your build directory +- Extracts the images width & height +- Builds an `` tag with width, height, and the othwer attributes specified in the tag + +#### Examples + +Basic example: + +```jinja +{% blurry_image page.thumbnailUrl, alt="Image description" %} +``` + +Example with explicit width (image with this width must be present in the build folder): + +```jinja +{% blurry_image page.thumbnailUrl, 250, id="image-id", class="responsive-image", loading="lazy" %} +``` diff --git a/docs/poetry.lock b/docs/poetry.lock index 2d64f50..022e451 100644 --- a/docs/poetry.lock +++ b/docs/poetry.lock @@ -1,9 +1,10 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. [[package]] name = "annotated-types" version = "0.6.0" description = "Reusable constraint types to use with typing.Annotated" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -13,8 +14,9 @@ files = [ [[package]] name = "blurry-cli" -version = "0.7.0" +version = "0.7.2" description = "A Mistune-based static site generator for Python" +category = "main" optional = false python-versions = "^3.10" files = [] @@ -25,6 +27,7 @@ dpath = "^2.1.6" ffmpeg-python = "^0.2.0" htmlmin2 = "^0.1.13" Jinja2 = "^3.0.0" +jinja2-simple-tags = "^0.6.1" livereload = "^2.6.3" mistune = "^3.0.0rc5" pydantic2-schemaorg = "^0.1.1" @@ -43,6 +46,7 @@ url = ".." name = "blurry-plugin-blur-blurry-name" version = "0.1.0" description = "A simple plugin to blur 'Blurry' in the Blurry documentation" +category = "main" optional = false python-versions = "^3.10" files = [] @@ -62,6 +66,7 @@ resolved_reference = "4255c21c98fe9c24eec00257d613ff7aecc23b66" name = "cachetools" version = "5.3.3" description = "Extensible memoizing collections and decorators" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -73,6 +78,7 @@ files = [ name = "click" version = "8.1.7" description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -87,6 +93,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -98,6 +105,7 @@ files = [ name = "dpath" version = "2.1.6" description = "Filesystem-like pathing and searching for dictionaries" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -109,6 +117,7 @@ files = [ name = "ffmpeg-python" version = "0.2.0" description = "Python bindings for FFmpeg - with complex filtering support" +category = "main" optional = false python-versions = "*" files = [ @@ -126,6 +135,7 @@ dev = ["Sphinx (==2.1.0)", "future (==0.17.1)", "numpy (==1.16.4)", "pytest (==4 name = "frozendict" version = "2.4.1" description = "A simple immutable dictionary" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -171,6 +181,7 @@ files = [ name = "future" version = "1.0.0" description = "Clean single-source support for Python 3 and 2" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -182,6 +193,7 @@ files = [ name = "htmlmin2" version = "0.1.13" description = "An HTML Minifier" +category = "main" optional = false python-versions = "*" files = [ @@ -192,6 +204,7 @@ files = [ name = "jinja2" version = "3.1.3" description = "A very fast and expressive template engine." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -205,10 +218,26 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jinja2-simple-tags" +version = "0.6.1" +description = "Base classes for quick-and-easy template tag development" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "jinja2-simple-tags-0.6.1.tar.gz", hash = "sha256:54abf83883dcd13f8fd2ea2c42feeea8418df3640907bd5251dec5e25a6af0e3"}, + {file = "jinja2_simple_tags-0.6.1-py2.py3-none-any.whl", hash = "sha256:7b7cfa92f6813a1e0f0b61b9efcab60e6793674753e1f784ff270542e80ae20f"}, +] + +[package.dependencies] +Jinja2 = ">=2.10" + [[package]] name = "livereload" version = "2.6.3" description = "Python LiveReload is an awesome tool for web developers" +category = "main" optional = false python-versions = "*" files = [ @@ -224,6 +253,7 @@ tornado = {version = "*", markers = "python_version > \"2.7\""} name = "lxml" version = "5.2.1" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -395,6 +425,7 @@ source = ["Cython (>=3.0.10)"] name = "markdown-it-py" version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -419,6 +450,7 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "markupsafe" version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -488,6 +520,7 @@ files = [ name = "mdurl" version = "0.1.2" description = "Markdown URL utilities" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -499,6 +532,7 @@ files = [ name = "mistune" version = "3.0.2" description = "A sane and fast Markdown parser with useful plugins and renderers" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -510,6 +544,7 @@ files = [ name = "pydantic" version = "2.6.4" description = "Data validation using Python type hints" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -529,6 +564,7 @@ email = ["email-validator (>=2.0.0)"] name = "pydantic-core" version = "2.16.3" description = "" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -620,6 +656,7 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" name = "pydantic2-schemaorg" version = "0.1.1" description = "Pydantic classes for Schema.org" +category = "main" optional = false python-versions = "<4.0,>=3.10" files = [ @@ -634,6 +671,7 @@ pydantic = ">=2.6.1,<3.0.0" name = "pygments" version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -649,6 +687,7 @@ windows-terminal = ["colorama (>=0.4.6)"] name = "pyld" version = "2.0.4" description = "Python implementation of the JSON-LD API" +category = "main" optional = false python-versions = "*" files = [ @@ -671,6 +710,7 @@ requests = ["requests"] name = "rich" version = "13.7.1" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -689,6 +729,7 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] name = "selectolax" version = "0.3.21" description = "Fast HTML5 parser with CSS selectors." +category = "main" optional = false python-versions = "*" files = [ @@ -757,6 +798,7 @@ cython = ["Cython (==0.29.36)"] name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -768,6 +810,7 @@ files = [ name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -779,6 +822,7 @@ files = [ name = "tornado" version = "6.4" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +category = "main" optional = false python-versions = ">= 3.8" files = [ @@ -799,6 +843,7 @@ files = [ name = "typer" version = "0.6.1" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -819,6 +864,7 @@ test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6. name = "typing-extensions" version = "4.11.0" description = "Backported and Experimental Type Hints for Python 3.8+" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -830,6 +876,7 @@ files = [ name = "wand" version = "0.6.13" description = "Ctypes-based simple MagickWand API binding for Python" +category = "main" optional = false python-versions = "*" files = [ diff --git a/docs/templates/base.html b/docs/templates/base.html index fb7cf72..22502da 100644 --- a/docs/templates/base.html +++ b/docs/templates/base.html @@ -63,6 +63,7 @@
  • Intro
  • Write a Markdown plugin
  • Write an HTML plugin
  • +
  • Write a Jinja extension plugin
  • Write a Jinja filter plugin
  • diff --git a/poetry.lock b/poetry.lock index 026aa76..7e22d43 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,9 +1,10 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. [[package]] name = "annotated-types" version = "0.6.0" description = "Reusable constraint types to use with typing.Annotated" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -15,6 +16,7 @@ files = [ name = "argcomplete" version = "3.2.3" description = "Bash tab completion for argparse" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -29,6 +31,7 @@ test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] name = "atomicwrites" version = "1.4.1" description = "Atomic file writes." +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -39,6 +42,7 @@ files = [ name = "attrs" version = "23.2.0" description = "Classes Without Boilerplate" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -58,6 +62,7 @@ tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "p name = "black" version = "22.12.0" description = "The uncompromising code formatter." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -92,6 +97,7 @@ uvloop = ["uvloop (>=0.15.2)"] name = "cachetools" version = "5.3.3" description = "Extensible memoizing collections and decorators" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -103,6 +109,7 @@ files = [ name = "click" version = "8.1.7" description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -117,6 +124,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "colorama" version = "0.4.6" description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ @@ -128,6 +136,7 @@ files = [ name = "colorlog" version = "6.8.2" description = "Add colours to the output of Python's logging module." +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -145,6 +154,7 @@ development = ["black", "flake8", "mypy", "pytest", "types-colorama"] name = "coverage" version = "7.4.4" description = "Code coverage measurement for Python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -209,6 +219,7 @@ toml = ["tomli"] name = "distlib" version = "0.3.8" description = "Distribution utilities" +category = "dev" optional = false python-versions = "*" files = [ @@ -220,6 +231,7 @@ files = [ name = "docopt" version = "0.6.2" description = "Pythonic argument parser, that will make you smile" +category = "dev" optional = false python-versions = "*" files = [ @@ -230,6 +242,7 @@ files = [ name = "dpath" version = "2.1.6" description = "Filesystem-like pathing and searching for dictionaries" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -241,6 +254,7 @@ files = [ name = "ffmpeg-python" version = "0.2.0" description = "Python bindings for FFmpeg - with complex filtering support" +category = "main" optional = false python-versions = "*" files = [ @@ -258,6 +272,7 @@ dev = ["Sphinx (==2.1.0)", "future (==0.17.1)", "numpy (==1.16.4)", "pytest (==4 name = "filelock" version = "3.13.4" description = "A platform independent file lock." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -274,6 +289,7 @@ typing = ["typing-extensions (>=4.8)"] name = "frozendict" version = "2.4.1" description = "A simple immutable dictionary" +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -319,6 +335,7 @@ files = [ name = "future" version = "1.0.0" description = "Clean single-source support for Python 3 and 2" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -330,6 +347,7 @@ files = [ name = "htmlmin2" version = "0.1.13" description = "An HTML Minifier" +category = "main" optional = false python-versions = "*" files = [ @@ -340,6 +358,7 @@ files = [ name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -351,6 +370,7 @@ files = [ name = "jinja2" version = "3.1.3" description = "A very fast and expressive template engine." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -364,10 +384,26 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jinja2-simple-tags" +version = "0.6.1" +description = "Base classes for quick-and-easy template tag development" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "jinja2-simple-tags-0.6.1.tar.gz", hash = "sha256:54abf83883dcd13f8fd2ea2c42feeea8418df3640907bd5251dec5e25a6af0e3"}, + {file = "jinja2_simple_tags-0.6.1-py2.py3-none-any.whl", hash = "sha256:7b7cfa92f6813a1e0f0b61b9efcab60e6793674753e1f784ff270542e80ae20f"}, +] + +[package.dependencies] +Jinja2 = ">=2.10" + [[package]] name = "livereload" version = "2.6.3" description = "Python LiveReload is an awesome tool for web developers" +category = "main" optional = false python-versions = "*" files = [ @@ -383,6 +419,7 @@ tornado = {version = "*", markers = "python_version > \"2.7\""} name = "lxml" version = "5.2.1" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -554,6 +591,7 @@ source = ["Cython (>=3.0.10)"] name = "markdown-it-py" version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -578,6 +616,7 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "markupsafe" version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -647,6 +686,7 @@ files = [ name = "mdurl" version = "0.1.2" description = "Markdown URL utilities" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -658,6 +698,7 @@ files = [ name = "mistune" version = "3.0.2" description = "A sane and fast Markdown parser with useful plugins and renderers" +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -669,6 +710,7 @@ files = [ name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." +category = "dev" optional = false python-versions = ">=3.5" files = [ @@ -680,6 +722,7 @@ files = [ name = "nodeenv" version = "1.8.0" description = "Node.js virtual environment builder" +category = "dev" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ @@ -694,6 +737,7 @@ setuptools = "*" name = "nox" version = "2024.3.2" description = "Flexible test automation." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -715,6 +759,7 @@ uv = ["uv"] name = "packaging" version = "24.0" description = "Core utilities for Python packages" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -726,6 +771,7 @@ files = [ name = "pathspec" version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -737,6 +783,7 @@ files = [ name = "platformdirs" version = "4.2.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -752,6 +799,7 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest- name = "pluggy" version = "1.4.0" description = "plugin and hook calling mechanisms for python" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -767,6 +815,7 @@ testing = ["pytest", "pytest-benchmark"] name = "py" version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -778,6 +827,7 @@ files = [ name = "pydantic" version = "2.7.0" description = "Data validation using Python type hints" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -797,6 +847,7 @@ email = ["email-validator (>=2.0.0)"] name = "pydantic-core" version = "2.18.1" description = "Core functionality for Pydantic validation and serialization" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -888,6 +939,7 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" name = "pydantic2-schemaorg" version = "0.1.1" description = "Pydantic classes for Schema.org" +category = "main" optional = false python-versions = "<4.0,>=3.10" files = [ @@ -902,6 +954,7 @@ pydantic = ">=2.6.1,<3.0.0" name = "pygments" version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." +category = "main" optional = false python-versions = ">=3.7" files = [ @@ -917,6 +970,7 @@ windows-terminal = ["colorama (>=0.4.6)"] name = "pyld" version = "2.0.4" description = "Python implementation of the JSON-LD API" +category = "main" optional = false python-versions = "*" files = [ @@ -939,6 +993,7 @@ requests = ["requests"] name = "pyright" version = "1.1.358" description = "Command line wrapper for pyright" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -957,6 +1012,7 @@ dev = ["twine (>=3.4.1)"] name = "pytest" version = "6.2.5" description = "pytest: simple powerful testing with Python" +category = "dev" optional = false python-versions = ">=3.6" files = [ @@ -981,6 +1037,7 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xm name = "pytest-cov" version = "2.12.1" description = "Pytest plugin for measuring coverage." +category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -1000,6 +1057,7 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale name = "pytest-watch" version = "4.2.0" description = "Local continuous test runner with pytest and watchdog." +category = "dev" optional = false python-versions = "*" files = [ @@ -1016,6 +1074,7 @@ watchdog = ">=0.6.0" name = "rich" version = "13.7.1" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -1034,6 +1093,7 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] name = "ruff" version = "0.1.15" description = "An extremely fast Python linter and code formatter, written in Rust." +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1060,6 +1120,7 @@ files = [ name = "selectolax" version = "0.3.21" description = "Fast HTML5 parser with CSS selectors." +category = "main" optional = false python-versions = "*" files = [ @@ -1128,6 +1189,7 @@ cython = ["Cython (==0.29.36)"] name = "setuptools" version = "69.5.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1144,6 +1206,7 @@ testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jar name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1155,6 +1218,7 @@ files = [ name = "toml" version = "0.10.2" description = "Python Library for Tom's Obvious, Minimal Language" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -1166,6 +1230,7 @@ files = [ name = "tomli" version = "2.0.1" description = "A lil' TOML parser" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1177,6 +1242,7 @@ files = [ name = "tornado" version = "6.4" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +category = "main" optional = false python-versions = ">= 3.8" files = [ @@ -1197,6 +1263,7 @@ files = [ name = "typer" version = "0.6.1" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1217,6 +1284,7 @@ test = ["black (>=22.3.0,<23.0.0)", "coverage (>=5.2,<6.0)", "isort (>=5.0.6,<6. name = "typing-extensions" version = "4.11.0" description = "Backported and Experimental Type Hints for Python 3.8+" +category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1228,6 +1296,7 @@ files = [ name = "virtualenv" version = "20.25.1" description = "Virtual Python Environment builder" +category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -1248,6 +1317,7 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess name = "wand" version = "0.6.13" description = "Ctypes-based simple MagickWand API binding for Python" +category = "main" optional = false python-versions = "*" files = [ @@ -1263,6 +1333,7 @@ test = ["pytest (>=7.2.0)"] name = "watchdog" version = "4.0.0" description = "Filesystem events monitoring" +category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1303,4 +1374,4 @@ watchmedo = ["PyYAML (>=3.10)"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "97f3dca65d2ff7f20db8edd47b2346631f1eb307eab78f9002eb08909bbba90e" +content-hash = "c6aa303093c8a09f022adead8d88cd15aeb433ce4d303b89a7a5eaaed4dbe849" diff --git a/pyproject.toml b/pyproject.toml index d0a226c..38e6094 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,7 @@ typer = "^0.6.1" htmlmin2 = "^0.1.13" pydantic2-schemaorg = "^0.1.1" dpath = "^2.1.6" +jinja2-simple-tags = "^0.6.1" [tool.poetry.scripts] blurry = 'blurry:main' @@ -70,3 +71,6 @@ python_code = 'blurry.plugins.markdown_plugins.python_code_plugin:python_code' python_code_in_list = 'blurry.plugins.markdown_plugins.python_code_plugin:python_code_in_list' punctuation = 'blurry.plugins.markdown_plugins.punctuation_plugin:punctuation' container = 'blurry.plugins.markdown_plugins.container_plugin:container' + +[tool.poetry.plugins."blurry.jinja_extensions"] +blurry_image = "blurry.plugins.jinja_plugins.blurry_image_extension:BlurryImage"