mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 05:56:37 +01:00
main
1
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
fa3a2400b5 |
v1.91.251.0 feat(design-lint): bundled free design lint (bin/gstack-design-lint + lib/design-lint/), hallmark sloplint port (#3459)
* feat(design-lint): core of the bundled free design lint (parsers, colour, tokens, reporter, waivers, CLI)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(design-lint): CHANGELOG entry, NOTICE and MIT-hallmark licence, module-size ratchet entries
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): port the colour and type rule families from sloplint
rules/color.ts: gates 2a 2b 7a 7b 22 23 29 48 65 74 (check2, check7, check22,
check23, check29Glow, check48, check65, check65Tailwind). rules/type.ts: gates
1 25 37 38i 38ii 38iii 55a 55b 64 67 (check1, check25, check37, check38a,
check38c, check55, check64, check67, check67Html). Thresholds and heuristics
are hallmark's; evidence and fixes are rewritten in gstack's voice; the stamp,
genre and posture guards are gone, so every check runs in its strict form.
The clean fixture carried two real tells hallmark's own sloplint also flags:
an oklch literal on .button:hover (48) and the cream paper + Fraunces + clay
accent look (65). The hover colour is now a token and the display face is
Literata.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): port the Tailwind reader and component rules
Replaces the tailwind.ts stub with sloplint's utility reader (twParse,
twInfo, twGroup, variants, stops, sizes, tracking, families, shared
project tokens) and the tells it feeds, and fills rules/component.ts
with checkTailwind and checkComponentText: layout-transition,
bounce-easing, purple-blue-gradient, gradient-text, glow-wash,
literal-outside-tokens, hover-tells, wide-tracking, kicker-above-heading,
monospace-costume, framework-palette, vh-height, template-cards,
template-punctuation and emoji-decoration over class strings in HTML,
JSX, Vue, Svelte and Astro files and cn()/clsx()/cva() calls.
test/design-lint-tailwind.test.ts holds a negative control and a planted
tell per rule plus the tailwind-fail, tailwind-pass and clean fixtures.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(design-lint): mark line-length, cream-palette and the caps leading rules page-only
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): port the structure and motion rule families from sloplint
Structure: template-cards, nested-cards, vh-height, raw-spacing, off-scale-spacing, overflow-x-unclipped (static half), bare-fr-track, display-head-unwrapped, radio-tab-jump, double-sticky, screen-word-budget (static half), and a conservative static half of wide-container. Motion: layout-transition, spacing-transition, hover-tells, bounce-easing, focus-ring-fade, tooltip-focus-delay, autorotate-no-pause, missing-focus-visible, missing-states, missing-reduced-motion, autoplay-unmuted, lazy-lcp, video-without-poster, input-state-shift, control-height (static half), content-hidden-at-rest. Every rule has a planted positive and a negative control; the clean fixture lede drops to eleven words so the hero-paragraph budget holds.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(design-lint): the Tailwind gradient half of 2a/2b lives in the component family only
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore(design-lint): tidy the colour test imports; control-height page-only; lazy-lcp title
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore(design-lint): drop unused colour test imports
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): port the chrome, assets and finish rule families from sloplint
Chrome (gates 19 42 46a 47 54 63 68 69 70 85): gate 19 split by tell onto
aphoristic-cadence, generic-hero-copy, generic-cta-copy, em-dash-overuse and
template-footer-line in rules/chrome-copy.ts (with the two-filled-buttons half
of F4 and the shared prose mask); the eyebrow in rules/chrome-eyebrow.ts; the
nav and footer shapes, invented proof, drawn chrome, placeholder services,
template punctuation, wireframe slots, repeated facts, the fake send and a
static version of the email-band close in rules/chrome.ts.
Assets (gates 30 33 40 41 49 76): emoji icons, mixed icon libraries, unlabelled
svg/canvas, contrast pairs and surface inks (suspected at ask in the static
tier), wrapping labels split into button-label-wraps and link-wraps, broken
images and stock hotlinks.
Finish (F1-F9 F15 F16 F21-F24): all polish except fake-avatar.
Tests cover every id with a negative control and a planted positive; the clean
fixture gains scrollbar-color so its committed palette themes every browser
surface.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): chrome, assets and finish families merged; maskedProse moves to html.ts; isTokenRule takes a Pick; ratchet watches every lint module
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(design-lint): the eyebrow-pass and tailwind-pass fixtures carry a skip link, main id and aria-current so the copy tier passes them too; waiver fixture gets a meta description
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): render tier on gstack's own browser (sloplint-render port)
Ports hallmark's sloplint-render.mjs onto lib/aside-render: one tab per
page, the in-page probes installed once and run at each viewport, a second
pass with full-page screenshots only when a contrast claim needs the painted
pixels (a small PNG reader replaces canvas sampling). Gates 23, 25, 26a, 34,
40, 41, 44a-d, 49a/b, 58, 71, 72, 73, 75, 77-83, F17-F20, plus the page that
did not render. The stamp's posture, hero-shape, photo-shape and genre
guards are gone: the strict form applies. Focus rings are read by focusing
each control in turn (programmatic focus matches :focus-visible on the
daemon with no prior pointer input; a stylesheet scan is the fallback).
lib/aside-render: an eval step takes width/height like a screenshot step
(device metrics on Aside, viewport on browse, cleared after), and spec.file
may be an http(s) URL, opened as it is with nothing served.
The clean fixture gained border-box on its hero, a centred, taller hero
visual, a wrapping actions row, a statement-sized close head and a shorter
story paragraph: the browser showed the action below the 1280x800 fold, a
dead band under the hero, a 600px image spilling past a phone screen and a
thin close section.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): render tier merged; four probe modules join the ratchet; the clean hero sits at a fixed measure so text and visual stand together; CHANGELOG names the aside-render eval viewport
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(design-lint): register the lint fixtures as free fixtures and the hallmark licence texts as free-only PR files, so the PR paid lane stays narrow and test/free-fixtures.test.ts passes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(design-lint): section-gap measured in the render tier (gate 59, with the six-to-nine section count) and the hero action count; a free test over the recorded review slop page; usage, render glue, file walk, multi-page ownership and copy-tier tests; NOTICE and licences leave FREE_ONLY_PR_FILES so the paid-free boundary test stands
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: mark hallmark PAGE_ONLY gates and craft page checks pageOnly so --scope component drops them
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: ship review fixes
Waivers reach render findings; a blocking rule the lint only suspected is
waivable like any ask, a measured or absent Floor stays refused. A stylesheet
a page links from another directory belongs to that page and is not linted
again on its own; a stylesheet linted alone keeps its waivers. Root-relative
hrefs resolve against the lint root. Stylesheets are read and parsed once per
run. A rule family that throws reports internal-error at ask instead of a
silent pass; aria-labelledby and probe tag names are escaped before they
reach a RegExp; a probe result naming an unknown rule is a render finding,
not a crash; fix strings are one line. overused-font follows gstack's
catalog of display faces; one MONO_FACE list for every monospace check.
parseCss caps nesting depth; medianRgb uses histograms; glHide batches its
layout reads. Dead exports removed (isPage, openTags, over, ComponentTag,
PixelRect, the ids re-exports).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: name the tracked-caps thresholds once, string-aware brace scan, drop an unused parameter, clean up test tmpdirs
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: second review cycle
Waivers settle once per page after both tiers, so a blocking rule only the
render tier suspects is waivable and one it measures is refused; a claim in a
stylesheet answers for that stylesheet on every page that links it (no
shared-word check), so a sheet shared by two pages is no longer waived on one
and refused on the other. Every printed field is one line with control
characters stripped; the waiver regex is linear and ends at a carriage
return; a root-relative href cannot climb out of the lint root. The ancestor
map closes optional end tags implicitly and pops to the matching open tag, so
unclosed <li> no longer makes it quadratic. The static tier reports outline:
none with no ring anywhere as missing-focus-visible at its line;
literal-outside-tokens needs a --color-* or --font-* token to exist; the
banned gradient includes indigo-to-violet; a new banned-font rule reads
gstack's BANNED_FONTS; MONO_FACE matches whole words; bold keywords and
tokens count as weight 700 for the contrast threshold. stylesFor reads only
the entries that can match; glOcclusion memoises the pinned walk; the
confirm screenshot is taken at 1x; a page that throws in the render tier is a
render finding and the CLI exits 3 on an internal error. Docs name the token
conventions and what the lint does not cover.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: pair open and close tags once per document, scan markup in linear time, keep commented-out style and script dead
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: third review cycle fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: third review cycle tests; render keeps the measured horizontal-scroll when merging widths
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: document the third-cycle limits and waiver scope
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: fourth review cycle fixes
Commented-out markup is dead for every rule (Doc.src is the comment-blanked text; craft copy, the module-script check and the border+shadow scan read it). Headings, buttons, links, labels, selects, forms and an open <p> close the way the browser closes them, a tree nests at most 512 deep, and the heading, footer-column, sign-up-button and span readers walk the shared pairing instead of lazy regexes, with each element's text computed once (textOf). Tailwind frames and wireframe slots answer from treeOf. resolveVars stops on a cycle and caps its size; every parseCss at-rule branch honours the depth guard and an inline <style> that fails to parse is skipped with a warning. cwd and lint roots are read through their real paths, a skipped source file is one internal-error finding, relative refs stay inside the project, a linked stylesheet over 2 MB is skipped. overused-font and banned-font match a catalog stem to a family name's first words; width: min()/clamp() caps a container; a box-shadow focus ring beside a border-colour change is not input-state-shift; Meet and triad headings below the hero are suspected; the stylesheet-waiver key goes through oneLine; pxOf reads leading-dot lengths; check67 precomputes selector bases; the render tier reports a wrong-shaped answer per probe and keeps every measured finding, flags a bad grade as tampering, and never repeats the kept width when merging horizontal-scroll.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: fourth review cycle tests and docs
test/design-lint-fourth-cycle.test.ts pins commented-out markup dead for every rule, unclosed <li> Tailwind frames and wireframe slots, linear-time unclosed runs and component scripts, cyclic var() and nested @media, leading-dot lengths, a symlinked lint root, oversize files reported, a whitespace-named stylesheet's waiver, the overused-font stems, width: min() caps, box-shadow rings, Meet headings below the hero, wrong-shaped render answers and the never-waivable refusals by class; the settle golden no longer repeats the kept width and expects the bad grade as tampering. docs/design-lint.md describes the caps, implicit closes, skipped-file findings and the matching rules.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: fourth-cycle simplifications and the pixel pass pinned without a browser
heroClasses reads the hero through heroIndexOf, check64 uses twMonoIsMaterial, check67Html imports capsRatio from chrome-eyebrow, sideStripes loses its bare block; a settle test drives confirmPixels with the swatch fixture (a claim dropped by the pixels behind it, one rewritten, a weak ring confirmed).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: heroIndexOf carries its own doc comment
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: fifth review cycle fixes
The placeholder emoji scan reads the comment-blanked text, so markup inside <!-- --> is dead for every rule. A digit run, a long mono word and a run of scheme prefixes cost their length (FACT and UNSPLASH_URL only start at a token, twDataText bounds its text); a 2 MB sheet of 699k rules no longer blows the stack (rules are appended in loops); JsxScanner spends one failure budget across jsScan and el; the Tailwind had() lookup is a Set; accentedHeads indexes rules by class once; contexts drop their caches once their families have run; the parsed-token cache is bounded. treeOf gives a close tag its parent so a fact after an inline close is counted in its section. Waivers are keyed per rule for a page claim and per rule@sheet for a stylesheet claim, so two linked sheets each answer for their own findings. The render tier validates every page-supplied field (at.cls, ring colour and ratio, probe fg and threshold, PAGE_ERRORS entries, a malformed entry naming the render rule) and keeps its measured findings; lineOf answers from one line index. Rule judgement: a textarea's min-height is not control-height, attribute-selected inputs are read for input-state-shift, a glyph-only <i> is not an italic word, a bounce keyframe by name is bounce-easing, single-quoted inline styles are read, a project root is a package.json or .git. Housekeeping: Probes typed from PROBE_FNS, EYEBROW_* shared from chrome-eyebrow, WaiverClaim.raw and dead imports removed, evidence wording for tracked-only controls and black glass, emoji icon tiles capped like every other emoji path, unreadable files get their own fix text.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: fifth review cycle tests and docs
test/design-lint-fifth-cycle.test.ts (21 tests) pins the comment-dead placeholder, the linear-time digit run, 699k-rule sheet, unclosed JSX and tracked-label pages, per-sheet waivers and the remaining state-matrix cells, every wrong-shaped render field, and the rule judgements; the fourth-cycle shell test asserts the observable effect, the RSS assertion is structural, time bounds are widened for shared CI shards, the stale empty block is gone, and the FREE_FIXTURES inventory names both cycle files. docs/design-lint.md states the project-root bound on relative hrefs and the three narrow readings (whole-page focus ring, unconditional 4px scale, scroll-container-blind double-sticky).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: sixth review cycle fixes
line-length computes its floor only for a measure between 28 and 45ch and
answers shortProse once per class; wide-tracking resolves inherited case
through a prefix index instead of a scan of every rule; the JSX scanner
fails every ancestor of an element that ran to the end of the file at once;
the hairline-under-shadow pair reads class tokens instead of a two-sided
regex. tooltip-focus-delay names the sheet that holds the :focus delay;
the placeholder emoji scan reads the comment-blanked body for every kind;
fake-send finds its line in a component's script text. A stylesheet href is
bounded by its real path too. The LINT line's separator is kept out of
page-supplied text. Waivers: a component claim answers for its own file,
weighed against its own text; the Waiver shape is a reason string; refusals
go through Reporter. Render: a later fail replaces a warn with the same
evidence, a non-string fix is dropped, the timeout is a constant. Rules:
a meta label in mono is a costume, a leading-dot length reads as a fraction,
a percentage leading collides like a unitless one, an italic word after an
icon is still read, an italic rule on the word is not a display system, en
dashes between digits are ranges, and the catalog's two hero lines are
generic-hero-copy. The Tailwind parse cache and its eviction are gone.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* design-lint: sixth review cycle tests and docs
test/design-lint-sixth-cycle.test.ts (18 tests; 13 red at
|