Files
ClassFeedback/.claude/memory/temp/fix_star_slider.py

135 lines
4.5 KiB
Python

# -*- coding: utf-8 -*-
"""Batch fix for 课评汇总 class pages:
1) Remove the 评星 (star rating) feature: strip each <div class="metrics">…</div> block,
delete star/metric CSS rules, and remove the dead star JS functions.
2) Fix the 翻页卡死 (pagination freeze) on carousel pages: switch slides from
absolute-stacked opacity to display:none for inactive cards (only the active
card is ever laid out/painted), and remove backdrop-filter blur (compositing cost).
Only applied to the first-week pages when <target> is the folder.
"""
import os, re, sys
# ------------- balanced <div class="metrics"> removal -------------
def remove_metrics(html):
marker = '<div class="metrics">'
res = []
i = 0
n = len(html)
while True:
idx = html.find(marker, i)
if idx == -1:
res.append(html[i:])
break
res.append(html[i:idx])
depth = 1
j = idx + len(marker)
while depth > 0 and j < n:
oi = html.find('<div', j)
ci = html.find('</div>', j)
if ci == -1:
j = n
break
if oi != -1 and oi < ci:
depth += 1
j = oi + 4
else:
depth -= 1
j = ci + 6
i = j
return ''.join(res)
# ------------- balanced CSS block parser -------------
def strip_css(css, is_carousel):
out = []
i = 0
n = len(css)
while i < n:
m = re.match(r'\s+', css[i:])
if m:
out.append(m.group(0)); i += m.end(); continue
m = re.match(r'/\*.*?\*/', css[i:], re.S)
if m:
out.append(m.group(0)); i += m.end(); continue
brace = css.find('{', i)
if brace == -1:
out.append(css[i:]); break
sel = css[i:brace]
depth = 1
j = brace + 1
while depth > 0 and j < n:
if css[j] == '{': depth += 1
elif css[j] == '}': depth -= 1
j += 1
body = css[brace+1:j-1]
full = css[i:j]
selnorm = sel.strip()
if selnorm.startswith('@media') or selnorm.startswith('@supports'):
out.append(selnorm + '{' + strip_css(body, is_carousel) + '}')
elif re.search(r'\.(?:metric|star)', selnorm):
pass # drop star / metric rules
elif is_carousel and re.match(r'^\.student-card', selnorm):
if '.prev' in selnorm:
pass # drop the now-unneeded prev-state rule
elif '.active' in selnorm:
out.append('.student-card.active { display: block; position: relative; pointer-events: auto; }')
elif re.match(r'^\.student-card\s*$', selnorm):
out.append('.student-card { display: none; }')
else:
out.append(full) # .student-card:hover
else:
out.append(full)
i = j
return ''.join(out)
def process_styles(html, is_carousel):
def repl(m):
css = strip_css(m.group(2), is_carousel)
css = re.sub(r'backdrop-filter\s*:\s*blur\([^)]*\);?', '', css)
return m.group(1) + css + m.group(3)
return re.sub(r'(<style[^>]*>)(.*?)(</style>)', repl, html, flags=re.S)
# ------------- dead star JS removal -------------
def remove_function(js, name):
pat = re.compile(r'function\s+' + re.escape(name) + r'\s*\(')
m = pat.search(js)
if not m:
return js
brace = js.find('{', m.end())
if brace == -1:
return js
depth = 1
j = brace + 1
n = len(js)
while depth > 0 and j < n:
if js[j] == '{': depth += 1
elif js[j] == '}': depth -= 1
j += 1
return js[:m.start()] + js[j:]
def remove_call(js, name):
return re.sub(r'^[ \t]*' + re.escape(name) + r'\(\).*?$', '', js, flags=re.M)
def fix(html):
is_carousel = 'id="cardsSlider"' in html
html = remove_metrics(html)
html = process_styles(html, is_carousel)
if 'function initStarRatings' in html and 'initStarRatings' in html:
html = remove_call(html, 'initStarRatings')
html = remove_function(html, 'initStarRatings')
html = remove_function(html, 'setStarRating')
return html
def main(files):
for path in files:
with open(path, encoding='utf-8') as f:
html = f.read()
out = fix(html)
changed = out != html
with open(path, 'w', encoding='utf-8') as f:
f.write(out)
print(('CHANGED ' if changed else 'same ') + os.path.basename(path))
if __name__ == '__main__':
main(sys.argv[1:])