mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2025-07-23 19:22:27 +02:00
Compare commits
No commits in common. "cbe6c821ccc951e9586f355ffc5caada8ae77f48" and "acff3695bcb912c0785992fb1482a150fe13c7f9" have entirely different histories.
cbe6c821cc
...
acff3695bc
@ -1,3 +0,0 @@
|
|||||||
"""
|
|
||||||
Initializes the custom_css module.
|
|
||||||
"""
|
|
@ -1,25 +0,0 @@
|
|||||||
"""
|
|
||||||
Admin classes for custom_css app
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Django
|
|
||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
# Django Solos
|
|
||||||
from solo.admin import SingletonModelAdmin
|
|
||||||
|
|
||||||
# Alliance Auth Custom CSS
|
|
||||||
from allianceauth.custom_css.models import CustomCSS
|
|
||||||
from allianceauth.custom_css.forms import CustomCSSAdminForm
|
|
||||||
|
|
||||||
|
|
||||||
@admin.register(CustomCSS)
|
|
||||||
class CustomCSSAdmin(SingletonModelAdmin):
|
|
||||||
"""
|
|
||||||
Custom CSS Admin
|
|
||||||
"""
|
|
||||||
|
|
||||||
form = CustomCSSAdminForm
|
|
||||||
|
|
||||||
# Leave this here for when we decide to add syntax highlighting to the CSS editor
|
|
||||||
# change_form_template = 'custom_css/admin/change_form.html'
|
|
@ -1,13 +0,0 @@
|
|||||||
"""
|
|
||||||
Django app configuration for custom_css
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Django
|
|
||||||
from django.apps import AppConfig
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
|
|
||||||
class CustomCSSConfig(AppConfig):
|
|
||||||
name = "allianceauth.custom_css"
|
|
||||||
label = "custom_css"
|
|
||||||
verbose_name = _("Custom CSS")
|
|
@ -1,29 +0,0 @@
|
|||||||
"""
|
|
||||||
Forms for custom_css app
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Alliance Auth Custom CSS
|
|
||||||
from allianceauth.custom_css.models import CustomCSS
|
|
||||||
from allianceauth.custom_css.widgets import CssEditorWidget
|
|
||||||
|
|
||||||
# Django
|
|
||||||
from django import forms
|
|
||||||
|
|
||||||
|
|
||||||
class CustomCSSAdminForm(forms.ModelForm):
|
|
||||||
"""
|
|
||||||
Form for editing custom CSS
|
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = CustomCSS
|
|
||||||
fields = ("css",)
|
|
||||||
widgets = {
|
|
||||||
"css": CssEditorWidget(
|
|
||||||
attrs={
|
|
||||||
"style": "width: 90%; height: 100%;",
|
|
||||||
"data-editor": "code-highlight",
|
|
||||||
"data-language": "css",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
# Generated by Django 4.2.15 on 2024-08-14 11:25
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = []
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name="CustomCSS",
|
|
||||||
fields=[
|
|
||||||
(
|
|
||||||
"id",
|
|
||||||
models.AutoField(
|
|
||||||
auto_created=True,
|
|
||||||
primary_key=True,
|
|
||||||
serialize=False,
|
|
||||||
verbose_name="ID",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"css",
|
|
||||||
models.TextField(
|
|
||||||
blank=True,
|
|
||||||
help_text="This CSS will be added to the site after the default CSS.",
|
|
||||||
null=True,
|
|
||||||
verbose_name="Your custom CSS",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("timestamp", models.DateTimeField(auto_now=True)),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
"verbose_name": "Custom CSS",
|
|
||||||
"verbose_name_plural": "Custom CSS",
|
|
||||||
"default_permissions": (),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,143 +0,0 @@
|
|||||||
"""
|
|
||||||
Models for the custom_css app
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
|
|
||||||
# Django Solo
|
|
||||||
from solo.models import SingletonModel
|
|
||||||
|
|
||||||
# Django
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import models
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
|
|
||||||
class CustomCSS(SingletonModel):
|
|
||||||
"""
|
|
||||||
Model for storing custom CSS for the site
|
|
||||||
"""
|
|
||||||
|
|
||||||
css = models.TextField(
|
|
||||||
blank=True,
|
|
||||||
null=True,
|
|
||||||
verbose_name=_("Your custom CSS"),
|
|
||||||
help_text=_("This CSS will be added to the site after the default CSS."),
|
|
||||||
)
|
|
||||||
timestamp = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""
|
|
||||||
Meta for CustomCSS
|
|
||||||
"""
|
|
||||||
|
|
||||||
default_permissions = ()
|
|
||||||
verbose_name = _("Custom CSS")
|
|
||||||
verbose_name_plural = _("Custom CSS")
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
"""
|
|
||||||
String representation of CustomCSS
|
|
||||||
|
|
||||||
:return:
|
|
||||||
:rtype:
|
|
||||||
"""
|
|
||||||
|
|
||||||
return str(_("Custom CSS"))
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
"""
|
|
||||||
Save method for CustomCSS
|
|
||||||
|
|
||||||
:param args:
|
|
||||||
:type args:
|
|
||||||
:param kwargs:
|
|
||||||
:type kwargs:
|
|
||||||
:return:
|
|
||||||
:rtype:
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.pk = 1
|
|
||||||
|
|
||||||
if self.css and len(self.css.replace(" ", "")) > 0:
|
|
||||||
# Write the custom CSS to a file
|
|
||||||
custom_css_file = open(
|
|
||||||
f"{settings.STATIC_ROOT}allianceauth/custom-styles.css", "w+"
|
|
||||||
)
|
|
||||||
custom_css_file.write(self.compress_css())
|
|
||||||
custom_css_file.close()
|
|
||||||
else:
|
|
||||||
# Remove the custom CSS file
|
|
||||||
try:
|
|
||||||
os.remove(f"{settings.STATIC_ROOT}allianceauth/custom-styles.css")
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
super().save(*args, **kwargs)
|
|
||||||
|
|
||||||
def compress_css(self) -> str:
|
|
||||||
"""
|
|
||||||
Compress CSS
|
|
||||||
|
|
||||||
:return:
|
|
||||||
:rtype:
|
|
||||||
"""
|
|
||||||
|
|
||||||
css = self.css
|
|
||||||
new_css = ""
|
|
||||||
|
|
||||||
# Remove comments
|
|
||||||
css = re.sub(pattern=r"\s*/\*\s*\*/", repl="$$HACK1$$", string=css)
|
|
||||||
css = re.sub(pattern=r"/\*[\s\S]*?\*/", repl="", string=css)
|
|
||||||
css = css.replace("$$HACK1$$", "/**/")
|
|
||||||
|
|
||||||
# url() doesn't need quotes
|
|
||||||
css = re.sub(pattern=r'url\((["\'])([^)]*)\1\)', repl=r"url(\2)", string=css)
|
|
||||||
|
|
||||||
# Spaces may be safely collapsed as generated content will collapse them anyway.
|
|
||||||
css = re.sub(pattern=r"\s+", repl=" ", string=css)
|
|
||||||
|
|
||||||
# Shorten collapsable colors: #aabbcc to #abc
|
|
||||||
css = re.sub(
|
|
||||||
pattern=r"#([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3(\s|;)",
|
|
||||||
repl=r"#\1\2\3\4",
|
|
||||||
string=css,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Fragment values can loose zeros
|
|
||||||
css = re.sub(
|
|
||||||
pattern=r":\s*0(\.\d+([cm]m|e[mx]|in|p[ctx]))\s*;", repl=r":\1;", string=css
|
|
||||||
)
|
|
||||||
|
|
||||||
for rule in re.findall(pattern=r"([^{]+){([^}]*)}", string=css):
|
|
||||||
# We don't need spaces around operators
|
|
||||||
selectors = [
|
|
||||||
re.sub(
|
|
||||||
pattern=r"(?<=[\[\(>+=])\s+|\s+(?=[=~^$*|>+\]\)])",
|
|
||||||
repl=r"",
|
|
||||||
string=selector.strip(),
|
|
||||||
)
|
|
||||||
for selector in rule[0].split(",")
|
|
||||||
]
|
|
||||||
|
|
||||||
# Order is important, but we still want to discard repetitions
|
|
||||||
properties = {}
|
|
||||||
porder = []
|
|
||||||
|
|
||||||
for prop in re.findall(pattern="(.*?):(.*?)(;|$)", string=rule[1]):
|
|
||||||
key = prop[0].strip().lower()
|
|
||||||
|
|
||||||
if key not in porder:
|
|
||||||
porder.append(key)
|
|
||||||
|
|
||||||
properties[key] = prop[1].strip()
|
|
||||||
|
|
||||||
# output rule if it contains any declarations
|
|
||||||
if properties:
|
|
||||||
new_css += "{}{{{}}}".format(
|
|
||||||
",".join(selectors),
|
|
||||||
"".join([f"{key}:{properties[key]};" for key in porder])[:-1],
|
|
||||||
)
|
|
||||||
|
|
||||||
return new_css
|
|
@ -1,48 +0,0 @@
|
|||||||
{% extends "admin/change_form.html" %}
|
|
||||||
|
|
||||||
{% block field_sets %}
|
|
||||||
{% for fieldset in adminform %}
|
|
||||||
<fieldset class="module aligned {{ fieldset.classes }}">
|
|
||||||
{% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %}
|
|
||||||
|
|
||||||
{% if fieldset.description %}
|
|
||||||
<div class="description">{{ fieldset.description|safe }}</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% for line in fieldset %}
|
|
||||||
<div class="form-row{% if line.fields|length == 1 and line.errors %} errors{% endif %}{% if not line.has_visible_field %} hidden{% endif %}{% for field in line %}{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% endfor %}">
|
|
||||||
{% if line.fields|length == 1 %}{{ line.errors }}{% else %}<div class="flex-container form-multiline">{% endif %}
|
|
||||||
|
|
||||||
{% for field in line %}
|
|
||||||
<div>
|
|
||||||
{% if not line.fields|length == 1 and not field.is_readonly %}{{ field.errors }}{% endif %}
|
|
||||||
|
|
||||||
<div class="flex-container{% if not line.fields|length == 1 %} fieldBox{% if field.field.name %} field-{{ field.field.name }}{% endif %}{% if not field.is_readonly and field.errors %} errors{% endif %}{% if field.field.is_hidden %} hidden{% endif %}{% elif field.is_checkbox %} checkbox-row{% endif %}">
|
|
||||||
{% if field.is_checkbox %}
|
|
||||||
{{ field.field }}{{ field.label_tag }}
|
|
||||||
{% else %}
|
|
||||||
{{ field.label_tag }}
|
|
||||||
{% if field.is_readonly %}
|
|
||||||
<div class="readonly">{{ field.contents }}</div>
|
|
||||||
{% else %}
|
|
||||||
{{ field.field }}
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if field.field.help_text %}
|
|
||||||
<div class="help"{% if field.field.id_for_label %} id="{{ field.field.id_for_label }}_helptext"{% endif %}>
|
|
||||||
<div>{{ field.field.help_text|safe }}</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% if not line.fields|length == 1 %}</div>{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</fieldset>
|
|
||||||
{% endfor %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block after_field_sets %}{% endblock %}
|
|
@ -1,3 +0,0 @@
|
|||||||
{% load custom_css %}
|
|
||||||
|
|
||||||
{% custom_css_static 'allianceauth/custom-styles.css' %}
|
|
@ -1,3 +0,0 @@
|
|||||||
"""
|
|
||||||
Init file for custom_css templatetags
|
|
||||||
"""
|
|
@ -1,48 +0,0 @@
|
|||||||
"""
|
|
||||||
Custom template tags for custom_css app
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Alliance Auth Custom CSS
|
|
||||||
from allianceauth.custom_css.models import CustomCSS
|
|
||||||
|
|
||||||
# Django
|
|
||||||
from django.conf import settings
|
|
||||||
from django.template.defaulttags import register
|
|
||||||
from django.templatetags.static import static
|
|
||||||
from django.utils.safestring import mark_safe
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag
|
|
||||||
def custom_css_static(path: str) -> str:
|
|
||||||
"""
|
|
||||||
Versioned static URL
|
|
||||||
This is to make sure to break the browser cache on CSS updates.
|
|
||||||
|
|
||||||
Example: /static/allianceauth/custom-styles.css?v=1234567890
|
|
||||||
|
|
||||||
:param path:
|
|
||||||
:type path:
|
|
||||||
:return:
|
|
||||||
:rtype:
|
|
||||||
"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
Path(f"{settings.STATIC_ROOT}{path}").resolve(strict=True)
|
|
||||||
except FileNotFoundError:
|
|
||||||
return ""
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
custom_css = CustomCSS.objects.get(pk=1)
|
|
||||||
except CustomCSS.DoesNotExist:
|
|
||||||
return ""
|
|
||||||
else:
|
|
||||||
custom_css_changed = custom_css.timestamp.timestamp()
|
|
||||||
custom_css_version = (
|
|
||||||
str(custom_css_changed).replace(" ", "").replace(":", "").replace("-", "")
|
|
||||||
) # remove spaces, colons, and dashes
|
|
||||||
static_url = static(path)
|
|
||||||
versioned_url = static_url + "?v=" + custom_css_version
|
|
||||||
|
|
||||||
return mark_safe(f'<link rel="stylesheet" href="{versioned_url}">')
|
|
@ -1,38 +0,0 @@
|
|||||||
"""
|
|
||||||
Form widgets for custom_css app
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Django
|
|
||||||
from django import forms
|
|
||||||
|
|
||||||
# Alliance Auth
|
|
||||||
from allianceauth.custom_css.models import CustomCSS
|
|
||||||
|
|
||||||
|
|
||||||
class CssEditorWidget(forms.Textarea):
|
|
||||||
"""
|
|
||||||
Widget for editing CSS
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, attrs=None):
|
|
||||||
default_attrs = {"class": "custom-css-editor"}
|
|
||||||
|
|
||||||
if attrs:
|
|
||||||
default_attrs.update(attrs)
|
|
||||||
|
|
||||||
super().__init__(default_attrs)
|
|
||||||
|
|
||||||
# For when we want to add some sort of syntax highlight to it, which is not that
|
|
||||||
# easy to do on a textarea field though.
|
|
||||||
# `highlight.js` is just used as an example here, and doesn't work on a textarea field.
|
|
||||||
# class Media:
|
|
||||||
# css = {
|
|
||||||
# "all": (
|
|
||||||
# "/static/custom_css/libs/highlight.js/11.10.0/styles/github.min.css",
|
|
||||||
# )
|
|
||||||
# }
|
|
||||||
# js = (
|
|
||||||
# "/static/custom_css/libs/highlight.js/11.10.0/highlight.min.js",
|
|
||||||
# "/static/custom_css/libs/highlight.js/11.10.0/languages/css.min.js",
|
|
||||||
# "/static/custom_css/javascript/custom-css.min.js",
|
|
||||||
# )
|
|
@ -22,7 +22,6 @@ INSTALLED_APPS = [
|
|||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'django.contrib.humanize',
|
'django.contrib.humanize',
|
||||||
'django_celery_beat',
|
'django_celery_beat',
|
||||||
'solo',
|
|
||||||
'bootstrapform',
|
'bootstrapform',
|
||||||
'django_bootstrap5', # https://github.com/zostera/django-bootstrap5
|
'django_bootstrap5', # https://github.com/zostera/django-bootstrap5
|
||||||
'sortedm2m',
|
'sortedm2m',
|
||||||
@ -40,7 +39,6 @@ INSTALLED_APPS = [
|
|||||||
'allianceauth.theme.darkly',
|
'allianceauth.theme.darkly',
|
||||||
'allianceauth.theme.flatly',
|
'allianceauth.theme.flatly',
|
||||||
'allianceauth.theme.materia',
|
'allianceauth.theme.materia',
|
||||||
"allianceauth.custom_css",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
SECRET_KEY = "wow I'm a really bad default secret key"
|
SECRET_KEY = "wow I'm a really bad default secret key"
|
||||||
|
@ -35,8 +35,6 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
{% block extra_css %}{% endblock extra_css %}
|
{% block extra_css %}{% endblock extra_css %}
|
||||||
|
|
||||||
{% include 'custom_css/bundles/custom-css.html' %}
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -27,7 +27,6 @@ class BootstrapThemeHook(ThemeHook):
|
|||||||
self,
|
self,
|
||||||
"Bootstrap",
|
"Bootstrap",
|
||||||
"Powerful, extensible, and feature-packed frontend toolkit.",
|
"Powerful, extensible, and feature-packed frontend toolkit.",
|
||||||
html_tags={"data-theme": "bootstrap"},
|
|
||||||
css=CSS_STATICS,
|
css=CSS_STATICS,
|
||||||
js=JS_STATICS,
|
js=JS_STATICS,
|
||||||
header_padding="3.5em"
|
header_padding="3.5em"
|
||||||
@ -45,9 +44,9 @@ class BootstrapDarkThemeHook(ThemeHook):
|
|||||||
self,
|
self,
|
||||||
"Bootstrap Dark",
|
"Bootstrap Dark",
|
||||||
"Powerful, extensible, and feature-packed frontend toolkit.",
|
"Powerful, extensible, and feature-packed frontend toolkit.",
|
||||||
html_tags={"data-theme": "bootstrap-dark"},
|
|
||||||
css=CSS_STATICS,
|
css=CSS_STATICS,
|
||||||
js=JS_STATICS,
|
js=JS_STATICS,
|
||||||
|
html_tags="data-bs-theme=dark",
|
||||||
header_padding="3.5em"
|
header_padding="3.5em"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ class DarklyThemeHook(ThemeHook):
|
|||||||
self,
|
self,
|
||||||
"Darkly",
|
"Darkly",
|
||||||
"Flatly in night mode!",
|
"Flatly in night mode!",
|
||||||
html_tags={"data-theme": "darkly"},
|
|
||||||
css=[{
|
css=[{
|
||||||
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/darkly/bootstrap.min.css",
|
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/darkly/bootstrap.min.css",
|
||||||
"integrity": "sha512-HDszXqSUU0om4Yj5dZOUNmtwXGWDa5ppESlX98yzbBS+z+3HQ8a/7kcdI1dv+jKq+1V5b01eYurE7+yFjw6Rdg=="
|
"integrity": "sha512-HDszXqSUU0om4Yj5dZOUNmtwXGWDa5ppESlX98yzbBS+z+3HQ8a/7kcdI1dv+jKq+1V5b01eYurE7+yFjw6Rdg=="
|
||||||
|
@ -13,7 +13,6 @@ class FlatlyThemeHook(ThemeHook):
|
|||||||
self,
|
self,
|
||||||
"Flatly",
|
"Flatly",
|
||||||
"Flat and modern!",
|
"Flat and modern!",
|
||||||
html_tags={"data-theme": "flatly"},
|
|
||||||
css=[{
|
css=[{
|
||||||
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/flatly/bootstrap.min.css",
|
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/flatly/bootstrap.min.css",
|
||||||
"integrity": "sha512-qoT4KwnRpAQ9uczPsw7GunsNmhRnYwSlE2KRCUPRQHSkDuLulCtDXuC2P/P6oqr3M5hoGagUG9pgHDPkD2zCDA=="
|
"integrity": "sha512-qoT4KwnRpAQ9uczPsw7GunsNmhRnYwSlE2KRCUPRQHSkDuLulCtDXuC2P/P6oqr3M5hoGagUG9pgHDPkD2zCDA=="
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
from typing import List, Optional, Union
|
from typing import List, Optional
|
||||||
|
|
||||||
|
|
||||||
class ThemeHook:
|
class ThemeHook:
|
||||||
"""
|
"""
|
||||||
Theme hook for injecting a Bootstrap 5 Theme and associated JS into alliance auth.
|
Theme hook for injecting a Bootstrap 5 Theme and associated JS into alliance auth.
|
||||||
These can be local or CDN delivered.
|
these can be local or CDN delivered
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
@ -14,7 +14,7 @@ class ThemeHook:
|
|||||||
js: List[dict],
|
js: List[dict],
|
||||||
css_template: Optional[str] = None,
|
css_template: Optional[str] = None,
|
||||||
js_template: Optional[str] = None,
|
js_template: Optional[str] = None,
|
||||||
html_tags: Optional[Union[dict, str]] = None,
|
html_tags: Optional[str] = "",
|
||||||
header_padding: Optional[str] = "4em"):
|
header_padding: Optional[str] = "4em"):
|
||||||
"""
|
"""
|
||||||
:param name: Theme python name
|
:param name: Theme python name
|
||||||
@ -29,10 +29,6 @@ class ThemeHook:
|
|||||||
:type css_template: Optional[str], optional
|
:type css_template: Optional[str], optional
|
||||||
:param js_template: _description_, defaults to None
|
:param js_template: _description_, defaults to None
|
||||||
:type js_template: Optional[str], optional
|
:type js_template: Optional[str], optional
|
||||||
:param html_tags: Attributes added to the `<html>` tag, defaults to None
|
|
||||||
:type html_tags: Optional[dict|str], optional
|
|
||||||
:param header_padding: Top padding, defaults to "4em"
|
|
||||||
:type header_padding: Optional[str], optional
|
|
||||||
"""
|
"""
|
||||||
self.name = name
|
self.name = name
|
||||||
self.description = description
|
self.description = description
|
||||||
@ -45,11 +41,7 @@ class ThemeHook:
|
|||||||
self.css_template = css_template
|
self.css_template = css_template
|
||||||
self.js_template = js_template
|
self.js_template = js_template
|
||||||
|
|
||||||
self.html_tags = (
|
self.html_tags = html_tags
|
||||||
" ".join([f"{key}={value}" for key, value in html_tags.items()])
|
|
||||||
if isinstance(html_tags, dict)
|
|
||||||
else html_tags
|
|
||||||
)
|
|
||||||
self.header_padding = header_padding
|
self.header_padding = header_padding
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
return f"{self.__class__.__module__}.{self.__class__.__name__}"
|
return f"{self.__class__.__module__}.{self.__class__.__name__}"
|
||||||
|
@ -13,7 +13,6 @@ class MateriaThemeHook(ThemeHook):
|
|||||||
self,
|
self,
|
||||||
"Materia",
|
"Materia",
|
||||||
"Material is the metaphor",
|
"Material is the metaphor",
|
||||||
html_tags={"data-theme": "materia"},
|
|
||||||
css=[{
|
css=[{
|
||||||
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/materia/bootstrap.min.css",
|
"url": "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.3/materia/bootstrap.min.css",
|
||||||
"integrity": "sha512-2S9Do+uTmZmmJpdmAcOKdUrK/YslcvAuRfIF2ws8+BW9AvZXMRZM+o8Wq+PZrfISD6ZlIaeCWWZAdeprXIoYuQ=="
|
"integrity": "sha512-2S9Do+uTmZmmJpdmAcOKdUrK/YslcvAuRfIF2ws8+BW9AvZXMRZM+o8Wq+PZrfISD6ZlIaeCWWZAdeprXIoYuQ=="
|
||||||
|
@ -50,7 +50,6 @@ dependencies = [
|
|||||||
"django-esi>=5",
|
"django-esi>=5",
|
||||||
"django-redis>=5.2",
|
"django-redis>=5.2",
|
||||||
"django-registration<3.4,>=3.3",
|
"django-registration<3.4,>=3.3",
|
||||||
"django-solo",
|
|
||||||
"django-sortedm2m",
|
"django-sortedm2m",
|
||||||
"dnspython",
|
"dnspython",
|
||||||
"mysqlclient>=2.1",
|
"mysqlclient>=2.1",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user