immosquare-cleaner 0.1.84 → 0.1.85

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5db4cb8de23d20003df752fda8dc72588776050a743e6c4f24cfaf9004e1a975
4
- data.tar.gz: 94dd38d03de54e6a216a83eec05f4ee92ddf8154e2552ec8b1930a53d8c4a295
3
+ metadata.gz: 4da0616be6e3657c0023070c486b125edc9918f12debff664fab78cc7615d39c
4
+ data.tar.gz: 22b571ee9ba71ebd2d1cbce4f5a092e7fef94b4b2b37722719018fb4c231f950
5
5
  SHA512:
6
- metadata.gz: 86c068a18ff2ef426704c1585d940f9ce702f026b98c37e67797b8a12fe93a5232ad21cadf1cbebdb5b6fcd7ca678a8956747e1d4c547710ec9a672106b7325a
7
- data.tar.gz: fae01ff6fb1c24ec38f95ca92095b17e85d8024f9fd35372941ce14a862a0a7dc00db3361545f6199620ebefdceb735cbd42c772d96bc7bbada453a575bb409f
6
+ metadata.gz: 22aef01e31f21d0effe4604ecc3721ba780865271d5ebce3e9f33a5dc4282999b90512989db0342876ed1e39a061856a5d4c61be2e2b737ba93ff8a5106270e1
7
+ data.tar.gz: 71f305128320e353d98f56710c4cdc9be6965029f0972ed0639a01e4d542905f8556d178d0b8e07560c72259809f247b972f7cac32d1300e1464d5a761726702
@@ -1,3 +1,3 @@
1
1
  module ImmosquareCleaner
2
- VERSION = "0.1.84".freeze
2
+ VERSION = "0.1.85".freeze
3
3
  end
@@ -168,7 +168,8 @@ module ImmosquareCleaner
168
168
  File.write(temp_file_path, File.read(file_path))
169
169
  cmds = []
170
170
  cmds << "bundle exec erb_lint --config #{erblint_config_with_version_path} #{file_path} #{ImmosquareCleaner.configuration.erblint_options || "--autocorrect"}" if file_path.end_with?(".erb")
171
- cmds << "bun eslint --config #{gem_root}/linters/eslint.config.mjs #{temp_file_path} --fix"
171
+ cmds << "bun #{gem_root}/linters/normalize-comments.mjs #{temp_file_path}"
172
+ cmds << "bun eslint --config #{gem_root}/linters/eslint.config.mjs #{temp_file_path} --fix"
172
173
 
173
174
  launch_cmds(cmds)
174
175
  File.normalize_last_line(temp_file_path)
@@ -0,0 +1,229 @@
1
+ import { readFileSync, writeFileSync } from "fs"
2
+ import * as babelParser from "@babel/parser"
3
+
4
+ //============================================================//
5
+ // Constants
6
+ //============================================================//
7
+ const BORDER_LINE = "//" + "=".repeat(60) + "//"
8
+ const INSIDE_SEPARATOR = "// ---------"
9
+
10
+ //============================================================//
11
+ // Main function
12
+ //============================================================//
13
+ const normalizeComments = (filePath) => {
14
+ const code = readFileSync(filePath, "utf-8")
15
+ const lines = code.split("\n")
16
+
17
+ //============================================================//
18
+ // Parse the code with babel to get comment positions
19
+ //============================================================//
20
+ const ast = babelParser.parse(code, {
21
+ sourceType: "module",
22
+ plugins: ["typescript", "jsx"]
23
+ })
24
+
25
+ //============================================================//
26
+ // Get all comments from the AST
27
+ //============================================================//
28
+ const comments = ast.comments || []
29
+
30
+ //============================================================//
31
+ // Group consecutive standalone line comments
32
+ //============================================================//
33
+ const commentBlocks = groupConsecutiveComments(comments, lines)
34
+
35
+ //============================================================//
36
+ // Process blocks in reverse order to avoid line number shifts
37
+ //============================================================//
38
+ const blocksReversed = [...commentBlocks].reverse()
39
+
40
+ blocksReversed.forEach((block) => {
41
+ const normalized = normalizeCommentBlock(block, lines)
42
+ if (normalized) {
43
+ const startLine = block[0].loc.start.line - 1
44
+ const endLine = block[block.length - 1].loc.start.line - 1
45
+
46
+ //============================================================//
47
+ // Replace the lines in the original array
48
+ //============================================================//
49
+ lines.splice(startLine, endLine - startLine + 1, ...normalized)
50
+ }
51
+ })
52
+
53
+ writeFileSync(filePath, lines.join("\n"))
54
+ }
55
+
56
+ //============================================================//
57
+ // Group consecutive line comments together
58
+ // Only includes standalone comments (not end-of-line comments)
59
+ //============================================================//
60
+ const groupConsecutiveComments = (comments, originalLines) => {
61
+ const blocks = []
62
+ let currentBlock = []
63
+ let lastLine = -2
64
+
65
+ comments.forEach((comment) => {
66
+ //============================================================//
67
+ // Only process line comments (// style), not block comments (/* */)
68
+ //============================================================//
69
+ if (comment.type !== "CommentLine") {
70
+ if (currentBlock.length > 0) {
71
+ blocks.push(currentBlock)
72
+ currentBlock = []
73
+ }
74
+ lastLine = -2
75
+ return
76
+ }
77
+
78
+ //============================================================//
79
+ // Skip triple-slash comments (/// for TypeScript docs)
80
+ //============================================================//
81
+ if (comment.value.startsWith("/")) {
82
+ if (currentBlock.length > 0) {
83
+ blocks.push(currentBlock)
84
+ currentBlock = []
85
+ }
86
+ lastLine = -2
87
+ return
88
+ }
89
+
90
+ //============================================================//
91
+ // Check if this is a standalone comment (line starts with //)
92
+ // Skip end-of-line comments (e.g., const x = 1 // comment)
93
+ //============================================================//
94
+ const lineContent = originalLines[comment.loc.start.line - 1]
95
+ const isStandalone = lineContent.trim().startsWith("//")
96
+
97
+ if (!isStandalone) {
98
+ if (currentBlock.length > 0) {
99
+ blocks.push(currentBlock)
100
+ currentBlock = []
101
+ }
102
+ lastLine = -2
103
+ return
104
+ }
105
+
106
+ const currentLine = comment.loc.start.line
107
+
108
+ if (currentLine === lastLine + 1) {
109
+ currentBlock.push(comment)
110
+ } else {
111
+ if (currentBlock.length > 0) {
112
+ blocks.push(currentBlock)
113
+ }
114
+ currentBlock = [comment]
115
+ }
116
+ lastLine = currentLine
117
+ })
118
+
119
+ if (currentBlock.length > 0) {
120
+ blocks.push(currentBlock)
121
+ }
122
+
123
+ return blocks
124
+ }
125
+
126
+ //============================================================//
127
+ // Normalize a block of comments
128
+ // Returns an array of new lines, or null if no change needed
129
+ //============================================================//
130
+ const normalizeCommentBlock = (block, originalLines) => {
131
+ if (block.length === 0) return null
132
+
133
+ //============================================================//
134
+ // Get the indentation from the first comment
135
+ //============================================================//
136
+ const firstLine = originalLines[block[0].loc.start.line - 1]
137
+ const indent = firstLine.match(/^(\s*)/)[1]
138
+
139
+ //============================================================//
140
+ // Extract the text content from each comment
141
+ //============================================================//
142
+ const bodyLines = []
143
+ let firstLineWithTextFound = false
144
+
145
+ block.forEach((comment) => {
146
+ const text = comment.value.trim()
147
+ const hasAlphaNum = /[\p{L}0-9]/u.test(text)
148
+
149
+ if (isBorderLine(text)) {
150
+ return
151
+ } else if (isSeparatorLine(text)) {
152
+ if (firstLineWithTextFound) {
153
+ bodyLines.push(INSIDE_SEPARATOR)
154
+ }
155
+ } else if (hasAlphaNum) {
156
+ firstLineWithTextFound = true
157
+ bodyLines.push("// " + cleanedLine(text))
158
+ } else if (firstLineWithTextFound && text === "") {
159
+ bodyLines.push("//")
160
+ }
161
+ })
162
+
163
+ //============================================================//
164
+ // If block is empty, add a placeholder
165
+ //============================================================//
166
+ if (bodyLines.length === 0) {
167
+ bodyLines.push("// ...")
168
+ }
169
+
170
+ //============================================================//
171
+ // Build the new lines with borders
172
+ //============================================================//
173
+ const result = []
174
+ result.push(indent + BORDER_LINE)
175
+ bodyLines.forEach((line) => {
176
+ result.push(indent + line)
177
+ })
178
+ result.push(indent + BORDER_LINE)
179
+
180
+ return result
181
+ }
182
+
183
+ //============================================================//
184
+ // Check if a line is a border (long line of = or #)
185
+ //============================================================//
186
+ const isBorderLine = (text) => {
187
+ const cleaned = text.replace(/[/=\-\s#]/g, "")
188
+ const hasEquals = text.includes("=")
189
+ const longEnough = text.length > 20
190
+
191
+ return cleaned === "" && hasEquals && longEnough
192
+ }
193
+
194
+ //============================================================//
195
+ // Check if a line is an internal separator (---------)
196
+ //============================================================//
197
+ const isSeparatorLine = (text) => {
198
+ const cleaned = text.replace(/[-\s]/g, "")
199
+ return cleaned === "" && text.length >= 5
200
+ }
201
+
202
+ //============================================================//
203
+ // Clean a comment line
204
+ //============================================================//
205
+ const cleanedLine = (text) => {
206
+ //============================================================//
207
+ // Preserve lines with | (markdown tables)
208
+ //============================================================//
209
+ if (text.startsWith("|")) {
210
+ return text
211
+ }
212
+
213
+ //============================================================//
214
+ // Remove leading special characters and normalize
215
+ //============================================================//
216
+ return text.replace(/^[/=\s]*(?=[\p{L}0-9])/u, "").trim()
217
+ }
218
+
219
+ //============================================================//
220
+ // Run the script
221
+ //============================================================//
222
+ const filePath = process.argv[2]
223
+
224
+ if (!filePath) {
225
+ console.error("Usage: bun normalize-comments.mjs <file>")
226
+ process.exit(1)
227
+ }
228
+
229
+ normalizeComments(filePath)
@@ -18,16 +18,6 @@ module RuboCop
18
18
 
19
19
  comment_blocks = find_comment_blocks(processed_source.comments)
20
20
 
21
-
22
- ##============================================================##
23
- ## On ne veut traiter que les blocs de commentaires où la première ligne
24
- ## du bloc commence par ##
25
- ##============================================================##
26
- comment_blocks = comment_blocks.select do |block|
27
- block.first.text.strip.start_with?("##")
28
- end
29
-
30
-
31
21
  comment_blocks.each do |block|
32
22
  correct_block = normalize_comment_block(block)
33
23
 
@@ -59,7 +49,7 @@ module RuboCop
59
49
 
60
50
 
61
51
  ##============================================================##
62
- ## On ne veut traiter que les commentaires qui ne sont pas
52
+ ## On ne veut traiter que les commentaires ## qui ne sont pas
63
53
  ## des commentaires de fin de ligne ruby
64
54
  ##============================================================##
65
55
  def find_comment_blocks(comments)
@@ -67,26 +57,14 @@ module RuboCop
67
57
  current_block = []
68
58
  standalone_comments = comments.select do |comment|
69
59
  line = processed_source.lines[comment.location.line - 1]
70
- line.strip.start_with?("#")
60
+ line.strip.start_with?("##")
71
61
  end
72
62
 
73
63
  standalone_comments.each_with_index do |comment, index|
74
- next_comment = standalone_comments[index + 1]
75
- comment_text = comment.text.strip
76
- next_comment_text = next_comment&.text&.strip
77
- is_double_hash = comment_text.start_with?("##")
78
-
79
- ##============================================================##
80
- ## On vérifie si le prochain commentaire est sur la ligne suivante
81
- ## ET si les deux commentaires sont du même "type" (## ou #)
82
- ## Cela permet de ne pas fusionner les commentaires temporaires
83
- ## (# x = 1) avec les vrais commentaires (##)
84
- ##============================================================##
85
- next_is_double_hash = next_comment_text&.start_with?("##")
86
- same_type = is_double_hash == next_is_double_hash
64
+ next_comment = standalone_comments[index + 1]
87
65
  next_line_contiguous = next_comment && next_comment.location.line == comment.location.line + 1
88
66
 
89
- if next_line_contiguous && same_type
67
+ if next_line_contiguous
90
68
  current_block << comment
91
69
  else
92
70
  current_block << comment
@@ -106,7 +84,6 @@ module RuboCop
106
84
 
107
85
  body = block.map do |comment|
108
86
  text = comment.text.to_s.strip
109
- chars = text.chars.uniq
110
87
  alphanumercic = text.match?(/[\p{L}0-9]/)
111
88
  first_line_with_text_found = true if alphanumercic && !first_line_with_text_found
112
89
  if text == BORDER_LINE
@@ -145,25 +122,18 @@ module RuboCop
145
122
 
146
123
  ##============================================================##
147
124
  ## Expliquons la regex :
125
+ ## ##\s*#*\s*(?=[[:alnum:]])
126
+ ## ---------
148
127
  ## ## : match littéralement "##"
149
- ## | \s* : match 0 ou plusieurs espaces
150
- ## | #* : match 0 ou plusieurs #
151
- ## | \s* : match encore 0 ou plusieurs espaces
152
- ## | (?=[[:alnum:]]) : lookahead positif qui vérifie qu'on a un caractère alphanumérique après
128
+ ## \s* : match 0 ou plusieurs espaces
129
+ ## #* : match 0 ou plusieurs #
130
+ ## \s* : match encore 0 ou plusieurs espaces
131
+ ## (?=[[:alnum:]]) : lookahead positif qui vérifie qu'on a un caractère alphanumérique après
153
132
  ##============================================================##
154
133
  def cleaned_line(line)
155
- if line.start_with?("## |")
156
- line
157
- elsif line.start_with?("##")
158
- line.gsub(/##\s*#*\s*(?=[[:alnum:]])/, "## ")
159
- else
160
- ##============================================================##
161
- ## Pour une ligne commençant par # simple, on la convertit en ##
162
- ## On enlève d'abord le # initial et tous les espaces qui suivent
163
- ##============================================================##
164
- cleaned = line.gsub(/^#\s*/, "")
165
- "## #{cleaned}"
166
- end
134
+ return line if line.start_with?("## |")
135
+
136
+ line.gsub(/##\s*#*\s*(?=[[:alnum:]])/, "## ")
167
137
  end
168
138
 
169
139
  def needs_correction?(block, correct_block)
data/package.json CHANGED
@@ -2,6 +2,7 @@
2
2
  "name": "immosquare-cleaner",
3
3
  "private": true,
4
4
  "dependencies": {
5
+ "@babel/parser": "^7.28.5",
5
6
  "@eslint/js": "^9.39.1",
6
7
  "@typescript-eslint/eslint-plugin": "^8.48.1",
7
8
  "@typescript-eslint/parser": "^8.48.1",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: immosquare-cleaner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.84
4
+ version: 0.1.85
5
5
  platform: ruby
6
6
  authors:
7
7
  - immosquare
@@ -152,6 +152,7 @@ files:
152
152
  - linters/erb_lint/custom_html_to_content_tag.rb
153
153
  - linters/erb_lint/custom_single_line_if_modifier.rb
154
154
  - linters/eslint.config.mjs
155
+ - linters/normalize-comments.mjs
155
156
  - linters/prettier.yml
156
157
  - linters/rubocop-3.4.1.yml
157
158
  - linters/rubocop.yml