Class: Guardrails::Audit::MarkdownWriter

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

Constant Summary collapse

OUTPUT_DIR =
"doc"
SUGGESTIONS =
{
  inline_style: {
    rule: "Move styles to a stylesheet using design tokens.",
    replacement: "Extract the styles to a CSS class or component stylesheet that references defined tokens."
  },
  raw_color: {
    rule: "Replace raw color literals with a defined token.",
    replacement: "Use a CSS custom property or SCSS variable from your tokens file (see guardrails.yml → tokens.colors_file)."
  },
  tailwind_arbitrary: {
    rule: "Avoid arbitrary Tailwind values — extend the theme or use an existing utility.",
    replacement: "Add this value to your Tailwind theme (e.g. theme.colors.* or theme.fontSize.*) and reference the named utility instead."
  },
  helper_recommended: {
    rule: "Wrapping ERB output in a literal element hides intent from static analysis and a11y tooling.",
    replacement: "Use the Rails helper for this element so attributes (including aria-*) flow through one place."
  }
}.freeze
HELPER_REPLACEMENTS =
{
  "button" => "Replace with `tag.button(label, ...)` (or `button_to(label, path)` for form-submission buttons).",
  "a" => "Replace with `link_to(label, path, ...)` so the link text is explicit and helper-managed."
}.freeze
COMPATIBLE_SYNTAX =

Per-violation-type token compatibility for suggestions, expressed as an ordered list of matcher layers. The first layer that produces any match (exact or near) wins, so the preferred substitute syntax is genuinely preferred even on tied near matches. tailwind_arbitrary tries :tailwind utility names first; if no theme entry matches, it falls back to :css_var (parameterized arbitrary ‘bg-`).

{
  raw_color: [[:css_var]],
  tailwind_arbitrary: [[:tailwind], [:css_var]]
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(root, output: $stdout, now: Time.now, tokens: [], near_match_policy: "notify", near_match_threshold: TokenMatcher::NEAR_MATCH_THRESHOLD) ⇒ MarkdownWriter

Returns a new instance of MarkdownWriter.



47
48
49
50
51
52
53
54
# File 'lib/guardrails/audit/markdown_writer.rb', line 47

def initialize(root, output: $stdout, now: Time.now, tokens: [], near_match_policy: "notify",
               near_match_threshold: TokenMatcher::NEAR_MATCH_THRESHOLD)
  @root = Pathname(root)
  @output = output
  @now = now
  @matchers = build_matchers(tokens, near_match_threshold)
  @near_match_policy = near_match_policy
end

Instance Method Details

#write(violations) ⇒ Object



56
57
58
59
60
61
62
# File 'lib/guardrails/audit/markdown_writer.rb', line 56

def write(violations)
  path = output_path
  path.dirname.mkpath
  File.write(path, markdown_for(violations), encoding: Encoding::UTF_8)
  @output.puts "Wrote suggestions to #{path.relative_path_from(@root)}"
  path
end