Files
backend/frontend/src/check_remaining_buttons.py
T
34047007@qq.com a6cd99a4ca
CI / backend (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
feat: initial commit - oncology literature search platform
OncoLit: a multi-tenant oncology literature search, feed, and
collaboration platform. Built with FastAPI + Vue 3 + PostgreSQL.
Includes PubMed pipeline, drug approvals, AI summaries, and
systematic review tools.
2026-07-27 07:59:18 +08:00

166 lines
4.9 KiB
Python

"""
Find sky-btn NButton tags that still lack <template #icon>.
Writes report to a file to avoid terminal encoding issues.
"""
import re, os, sys
SRC = 'd:/ClaudeCode/frontend/src'
OUT = 'd:/ClaudeCode/frontend/src/sky_btn_report.txt'
def find_sky_btn_gaps(content):
template_start = content.find('<template>')
if template_start < 0:
m = re.search(r'<template\b[^>]*>', content)
if not m:
return []
template_start = m.start()
template_end = content.rfind('</template>')
if template_end < 0:
return []
template_end += len('</template>')
template = content[template_start:template_end]
results = []
for m in re.finditer(r'<[Nn][-]?[Bb]utton\b', template):
tag_start = m.start()
in_dq = False
in_sq = False
for i in range(tag_start):
ch = template[i]
if ch == '\\':
continue
if ch == '"' and not in_sq:
in_dq = not in_dq
elif ch == "'" and not in_dq:
in_sq = not in_sq
if in_dq or in_sq:
continue
pos = m.end()
in_dq = False
in_sq = False
tag_end = -1
while pos < len(template):
ch = template[pos]
if ch == '\\':
pos += 2
continue
if ch == '"' and not in_sq:
in_dq = not in_dq
elif ch == "'" and not in_dq:
in_sq = not in_sq
elif ch == '>' and not in_dq and not in_sq:
tag_end = pos + 1
break
pos += 1
if tag_end < 0:
continue
tag_text = template[tag_start:tag_end]
if 'sky-btn' not in tag_text:
continue
# Check if already has icon template
if '/>' in tag_text:
continue
rest = template[tag_end:]
# find matching close
depth = 0
p = 0
while p < len(rest):
if re.match(r'<[Nn][-]?[Bb]utton\b', rest[p:]):
depth += 1
p += 1
continue
cm = re.match(r'</[Nn][-]?[Bb]utton\s*>', rest[p:])
if cm:
if depth == 0:
break
depth -= 1
p += cm.end()
continue
p += 1
content_before_close = rest[:p]
if re.search(r'<template\s+#icon\b', content_before_close):
continue
if re.search(r'<template\s+v-slot:icon\b', content_before_close):
continue
# text prop
stripped = re.sub(r'"[^"]*"', '', tag_text)
stripped = re.sub(r"'[^']*'", '', stripped)
has_text_prop = False
for tp in re.finditer(r'\btext\b', stripped):
pre = stripped[tp.start()-1] if tp.start() > 0 else ' '
if pre in (' ', '\t', '\n', '\r', '>'):
has_text_prop = True
break
if has_text_prop:
continue
if re.search(r'\bsize\s*=\s*"(tiny|mini)"', tag_text):
continue
qm = re.search(r'\bquaternary\b', tag_text)
if qm and (qm.start() == 0 or tag_text[qm.start()-1] != ':'):
continue
# Extract text
if '/>' in tag_text:
continue
depth = 0
p = 0
while p < len(rest):
if re.match(r'<[Nn][-]?[Bb]utton\b', rest[p:]):
depth += 1
p += 1
continue
cm = re.match(r'</[Nn][-]?[Bb]utton\s*>', rest[p:])
if cm:
if depth == 0:
break
depth -= 1
p += cm.end()
continue
p += 1
text = re.sub(r'<[^>]+>', '', rest[:p]).strip()
if not text:
continue
results.append((tag_start, tag_text, text))
return results
def main():
lines = []
total_gaps = 0
for root, dirs, files in os.walk(SRC):
for f in sorted(files):
if not f.endswith('.vue'):
continue
filepath = os.path.join(root, f)
with open(filepath, 'r', encoding='utf-8') as fh:
content = fh.read()
if 'sky-btn' not in content:
continue
gaps = find_sky_btn_gaps(content)
if gaps:
rel = os.path.relpath(filepath, SRC)
lines.append(f'\n{rel} ({len(gaps)} buttons):')
total_gaps += len(gaps)
for _, tag_text, btn_text in gaps:
lines.append(f' btn_text="{btn_text}"')
lines.append(f' tag_text={tag_text[:80]}')
lines.append('')
lines.insert(0, f'Total buttons without icons: {total_gaps}')
report = '\n'.join(lines)
with open(OUT, 'w', encoding='utf-8') as f:
f.write(report)
print(f'Report written to {OUT}')
if __name__ == '__main__':
main()