ui_guardrails 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/doc/RESEARCH-visual-diff.md +226 -0
- data/lib/guardrails/a11y_audit.rb +21 -5
- data/lib/guardrails/a11y_deep.rb +28 -7
- data/lib/guardrails/audit.rb +160 -6
- data/lib/guardrails/class_itis.rb +34 -7
- data/lib/guardrails/cross_codebase_patterns.rb +38 -7
- data/lib/guardrails/partial_similarity.rb +38 -10
- data/lib/guardrails/report/style.rb +124 -0
- data/lib/guardrails/report/summary.rb +104 -0
- data/lib/guardrails/stimulus_audit.rb +30 -6
- data/lib/guardrails/version.rb +1 -1
- data/lib/guardrails/view_component_audit.rb +30 -7
- data/lib/guardrails/visual_diff.rb +18 -8
- data/lib/tasks/guardrails.rake +93 -6
- metadata +9 -9
data/lib/tasks/guardrails.rake
CHANGED
|
@@ -107,19 +107,106 @@ namespace :guardrails do
|
|
|
107
107
|
}
|
|
108
108
|
$stdout.puts JSON.pretty_generate(payload)
|
|
109
109
|
else
|
|
110
|
+
# Run each sub-audit against an in-memory sink first so we can
|
|
111
|
+
# render the top-of-report summary before the per-category
|
|
112
|
+
# details (the summary needs every detector's count). Then
|
|
113
|
+
# write the sink + per-category sections out together.
|
|
114
|
+
#
|
|
115
|
+
# Important: detectors write into `sink` (StringIO) but make
|
|
116
|
+
# ANSI-color decisions against `$stdout`. If we let each
|
|
117
|
+
# detector instantiate its own Style bound to the sink, every
|
|
118
|
+
# color() call would be false (StringIO isn't a TTY) and the
|
|
119
|
+
# body of the report would print plain even on a real terminal,
|
|
120
|
+
# while the top/bottom summary printed straight to $stdout
|
|
121
|
+
# would still be colored. Pre-build one Style here and thread
|
|
122
|
+
# it through every detector so the whole report tracks the
|
|
123
|
+
# real terminal's TTY/NO_COLOR signal consistently.
|
|
124
|
+
require "guardrails/report/summary"
|
|
125
|
+
require "guardrails/report/style"
|
|
126
|
+
sink = StringIO.new
|
|
127
|
+
report_style = Guardrails::Report::Style.new(io: $stdout)
|
|
110
128
|
violations = Guardrails::Audit.new(
|
|
111
|
-
root: root, suggest: suggest, apply: apply, format: :text
|
|
129
|
+
root: root, output: sink, suggest: suggest, apply: apply, format: :text,
|
|
130
|
+
style: report_style
|
|
112
131
|
).run
|
|
113
|
-
stimulus = Guardrails::StimulusAudit.new(root: root).run
|
|
132
|
+
stimulus = Guardrails::StimulusAudit.new(root: root, output: sink, style: report_style).run
|
|
133
|
+
similarity_opts[:output] = sink
|
|
134
|
+
similarity_opts[:style] = report_style
|
|
114
135
|
similarity = Guardrails::PartialSimilarity.new(**similarity_opts).run
|
|
115
|
-
vc = Guardrails::ViewComponentAudit.new(root: root).run
|
|
116
|
-
a11y = Guardrails::A11yAudit.new(root: root).run
|
|
136
|
+
vc = Guardrails::ViewComponentAudit.new(root: root, output: sink, style: report_style).run
|
|
137
|
+
a11y = Guardrails::A11yAudit.new(root: root, output: sink, style: report_style).run
|
|
138
|
+
pattern_opts[:output] = sink
|
|
139
|
+
pattern_opts[:style] = report_style
|
|
117
140
|
patterns = Guardrails::CrossCodebasePatterns.new(**pattern_opts).run
|
|
141
|
+
classitis_opts[:output] = sink
|
|
142
|
+
classitis_opts[:style] = report_style
|
|
118
143
|
classitis = Guardrails::ClassItis.new(**classitis_opts).run
|
|
119
|
-
a11y_deep_runner = axe_json_path ? Guardrails::A11yDeep.new(input: axe_json_path) : nil
|
|
144
|
+
a11y_deep_runner = axe_json_path ? Guardrails::A11yDeep.new(input: axe_json_path, output: sink, style: report_style) : nil
|
|
120
145
|
a11y_deep = a11y_deep_runner&.run || []
|
|
121
|
-
visual_diff_runner = visual_diff_on ? Guardrails::VisualDiff.new(root: root) : nil
|
|
146
|
+
visual_diff_runner = visual_diff_on ? Guardrails::VisualDiff.new(root: root, output: sink, style: report_style) : nil
|
|
122
147
|
visual_diff = visual_diff_runner&.run || []
|
|
148
|
+
|
|
149
|
+
summary_entries = [
|
|
150
|
+
Guardrails::Report::Summary::Entry.new(
|
|
151
|
+
category: "raw_color", count: violations.count { |v| v.type == :raw_color },
|
|
152
|
+
severity: :error, auto_fix: true
|
|
153
|
+
),
|
|
154
|
+
Guardrails::Report::Summary::Entry.new(
|
|
155
|
+
category: "tailwind_arbitrary", count: violations.count { |v| v.type == :tailwind_arbitrary },
|
|
156
|
+
severity: :error, auto_fix: true
|
|
157
|
+
),
|
|
158
|
+
Guardrails::Report::Summary::Entry.new(
|
|
159
|
+
category: "inline_style", count: violations.count { |v| v.type == :inline_style },
|
|
160
|
+
severity: :warning
|
|
161
|
+
),
|
|
162
|
+
Guardrails::Report::Summary::Entry.new(
|
|
163
|
+
category: "helper_recommended", count: violations.count { |v| v.type == :helper_recommended },
|
|
164
|
+
severity: :warning
|
|
165
|
+
),
|
|
166
|
+
Guardrails::Report::Summary::Entry.new(
|
|
167
|
+
category: "a11y (static)", count: a11y.length, severity: :error
|
|
168
|
+
),
|
|
169
|
+
Guardrails::Report::Summary::Entry.new(
|
|
170
|
+
category: "a11y (deep)", count: a11y_deep.length, severity: :error
|
|
171
|
+
),
|
|
172
|
+
Guardrails::Report::Summary::Entry.new(
|
|
173
|
+
category: "stimulus orphaned", count: stimulus.orphaned.length, severity: :warning
|
|
174
|
+
),
|
|
175
|
+
Guardrails::Report::Summary::Entry.new(
|
|
176
|
+
category: "stimulus dead", count: stimulus.dead.length, severity: :warning
|
|
177
|
+
),
|
|
178
|
+
Guardrails::Report::Summary::Entry.new(
|
|
179
|
+
category: "missing previews", count: vc.missing_previews.length, severity: :warning
|
|
180
|
+
),
|
|
181
|
+
Guardrails::Report::Summary::Entry.new(
|
|
182
|
+
category: "orphan slots", count: vc.orphan_slots.length, severity: :warning
|
|
183
|
+
),
|
|
184
|
+
Guardrails::Report::Summary::Entry.new(
|
|
185
|
+
category: "visual diff", count: visual_diff.length, severity: :error
|
|
186
|
+
),
|
|
187
|
+
Guardrails::Report::Summary::Entry.new(
|
|
188
|
+
category: "similar partials", count: similarity.length, severity: :suggestion,
|
|
189
|
+
unit: "pairs", action: "consider deduplicating"
|
|
190
|
+
),
|
|
191
|
+
Guardrails::Report::Summary::Entry.new(
|
|
192
|
+
category: "cross-codebase patterns", count: patterns.length, severity: :suggestion,
|
|
193
|
+
unit: "candidates", action: "consider extracting partials"
|
|
194
|
+
),
|
|
195
|
+
Guardrails::Report::Summary::Entry.new(
|
|
196
|
+
category: "class-itis", count: classitis.length, severity: :suggestion,
|
|
197
|
+
unit: "clusters", action: "consider extracting component / @apply"
|
|
198
|
+
)
|
|
199
|
+
]
|
|
200
|
+
|
|
201
|
+
# Render the summary twice — once at the top so the reader
|
|
202
|
+
# knows what to expect, once at the bottom as a recap so they
|
|
203
|
+
# don't have to scroll back up after the per-detector dump.
|
|
204
|
+
# On a long output (Patchvault has 981 findings) the bottom
|
|
205
|
+
# recap is the load-bearing one.
|
|
206
|
+
summary = Guardrails::Report::Summary.new(entries: summary_entries, output: $stdout, style: report_style)
|
|
207
|
+
summary.render
|
|
208
|
+
$stdout.write sink.string
|
|
209
|
+
summary.render(recap: true)
|
|
123
210
|
end
|
|
124
211
|
|
|
125
212
|
# Deep a11y findings only fail the audit when their impact crosses
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ui_guardrails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- John Athayde
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: railties
|
|
@@ -16,14 +15,14 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - ">="
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '7.
|
|
18
|
+
version: '7.2'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '7.
|
|
25
|
+
version: '7.2'
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: herb
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -80,6 +79,7 @@ files:
|
|
|
80
79
|
- doc/LOOKBOOK.md
|
|
81
80
|
- doc/PRD.md
|
|
82
81
|
- doc/PUBLISHING.md
|
|
82
|
+
- doc/RESEARCH-visual-diff.md
|
|
83
83
|
- doc/ROADMAP.md
|
|
84
84
|
- doc/UPSTREAM-snap_diff-issue-draft.md
|
|
85
85
|
- doc/VISUAL-DIFF.md
|
|
@@ -105,6 +105,8 @@ files:
|
|
|
105
105
|
- lib/guardrails/lookbook/views/lookbook_panels/_guardrails.html.erb
|
|
106
106
|
- lib/guardrails/partial_similarity.rb
|
|
107
107
|
- lib/guardrails/railtie.rb
|
|
108
|
+
- lib/guardrails/report/style.rb
|
|
109
|
+
- lib/guardrails/report/summary.rb
|
|
108
110
|
- lib/guardrails/stimulus_audit.rb
|
|
109
111
|
- lib/guardrails/token_matcher.rb
|
|
110
112
|
- lib/guardrails/tokens.rb
|
|
@@ -123,7 +125,6 @@ metadata:
|
|
|
123
125
|
source_code_uri: https://github.com/meticulous/guardrails
|
|
124
126
|
changelog_uri: https://github.com/meticulous/guardrails/blob/main/CHANGELOG.md
|
|
125
127
|
rubygems_mfa_required: 'true'
|
|
126
|
-
post_install_message:
|
|
127
128
|
rdoc_options: []
|
|
128
129
|
require_paths:
|
|
129
130
|
- lib
|
|
@@ -131,15 +132,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
131
132
|
requirements:
|
|
132
133
|
- - ">="
|
|
133
134
|
- !ruby/object:Gem::Version
|
|
134
|
-
version: 3.
|
|
135
|
+
version: 3.4.0
|
|
135
136
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
137
|
requirements:
|
|
137
138
|
- - ">="
|
|
138
139
|
- !ruby/object:Gem::Version
|
|
139
140
|
version: '0'
|
|
140
141
|
requirements: []
|
|
141
|
-
rubygems_version: 3.
|
|
142
|
-
signing_key:
|
|
142
|
+
rubygems_version: 3.6.9
|
|
143
143
|
specification_version: 4
|
|
144
144
|
summary: Rails toolset for preventing UI drift in AI-assisted applications.
|
|
145
145
|
test_files: []
|