Class: ERBLint::Linters::PartialPath

Inherits:
Linter
  • Object
show all
Includes:
LinterRegistry
Defined in:
lib/erb_lint/linters/partial_path_linter.rb

Overview

Lint ERB partial paths.

This linter ensures that partials are rendered with their full path relative to the views directory. For example, in app/views/posts/index.html.erb, it will flag ‘render “post”` and suggest `render “posts/post”`.

It allows configuring prefixes that are exempt from this rule via the ‘allowed_prefixes` configuration option.

Defined Under Namespace

Classes: ConfigSchema

Instance Method Summary collapse

Instance Method Details

#allowed_prefix?(path) ⇒ Boolean

Checks if the given path starts with any of the allowed prefixes.

Parameters:

  • path (String)

    The partial path to check

Returns:

  • (Boolean)

    true if the path starts with an allowed prefix, false otherwise



73
74
75
76
77
# File 'lib/erb_lint/linters/partial_path_linter.rb', line 73

def allowed_prefix?(path)
  return false unless @config.allowed_prefixes

  @config.allowed_prefixes.any? { |prefix| path.start_with?(prefix) }
end

#autocorrect(processed_source, offense) ⇒ Proc?

Generates the autocorrection lambda for the given offense.

This method creates a lambda that will replace the partial path with its full path when the linter’s autocorrect feature is used.

Parameters:

  • processed_source (ERBLint::ProcessedSource)

    The processed source containing the offense

  • offense (ERBLint::Offense)

    The offense to generate a correction for

Returns:

  • (Proc, nil)

    A lambda that performs the correction, or nil if correction is not possible



87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/erb_lint/linters/partial_path_linter.rb', line 87

def autocorrect(processed_source, offense)
  return unless processed_source.filename =~ %r{app/views/(.+?)/_?([^/]+)\.html\.erb$}
  return if processed_source.filename.include?("/cells/")

  current_directory = Regexp.last_match(1)

  lambda do |corrector|
    partial_path = offense.source_range.source
    full_path = "#{current_directory}/#{partial_path}"
    corrector.replace(offense.source_range, full_path)
  end
end

#run(processed_source) ⇒ void

This method returns an undefined value.

Runs the linter on the given processed source.

This method scans the source code for ERB render calls and checks if they are using the full path for partials. If not, it adds an offense.

Parameters:

  • processed_source (ERBLint::ProcessedSource)

    The processed source to lint



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/erb_lint/linters/partial_path_linter.rb', line 38

def run(processed_source)
  file_path = processed_source.filename

  return unless file_path =~ %r{app/views/(.+?)/_?([^/]+)\.html\.erb$}
  return if file_path.include?("/cells/")

  current_directory = Regexp.last_match(1)
  source = processed_source.file_content

  source.scan(/<%=\s*render\s+"([^"]+)"[^%]*%>/) do
    partial_path = Regexp.last_match(1)
    start_pos = Regexp.last_match.begin(1)

    next if partial_path.start_with?("layouts/")
    next if partial_path.start_with?("/")
    next if partial_path.include?("/")

    next if allowed_prefix?(partial_path)

    full_path = "#{current_directory}/#{partial_path}"
    range = processed_source.to_source_range(
      start_pos...(start_pos + partial_path.length)
    )

    add_offense(
      range,
      "Use the full path for partials. Replace `render \"#{partial_path}\"` with `render \"#{full_path}\"`"
    )
  end
end