Source code for wildewidgets.widgets.text
from __future__ import annotations
import warnings
from typing import Any
try:
from pygments import highlight
from pygments.formatters import HtmlFormatter
from pygments.lexers import get_lexer_by_name
except ModuleNotFoundError:
# Only needed if using syntax highlighting
pass
from .base import Block, TemplateWidget
[docs]class CodeWidget(Block):
"""
A widget that displays code with syntax highlighting.
This widget uses Pygments to apply syntax highlighting to code snippets.
The programming language must be specified to determine the highlighting rules.
Example:
.. code-block:: python
from wildewidgets import CodeWidget
python_code = '''
def hello_world():
print("Hello, world!")
'''
code_widget = CodeWidget(
code=python_code,
language="python",
line_numbers=True
)
Note:
Requires the `pygments` package to be installed.
Args:
code: The code to be displayed
language: The programming language for syntax highlighting
line_numbers: Whether to display line numbers
**kwargs: Additional arguments passed to the parent class
Raises:
ValueError: If no language is specified
RuntimeError: If Pygments is not installed
"""
#: The name of the block for CSS styling
block: str = "wildewidgets_highlight_container"
#: The code to be displayed
code: str = ""
#: The programming language for the :py:attr:`code`
language: str | None = None
#: If ``True``, show line numbers
line_numbers: bool = False
def __init__(
self,
code: str | None = None,
language: str | None = None,
line_numbers: bool = False,
**kwargs: Any,
):
# Raise RuntimeError if pygments is not installed
if not (get_lexer_by_name and highlight and HtmlFormatter):
msg = "Pygments is not installed. Please install it to use CodeWidget."
raise RuntimeError(msg)
self.code = code or self.code
self.language = language or self.language
if not self.language:
msg = (
f'{self.__class__.__name__}: "language" must be defined either as a '
"class attribute or a keyword arg"
)
raise ValueError(msg)
self.line_numbers = line_numbers or self.line_numbers
super().__init__(**kwargs)
self.add_code(self.code, language=self.language, line_numbers=self.line_numbers)
[docs] def add_code(self, code: str, language: str, line_numbers: bool = False) -> None:
"""
Apply syntax highlighting to code and add it to the widget.
Args:
code: The code to highlight
language: The programming language to use for highlighting
line_numbers: Whether to display line numbers
"""
lexer = get_lexer_by_name(language)
formatter = HtmlFormatter(
linenos=line_numbers, cssclass="wildewidgets_highlight"
)
self.add_block(highlight(code, lexer, formatter))
[docs]class MarkdownWidget(TemplateWidget):
"""
A widget that renders Markdown text as HTML.
This widget converts Markdown formatted text to HTML and displays it.
It requires Django's template system to render the HTML.
Attributes:
template_name: The Django template used to render the widget
text: The Markdown text to render
css_class: CSS classes to apply to the container
Example:
.. code-block:: python
from wildewidgets import MarkdownWidget
markdown_text = '''
# Hello World
This is a **bold** statement with *emphasis*.
- Item 1
- Item 2
'''
widget = MarkdownWidget(text=markdown_text, css_class="my-markdown")
Args:
*args: Positional arguments passed to the parent class
Keyword Args:
**kwargs: Keyword arguments including:
text: The Markdown text to render
css_class: CSS classes to apply to the container
"""
template_name = "wildewidgets/markdown_widget.html"
text: str = ""
css_class: str = ""
def __init__(self, *args: Any, **kwargs: Any):
self.text = kwargs.pop("text", self.text)
self.css_class = kwargs.pop("css_class", self.css_class)
super().__init__(*args, **kwargs)
[docs] def get_context_data(self, *args: Any, **kwargs: Any) -> dict[str, Any]:
"""
Prepare the context data for template rendering.
Args:
*args: Positional arguments passed to the parent method
**kwargs: Keyword arguments passed to the parent method
Returns:
dict: The context dictionary with markdown text and CSS classes
"""
kwargs = super().get_context_data(*args, **kwargs)
kwargs["text"] = self.text
kwargs["css_class"] = self.css_class
return kwargs
[docs]class HTMLWidget(TemplateWidget):
"""
A widget that renders raw HTML content.
This widget allows for displaying arbitrary HTML content within
your Django application. Use with caution as it can introduce
security risks if displaying user-provided content.
Attributes:
template_name: The Django template used to render the widget
html: The raw HTML content to display
css_class: CSS classes to apply to the container
Example:
.. code-block:: python
from wildewidgets import HTMLWidget
html_content = '<p>This is <strong>HTML</strong> content</p>'
widget = HTMLWidget(html=html_content, css_class="custom-html-block")
Warning:
Be careful when using this widget with user-provided content as it
could lead to cross-site scripting (XSS) vulnerabilities.
Args:
*args: Positional arguments passed to the parent class
Keyword Args:
**kwargs: Keyword arguments including:
html: The raw HTML content to display
css_class: CSS classes to apply to the container
"""
template_name = "wildewidgets/html_widget.html"
html: str = ""
css_class: str | None = None
def __init__(self, *args: Any, **kwargs: Any):
self.html = kwargs.pop("html", self.html)
self.css_class = kwargs.pop("css_class", self.css_class)
super().__init__(*args, **kwargs)
[docs] def get_context_data(self, *args: Any, **kwargs: Any) -> dict[str, Any]:
"""
Prepare the context data for template rendering.
Args:
*args: Positional arguments passed to the parent method
**kwargs: Keyword arguments passed to the parent method
Returns:
dict: The context dictionary with HTML content and CSS classes
"""
kwargs = super().get_context_data(*args, **kwargs)
kwargs["html"] = self.html
kwargs["css_class"] = self.css_class
return kwargs
[docs]class StringBlock(Block):
"""
A basic widget that displays a string.
This is a simple wrapper around Block that initializes with a text string.
.. deprecated:: 0.14.0
Use :py:class:`wildewidgets.Block` directly instead.
It works exactly like :py:class:`StringBlock`
Args:
text: The text to display
**kwargs: Additional arguments passed to the parent class
Example:
.. code-block:: python
# Deprecated usage
from wildewidgets import StringBlock
text_block = StringBlock("Hello, world!")
# Preferred usage
from wildewidgets import Block
text_block = Block("Hello, world!")
Args:
text: The text to display
Keyword Args:
**kwargs: Additional arguments passed to the parent class
"""
def __init__(self, text: str, **kwargs: Any):
warnings.warn(
"Deprecated in 0.14.0; use Block directly instead.",
DeprecationWarning,
stacklevel=2,
)
super().__init__(*[text], **kwargs)
[docs]class TimeStamp(Block):
"""
A widget that displays text formatted as a timestamp.
This widget renders text in a small font with light styling,
making it suitable for timestamps, captions, or other secondary text.
Attributes:
tag: HTML tag to use for the timestamp (small)
css_class: CSS class for styling the timestamp
Example:
.. code-block:: python
from wildewidgets import TimeStamp
timestamp = TimeStamp("Last updated: 2023-06-15 14:30")
"""
tag = "small"
css_class = "fw-light"
[docs]class TagBlock(Block):
"""
A widget that displays text as a colored badge/tag.
This widget creates a Bootstrap badge with customizable color,
useful for status indicators, categories, or other labeled items.
Example:
.. code-block:: python
from wildewidgets import TagBlock
# Creates a success (green) badge
status_tag = TagBlock("Active", color="success")
# Creates a danger (red) badge
error_tag = TagBlock("Error", color="danger")
# Creates a custom colored badge
custom_tag = TagBlock("Custom", color="info")
Note:
The color parameter accepts standard Bootstrap color names like
"primary", "secondary", "success", "danger", "warning", "info", etc.
Args:
text: The text to display in the badge
Keyword Args:
color: The Bootstrap color class to use (default: "secondary")
**kwargs: Additional arguments passed to the parent class
"""
block: str = "badge"
def __init__(self, text: str, color: str = "secondary", **kwargs: Any):
super().__init__(text, **kwargs)
self.add_class(f"bg-{color}")