الملفات
Building-API-and-Monitoring…/venv/lib/python3.12/site-packages/mistune/plugins/spoiler.py
2025-09-27 23:34:33 +03:00

88 أسطر
2.8 KiB
Python

import re
from typing import TYPE_CHECKING, Match
if TYPE_CHECKING:
from ..block_parser import BlockParser
from ..core import BaseRenderer, BlockState, InlineState
from ..inline_parser import InlineParser
from ..markdown import Markdown
__all__ = ["spoiler"]
_BLOCK_SPOILER_START = re.compile(r"^ {0,3}! ?", re.M)
_BLOCK_SPOILER_MATCH = re.compile(r"^( {0,3}![^\n]*\n)+$")
INLINE_SPOILER_PATTERN = r">!\s*(?P<spoiler_text>.+?)\s*!<"
def parse_block_spoiler(block: "BlockParser", m: Match[str], state: "BlockState") -> int:
text, end_pos = block.extract_block_quote(m, state)
if not text.endswith("\n"):
# ensure it endswith \n to make sure
# _BLOCK_SPOILER_MATCH.match works
text += "\n"
depth = state.depth()
if not depth and _BLOCK_SPOILER_MATCH.match(text):
text = _BLOCK_SPOILER_START.sub("", text)
tok_type = "block_spoiler"
else:
tok_type = "block_quote"
# scan children state
child = state.child_state(text)
if state.depth() >= block.max_nested_level - 1:
rules = list(block.block_quote_rules)
rules.remove("block_quote")
else:
rules = block.block_quote_rules
block.parse(child, rules)
token = {"type": tok_type, "children": child.tokens}
if end_pos:
state.prepend_token(token)
return end_pos
state.append_token(token)
return state.cursor
def parse_inline_spoiler(inline: "InlineParser", m: Match[str], state: "InlineState") -> int:
text = m.group("spoiler_text")
new_state = state.copy()
new_state.src = text
children = inline.render(new_state)
state.append_token({"type": "inline_spoiler", "children": children})
return m.end()
def render_block_spoiler(renderer: "BaseRenderer", text: str) -> str:
return '<div class="spoiler">\n' + text + "</div>\n"
def render_inline_spoiler(renderer: "BaseRenderer", text: str) -> str:
return '<span class="spoiler">' + text + "</span>"
def spoiler(md: "Markdown") -> None:
"""A mistune plugin to support block and inline spoiler. The
syntax is inspired by stackexchange:
.. code-block:: text
Block level spoiler looks like block quote, but with `>!`:
>! this is spoiler
>!
>! the content will be hidden
Inline spoiler is surrounded by `>!` and `!<`, such as >! hide me !<.
:param md: Markdown instance
"""
# reset block quote parser with block spoiler parser
md.block.register("block_quote", None, parse_block_spoiler)
md.inline.register("inline_spoiler", INLINE_SPOILER_PATTERN, parse_inline_spoiler)
if md.renderer and md.renderer.NAME == "html":
md.renderer.register("block_spoiler", render_block_spoiler)
md.renderer.register("inline_spoiler", render_inline_spoiler)