com.wallstop-studios.dxmessaging 2.1.5 → 2.1.6

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.
Files changed (161) hide show
  1. package/.artifacts/SourceGenerators.Tests/obj/Debug/net9.0/WallstopStudios.DxMessaging.SourceGenerators.Tests.AssemblyInfo.cs +1 -1
  2. package/.cspell.json +4 -1
  3. package/.github/workflows/actionlint.yml +11 -1
  4. package/.github/workflows/csharpier-autofix.yml +34 -3
  5. package/.github/workflows/dotnet-tests.yml +13 -0
  6. package/.github/workflows/format-on-demand.yml +38 -44
  7. package/.github/workflows/json-format-check.yml +24 -0
  8. package/.github/workflows/lint-doc-links.yml +13 -0
  9. package/.github/workflows/markdown-json.yml +21 -4
  10. package/.github/workflows/markdown-link-text-check.yml +10 -0
  11. package/.github/workflows/markdown-link-validity.yml +10 -0
  12. package/.github/workflows/markdownlint.yml +7 -5
  13. package/.github/workflows/prettier-autofix.yml +67 -11
  14. package/.github/workflows/release-drafter.yml +2 -2
  15. package/.github/workflows/sync-wiki.yml +3 -3
  16. package/.github/workflows/yaml-format-lint.yml +26 -0
  17. package/.llm/context.md +113 -3
  18. package/.llm/skills/documentation/changelog-management.md +38 -0
  19. package/.llm/skills/documentation/documentation-style-guide.md +18 -0
  20. package/.llm/skills/documentation/documentation-update-workflow.md +2 -0
  21. package/.llm/skills/documentation/documentation-updates.md +2 -0
  22. package/.llm/skills/documentation/markdown-compatibility.md +476 -0
  23. package/.llm/skills/documentation/mermaid-theming.md +326 -0
  24. package/.llm/skills/documentation/mkdocs-navigation.md +290 -0
  25. package/.llm/skills/github-actions/git-renormalize-patterns.md +231 -0
  26. package/.llm/skills/github-actions/workflow-consistency.md +346 -0
  27. package/.llm/skills/index.md +53 -27
  28. package/.llm/skills/scripting/javascript-code-quality.md +417 -0
  29. package/.llm/skills/scripting/regex-documentation.md +461 -0
  30. package/.llm/skills/scripting/shell-best-practices.md +55 -4
  31. package/.llm/skills/scripting/validation-patterns.md +418 -0
  32. package/.llm/skills/specification.md +4 -1
  33. package/.llm/skills/testing/test-code-quality.md +243 -0
  34. package/.llm/skills/testing/test-production-code.md +348 -0
  35. package/CHANGELOG.md +11 -0
  36. package/README.md +0 -11
  37. package/Tests/Runtime/Benchmarks/WallstopStudios.DxMessaging.Tests.Runtime.Benchmarks.asmdef +1 -6
  38. package/Tests/Runtime/Integrations/Reflex/WallstopStudios.DxMessaging.Tests.Runtime.Reflex.asmdef +1 -1
  39. package/Tests/Runtime/Integrations/VContainer/WallstopStudios.DxMessaging.Tests.Runtime.VContainer.asmdef +1 -1
  40. package/Tests/Runtime/Integrations/Zenject/WallstopStudios.DxMessaging.Tests.Runtime.Zenject.asmdef +1 -1
  41. package/coverage/clover.xml +216 -3
  42. package/coverage/clover.xml.meta +7 -7
  43. package/coverage/coverage-final.json +2 -1
  44. package/coverage/coverage-final.json.meta +7 -7
  45. package/coverage/lcov-report/base.css.meta +1 -1
  46. package/coverage/lcov-report/block-navigation.js.meta +1 -1
  47. package/coverage/lcov-report/favicon.png.meta +1 -1
  48. package/coverage/lcov-report/index.html +25 -10
  49. package/coverage/lcov-report/index.html.meta +7 -7
  50. package/coverage/lcov-report/prettify.css.meta +1 -1
  51. package/coverage/lcov-report/prettify.js.meta +1 -1
  52. package/coverage/lcov-report/sort-arrow-sprite.png.meta +1 -1
  53. package/coverage/lcov-report/sorter.js.meta +1 -1
  54. package/coverage/lcov-report/transform-docs-to-wiki.js.html +1 -1
  55. package/coverage/lcov-report/transform-docs-to-wiki.js.html.meta +7 -7
  56. package/coverage/lcov-report/vendor.meta +1 -1
  57. package/coverage/lcov-report.meta +8 -8
  58. package/coverage/lcov.info +365 -0
  59. package/coverage/lcov.info.meta +7 -7
  60. package/docs/architecture/design-and-architecture.md +0 -1
  61. package/docs/concepts/index.md +37 -0
  62. package/docs/concepts/index.md.meta +7 -0
  63. package/docs/concepts/interceptors-and-ordering.md +0 -2
  64. package/docs/concepts/mental-model.md +390 -0
  65. package/docs/concepts/mental-model.md.meta +7 -0
  66. package/docs/concepts/message-types.md +0 -1
  67. package/docs/getting-started/getting-started.md +1 -0
  68. package/docs/getting-started/index.md +6 -5
  69. package/docs/getting-started/overview.md +1 -0
  70. package/docs/getting-started/quick-start.md +2 -1
  71. package/docs/getting-started/visual-guide.md +4 -10
  72. package/docs/hooks.py +10 -1
  73. package/docs/images/DxMessaging-banner.svg +1 -1
  74. package/docs/index.md +7 -7
  75. package/docs/javascripts/mermaid-config.js +44 -4
  76. package/docs/reference/helpers.md +130 -154
  77. package/docs/reference/quick-reference.md +5 -1
  78. package/docs/reference/reference.md +124 -130
  79. package/mkdocs.yml +2 -0
  80. package/package.json +1 -1
  81. package/scripts/__tests__/generate-skills-index.test.js +397 -0
  82. package/scripts/__tests__/generate-skills-index.test.js.meta +7 -0
  83. package/scripts/__tests__/mermaid-config.test.js +467 -0
  84. package/scripts/__tests__/mermaid-config.test.js.meta +7 -0
  85. package/scripts/__tests__/validate-skills-optional-fields.test.js +1474 -0
  86. package/scripts/__tests__/validate-skills-optional-fields.test.js.meta +7 -0
  87. package/scripts/__tests__/validate-skills-required-fields.test.js +188 -0
  88. package/scripts/__tests__/validate-skills-required-fields.test.js.meta +7 -0
  89. package/scripts/__tests__/validate-skills-tags.test.js +353 -0
  90. package/scripts/__tests__/validate-skills-tags.test.js.meta +7 -0
  91. package/scripts/__tests__/validate-workflows.test.js +188 -0
  92. package/scripts/__tests__/validate-workflows.test.js.meta +7 -0
  93. package/scripts/generate-skills-index.js +88 -3
  94. package/scripts/validate-skills.js +230 -30
  95. package/scripts/validate-workflows.js +272 -0
  96. package/scripts/validate-workflows.js.meta +7 -0
  97. package/site/404.html +1 -1
  98. package/site/advanced/emit-shorthands/index.html +2 -2
  99. package/site/advanced/message-bus-providers/index.html +2 -2
  100. package/site/advanced/registration-builders/index.html +2 -2
  101. package/site/advanced/runtime-configuration/index.html +2 -2
  102. package/site/advanced/string-messages/index.html +2 -2
  103. package/site/advanced.meta +1 -1
  104. package/site/architecture/comparisons/index.html +2 -2
  105. package/site/architecture/design-and-architecture/index.html +2 -2
  106. package/site/architecture/performance/index.html +1 -1
  107. package/site/architecture.meta +1 -1
  108. package/site/concepts/index.html +1 -0
  109. package/site/concepts/index.html.meta +7 -0
  110. package/site/concepts/interceptors-and-ordering/index.html +4 -4
  111. package/site/concepts/listening-patterns/index.html +2 -2
  112. package/site/concepts/mental-model/index.html +146 -0
  113. package/site/concepts/mental-model/index.html.meta +7 -0
  114. package/site/concepts/mental-model.meta +8 -0
  115. package/site/concepts/message-types/index.html +2 -2
  116. package/site/concepts/targeting-and-context/index.html +2 -2
  117. package/site/concepts.meta +1 -1
  118. package/site/examples/end-to-end/index.html +2 -2
  119. package/site/examples/end-to-end-scene-transitions/index.html +2 -2
  120. package/site/examples.meta +1 -1
  121. package/site/getting-started/getting-started/index.html +3 -3
  122. package/site/getting-started/index.html +4 -4
  123. package/site/getting-started/install/index.html +3 -3
  124. package/site/getting-started/overview/index.html +2 -2
  125. package/site/getting-started/quick-start/index.html +2 -2
  126. package/site/getting-started/visual-guide/index.html +11 -11
  127. package/site/getting-started.meta +1 -1
  128. package/site/guides/advanced/index.html +2 -2
  129. package/site/guides/diagnostics/index.html +2 -2
  130. package/site/guides/migration-guide/index.html +2 -2
  131. package/site/guides/patterns/index.html +2 -2
  132. package/site/guides/testing/index.html +2 -2
  133. package/site/guides/unity-integration/index.html +2 -2
  134. package/site/guides.meta +1 -1
  135. package/site/hooks.py.meta +1 -1
  136. package/site/images/DxMessaging-banner.svg +119 -0
  137. package/site/images/DxMessaging-banner.svg.meta +7 -0
  138. package/site/images.meta +8 -0
  139. package/site/index.html +2 -2
  140. package/site/integrations/index.html +2 -2
  141. package/site/integrations/reflex/index.html +2 -2
  142. package/site/integrations/vcontainer/index.html +2 -2
  143. package/site/integrations/zenject/index.html +2 -2
  144. package/site/integrations.meta +1 -1
  145. package/site/javascripts/csharp-highlight.js.meta +7 -7
  146. package/site/javascripts/mermaid-config.js +4 -1
  147. package/site/javascripts/mermaid-config.js.meta +1 -1
  148. package/site/javascripts.meta +1 -1
  149. package/site/reference/compatibility/index.html +1 -1
  150. package/site/reference/faq/index.html +1 -1
  151. package/site/reference/glossary/index.html +2 -2
  152. package/site/reference/helpers/index.html +15 -15
  153. package/site/reference/quick-reference/index.html +3 -3
  154. package/site/reference/reference/index.html +37 -37
  155. package/site/reference/troubleshooting/index.html +1 -1
  156. package/site/reference.meta +1 -1
  157. package/site/search/search_index.json +1 -1
  158. package/site/sitemap.xml +46 -38
  159. package/site/sitemap.xml.gz +0 -0
  160. package/site/stylesheets/extra.css.meta +1 -1
  161. package/site/stylesheets.meta +1 -1
@@ -0,0 +1,461 @@
1
+ ---
2
+ title: "Regex Pattern Documentation"
3
+ id: "regex-documentation"
4
+ category: "scripting"
5
+ version: "1.0.0"
6
+ created: "2026-01-29"
7
+ updated: "2026-01-29"
8
+
9
+ source:
10
+ repository: "wallstop/DxMessaging"
11
+ files:
12
+ - path: "scripts/"
13
+ - path: "docs/"
14
+ url: "https://github.com/wallstop/DxMessaging"
15
+
16
+ tags:
17
+ - "regex"
18
+ - "documentation"
19
+ - "scripting"
20
+ - "patterns"
21
+ - "comments"
22
+ - "maintenance"
23
+
24
+ complexity:
25
+ level: "intermediate"
26
+ reasoning: "Requires regex knowledge to understand flag behaviors and documentation implications"
27
+
28
+ impact:
29
+ performance:
30
+ rating: "none"
31
+ details: "Documentation only; no runtime performance impact"
32
+ maintainability:
33
+ rating: "high"
34
+ details: "Improves code clarity and prevents maintenance bugs from misleading comments"
35
+ testability:
36
+ rating: "medium"
37
+ details: "Helps verify regex behavior matches documented expectations"
38
+
39
+ prerequisites:
40
+ - "Basic regex syntax"
41
+ - "Understanding of regex flags"
42
+
43
+ dependencies:
44
+ packages: []
45
+ skills:
46
+ - "shell-best-practices"
47
+
48
+ applies_to:
49
+ languages:
50
+ - "JavaScript"
51
+ - "PowerShell"
52
+ - "C#"
53
+ - "Bash"
54
+ frameworks: []
55
+ versions: {}
56
+
57
+ aliases:
58
+ - "Regex comments"
59
+ - "Pattern documentation"
60
+ - "Regular expression documentation"
61
+
62
+ related:
63
+ - shell-best-practices
64
+ - cross-platform-compatibility
65
+
66
+ status: "stable"
67
+ ---
68
+
69
+ # Regex Pattern Documentation
70
+
71
+ > **One-line summary**: Document regex patterns accurately by describing what they actually match,
72
+ > including all flag-dependent behavior.
73
+
74
+ ## Overview
75
+
76
+ This skill covers best practices for documenting regular expression patterns. Accurate comments are critical because regex behavior changes dramatically based on flags, and misleading comments cause maintenance bugs. Many subtle bugs arise when comments describe intended behavior rather than actual behavior.
77
+
78
+ ## Solution
79
+
80
+ 1. **Describe actual behavior** - Comments must answer "What will this pattern match?" not "What do I hope it matches?"
81
+ 1. **Document flag effects** - Global, case-insensitive, multiline, and dotall flags change matching behavior significantly
82
+ 1. **Use precise language** - Say "matches all occurrences" (global) vs "matches first occurrence" (non-global)
83
+ 1. **Include character class details** - Specify whether patterns match Unicode, newlines, or specific character ranges
84
+
85
+ ## Core Principle
86
+
87
+ ### Comments must describe actual behavior, not intended behavior
88
+
89
+ A regex comment should answer: "What will this pattern actually match?" not "What do I hope it matches?"
90
+
91
+ ## Whitespace Character Classes
92
+
93
+ ### `\s` vs `[ \t]` - A Critical Distinction
94
+
95
+ The `\s` shorthand matches **all whitespace characters including newlines**. This is a frequent source of bugs when you only want to match spaces and tabs.
96
+
97
+ | Pattern | Matches | Use When |
98
+ | ----------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------- |
99
+ | `\s` | Space, tab, newline (`\n`), carriage return (`\r`), form feed, vertical tab | You want to match ANY whitespace including line breaks |
100
+ | `[ \t]` | Only space and tab | You want horizontal whitespace only, preserving newlines |
101
+ | `[\r\n]` | Only newline characters | You want to match line breaks specifically |
102
+ | `[^\S\r\n]` | Whitespace except newlines (double negative trick) | Alternative to `[ \t]` that includes other horizontal whitespace |
103
+
104
+ #### Wrong Pattern
105
+
106
+ ```javascript
107
+ // WRONG: \s* consumes newlines, concatenating lines when replaced
108
+ const DIRECTIVE_PATTERN = /^%%\{init:.*?\}%%\s*/gm;
109
+ // Intended: Strip directive and trailing spaces
110
+ // Actual: Also consumes the newline, joining this line with the next
111
+ ```
112
+
113
+ #### Correct Pattern
114
+
115
+ ```javascript
116
+ // CORRECT: [ \t]* only matches horizontal whitespace
117
+ const DIRECTIVE_PATTERN = /^[ \t]*%%\{init:.*?\}%%[ \t]*\r?\n?/gm;
118
+ // Strips directive, surrounding spaces/tabs, and just its own line ending
119
+ // Preserves separation between other lines
120
+ ```
121
+
122
+ #### Practical Impact
123
+
124
+ ```javascript
125
+ const text = "line1\n%%{init:...}%%\nline2";
126
+
127
+ // Bug: \s* consumes the newline AFTER the directive
128
+ text.replace(/%%\{init:.*?\}%%\s*/g, "");
129
+ // Result: "line1\nline2" with missing newline before line2
130
+
131
+ // Fixed: [ \t]* preserves newlines
132
+ text.replace(/%%\{init:.*?\}%%[ \t]*/g, "");
133
+ // Result: "line1\n\nline2" - newlines preserved
134
+ ```
135
+
136
+ ## Flag Reference Table
137
+
138
+ | Flag | Name | Effect | Comment Implications |
139
+ | ---- | -------------------- | --------------------------------------------------------- | --------------------------------------------------------------- |
140
+ | `g` | Global | Match all occurrences, not just the first | Comments must use plural ("matches all X" not "matches X") |
141
+ | `i` | Case-insensitive | `[A-Za-z]` matches regardless of case | Comments must mention "case-insensitive" explicitly |
142
+ | `m` | Multiline | `^` and `$` match start/end of each line, not just string | Comments must say "at start/end of any line" not "at start/end" |
143
+ | `s` | DotAll (Single-line) | `.` matches newline characters too | Comments must mention "including newlines" when using `.` |
144
+ | `u` | Unicode | Enables full Unicode support, `\p{}` escapes | Comments should note Unicode-aware matching if relevant |
145
+
146
+ ## Flag-Specific Documentation Rules
147
+
148
+ ### Global Flag (`g`)
149
+
150
+ The global flag changes whether a pattern finds one or all matches. Comments must reflect this.
151
+
152
+ #### Wrong Comments
153
+
154
+ ```javascript
155
+ // WRONG: Comment implies single match, but /g finds all
156
+ const pattern = /\d+/g;
157
+ // Matches a number in the string
158
+ ```
159
+
160
+ ```javascript
161
+ // WRONG: Singular language with global flag
162
+ const emailPattern = /\w+@\w+\.\w+/g;
163
+ // Matches an email address
164
+ ```
165
+
166
+ #### Correct Comments
167
+
168
+ ```javascript
169
+ // CORRECT: Plural language matches global behavior
170
+ const pattern = /\d+/g;
171
+ // Matches all numbers in the string
172
+
173
+ const emailPattern = /\w+@\w+\.\w+/g;
174
+ // Matches all email addresses in the string
175
+ ```
176
+
177
+ ### Multiline Flag (`m`)
178
+
179
+ The multiline flag changes the meaning of `^` and `$` anchors. This is one of the most commonly misdocumented behaviors.
180
+
181
+ #### Wrong Comments
182
+
183
+ ```javascript
184
+ // WRONG: Says "at start" but /m means "at start of ANY line"
185
+ const pattern = /^function/m;
186
+ // Matches 'function' at start of string
187
+ ```
188
+
189
+ ```javascript
190
+ // WRONG: Omits multiline behavior entirely
191
+ const endPattern = /;$/m;
192
+ // Matches semicolon at end
193
+ ```
194
+
195
+ #### Correct Comments
196
+
197
+ ```javascript
198
+ // CORRECT: Explicitly mentions line-level matching
199
+ const pattern = /^function/m;
200
+ // Matches 'function' at start of any line (not just string start)
201
+
202
+ const endPattern = /;$/m;
203
+ // Matches semicolon at end of any line (not just string end)
204
+ ```
205
+
206
+ #### Multiline Behavior Demonstration
207
+
208
+ ```javascript
209
+ const text = `line1
210
+ function test() {
211
+ return 42;
212
+ }`;
213
+
214
+ // Without /m flag: ^ only matches position 0
215
+ /^function/.test(text); // false - 'function' is not at string start
216
+
217
+ // With /m flag: ^ matches after every newline too
218
+ /^function/m.test(text); // true - 'function' is at start of line 2
219
+ ```
220
+
221
+ ### DotAll Flag (`s`)
222
+
223
+ The DotAll flag makes `.` match newline characters. Without it, `.` matches any character except newlines.
224
+
225
+ #### Wrong Comments
226
+
227
+ ```javascript
228
+ // WRONG: Says "any character" but without /s, newlines are excluded
229
+ const pattern = /start.*end/;
230
+ // Matches 'start', then any characters, then 'end'
231
+ ```
232
+
233
+ ```javascript
234
+ // WRONG: Implies newlines are matched when they're not
235
+ const blockPattern = /<div>.*<\/div>/;
236
+ // Matches everything between div tags
237
+ ```
238
+
239
+ #### Correct Comments
240
+
241
+ ```javascript
242
+ // CORRECT: Explicitly notes newline exclusion
243
+ const pattern = /start.*end/;
244
+ // Matches 'start', any characters EXCEPT newlines, then 'end'
245
+
246
+ // CORRECT: With /s flag, mentions newline inclusion
247
+ const multilinePattern = /start.*end/s;
248
+ // Matches 'start', any characters INCLUDING newlines, then 'end'
249
+
250
+ // CORRECT: Alternative using explicit character class
251
+ const explicitPattern = /start[\s\S]*end/;
252
+ // Matches 'start', any characters including newlines, then 'end'
253
+ ```
254
+
255
+ #### DotAll Behavior Demonstration
256
+
257
+ ```javascript
258
+ const text = `start
259
+ middle
260
+ end`;
261
+
262
+ // Without /s: . doesn't match newlines
263
+ /start.*end/.test(text); // false - can't cross newlines
264
+
265
+ // With /s: . matches everything including newlines
266
+ /start.*end/s.test(text); // true - matches across lines
267
+
268
+ // Alternative: [\s\S] matches any character including newlines
269
+ /start[\s\S]*end/.test(text); // true - explicit any-character class
270
+ ```
271
+
272
+ ### Case-Insensitive Flag (`i`)
273
+
274
+ #### Wrong Comments
275
+
276
+ ```javascript
277
+ // WRONG: Doesn't mention case-insensitivity
278
+ const pattern = /error/i;
279
+ // Matches 'error' in the string
280
+ ```
281
+
282
+ #### Correct Comments
283
+
284
+ ```javascript
285
+ // CORRECT: Explicitly mentions case behavior
286
+ const pattern = /error/i;
287
+ // Matches 'error' case-insensitively (ERROR, Error, error, etc.)
288
+ ```
289
+
290
+ ### Unicode Flag (`u`)
291
+
292
+ #### Wrong Comments
293
+
294
+ ```javascript
295
+ // WRONG: Doesn't explain Unicode implications
296
+ const emojiPattern = /\p{Emoji}/u;
297
+ // Matches emoji
298
+ ```
299
+
300
+ #### Correct Comments
301
+
302
+ ```javascript
303
+ // CORRECT: Notes Unicode property escapes
304
+ const emojiPattern = /\p{Emoji}/u;
305
+ // Matches any Unicode emoji character (requires /u flag for \p{} syntax)
306
+
307
+ const letterPattern = /\p{Letter}+/gu;
308
+ // Matches all sequences of Unicode letters (any script, not just ASCII)
309
+ ```
310
+
311
+ ## Combined Flag Documentation
312
+
313
+ When patterns use multiple flags, document the combined effect.
314
+
315
+ ### Wrong Comments
316
+
317
+ ```javascript
318
+ // WRONG: Doesn't explain combined behavior
319
+ const pattern = /^todo:/gim;
320
+ // Matches TODO markers
321
+ ```
322
+
323
+ ### Correct Comments
324
+
325
+ ```javascript
326
+ // CORRECT: Documents each flag's contribution
327
+ const pattern = /^todo:/gim;
328
+ // Matches all 'todo:' markers at start of any line, case-insensitively
329
+ // - /g: finds all occurrences
330
+ // - /i: matches TODO, Todo, todo, etc.
331
+ // - /m: ^ matches start of each line, not just string start
332
+ ```
333
+
334
+ ## Anti-Patterns to Avoid
335
+
336
+ ### 1. Copy-Paste Comments
337
+
338
+ Never copy comments from a similar regex without verifying accuracy.
339
+
340
+ ```javascript
341
+ // ANTI-PATTERN: Comment copied from non-global version
342
+ const pattern = /\bword\b/g;
343
+ // Matches 'word' as a whole word // WRONG: should say "all occurrences"
344
+ ```
345
+
346
+ ### 2. Intent-Based Comments
347
+
348
+ Comments should describe behavior, not intent.
349
+
350
+ ```javascript
351
+ // ANTI-PATTERN: Describes intent, not behavior
352
+ const pattern = /^#.*/m;
353
+ // For matching comment lines // WRONG: doesn't explain what it actually does
354
+
355
+ // CORRECT: Describes actual matching behavior
356
+ const pattern = /^#.*/m;
357
+ // Matches lines starting with # (from # to end of line, on any line)
358
+ ```
359
+
360
+ ### 3. Incomplete Anchor Documentation
361
+
362
+ Always specify what anchors match in context.
363
+
364
+ ```javascript
365
+ // ANTI-PATTERN: Vague anchor description
366
+ const pattern = /^start/;
367
+ // Matches 'start' at the beginning
368
+
369
+ // CORRECT: Specific anchor behavior
370
+ const pattern = /^start/;
371
+ // Matches 'start' at string start only (not line start; no /m flag)
372
+ ```
373
+
374
+ ### 4. Omitting Quantifier Behavior
375
+
376
+ Document what quantifiers actually capture.
377
+
378
+ ```javascript
379
+ // ANTI-PATTERN: Doesn't explain greedy vs lazy
380
+ const pattern = /".+"/;
381
+ // Matches quoted strings
382
+
383
+ // CORRECT: Explains greedy matching implications
384
+ const pattern = /".+"/;
385
+ // Matches from first " to LAST " (greedy); may span multiple quoted sections
386
+ // Use /"[^"]+"/g or /".+?"/g for individual quoted strings
387
+ ```
388
+
389
+ ### 5. Ignoring Edge Cases
390
+
391
+ Document known limitations.
392
+
393
+ ```javascript
394
+ // ANTI-PATTERN: No edge case documentation
395
+ const urlPattern = /https?:\/\/\S+/g;
396
+ // Matches URLs
397
+
398
+ // CORRECT: Documents limitations
399
+ const urlPattern = /https?:\/\/\S+/g;
400
+ // Matches all http/https URLs (simple pattern)
401
+ // Note: May include trailing punctuation; doesn't validate URL structure
402
+ ```
403
+
404
+ ## Validation Checklist
405
+
406
+ Before committing any regex pattern with comments, verify:
407
+
408
+ ### Flag Verification
409
+
410
+ - [ ] **Global (`g`)**: Comments use plural forms ("all X" not "X")
411
+ - [ ] **Multiline (`m`)**: Comments say "any line" for `^` and `$` anchors
412
+ - [ ] **DotAll (`s`)**: Comments mention newline matching for `.`
413
+ - [ ] **Case-insensitive (`i`)**: Comments explicitly note case behavior
414
+ - [ ] **Unicode (`u`)**: Comments note Unicode-specific features if used
415
+
416
+ ### Anchor Verification
417
+
418
+ - [ ] `^` comment specifies: string start, line start, or both (based on `/m`)
419
+ - [ ] `$` comment specifies: string end, line end, or both (based on `/m`)
420
+ - [ ] `\b` and `\B` behavior is correctly described
421
+
422
+ ### Quantifier Verification
423
+
424
+ - [ ] Greedy vs lazy behavior is documented when it matters
425
+ - [ ] `*` vs `+` implications are clear (zero-or-more vs one-or-more)
426
+
427
+ ### Behavioral Verification
428
+
429
+ - [ ] Comment describes actual behavior, not intended behavior
430
+ - [ ] Edge cases and limitations are documented
431
+ - [ ] Combined flag effects are explained
432
+
433
+ ### Testing Verification
434
+
435
+ - [ ] Pattern has been tested with expected matches
436
+ - [ ] Pattern has been tested with expected non-matches
437
+ - [ ] Edge cases have been verified
438
+
439
+ ## Language-Specific Notes
440
+
441
+ ### JavaScript
442
+
443
+ - Use template literals for patterns with many escapes: ``new RegExp(`pattern`, 'flags')``
444
+ - Remember that string escaping doubles backslashes: `new RegExp('\\d+')` vs `/\d+/`
445
+
446
+ ### Shell (grep, sed, awk)
447
+
448
+ - BRE (Basic Regular Expressions): `grep 'pattern'`
449
+ - ERE (Extended Regular Expressions): `grep -E 'pattern'`
450
+ - Different flag syntax: `-i` for case-insensitive, not `/i`
451
+ - See [Shell Best Practices](shell-best-practices.md) for grep-specific guidance
452
+
453
+ ### Python
454
+
455
+ - Use raw strings: `r'\d+'` to avoid double-escaping
456
+ - `re.MULTILINE` corresponds to `/m`, `re.DOTALL` to `/s`
457
+
458
+ ## See Also
459
+
460
+ - [Shell Best Practices](shell-best-practices.md) - grep pattern matching guidelines
461
+ - [Cross-Platform Compatibility](cross-platform-compatibility.md) - regex differences across platforms
@@ -2,7 +2,7 @@
2
2
  title: "Shell Scripting Best Practices"
3
3
  id: "shell-best-practices"
4
4
  category: "scripting"
5
- version: "1.0.0"
5
+ version: "1.1.0"
6
6
  created: "2026-01-28"
7
7
  updated: "2026-01-28"
8
8
 
@@ -322,6 +322,56 @@ shellcheck scripts/*.sh
322
322
  shellcheck .husky/*
323
323
  ```
324
324
 
325
+ ## Avoid Redundant Pipe Patterns
326
+
327
+ ### Problem: Unnecessary `head` with `grep -q`
328
+
329
+ The `grep -q` flag (quiet mode) already stops reading after the first match, making a preceding
330
+ `head` command redundant:
331
+
332
+ ```bash
333
+ # WRONG: head -1 is redundant when using grep -q
334
+ git ls-files "*.md" | head -1 | grep -q .
335
+
336
+ # WRONG: head -N with grep -q adds no value
337
+ some_command | head -5 | grep -q "pattern"
338
+ ```
339
+
340
+ ### Solution: Use `grep -q` Alone
341
+
342
+ ```bash
343
+ # CORRECT: grep -q already stops on first match
344
+ git ls-files "*.md" | grep -q .
345
+
346
+ # CORRECT: Use if/then for clarity in conditional logic
347
+ if git ls-files "*.$ext" "**/*.$ext" | grep -q .; then
348
+ git add --renormalize -- "*.$ext" "**/*.$ext"
349
+ fi
350
+ ```
351
+
352
+ ### Why `grep -q` Is Sufficient
353
+
354
+ The `-q` (quiet) flag has two behaviors:
355
+
356
+ 1. **Suppresses output**: No matches are printed to stdout
357
+ 1. **Exits immediately on first match**: Does not read remaining input
358
+
359
+ This means `grep -q` is inherently optimized for existence checks. Adding `head -1` before it:
360
+
361
+ - Adds a process fork overhead
362
+ - Provides no functional benefit
363
+ - Obscures the intent of the code
364
+
365
+ ### When `head` IS Appropriate
366
+
367
+ Use `head` when you need to:
368
+
369
+ - **Limit display output**: `git log --oneline | head -10` (showing last 10 commits)
370
+ - **Process only first N lines**: `cat file.txt | head -100 | process_lines`
371
+ - **Debug/diagnose**: `some_command | head -5` (see first few lines of output)
372
+
373
+ But NOT when combined with `grep -q` for existence checks.
374
+
325
375
  ## See Also
326
376
 
327
377
  - [PowerShell Best Practices](./powershell-best-practices.md) - Cross-language scripting patterns
@@ -330,6 +380,7 @@ shellcheck .husky/*
330
380
 
331
381
  ## Changelog
332
382
 
333
- | Version | Date | Changes |
334
- | ------- | ---------- | -------------------------------------- |
335
- | 1.0.0 | 2026-01-28 | Initial version from PR feedback cycle |
383
+ | Version | Date | Changes |
384
+ | ------- | ---------- | ----------------------------------------------- |
385
+ | 1.1.0 | 2026-01-28 | Added redundant pipe patterns section (PR #150) |
386
+ | 1.0.0 | 2026-01-28 | Initial version from PR feedback cycle |