add markdown module
This commit is contained in:
parent
38eac17109
commit
d6e54f192f
5 changed files with 99 additions and 7 deletions
|
|
@ -2,10 +2,13 @@
|
|||
|
||||
## 0.3.0
|
||||
|
||||
- Add auth loaders i.e. `sqlalchemy.require_auth_base()`, `flask_sqlalchemy`
|
||||
- Add SQLAlchemy auth loaders i.e. `sqlalchemy.require_auth_base()`, `flask_sqlalchemy`.
|
||||
What auth loaders do is loading user token and signature into app
|
||||
- Implement `UserSigner()`
|
||||
- Improve JSON handling in `flask_restx`
|
||||
- Add base2048 (i.e. BIP-39) codec
|
||||
- Add `split_bits()` and `join_bits()`
|
||||
- Add base2048 (i.e. [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)) codec
|
||||
- Add `split_bits()`, `join_bits()`, `ltuple()`, `rtuple()`
|
||||
- Add `markdown` extensions
|
||||
|
||||
## 0.2.3
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ flask_sqlalchemy = [
|
|||
peewee = [
|
||||
"peewee>=3.0.0, <4.0"
|
||||
]
|
||||
|
||||
markdown = [
|
||||
"markdown>=3.0.0"
|
||||
]
|
||||
|
||||
[tool.setuptools.dynamic]
|
||||
version = { attr = "suou.__version__" }
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ from .classtools import Wanted, Incomplete
|
|||
from .itertools import makelist, kwargs_prefix, ltuple, rtuple
|
||||
from .i18n import I18n, JsonI18n, TomlI18n
|
||||
|
||||
__version__ = "0.3.0-dev21"
|
||||
__version__ = "0.3.0-dev22"
|
||||
|
||||
__all__ = (
|
||||
'Siq', 'SiqCache', 'SiqType', 'SiqGen', 'StringCase',
|
||||
|
|
|
|||
|
|
@ -50,8 +50,6 @@ def count_ones(n: int) -> int:
|
|||
def split_bits(buf: bytes, nbits: int) -> list[int]:
|
||||
'''
|
||||
Split a bytestring into chunks of equal size, and interpret each chunk as an unsigned integer.
|
||||
|
||||
XXX DOES NOT WORK DO NOT USE!!!!!!!!
|
||||
'''
|
||||
mem = memoryview(buf)
|
||||
chunk_size = nbits // math.gcd(nbits, 8)
|
||||
|
|
|
|||
89
src/suou/markdown.py
Normal file
89
src/suou/markdown.py
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
"""
|
||||
Plugins for markdown.
|
||||
|
||||
---
|
||||
|
||||
Copyright (c) 2025 Sakuragasaki46.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
See LICENSE for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
This software is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
import re
|
||||
import markdown
|
||||
from markdown.inlinepatterns import InlineProcessor, SimpleTagInlineProcessor
|
||||
import xml.etree.ElementTree as etree
|
||||
|
||||
class StrikethroughExtension(markdown.extensions.Extension):
|
||||
"""
|
||||
Turn ~~crossed out~~ (with double tilde) text into HTML strikethrough
|
||||
|
||||
well, markdown-strikethrough is a trivial dependency lol
|
||||
"""
|
||||
def extendMarkdown(self, md: markdown.Markdown, md_globals=None):
|
||||
postprocessor = StrikethroughPostprocessor(md)
|
||||
md.postprocessors.register(postprocessor, 'strikethrough', 0)
|
||||
|
||||
class StrikethroughPostprocessor(markdown.postprocessors.Postprocessor):
|
||||
PATTERN = re.compile(r"~~(((?!~~).)+)~~", re.DOTALL)
|
||||
|
||||
def run(self, html):
|
||||
return re.sub(self.PATTERN, self.convert, html)
|
||||
|
||||
def convert(self, match: re.Match):
|
||||
return '<del>' + match.group(1) + '</del>'
|
||||
|
||||
|
||||
class SpoilerExtension(markdown.extensions.Extension):
|
||||
"""
|
||||
Add spoiler tags to text, using >!Reddit syntax!<.
|
||||
|
||||
XXX remember to call SpoilerExtension.patch_blockquote_processor()
|
||||
to clear conflicts with the blockquote processor and allow
|
||||
spoiler tags to start at beginning of line.
|
||||
"""
|
||||
def extendMarkdown(self, md: markdown.Markdown, md_globals=None):
|
||||
md.inlinePatterns.register(SimpleTagInlineProcessor(r'()>!(.*?)!<', 'span class="spoiler"'), 'spoiler', 14)
|
||||
|
||||
@classmethod
|
||||
def patch_blockquote_processor(cls):
|
||||
"""Patch BlockquoteProcessor to make Spoiler prevail over blockquotes."""
|
||||
from markdown.blockprocessors import BlockQuoteProcessor
|
||||
BlockQuoteProcessor.RE = re.compile(r'(^|\n)[ ]{0,3}>(?!!)[ ]?(.*)')
|
||||
|
||||
|
||||
class MentionPattern(InlineProcessor):
|
||||
def __init__(self, regex, url_prefix: str):
|
||||
super().__init__(regex)
|
||||
self.url_prefix = url_prefix
|
||||
def handleMatch(self, m, data):
|
||||
el = etree.Element('a')
|
||||
el.attrib['href'] = self.url_prefix + m.group(1)
|
||||
el.text = m.group(0)
|
||||
return el, m.start(0), m.end(0)
|
||||
|
||||
class PingExtension(markdown.extensions.Extension):
|
||||
"""
|
||||
Convert @mentions into profile links.
|
||||
|
||||
Customizable by passing a dict as mappings= argument, where
|
||||
the key is the first character, and the value is the URL prefix.
|
||||
"""
|
||||
mappings: dict[str, str]
|
||||
DEFAULT_MAPPINGS = {'@': '/@'}
|
||||
CHARACTERS = r'[a-zA-Z0-9_-]{2,32}'
|
||||
|
||||
def __init__(self, /, mappings: dict | None = None, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.mappings = mappings or self.DEFAULT_MAPPINGS.copy()
|
||||
def extendMarkdown(self, md: markdown.Markdown, md_globals=None):
|
||||
for at, url_prefix in self.mappings.items():
|
||||
md.inlinePatterns.register(MentionPattern(re.escape(at) + r'(' + self.CHARACTERS + ')', url_prefix), 'ping_mention', 14)
|
||||
|
||||
|
||||
__all__ = ('PingExtension', 'SpoilerExtension', 'StrikethroughExtension')
|
||||
Loading…
Add table
Add a link
Reference in a new issue