This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
import re
|
||||
from collections.abc import Mapping
|
||||
from urllib.parse import parse_qs, urlparse, urlunparse
|
||||
|
||||
from django.forms.utils import flatatt
|
||||
from django.template.base import FilterExpression, TemplateSyntaxError, Variable, VariableDoesNotExist, kwarg_re
|
||||
from django.template.loader import get_template
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.html import format_html
|
||||
from django.utils.http import urlencode
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from .text import text_value
|
||||
|
||||
# RegEx for quoted string
|
||||
QUOTED_STRING = re.compile(r'^["\'](?P<noquotes>.+)["\']$')
|
||||
|
||||
|
||||
def handle_var(value, context):
|
||||
"""Handle template tag variable."""
|
||||
# Resolve FilterExpression and Variable immediately
|
||||
if isinstance(value, FilterExpression) or isinstance(value, Variable):
|
||||
return value.resolve(context)
|
||||
# Return quoted strings unquoted
|
||||
# http://djangosnippets.org/snippets/886
|
||||
stringval = QUOTED_STRING.search(value)
|
||||
if stringval:
|
||||
return stringval.group("noquotes")
|
||||
# Resolve variable or return string value
|
||||
try:
|
||||
return Variable(value).resolve(context)
|
||||
except VariableDoesNotExist:
|
||||
return value
|
||||
|
||||
|
||||
def parse_token_contents(parser, token):
|
||||
"""Parse template tag contents."""
|
||||
bits = token.split_contents()
|
||||
tag = bits.pop(0)
|
||||
args = []
|
||||
kwargs = {}
|
||||
asvar = None
|
||||
if len(bits) >= 2 and bits[-2] == "as":
|
||||
asvar = bits[-1]
|
||||
bits = bits[:-2]
|
||||
if len(bits):
|
||||
for bit in bits:
|
||||
match = kwarg_re.match(bit)
|
||||
if not match:
|
||||
raise TemplateSyntaxError('Malformed arguments to tag "{tag}"'.format(tag=tag))
|
||||
name, value = match.groups()
|
||||
if name:
|
||||
kwargs[name] = parser.compile_filter(value)
|
||||
else:
|
||||
args.append(parser.compile_filter(value))
|
||||
return {"tag": tag, "args": args, "kwargs": kwargs, "asvar": asvar}
|
||||
|
||||
|
||||
def split_css_classes(css_classes):
|
||||
"""Turn string into a list of CSS classes."""
|
||||
classes_list = text_value(css_classes).split(" ")
|
||||
return [c for c in classes_list if c]
|
||||
|
||||
|
||||
def add_css_class(css_classes, css_class, prepend=False):
|
||||
"""Add a CSS class to a string of CSS classes."""
|
||||
classes_list = split_css_classes(css_classes)
|
||||
classes_to_add = [c for c in split_css_classes(css_class) if c not in classes_list]
|
||||
if prepend:
|
||||
classes_list = classes_to_add + classes_list
|
||||
else:
|
||||
classes_list += classes_to_add
|
||||
return " ".join(classes_list)
|
||||
|
||||
|
||||
def remove_css_class(css_classes, css_class):
|
||||
"""Remove a CSS class from a string of CSS classes."""
|
||||
remove = set(split_css_classes(css_class))
|
||||
classes_list = [c for c in split_css_classes(css_classes) if c not in remove]
|
||||
return " ".join(classes_list)
|
||||
|
||||
|
||||
def render_script_tag(url):
|
||||
"""Build a script tag."""
|
||||
url_dict = sanitize_url_dict(url)
|
||||
url_dict.setdefault("src", url_dict.pop("url", None))
|
||||
return render_tag("script", url_dict)
|
||||
|
||||
|
||||
def render_link_tag(url, rel="stylesheet", media=None):
|
||||
"""Build a link tag."""
|
||||
url_dict = sanitize_url_dict(url, url_attr="href")
|
||||
url_dict.setdefault("href", url_dict.pop("url", None))
|
||||
url_dict["rel"] = rel
|
||||
if media:
|
||||
url_dict["media"] = media
|
||||
return render_tag("link", attrs=url_dict, close=False)
|
||||
|
||||
|
||||
def render_tag(tag, attrs=None, content=None, close=True):
|
||||
"""Render a HTML tag."""
|
||||
builder = "<{tag}{attrs}>{content}"
|
||||
if content or close:
|
||||
builder += "</{tag}>"
|
||||
return format_html(builder, tag=tag, attrs=mark_safe(flatatt(attrs)) if attrs else "", content=text_value(content))
|
||||
|
||||
|
||||
def render_template_file(template, context=None):
|
||||
"""Render a Template to unicode."""
|
||||
assert isinstance(context, Mapping)
|
||||
template = get_template(template)
|
||||
return template.render(context)
|
||||
|
||||
|
||||
def url_replace_param(url, name, value):
|
||||
"""Replace a GET parameter in an URL."""
|
||||
url_components = urlparse(force_str(url))
|
||||
|
||||
params = parse_qs(url_components.query)
|
||||
|
||||
if value is None:
|
||||
del params[name]
|
||||
else:
|
||||
params[name] = value
|
||||
|
||||
return mark_safe(
|
||||
urlunparse(
|
||||
[
|
||||
url_components.scheme,
|
||||
url_components.netloc,
|
||||
url_components.path,
|
||||
url_components.params,
|
||||
urlencode(params, doseq=True),
|
||||
url_components.fragment,
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def sanitize_url_dict(url, url_attr="src"):
|
||||
"""Sanitize url dict as used in django-bootstrap-v5 settings."""
|
||||
if isinstance(url, str):
|
||||
return {url_attr: url}
|
||||
return url.copy()
|
||||
Reference in New Issue
Block a user