add markdown-image-attrs 0.2.1 plugin

cloned from https://github.com/dairiki/lektor-markdown-image-attrs
and cleaned up unneccessary files
This commit is contained in:
Jérôme Charaoui 2022-11-01 12:45:33 -04:00
parent b362ba120c
commit 7170786d2a
No known key found for this signature in database
GPG Key ID: 69C52F658E988542
5 changed files with 405 additions and 0 deletions

View File

@ -0,0 +1,18 @@
## Changelog
### Release 0.2.1 (2022-09-20)
- Specify requires-python >= 3.7 in distribution metadata
### Release 0.2 (2022-09-20)
- Fix to work with Lektor 3.4
- Convert packaging to use `hatch`.
- Test under python 3.10.
- Drop support for python 2.7 and 3.6.
- Drop support for Lektor < 3.3.
### Version 0.1b1 (2021-02-14)
Split code out from North City NA Lektor website

View File

@ -0,0 +1,20 @@
Copyright © 2021 Geoffrey T. Dairiki
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.

View File

@ -0,0 +1,98 @@
# Lektor Markdown Extension for Image and Link attributes
[![PyPI version](https://img.shields.io/pypi/v/lektor-markdown-image-attrs.svg)](https://pypi.org/project/lektor-markdown-image-attrs/)
[![PyPI Supported Python Versions](https://img.shields.io/pypi/pyversions/lektor-markdown-image-attrs.svg)](https://pypi.python.org/pypi/lektor-markdown-image-attrs/)
[![GitHub license](https://img.shields.io/github/license/dairiki/lektor-markdown-image-attrs)](https://github.com/dairiki/lektor-markdown-image-attrs/blob/master/LICENSE)
[![GitHub Actions (Tests)](https://github.com/dairiki/lektor-markdown-image-attrs/workflows/Tests/badge.svg)](https://github.com/dairiki/lektor-markdown-image-attrs/actions)
This plugin hacks up Lektors Markdown renderer to add syntax which allows
arbitrary HTML attributes to be set on image and link tags.
## Motivation
Markdown, as implemented in Lektor, provides nice shorthand syntax for
marking up images. It does not provide any syntax for controlling
image styling, e.g., sizing and alignment. This plugin molests
Markdowns syntax for image (and link) titles to allow setting
arbitrary HTML attributes on image and link tags.
### On using raw HTML
It is true that one can simply include raw HTML `<img>` tags within
Markdown text. However, since this bypasses Markdown processing
altogether, it also bypasses Lektors resolution of image/link
URLs. This can be undesirable.
## Setting attributes on link and image tags in Markdown text
These hacks allow one to set attributes on image and link tags, by overloading
Markdowns syntax for setting title attributes.
If the title of a Markdown image or link looks like a set of
(non-empty) HTML attributes, they are interpreted as such, and stuck
onto the produced `<a>` or `<img>` tag.
```markdown
![My cat, Fluffy](fluffy.jpg "class=img-responsive")
```
will produce
```html
<img src="fluffy.jpg" class=img-responsive>
```
If you do want to set a title as well, you may surround the extra attributes
with angle brackets and append them at the end of the title. Both of these
are equivalent:
```markdown
![My cat, Fluffy](fluffy.jpg "Fluffy at rest <class=img-responsive>")
```
```markdown
![My cat, Fluffy](fluffy.jpg "title='Fluffy at rest' class=img-responsive")
```
If youd like to set a title, when the title text looks like a set of HTML attributes, simply append an empty set of angle brackets to the title:
```markdown
![My cat, Fluffy](fluffy.jpg "Fluffy=resting <>")
```
This works with reference-style links and images as well:
```markdown
Heres a photo of [my cat][]: ![fluffy][]
[fluffy]: fluffy.jpg (style='width: 80px;')
[my cat]: <http://fluffy.example.org> 'Fluffys website <class="external link">'
```
## Testing
We now use [hatch](https://hatch.pypa.io/latest/) for packaging and development.
To run all tests, including under a full matrix of python and lektor
versions, as well as combined coverage tests:
```sh
hatch run full
```
The `dev` environment specifies additional dependencies useful for
development. E.g. I start emacs via:
```sh
hatch run dev:emacs lektor_markdown_image_attrs.py &
```
## Acknowledgments
Ideas were gleaned from this [blog post](https://www.xaprb.com/blog/how-to-style-images-with-markdown/) by Baron Schwartz.
## Author
Jeff Dairiki <dairiki@dairiki.org>

View File

@ -0,0 +1,119 @@
"""Extend Markdown syntax to allow setting arbitrary HTML attributes
on images and links.
"""
from __future__ import annotations
import inspect
import re
import mistune
import lektor.pluginsystem
# Regex construction
_bits = {
# attribute name
'name': r'[_:a-z][-.0-9_:a-z]*', # NB: more restrictive than HTML spec
# unquoted attribute value
'uvalue': r'[-.0-9_:a-z]+', # NB: more restrictive than HTML sepc
# quoted attribute value
'qvalue1': r" ' [^'>]* ' ",
'qvalue2': r' " [^">]* " ',
}
_bits['value'] = r'(?: {uvalue} | {qvalue1} | {qvalue2})'.format(**_bits)
# non-empty attribute
_bits['nonempty_attribute'] = r'{name} \s* = \s* {value}'.format(**_bits)
# possibly-empty attribute
_bits['attribute'] = r'{name} (?: \s* = \s* {value})?'.format(**_bits)
# Trailing, possibly empty, list of attributes, surround by <>
trailing_attrs_re = re.compile(
r'''
\s* < \s* (?P<attrs>
(?: {attribute} (?: \s+ {attribute} )* )?
) \s* > \s* \Z
'''.format(**_bits), re.X | re.I)
# Nothing but a non-empty list of non-empty attribute (without angle brackets)
implicit_attrs_re = re.compile(
r'''
\A \s* (?P<attrs>
{nonempty_attribute} (?: \s+ {nonempty_attribute} )*
) \s* \Z
'''.format(**_bits), re.X | re.I)
def extract_attrs_from_title(bound: inspect.BoundArguments) -> str | None:
"""Extract explict HTML attributes from title parameter.
If such attributes are found, the bound arguments in ``bound``
are modified in-place, and the extracted attributes are returned.
"""
arguments = bound.arguments
attrs = None
title = arguments.get("title")
if title:
m = (trailing_attrs_re.search(title)
or implicit_attrs_re.match(title))
if m is not None:
attrs = m.group('attrs')
arguments["title"] = title[:m.start()] if m.start() > 0 else None
return attrs
try:
_renderer = mistune.HTMLRenderer()
except AttributeError:
_renderer = mistune.Renderer()
LINK_ARGS = inspect.signature(_renderer.link)
IMAGE_ARGS = inspect.signature(_renderer.image)
del _renderer
class MarkdownRendererMixin:
"""This allows one to set attributes on image and link tags by
including them in the markdown title for the image or link.
Examples::
![my cat](cat.jpg "Fluffy, my cat <class='img-responsive'>")
(Not to be confused with this one: ![my other cat][fluffy].)
[fluffy]: other-cat.jpg (Not Fluffy <style="width: 25px;">)
"""
def link(self, *args, **kwargs):
bound = LINK_ARGS.bind(*args, **kwargs)
attrs = extract_attrs_from_title(bound)
markup = super().link(*bound.args, *bound.kwargs)
if attrs:
# FIXME: hackish
markup = markup.replace(' href=', ' %s href=' % attrs)
return markup
def image(self, *args, **kwargs):
bound = IMAGE_ARGS.bind(*args, **kwargs)
attrs = extract_attrs_from_title(bound)
markup = super().image(*bound.args, *bound.kwargs)
if attrs:
# FIXME: hackish
markup = markup.replace(' src=', ' %s src=' % attrs)
return markup
class LektorPlugin(lektor.pluginsystem.Plugin):
name = 'Lektor Markdown Image and Link Attributes'
description = (
'Extend Lektors Markdown syntax to allow setting '
'arbitrary HTML attributes on images and links.')
def on_markdown_config(self, config, **extra):
# XXX: This is fragile, but I'm not sure how better to do this.
# Here we attempt to put our mixin the top of the MRO so that it
# will be called above any calls to other mixins which affect
# the rendering of images and/or links.
config.renderer_mixins.insert(0, MarkdownRendererMixin)

View File

@ -0,0 +1,150 @@
[build-system]
requires = [
"hatchling>=1.9.0",
"hatch-vcs",
]
build-backend = "hatchling.build"
[project]
name = "lektor-markdown-image-attrs"
dynamic = ["readme", "version"]
description = """\
Extend Lektors Markdown syntax to allow setting \
arbitrary HTML attributes on images and links.\
"""
license = "MIT"
authors = [
{ name = "Jeff Dairiki", email = "dairiki@dairiki.org" },
]
keywords = [
"Lektor",
"attributes",
"html",
"image",
"markdown",
"plugin",
"style",
]
classifiers = [
"Development Status :: 4 - Beta",
"Environment :: Plugins",
"Environment :: Web Environment",
"Framework :: Lektor",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Topic :: Text Processing :: Markup :: HTML",
"Topic :: Text Processing :: Markup :: Markdown",
]
requires-python = ">=3.7"
[project.entry-points."lektor.plugins"]
markdown-image-attrs = "lektor_markdown_image_attrs:LektorPlugin"
[project.urls]
Homepage = "https://github.com/dairiki/lektor-markdown-image-attrs"
[tool.hatch.version]
source = "vcs"
[tool.hatch.metadata.hooks.custom]
# Custom hook to form readme from README.md and CHANGES.md
path = "hatch_build.py"
[tool.hatch.build]
include = [
"/lektor_markdown_image_attrs.py",
]
[tool.hatch.build.targets.sdist]
include = [
"/lektor_markdown_image_attrs.py",
"/CHANGES.md",
"/tests",
]
[tool.hatch.envs.default]
dependencies = [
"pytest",
"beautifulsoup4",
"coverage[toml]",
"lektor",
]
[tool.hatch.envs.default.scripts]
test = [
"pip freeze | paste -sd , -",
"coverage run -m pytest tests",
]
full = [
# all tests
"hatch run lint:all",
"hatch run cover-clean",
"hatch run test:test",
"hatch run cover-report",
]
cover = [
# test under all versions of lektor, report combine coverage
"cover-clean",
"hatch run lektors:test",
"cover-report",
]
cover-clean = [
"- coverage combine",
"coverage erase",
]
cover-report = [
"- coverage combine --append",
"coverage report --fail-under=100",
]
[tool.hatch.envs.dev]
extra-dependencies = [
"flake8",
"flake8-bugbear",
"mypy==0.971",
"types-beautifulsoup4",
]
[[tool.hatch.envs.lektors.matrix]]
lektor = ["lektor33", "lektor34"]
[[tool.hatch.envs.test.matrix]]
python = ["37", "38", "39", "310"]
lektor = ["lektor33", "lektor34"]
[tool.hatch.envs.default.overrides]
matrix.lektor.dependencies = [
{ value = "lektor<3.4.0", if = ["lektor33"] },
{ value = "lektor>=3.4.0b2", if = ["lektor34"] },
]
[tool.hatch.envs.lint]
detached = true
dependencies = [
"flake8",
"twine",
]
[tool.hatch.envs.lint.scripts]
twine-check = [
"hatch build -t wheel -c",
"twine check dist/*",
]
all = [
"twine-check",
"flake8",
]
[tool.coverage.run]
parallel = true
source = ["lektor_markdown_image_attrs"]
[[tool.mypy.overrides]]
module = [
"lektor.*",
"mistune.*",
]
ignore_missing_imports = true