"""
Kapselt bleeter/html/style.css fuer die Einbettung in pc-live.
Warum nicht einfach einbinden: die Datei setzt Regeln auf *, html und body.
Die wuerden den gesamten PC einfaerben – Schrift, Hintergrund, alles. Also
bekommt jeder Selektor ein .bl-root davor, und die globalen Regeln werden
umgeschrieben statt uebernommen.
Rein mechanisch, damit es sich wiederholen laesst, wenn bleeter sein Aussehen
aendert: python3 nui/css/erzeuge-bleeter-css.py
"""
import io, re
import os
# Aus dem Verzeichnis dieser Datei heraus aufrufbar:
# python3 nui/css/erzeuge-bleeter-css.py
HERE = os.path.dirname(os.path.abspath(__file__))
SRC = os.path.join(HERE, '..', '..', '..', 'bleeter', 'html', 'style.css')
DST = os.path.join(HERE, 'bleeter-embedded.css')
SCOPE = '.bl-root'
# Vom Wurzelelement uebernehmen wir Farben, Schrift und Variablen – aber kein
# Layout. Im Original ist .bleeter-root ein bildschirmfuellendes Overlay
# (position:fixed; inset:0). Uebernaehme man das, laege die App ueber dem
# gesamten PC, inklusive Titelleiste – man kaeme nicht mehr heraus.
ROOT_SELECTORS = (':root', 'html', 'body')
ROOT_KEEP = ('color', 'font-family', 'font-size', 'font-weight',
'letter-spacing', 'line-height')
def is_root_selector(sel):
return sel in ROOT_SELECTORS or sel.startswith('.bleeter-root')
def filter_root_declarations(body):
"""Nur Variablen und Schrift behalten, alles Raeumliche verwerfen."""
kept = []
for decl in body.split(';'):
decl = decl.strip()
if not decl:
continue
prop = decl.split(':', 1)[0].strip().lower()
if prop.startswith('--') or prop in ROOT_KEEP:
kept.append(decl)
return ';'.join(kept)
def scope_selector(sel):
sel = sel.strip()
if not sel:
return sel
if is_root_selector(sel):
return SCOPE
if sel == '*':
return SCOPE + ' *'
return SCOPE + ' ' + sel
def rule(selector_list, body):
sels_raw = [s.strip() for s in selector_list.split(',')]
if any(is_root_selector(s) for s in sels_raw):
body = filter_root_declarations(body)
if not body:
return None
sels = ','.join(scope_selector(s) for s in sels_raw)
return sels + '{' + body.strip() + '}'
def scope_block(block):
parts = []
for m in re.finditer(r'([^{}]+)\{([^{}]*)\}', block, flags=re.S):
r = rule(m.group(1), m.group(2))
if r:
parts.append(r)
return '\n'.join(parts)
css = re.sub(r'/\*.*?\*/', '', io.open(SRC, encoding='utf-8').read(), flags=re.S)
out, i, n = [], 0, len(css)
while i < n:
m = re.match(r'\s*@(media|supports|keyframes|-webkit-keyframes)([^{]*)\{', css[i:])
if m:
depth, j = 1, i + m.end()
while j < n and depth:
if css[j] == '{':
depth += 1
elif css[j] == '}':
depth -= 1
j += 1
inner = css[i + m.end(): j - 1]
head = '@' + m.group(1) + m.group(2) + '{'
# Prozentschritte in keyframes sind keine Selektoren
out.append(head + (inner if 'keyframes' in m.group(1) else scope_block(inner)) + '}')
i = j
continue
m = re.match(r'([^{}]+)\{([^{}]*)\}', css[i:], flags=re.S)
if not m:
i += 1
continue
r = rule(m.group(1), m.group(2))
if r:
out.append(r)
i += m.end()
header = (
'/* Erzeugt aus bleeter/html/style.css – nicht von Hand aendern.\n'
' Jeder Selektor ist auf .bl-root gekapselt, damit Bleeters Farben und\n'
' Schrift nicht den uebrigen PC einfaerben. */\n'
)
io.open(DST, 'w', encoding='utf-8').write(header + '\n'.join(out) + '\n')
print(f'{len(out)} Regeln -> {DST}')