refactor(frontend): the last pay-down, part 1 — three dead views deleted, editor rules shared, .page-container + .fs-input canon, rules-shared.css; a one-declaration CSS body is not a shape (#2903, milestone 299 step 5)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 10s
CI & Build / TypeScript typecheck (push) Successful in 34s
CI & Build / integration (push) Successful in 34s
CI & Build / Python tests (push) Failing after 54s
CI & Build / Build & push image (push) Skipped
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 10s
CI & Build / TypeScript typecheck (push) Successful in 34s
CI & Build / integration (push) Successful in 34s
CI & Build / Python tests (push) Failing after 54s
CI & Build / Build & push image (push) Skipped
The derive queue said the biggest duplicate families were whole views: TaskViewerView, UserManagementView and LogsView were imported nowhere — left behind when tasks moved to the editor and users/logs became SettingsView tabs. Deleted (rule 22). Note/TaskEditorView carried six identical scoped rules -> editor-shared.css (the .tag-suggest-row gap the scoped copies actually rendered wins). Three views wrapped the page under three names -> .page-container in components.css. Three scoped input recipes -> the design system fs-input recipe (snippet #2336), verbatim, in components.css; width/ box-sizing stay with the caller. The three rules panes share .pane and the pane heading via rules-shared.css (the auth-shared pattern, #2852). Ledger: a single-declaration CSS rule keeps its selector in its fingerprint, so `color: var(--fs-text-tertiary)` under five different names is no longer a five-file "identical body" family — the first pay-down found that most of the 148 dup families were exactly this, and nobody would consolidate them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -156,6 +156,12 @@ def _block_sha(lines: list[str]) -> str:
|
||||
return hashlib.sha1("\n".join(kept).encode("utf-8")).hexdigest()[:16]
|
||||
|
||||
|
||||
def _declaration_count(lines: list[str]) -> int:
|
||||
"""How many `prop: value` declarations a CSS block body carries."""
|
||||
body = " ".join(lines)
|
||||
return sum(1 for part in body.replace("}", "").split(";") if ":" in part)
|
||||
|
||||
|
||||
def extract_definitions(text: str) -> list[Definition]:
|
||||
"""Every definition this text makes, with signature + fingerprint.
|
||||
|
||||
@@ -202,6 +208,15 @@ def extract_definitions(text: str) -> list[Definition]:
|
||||
hashed = head + block[1:]
|
||||
if not any(x.strip() for x in hashed):
|
||||
hashed = block
|
||||
# A SINGLE declaration is not a shape (#2903): `color: var(--fs-
|
||||
# text-tertiary)` under .text-muted, .task-mark and .pin-badge-auto
|
||||
# is three meanings sharing one line, not three copies of one
|
||||
# rule — the first pay-down found 5-file "families" of exactly
|
||||
# this and nobody would consolidate them. Keep the selector in the
|
||||
# hash for one-liners, so they group only with same-name copies;
|
||||
# two declarations and up stay selector-agnostic.
|
||||
elif _declaration_count(hashed) < 2:
|
||||
hashed = block
|
||||
else:
|
||||
hashed = block
|
||||
out.append(Definition(
|
||||
|
||||
Reference in New Issue
Block a user