import re from django.conf import settings from django.forms import Media from django.http import StreamingHttpResponse from django_components.component_registry import registry RENDERED_COMPONENTS_CONTEXT_KEY = "_COMPONENT_DEPENDENCIES" CSS_DEPENDENCY_PLACEHOLDER = '' JS_DEPENDENCY_PLACEHOLDER = '' SCRIPT_TAG_REGEX = re.compile("[\w\-/]+?) -->") PLACEHOLDER_REGEX = re.compile( rb"" rb'|' rb'|' ) class ComponentDependencyMiddleware: """Middleware that inserts CSS/JS dependencies for all rendered components at points marked with template tags.""" dependency_regex = COMPONENT_COMMENT_REGEX def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) if ( getattr(settings, "COMPONENTS", {}).get("RENDER_DEPENDENCIES", False) and not isinstance(response, StreamingHttpResponse) and response.get("Content-Type", "").startswith("text/html") ): response.content = process_response_content(response.content) return response def process_response_content(content): component_names_seen = {match.group("name") for match in COMPONENT_COMMENT_REGEX.finditer(content)} all_components = [registry.get(name.decode("utf-8"))("") for name in component_names_seen] all_media = join_media(all_components) js_dependencies = b"".join(media.encode("utf-8") for media in all_media.render_js()) css_dependencies = b"".join(media.encode("utf-8") for media in all_media.render_css()) return PLACEHOLDER_REGEX.sub(DependencyReplacer(css_dependencies, js_dependencies), content) def add_module_attribute_to_scripts(scripts): return re.sub(SCRIPT_TAG_REGEX, '