platformos-check 0.4.8 → 0.4.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/README.md +28 -19
  4. data/config/default.yml +13 -1
  5. data/docs/checks/form_action.md +6 -0
  6. data/docs/checks/form_authenticity_token.md +22 -3
  7. data/docs/checks/include_in_render.md +62 -0
  8. data/docs/checks/translation_files_match.md +70 -0
  9. data/docs/checks/translation_key_exists.md +44 -0
  10. data/docs/platformos-check.jpg +0 -0
  11. data/lib/platformos_check/app.rb +13 -0
  12. data/lib/platformos_check/app_file.rb +10 -3
  13. data/lib/platformos_check/checks/convert_include_to_render.rb +41 -2
  14. data/lib/platformos_check/checks/form_action.rb +3 -1
  15. data/lib/platformos_check/checks/form_authenticity_token.rb +20 -0
  16. data/lib/platformos_check/checks/img_lazy_loading.rb +6 -2
  17. data/lib/platformos_check/checks/include_in_render.rb +45 -0
  18. data/lib/platformos_check/checks/invalid_args.rb +4 -1
  19. data/lib/platformos_check/checks/translation_files_match.rb +83 -0
  20. data/lib/platformos_check/checks/translation_key_exists.rb +48 -0
  21. data/lib/platformos_check/checks/undefined_object.rb +55 -26
  22. data/lib/platformos_check/checks/unreachable_code.rb +9 -9
  23. data/lib/platformos_check/checks/unused_assign.rb +33 -24
  24. data/lib/platformos_check/cli.rb +1 -1
  25. data/lib/platformos_check/ext/hash.rb +19 -0
  26. data/lib/platformos_check/graphql_file.rb +4 -0
  27. data/lib/platformos_check/language_server/constants.rb +18 -2
  28. data/lib/platformos_check/language_server/document_link_provider.rb +67 -10
  29. data/lib/platformos_check/language_server/document_link_providers/localize_document_link_provider.rb +38 -0
  30. data/lib/platformos_check/language_server/document_link_providers/theme_render_document_link_provider.rb +2 -1
  31. data/lib/platformos_check/language_server/document_link_providers/translation_document_link_provider.rb +36 -0
  32. data/lib/platformos_check/tags/graphql.rb +3 -0
  33. data/lib/platformos_check/translation_file.rb +40 -0
  34. data/lib/platformos_check/version.rb +1 -1
  35. data/lib/platformos_check/yaml_file.rb +7 -2
  36. data/lib/platformos_check.rb +1 -0
  37. metadata +13 -4
  38. data/docs/preview.png +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 579d15b95d0e00e65eb562778f0870bc28698bfe2f6c97ca66e7ca81a18b855c
4
- data.tar.gz: 2f6afe88f067cccc169d62a9744399b5b11294537dd8c7653ca9d5ed9165f1f3
3
+ metadata.gz: 269921738309c4cc1a1d7afef16318af6a75f050fad261530d008f53c464ce62
4
+ data.tar.gz: 0a3c1b2704f40a8244a4608ff6d9f26b0cb7757f7e93182e875edb55344c6fd9
5
5
  SHA512:
6
- metadata.gz: 2fa86abf31229208eaff48e7f95b212977682bd560234d99d2fa9b3162a33ca7139b8faad2960152951295b056ef41b834e9faa756b0627f02a14034f6d4e468
7
- data.tar.gz: 18fa38e2613faf4e31dfdf0a432e4fbe3a8ced0b18f8f194698bf73606affd770cf2589dadb852c26c19f5ec31146535e95e863d7c31ab9c8977feb67fa99a07
6
+ metadata.gz: 6de2d63705409c6b3d818f48799c5c65809c26304b64d675248c21a170562098af119d954c4d5ea77f0a09559c571e64ea10a8f3417fd406c7644999048e8916
7
+ data.tar.gz: bc35549e8dc86f7f924937a9abc7306dfb6629c05311e38b092219432b9984a855b5d1bbeda8e23503cbe903fbebeff2fb4e4538a012ec4a0dd2697a8bc6f183
data/CHANGELOG.md CHANGED
@@ -1,3 +1,30 @@
1
+ v0.4.10 / 2024-02-19
2
+ ==================
3
+
4
+ * Add documentLink for translations (both for `| t` and `| l` filters)
5
+ * Add TranslationKeyExists, TranslationFilesMatch offenses to warn about issues with missing translation or inconsistency between multiple language translation files
6
+
7
+ v0.4.9 / 2024-01-10
8
+ ==================
9
+
10
+ * Skip FormAuthenticityToken check for GET forms
11
+ * Skip FormAuthenticityToken for action which is not relative path
12
+ * Fix FormAction to not report offenses on valid scenarios
13
+ * UnusedAssign will not automatically remove assign if it might change the business logic (which is a scenario when filters modifying objects are used)
14
+ * UnusedAssign will automatically rename result of background tag if variable not used
15
+ * Fix reporting UndefinedObject's missing argument offenses when the same partial is used multiple times (previously offenses where displayed only for the last render)
16
+ * Add autocorrector for UndefinedObject's missing argument error (explicitly provide null)
17
+ * Add autocorrector for ImgLazyLoading
18
+ * ConvertIncludeToRender will not report offense as autocorrect
19
+ * Improve inline GraphQL syntax check to raise error if result variable not provided
20
+ * Add autocorrector for UndefinedObject (Unused Argument offense) (FIXME: for N unused arguments in the same line it needs to be invoked N times)
21
+ * Add autocorrector for InvalidArgs - remove duplicates arguments
22
+ * Do not report ConvertIncludeToRender offenses for valid use cases (using `break` and using variable as a template name)
23
+ * Add IncludeInRender check
24
+ * Improve autocorrector for UndefinedObject's missing argument error - if variable is defined, it will be passed instead of hardcoding null
25
+ * Re-enable autocorrector for ConvertIncludeToRender
26
+ * Make UndefinedObject more clever - it will report undefined object if variable is used before declaration
27
+
1
28
  v0.4.8 / 2023-12-20
2
29
  ==================
3
30
 
data/README.md CHANGED
@@ -8,29 +8,29 @@ PlatformOS Check is a tool that helps you follow platformOS recommendations & be
8
8
 
9
9
  PlatformOS Check currently checks for the following:
10
10
 
11
- ✅ Liquid syntax errors
12
- ✅ JSON syntax errors
13
- ✅ Missing partials and graphqls
14
- ✅ Unused `{% assign ... %}`
15
- ✅ Unused partials
16
- ✅ Template length
17
- ✅ Deprecated tags
18
- ✅ Unknown tags
19
- ✅ Unknown filters
20
- ✅ Missing or extra spaces inside `{% ... %}` and `{{ ... }}`
21
- ✅ Using several `{% ... %}` instead of `{% liquid ... %}`
22
- ✅ Undefined objects
23
- ✅ Deprecated filters
24
- ✅ Missing `platformos-check-enable` comment
25
- ✅ Invalid arguments provided to `{% graphql %}` tags
11
+ ✅ Liquid syntax errors
12
+ ✅ JSON syntax errors
13
+ ✅ Missing partials and graphqls
14
+ ✅ Unused variables (via `{% assign var = ... %}`, {% function var = ... %} etc.)
15
+ ✅ Unused partials
16
+ ✅ Template length
17
+ ✅ Deprecated tags
18
+ ✅ Unknown tags
19
+ ✅ Unknown filters
20
+ ✅ Missing or extra spaces inside `{% ... %}` and `{{ ... }}`
21
+ ✅ Using several `{% ... %}` instead of `{% liquid ... %}`
22
+ ✅ Undefined objects
23
+ ✅ Deprecated filters
24
+ ✅ Missing `platformos-check-enable` comment
25
+ ✅ Invalid arguments provided to `{% graphql %}` tags
26
+ ✅ Missing `authenticity_token` in `<form>`
27
+ ✅ Unreachable code
26
28
 
27
29
  As well as checks that prevent easy to spot performance problems:
28
30
 
29
- Use of [parser-blocking](/docs/checks/parser_blocking_javascript.md) JavaScript
30
- [Use of non-platformOS domains for assets](/docs/checks/remote_asset.md)
31
+ [GraphQL in for loop](/docs/checks/graphql_in_for_loop.md)
32
+ ✅ Use of [parser-blocking](/docs/checks/parser_blocking_javascript.md) JavaScript
31
33
  ✅ [Missing width and height attributes on `img` tags](/docs/checks/img_width_and_height.md)
32
- ✅ [Too much JavaScript](/docs/checks/asset_size_javascript.md)
33
- ✅ [Too much CSS](/docs/checks/asset_size_css.md)
34
34
 
35
35
  For detailed descriptions and configuration options, [take a look at the complete list.](/docs/checks/)
36
36
 
@@ -52,12 +52,21 @@ With more to come! Suggestions welcome ([create an issue](https://github.com/Pla
52
52
  ### Install ruby and platform-check gem
53
53
 
54
54
  1. Download the latest version of Ruby - https://www.ruby-lang.org/en/documentation/installation/
55
+
56
+ Verify that you've installed at least version 3.2:
57
+
58
+ `ruby -v`
59
+
60
+ ⚠️ **Note:** You might need to restart the terminal after installing.
61
+ ⚠️ **Note:*** Please make sure you install ruby for your user, not the root
62
+
55
63
  2. Install platformos-check gem
56
64
 
57
65
  `gem install platformos-check`
58
66
 
59
67
  You can verify the installation was successful by invoking `platformos-check --version`. If you chose this method, use `platformos-check-language-server` as a path to your language server instead of `/Users/<username/platformos-check-language-server`
60
68
 
69
+ ⚠️ **Note:*** Please make sure you install the gem for your user, not the root - i.e. without `sudo`
61
70
 
62
71
  ### Using Docker
63
72
 
data/config/default.yml CHANGED
@@ -15,6 +15,10 @@ ConvertIncludeToRender:
15
15
  enabled: true
16
16
  ignore: []
17
17
 
18
+ IncludeInRender:
19
+ enabled: true
20
+ ignore: []
21
+
18
22
  LiquidTag:
19
23
  enabled: true
20
24
  ignore: []
@@ -69,7 +73,6 @@ ValidYaml:
69
73
  UndefinedObject:
70
74
  enabled: true
71
75
  ignore: []
72
- config_type: :default
73
76
 
74
77
  DeprecatedFilter:
75
78
  enabled: true
@@ -107,7 +110,16 @@ HtmlParsingError:
107
110
  enabled: true
108
111
  ignore: []
109
112
 
113
+ TranslationKeyExists:
114
+ enabled: true
115
+ ignore: []
116
+
117
+ TranslationFilesMatch:
118
+ enabled: true
119
+ ignore: []
120
+
110
121
  ParseJsonFormat:
111
122
  enabled: false
112
123
  start_level: 0
113
124
  indent: ' '
125
+
@@ -30,6 +30,12 @@ This check is aimed at ensuring you have not forgotten to start the path with /.
30
30
  </form>
31
31
  ```
32
32
 
33
+ ```liquid
34
+ <form action="https://example.com/external">
35
+ ...
36
+ </form>
37
+ ```
38
+
33
39
  ## Check Options
34
40
 
35
41
  The default configuration for this check is the following:
@@ -3,7 +3,7 @@
3
3
  In platformOS all POST/PATCH/PUT/DELETE requests are protected from [CSRF Attacks][csrf-attack] through [authenticity_token][page-csrf]
4
4
  Form action defines the endpoint to which browser will make a request after submitting it.
5
5
 
6
- As a general rule you should include hidden input `<input type="hidden" name="authenticity_token" value="{{ context.authenticity_token }}">` in every form. Missing it will result in session invalidation and any logged in user will be automatically logged out.
6
+ As a general rule you should include hidden input `<input type="hidden" name="authenticity_token" value="{{ context.authenticity_token }}">` in every form. Missing it will result in session invalidation and the logged in user will be automatically logged out.
7
7
 
8
8
  ## Check Details
9
9
 
@@ -12,18 +12,37 @@ This check is aimed at ensuring you have not forgotten to include authenticity_t
12
12
  :-1: Examples of **incorrect** code for this check:
13
13
 
14
14
  ```liquid
15
- <form action="dummy/create">
15
+ <form action="/dummy/create" method="post">
16
16
  </form>
17
17
  ```
18
18
 
19
19
  :+1: Examples of **correct** code for this check:
20
20
 
21
+ With token:
21
22
  ```liquid
22
- <form action="/dummy/create">
23
+ <form action="/dummy/create" method="post">
23
24
  <input type="hidden" name="authenticity_token" value="{{ context.authenticity_token }}">
24
25
  </form>
25
26
  ```
26
27
 
28
+ For GET request:
29
+ ```liquid
30
+ <form action="/dummy/create">
31
+ </form>
32
+ ```
33
+
34
+ For external request:
35
+ ```liquid
36
+ <form action="https://example.com/dummy/create" method="post">
37
+ </form>
38
+ ```
39
+
40
+ For parameterized request:
41
+ ```liquid
42
+ <form action="{{ context.constants.MY_REQUEST_URL }}" method="post">
43
+ </form>
44
+ ```
45
+
27
46
  ## Check Options
28
47
 
29
48
  The default configuration for this check is the following:
@@ -0,0 +1,62 @@
1
+ # Reports usage of `include` tag inside `render` (`IncludeInRender`)
2
+
3
+ Runtime error is used when `include` tag is used inside `render` tag.
4
+
5
+ ## Check Details
6
+
7
+ This check is aimed at eliminating the use of `include` tags `render` tag.
8
+
9
+ :-1: Examples of **incorrect** code for this check:
10
+
11
+ ```liquid
12
+ {% liquid
13
+ # app/views/pages/index.liquid
14
+ render 'foo'
15
+ %}
16
+ ```liquid
17
+ {% liquid
18
+ # app/views/partials/foo.liquid
19
+ include 'bar'
20
+ %}
21
+ ```
22
+
23
+ :+1: Examples of **correct** code for this check:
24
+
25
+ ```liquid
26
+ {% liquid
27
+ # app/views/pages/index.liquid
28
+ render 'foo'
29
+ %}
30
+ ```liquid
31
+ {% liquid
32
+ # app/views/partials/foo.liquid
33
+ render 'bar'
34
+ %}
35
+ ```
36
+
37
+ ## Check Options
38
+
39
+ The default configuration for this check is the following:
40
+
41
+ ```yaml
42
+ IncludeInRender:
43
+ enabled: true
44
+ ```
45
+
46
+ ## When Not To Use It
47
+
48
+ It is discouraged to disable this rule.
49
+
50
+ ## Version
51
+
52
+ This check has been introduced in PlatformOS Check 0.4.9.
53
+
54
+ ## Resources
55
+
56
+ - [Deprecated Tags Reference][deprecated]
57
+ - [Rule Source][codesource]
58
+ - [Documentation Source][docsource]
59
+
60
+ [deprecated]: https://documentation.platformos.com/api-reference/liquid/include
61
+ [codesource]: /lib/platformos_check/checks/convert_include_to_render.rb
62
+ [docsource]: /docs/checks/convert_include_to_render.md
@@ -0,0 +1,70 @@
1
+ # Translation Files Match (`TranslationFilesMatch`)
2
+
3
+ Checks if translation files for different language have the same keys.
4
+
5
+ ## Check Details
6
+
7
+ This check is aimed at avoiding inconsistences between translation files to avoid errors hard to spot and make maintenance easier.
8
+
9
+ :-1: Examples of **incorrect** code for this check:
10
+
11
+ ```yaml
12
+ # app/translations/en/item.yml
13
+ en:
14
+ app:
15
+ item:
16
+ title: "Item"
17
+ description: "Description"
18
+
19
+ # app/translations/de/item.yml
20
+ en:
21
+ app:
22
+ item:
23
+ description: "Beschreibung"
24
+ ```
25
+
26
+ Missing "title" in de/item.yml
27
+
28
+ :+1: Examples of **correct** code for this check:
29
+
30
+ ```yaml
31
+ # app/translations/en/item.yml
32
+ en:
33
+ app:
34
+ item:
35
+ title: "Item"
36
+ description: "Description"
37
+
38
+ # app/translations/de/item.yml
39
+ en:
40
+ app:
41
+ item:
42
+ title: "Artikel"
43
+ description: "Beschreibung"
44
+ ```
45
+
46
+ ## Check Options
47
+
48
+ The default configuration for this check is the following:
49
+
50
+ ```yaml
51
+ TranslationFilesMatch:
52
+ enabled: true
53
+ ```
54
+
55
+ ## When Not To Use It
56
+
57
+ There should be no cases where disabling this rule is needed. For keys that are set via UI, and hence should not be part of the codebase,
58
+ use proper configuration option in [app/config.yml](https://documentation.platformos.com/developer-guide/platformos-workflow/codebase/config)
59
+
60
+ ## Version
61
+
62
+ This check has been introduced in PlatformOS Check 0.4.10.
63
+
64
+ ## Resources
65
+
66
+ - [Rule Source][codesource]
67
+ - [Documentation Source][docsource]
68
+
69
+ [codesource]: /lib/platformos_check/checks/translation_files_match.rb
70
+ [docsource]: /docs/checks/translation_files_match.md
@@ -0,0 +1,44 @@
1
+ # Translation Key Exists (`TranslationKeyExists`)
2
+
3
+ Checks if translation key is defined in the default language
4
+
5
+ ## Check Details
6
+
7
+ This check is aimed at avoiding missing translation error.
8
+
9
+ :-1: Examples of **incorrect** code for this check:
10
+
11
+ ```liquid
12
+ {{ 'undefined.key' | t }}
13
+ ```
14
+
15
+ :+1: Examples of **correct** code for this check:
16
+
17
+ ```liquid
18
+ {{ 'defined.key' | t }}
19
+
20
+ ## Check Options
21
+
22
+ The default configuration for this check is the following:
23
+
24
+ ```yaml
25
+ TranslationKeyExists:
26
+ enabled: true
27
+ ```
28
+
29
+ ## When Not To Use It
30
+
31
+ There should be no cases where disabling this rule is needed. For keys that are set via UI, and hence should not be part of the codebase,
32
+ use proper configuration option in [app/config.yml](https://documentation.platformos.com/developer-guide/platformos-workflow/codebase/config)
33
+
34
+ ## Version
35
+
36
+ This check has been introduced in PlatformOS Check 0.4.10.
37
+
38
+ ## Resources
39
+
40
+ - [Rule Source][codesource]
41
+ - [Documentation Source][docsource]
42
+
43
+ [codesource]: /lib/platformos_check/checks/translation_key_exists.rb
44
+ [docsource]: /docs/checks/translation_key_exists.md
Binary file
@@ -39,6 +39,8 @@ module PlatformosCheck
39
39
  CONFIG_REGEX => ConfigFile
40
40
  }
41
41
 
42
+ DEFAULT_LANGUAGE = 'en'
43
+
42
44
  attr_reader :storage, :grouped_files
43
45
 
44
46
  def initialize(storage)
@@ -139,5 +141,16 @@ module PlatformosCheck
139
141
  all.find { |t| t.relative_path.to_s == name_or_relative_path }
140
142
  end
141
143
  end
144
+
145
+ def default_language
146
+ DEFAULT_LANGUAGE
147
+ end
148
+
149
+ def translations_hash
150
+ @translations_hash ||= translations.each_with_object({}) do |translation_file, hash|
151
+ hash.deep_merge!(translation_file.content)
152
+ hash
153
+ end
154
+ end
142
155
  end
143
156
  end
@@ -34,16 +34,19 @@ module PlatformosCheck
34
34
  n = remove_extension(relative_path.sub(dir_prefix, '')).to_s
35
35
  return n if module_name.nil?
36
36
 
37
- prefix = "modules#{File::SEPARATOR}#{module_name}#{File::SEPARATOR}"
38
- return n if n.start_with?(prefix)
37
+ return n if n.start_with?(module_prefix)
39
38
 
40
- "#{prefix}#{n}"
39
+ "#{module_prefix}#{n}"
41
40
  end
42
41
 
43
42
  def dir_prefix
44
43
  nil
45
44
  end
46
45
 
46
+ def module_prefix
47
+ @module_prefix ||= "modules#{File::SEPARATOR}#{module_name}#{File::SEPARATOR}"
48
+ end
49
+
47
50
  def module_name
48
51
  @module_name ||= begin
49
52
  dir_names = @relative_path.split(File::SEPARATOR).reject(&:empty?)
@@ -85,6 +88,10 @@ module PlatformosCheck
85
88
  false
86
89
  end
87
90
 
91
+ def translation?
92
+ false
93
+ end
94
+
88
95
  def ==(other)
89
96
  other.is_a?(self.class) && relative_path == other.relative_path
90
97
  end
@@ -3,15 +3,54 @@
3
3
  module PlatformosCheck
4
4
  # Recommends replacing `include` for `render`
5
5
  class ConvertIncludeToRender < LiquidCheck
6
+ RENDER_INCOMPATIBLE_TAGS = %w[break include].freeze
7
+
6
8
  severity :suggestion
7
9
  category :liquid
8
10
  doc docs_url(__FILE__)
9
11
 
12
+ def initialize
13
+ @processed_files = {}
14
+ end
15
+
10
16
  def on_include(node)
17
+ return if allowed_usecase?(node)
18
+
11
19
  add_offense("`include` is deprecated - convert it to `render`", node:) do |corrector|
12
- # We need to fix #445 and pass the variables from the context or don't replace at all.
13
- # corrector.replace(node, "render \'#{node.value.template_name_expr}\' ")
20
+ match = node.markup.match(/(?<include>include\s*)/)
21
+ corrector.replace(node, node.markup.sub(match[:include], 'render '), node.start_index...node.end_index)
22
+ end
23
+ end
24
+
25
+ protected
26
+
27
+ def allowed_usecase?(node)
28
+ return true if name_is_variable?(node)
29
+ return true if include_node_contains_render_incompatible_tag?(root_node_from_include(node.value.template_name_expr))
30
+
31
+ false
32
+ end
33
+
34
+ def name_is_variable?(node)
35
+ !node.value.template_name_expr.is_a?(String)
36
+ end
37
+
38
+ def include_node_contains_render_incompatible_tag?(node)
39
+ return false if node.nil?
40
+
41
+ node.nodelist.any? do |n|
42
+ if RENDER_INCOMPATIBLE_TAGS.include?(n.respond_to?(:tag_name) && n.tag_name)
43
+ true
44
+ elsif n.respond_to?(:nodelist) && n.nodelist
45
+ include_node_contains_render_incompatible_tag?(n)
46
+ else
47
+ false
48
+ end
14
49
  end
15
50
  end
51
+
52
+ def root_node_from_include(path)
53
+ @platformos_app.grouped_files[PlatformosCheck::PartialFile][path]&.parse&.root
54
+ end
16
55
  end
17
56
  end
@@ -6,11 +6,13 @@ module PlatformosCheck
6
6
  categories :html
7
7
  doc docs_url(__FILE__)
8
8
 
9
+ VALID_ACTION_START = ['/', '{%', '{{', '#', 'http'].freeze
10
+
9
11
  def on_form(node)
10
12
  action = node.attributes["action"]&.strip
11
13
  return if action.nil?
12
14
  return if action.empty?
13
- return if action.start_with?('/', '{{')
15
+ return if action.start_with?(*VALID_ACTION_START)
14
16
 
15
17
  add_offense("Use action=\"/#{action}\" (start with /) to ensure the form can be submitted multiple times in case of validation errors", node:)
16
18
  end
@@ -9,6 +9,9 @@ module PlatformosCheck
9
9
  AUTHENTICITY_TOKEN_VALUE = /\A\s*{{\s*context\.authenticity_token\s*}}\s*\z/
10
10
 
11
11
  def on_form(node)
12
+ return if method_is_get(node.attributes['method'])
13
+ return unless action_is_relative_url(node.attributes['action'])
14
+
12
15
  authenticity_toke_inputs = node.children.select { |c| c.name == 'input' && c.attributes['name'] == 'authenticity_token' && c.attributes['value']&.match?(AUTHENTICITY_TOKEN_VALUE) }
13
16
  return if authenticity_toke_inputs.size == 1
14
17
  return add_offense('Duplicated authenticity_token inputs', node:) if authenticity_toke_inputs.size > 1
@@ -17,5 +20,22 @@ module PlatformosCheck
17
20
  corrector.insert_after(node, "\n<input type=\"hidden\" name=\"authenticity_token\" value=\"{{ context.authenticity_token }}\">")
18
21
  end
19
22
  end
23
+
24
+ protected
25
+
26
+ def method_is_get(method)
27
+ return true if method.nil?
28
+
29
+ method = method.downcase.strip
30
+ return true if method == ''
31
+
32
+ method == 'get'
33
+ end
34
+
35
+ def action_is_relative_url(action)
36
+ return true if action.nil?
37
+
38
+ action.lstrip[0] == '/'
39
+ end
20
40
  end
21
41
  end
@@ -6,13 +6,17 @@ module PlatformosCheck
6
6
  categories :html, :performance
7
7
  doc docs_url(__FILE__)
8
8
 
9
- ACCEPTED_LOADING_VALUES = %w[lazy eager]
9
+ ACCEPTED_LOADING_VALUES = Set.new(%w[lazy eager]).freeze
10
+ LOADING_DEFAULT_ATTRIBUTE = ' loading="eager"'
10
11
 
11
12
  def on_img(node)
12
13
  loading = node.attributes["loading"]&.downcase
13
14
  return if ACCEPTED_LOADING_VALUES.include?(loading)
14
15
 
15
- add_offense("Use loading=\"eager\" for images visible in the viewport on load and loading=\"lazy\" for others", node:)
16
+ add_offense("Use loading=\"eager\" for images visible in the viewport on load and loading=\"lazy\" for others", node:) do |corrector|
17
+ start_pos = node.start_index + node.markup.index('>')
18
+ corrector.insert_after(node, LOADING_DEFAULT_ATTRIBUTE, start_pos...start_pos)
19
+ end
16
20
  end
17
21
  end
18
22
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PlatformosCheck
4
+ # Recommends replacing `include` for `render`
5
+ class IncludeInRender < LiquidCheck
6
+ severity :error
7
+ category :liquid
8
+ doc docs_url(__FILE__)
9
+
10
+ def initialize
11
+ @processed_files = {}
12
+ end
13
+
14
+ def on_render(node)
15
+ path = node.value.template_name_expr
16
+ return unless include_tag_in_render?(root_node_for_render(path))
17
+
18
+ add_offense("`render` context does not allow to use `include`, either remove all includes from `#{app_file_for_path(path).relative_path}` or change `render` to `include`", node:)
19
+ end
20
+
21
+ protected
22
+
23
+ def include_tag_in_render?(node)
24
+ return false if node.nil?
25
+
26
+ node.nodelist.any? do |n|
27
+ if n.respond_to?(:tag_name) && n.tag_name == 'include'
28
+ true
29
+ elsif n.respond_to?(:nodelist) && n.nodelist
30
+ include_tag_in_render?(n)
31
+ else
32
+ false
33
+ end
34
+ end
35
+ end
36
+
37
+ def root_node_for_render(path)
38
+ app_file_for_path(path)&.parse&.root
39
+ end
40
+
41
+ def app_file_for_path(path)
42
+ @platformos_app.grouped_files[PlatformosCheck::PartialFile][path]
43
+ end
44
+ end
45
+ end
@@ -42,7 +42,10 @@ module PlatformosCheck
42
42
 
43
43
  def add_duplicated_key_offense(node)
44
44
  node.value.duplicated_attrs.each do |duplicated_arg|
45
- add_offense("Duplicated argument `#{duplicated_arg}`", node:)
45
+ add_offense("Duplicated argument `#{duplicated_arg}`", node:) do |corrector|
46
+ match = node.markup.match(/(?<attribute>,?\s*#{duplicated_arg}\s*:\s*#{Liquid::QuotedFragment})\s*/)
47
+ corrector.replace(node, node.markup.sub(match[:attribute], ''), node.start_index...node.end_index)
48
+ end
46
49
  end
47
50
  end
48
51
  end