107 lines
2.9 KiB
Python
107 lines
2.9 KiB
Python
from bs4 import BeautifulSoup, Tag
|
|
from files.helpers.config.const import SITE_FULL_IMAGES
|
|
from files.helpers.marseyfx.parser import Modifier
|
|
from files.helpers.marseyfx.tokenizer import StringLiteralToken
|
|
|
|
modifier_whitelist = []
|
|
|
|
def modifier(fn):
|
|
modifier_whitelist.append(fn.__name__)
|
|
|
|
def wrapper(*args, **kwargs):
|
|
args[0].el['class'].append('marseyfx-modifier-' + fn.__name__)
|
|
return fn(*args, **kwargs)
|
|
return wrapper
|
|
|
|
class Modified:
|
|
soup: BeautifulSoup
|
|
el: Tag #BeautifulSoup element
|
|
|
|
def __init__(self, el):
|
|
self.soup = BeautifulSoup()
|
|
self.el = el.wrap(self.soup.new_tag('div', class_='marseyfx-container'))
|
|
|
|
def add_class(self, class_: str):
|
|
self.el.attrs['class'].append(' ' + class_)
|
|
|
|
def apply_modifiers(self, modifiers: list[Modifier]):
|
|
for modifier in modifiers:
|
|
if modifier.name in modifier_whitelist:
|
|
getattr(self, modifier.name)(*modifier.args)
|
|
|
|
# Using this instead of throwing everything in a string and then parsing it helps
|
|
# mitigate the risk of XSS attacks
|
|
def image(self, name: str):
|
|
return self.soup.new_tag(
|
|
'img',
|
|
loading='lazy',
|
|
class_=f'marseyfx-{name}',
|
|
src=f'{SITE_FULL_IMAGES}/i/{name}.webp'
|
|
)
|
|
|
|
def underlay(self, underlay: Tag):
|
|
self.el.insert(0, underlay)
|
|
|
|
def overlay(self, overlay: Tag):
|
|
self.el.append(overlay)
|
|
|
|
@modifier
|
|
def pat(self):
|
|
self.overlay(self.el, self.image('pat'))
|
|
|
|
@modifier
|
|
def love(self):
|
|
self.overlay(self.el, self.image('love-foreground'))
|
|
self.underlay(self.el, self.image('love-background'))
|
|
|
|
@modifier
|
|
def talking(self):
|
|
self.overlay(self.el, self.image('talking'))
|
|
|
|
@modifier
|
|
def genocide(self):
|
|
pass
|
|
|
|
@modifier
|
|
def says(self, msg):
|
|
if not isinstance(msg, StringLiteralToken):
|
|
return
|
|
|
|
self.overlay(self.el, self.image('says'))
|
|
self.el.append(self.soup.new_tag(
|
|
'span',
|
|
class_='marseyfx-modifier-says-text',
|
|
string=msg.value
|
|
))
|
|
|
|
@modifier
|
|
def fallover(self):
|
|
self.el.wrap(self.soup.new_tag(
|
|
'div',
|
|
class_='marseyfx-modifier-fallover-container'
|
|
))
|
|
|
|
@modifier
|
|
def transform(self, transformstyle: str):
|
|
if not transformstyle.fullmatch(r'[\w()\s%\.]*'):
|
|
return
|
|
|
|
if not 'style' in self.el.attrs:
|
|
self.el.attrs['style'] = ''
|
|
|
|
self.el.attrs['style'] += f'transform: {transformstyle};'
|
|
|
|
@modifier
|
|
def enraged(self):
|
|
self.underlay(self.soup.new_tag(
|
|
'div',
|
|
class_='marseyfx-enraged-underlay'
|
|
))
|
|
|
|
@modifier
|
|
def corrupted(self):
|
|
pass
|
|
|
|
@modifier
|
|
def wavy(self):
|
|
self.el.wrap(self.soup.new_tag('svg')) |