Class: Guardrails::Audit

Inherits:
Object
  • Object
show all
Defined in:
lib/guardrails/audit.rb,
lib/guardrails/audit/auto_fixer.rb,
lib/guardrails/audit/markdown_writer.rb

Defined Under Namespace

Classes: AutoFixer, MarkdownWriter, Violation

Constant Summary collapse

DEFAULT_SCAN_PATHS =
["app/views", "app/components"].freeze
SCAN_PATTERNS =
DEFAULT_SCAN_PATHS.map { |p| "#{p}/**/*.html.erb" }.freeze
IMPLICIT_IGNORE =

Subtrees that should never be scanned even if they happen to contain ERB. These are merged with any user-supplied ignore paths from guardrails.yml (in addition, not in place of). Vendor / node_modules / tmp / public regularly contain third-party code that nobody wants to “fix” through this lens.

Note: ‘audit.ignore` entries are matched as exact paths or directory prefixes (e.g. “app/views/layouts” excludes that subtree); they are NOT interpreted as shell globs.

%w[vendor node_modules tmp public log].freeze
IMPLICIT_IGNORE_PATTERNS =

Path-component patterns that are also implicit-ignored. Mailer views are auto-skipped because email clients require inline styles — flagging them as design-system drift is incorrect by design.

Matches both Rails conventions:

app/views/contact_mailer/    (*_mailer convention from Talos)
app/views/devise/mailer/     (plain `mailer` from Forem/Devise)

The leading-underscore prefix is required for the prefix path so ‘_mailer_partial/` (a regular partials dir) doesn’t match.

[
  /\A(?:\w+_)?mailer\z/
].freeze
HEX_LITERAL_PATTERN =

Color literal patterns — applied to the static portion of an attribute value extracted via the AST.

/#[0-9a-fA-F]{3,8}\b/
RGB_LITERAL_PATTERN =
/\brgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+(?:\s*,\s*[\d.]+)?\s*\)/
ARBITRARY_VALUE_PATTERN =

Tailwind arbitrary-value bracket pattern — applied to the static portion of a class attribute value.

/\[[^\]]+\]/
INLINE_STYLE_PATTERN =

Pattern used only to recover the on-disk ‘style=“…”` snippet for the inline_style violation’s ‘value` field. Detection itself is AST-based; this is just for nicer reporting.

/\bstyle\s*=\s*["'][^"']+["']/
{
  "button" => "tag.button(label, ...) or button_to(label, path) for forms",
  "a" => "link_to(label, path, ...)"
}.freeze
COLOR_ATTRIBUTE_NAMES =

Attributes whose values legitimately carry color literals. Scoping raw_color detection to these keeps href=“#section” or data-id=“abc” from being misreported as color drift.

%w[
  fill stroke color bgcolor background
  flood-color lighting-color stop-color
].freeze

Instance Method Summary collapse

Constructor Details

#initialize(root:, output: $stdout, suggest: false, format: :text, apply: false) ⇒ Audit

Returns a new instance of Audit.



72
73
74
75
76
77
78
79
# File 'lib/guardrails/audit.rb', line 72

def initialize(root:, output: $stdout, suggest: false, format: :text, apply: false)
  @root = Pathname(root)
  @output = output
  @suggest = suggest
  @format = format
  @apply = apply
  @config = load_audit_config
end

Instance Method Details

#runObject



81
82
83
84
85
86
87
# File 'lib/guardrails/audit.rb', line 81

def run
  violations = collect_files.flat_map { |file| scan_file(file) }
  print_report(violations)
  remaining = @apply ? apply_auto_fixes(violations) : violations
  write_suggestions(remaining) if @suggest
  remaining
end