mirror of
https://github.com/torproject/lego.git
synced 2024-11-26 19:20:22 +00:00
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:
parent
b362ba120c
commit
7170786d2a
18
packages/markdown-image-attrs/CHANGES.md
Normal file
18
packages/markdown-image-attrs/CHANGES.md
Normal 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
|
||||
|
20
packages/markdown-image-attrs/LICENSE
Normal file
20
packages/markdown-image-attrs/LICENSE
Normal 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.
|
98
packages/markdown-image-attrs/README.md
Normal file
98
packages/markdown-image-attrs/README.md
Normal 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 Lektor’s 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 Lektor’s 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
|
||||
Markdown’s 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 you’d 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
|
||||
Here’s a photo of [my cat][]: ![fluffy][]
|
||||
|
||||
[fluffy]: fluffy.jpg (style='width: 80px;')
|
||||
[my cat]: <http://fluffy.example.org> 'Fluffy’s 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>
|
||||
|
||||
|
||||
|
119
packages/markdown-image-attrs/lektor_markdown_image_attrs.py
Normal file
119
packages/markdown-image-attrs/lektor_markdown_image_attrs.py
Normal 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 Lektor’s 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)
|
150
packages/markdown-image-attrs/pyproject.toml
Normal file
150
packages/markdown-image-attrs/pyproject.toml
Normal 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 Lektor’s 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
|
Loading…
Reference in New Issue
Block a user