ima-claude 2.9.0

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 (182) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +463 -0
  3. package/dist/cli.js +1064 -0
  4. package/package.json +49 -0
  5. package/platforms/claude/adapter.ts +115 -0
  6. package/platforms/junie/adapter.ts +254 -0
  7. package/platforms/junie/agents-template.md +113 -0
  8. package/platforms/junie/hook-translations.md +84 -0
  9. package/platforms/shared/detector.ts +27 -0
  10. package/platforms/shared/installer.ts +202 -0
  11. package/platforms/shared/types.ts +78 -0
  12. package/plugins/ima-claude/.claude-plugin/plugin.json +25 -0
  13. package/plugins/ima-claude/agents/explorer.md +30 -0
  14. package/plugins/ima-claude/agents/implementer.md +30 -0
  15. package/plugins/ima-claude/agents/memory.md +42 -0
  16. package/plugins/ima-claude/agents/reviewer.md +53 -0
  17. package/plugins/ima-claude/agents/tester.md +33 -0
  18. package/plugins/ima-claude/agents/wp-developer.md +46 -0
  19. package/plugins/ima-claude/hooks/README.md +145 -0
  20. package/plugins/ima-claude/hooks/atlassian_prereqs.py +112 -0
  21. package/plugins/ima-claude/hooks/block_sed_edits.py +59 -0
  22. package/plugins/ima-claude/hooks/bootstrap.sh +90 -0
  23. package/plugins/ima-claude/hooks/bootstrap_utility_check.py +94 -0
  24. package/plugins/ima-claude/hooks/composer_autoload_check.py +70 -0
  25. package/plugins/ima-claude/hooks/docs_organization.py +104 -0
  26. package/plugins/ima-claude/hooks/enforce_rg_over_grep.py +56 -0
  27. package/plugins/ima-claude/hooks/fp_utility_check.py +90 -0
  28. package/plugins/ima-claude/hooks/hook_logger.py +69 -0
  29. package/plugins/ima-claude/hooks/hooks.json +239 -0
  30. package/plugins/ima-claude/hooks/jira_issue_fetch.py +79 -0
  31. package/plugins/ima-claude/hooks/jquery_in_wordpress.py +92 -0
  32. package/plugins/ima-claude/hooks/memory_bootstrap.py +79 -0
  33. package/plugins/ima-claude/hooks/memory_store_reminder.py +75 -0
  34. package/plugins/ima-claude/hooks/prompt_coach.py +125 -0
  35. package/plugins/ima-claude/hooks/prompt_coach_digest.md +48 -0
  36. package/plugins/ima-claude/hooks/prompt_coach_system.md +30 -0
  37. package/plugins/ima-claude/hooks/sequential_thinking_check.py +81 -0
  38. package/plugins/ima-claude/hooks/serena_over_grep.py +96 -0
  39. package/plugins/ima-claude/hooks/serena_over_read.py +66 -0
  40. package/plugins/ima-claude/hooks/serena_project_check.py +133 -0
  41. package/plugins/ima-claude/hooks/sql_injection_check.py +73 -0
  42. package/plugins/ima-claude/hooks/task_master_after_plan.py +31 -0
  43. package/plugins/ima-claude/hooks/task_master_before_impl.py +93 -0
  44. package/plugins/ima-claude/hooks/tavily_extract_advanced.py +48 -0
  45. package/plugins/ima-claude/hooks/vestige_before_external.py +86 -0
  46. package/plugins/ima-claude/hooks/webfetch_to_tavily.py +42 -0
  47. package/plugins/ima-claude/hooks/websearch_to_tavily.py +41 -0
  48. package/plugins/ima-claude/hooks/wp_security_check.py +150 -0
  49. package/plugins/ima-claude/personalities/README.md +45 -0
  50. package/plugins/ima-claude/personalities/enable-40k.md +69 -0
  51. package/plugins/ima-claude/personalities/enable-templars.md +69 -0
  52. package/plugins/ima-claude/skills/.research-summary.md +340 -0
  53. package/plugins/ima-claude/skills/architect/SKILL.md +304 -0
  54. package/plugins/ima-claude/skills/compound-bridge/SKILL.md +200 -0
  55. package/plugins/ima-claude/skills/discourse/SKILL.md +440 -0
  56. package/plugins/ima-claude/skills/discourse-admin/SKILL.md +192 -0
  57. package/plugins/ima-claude/skills/discourse-admin/references/api-endpoints.md +441 -0
  58. package/plugins/ima-claude/skills/discourse-admin/references/gotchas.md +107 -0
  59. package/plugins/ima-claude/skills/discourse-admin/references/staging-defaults.md +98 -0
  60. package/plugins/ima-claude/skills/discourse-admin/scripts/discourse-admin.py +319 -0
  61. package/plugins/ima-claude/skills/docs-organize/SKILL.md +254 -0
  62. package/plugins/ima-claude/skills/docs-organize/templates/active-README.md +50 -0
  63. package/plugins/ima-claude/skills/docs-organize/templates/archive-README.md +57 -0
  64. package/plugins/ima-claude/skills/docs-organize/templates/docs-README.md +43 -0
  65. package/plugins/ima-claude/skills/docs-organize/templates/phase-archive-README.md +83 -0
  66. package/plugins/ima-claude/skills/docs-organize/templates/section-README.md +48 -0
  67. package/plugins/ima-claude/skills/docs-organize/templates/transient-README.md +79 -0
  68. package/plugins/ima-claude/skills/docs-organize/templates/transient-gitignore +9 -0
  69. package/plugins/ima-claude/skills/ember-discourse/SKILL.md +496 -0
  70. package/plugins/ima-claude/skills/functional-programmer/SKILL.md +258 -0
  71. package/plugins/ima-claude/skills/ima-bootstrap/SKILL.md +278 -0
  72. package/plugins/ima-claude/skills/ima-bootstrap/references/bootstrap-patterns.md +356 -0
  73. package/plugins/ima-claude/skills/ima-bootstrap/references/ima-brand.md +273 -0
  74. package/plugins/ima-claude/skills/ima-bootstrap/references/theme-integration.md +212 -0
  75. package/plugins/ima-claude/skills/ima-brand/SKILL.md +108 -0
  76. package/plugins/ima-claude/skills/ima-brand/references/brand-identity.md +140 -0
  77. package/plugins/ima-claude/skills/ima-brand/references/digital-standards.md +180 -0
  78. package/plugins/ima-claude/skills/ima-brand/references/visual-system.md +173 -0
  79. package/plugins/ima-claude/skills/ima-forms-expert/SKILL.md +175 -0
  80. package/plugins/ima-claude/skills/ima-forms-expert/references/container-components.md +154 -0
  81. package/plugins/ima-claude/skills/ima-forms-expert/references/examples.md +328 -0
  82. package/plugins/ima-claude/skills/ima-forms-expert/references/field-components.md +298 -0
  83. package/plugins/ima-claude/skills/ima-forms-expert/references/form-factory.md +193 -0
  84. package/plugins/ima-claude/skills/ima-forms-expert/references/quick-reference.md +153 -0
  85. package/plugins/ima-claude/skills/ima-forms-expert/references/validation-engine.md +336 -0
  86. package/plugins/ima-claude/skills/jira-checkpoint/SKILL.md +178 -0
  87. package/plugins/ima-claude/skills/jquery/SKILL.md +413 -0
  88. package/plugins/ima-claude/skills/js-fp/SKILL.md +463 -0
  89. package/plugins/ima-claude/skills/js-fp/core-principles.md +487 -0
  90. package/plugins/ima-claude/skills/js-fp/examples/pure-functions.js +260 -0
  91. package/plugins/ima-claude/skills/js-fp/examples/tests/pure-functions.test.js +262 -0
  92. package/plugins/ima-claude/skills/js-fp/references/anti-patterns.md +120 -0
  93. package/plugins/ima-claude/skills/js-fp/references/performance-patterns.md +116 -0
  94. package/plugins/ima-claude/skills/js-fp/references/testing-patterns.md +134 -0
  95. package/plugins/ima-claude/skills/js-fp-api/SKILL.md +280 -0
  96. package/plugins/ima-claude/skills/js-fp-api/examples/crud-endpoint.js +258 -0
  97. package/plugins/ima-claude/skills/js-fp-api/references/middleware-patterns.md +134 -0
  98. package/plugins/ima-claude/skills/js-fp-api/references/security-sql.md +110 -0
  99. package/plugins/ima-claude/skills/js-fp-api/references/validation-patterns.md +165 -0
  100. package/plugins/ima-claude/skills/js-fp-react/SKILL.md +447 -0
  101. package/plugins/ima-claude/skills/js-fp-react/examples/ProductCard.tsx +65 -0
  102. package/plugins/ima-claude/skills/js-fp-react/references/hooks-advanced.md +136 -0
  103. package/plugins/ima-claude/skills/js-fp-react/references/performance-patterns.md +175 -0
  104. package/plugins/ima-claude/skills/js-fp-vue/SKILL.md +322 -0
  105. package/plugins/ima-claude/skills/js-fp-vue/references/complete-examples.md +397 -0
  106. package/plugins/ima-claude/skills/js-fp-vue/references/composables-advanced.md +282 -0
  107. package/plugins/ima-claude/skills/js-fp-vue/references/reactivity-patterns.md +348 -0
  108. package/plugins/ima-claude/skills/js-fp-vue/references/testing.md +314 -0
  109. package/plugins/ima-claude/skills/js-fp-wordpress/SKILL.md +301 -0
  110. package/plugins/ima-claude/skills/js-fp-wordpress/references/ajax-patterns.md +192 -0
  111. package/plugins/ima-claude/skills/js-fp-wordpress/references/event-patterns.md +136 -0
  112. package/plugins/ima-claude/skills/js-fp-wordpress/references/wp-integration.md +248 -0
  113. package/plugins/ima-claude/skills/livecanvas/SKILL.md +209 -0
  114. package/plugins/ima-claude/skills/livecanvas/references/livecanvas-features.md +311 -0
  115. package/plugins/ima-claude/skills/livecanvas/references/loops-and-logic.md +730 -0
  116. package/plugins/ima-claude/skills/livecanvas/references/picostrap.md +227 -0
  117. package/plugins/ima-claude/skills/mcp-atlassian/SKILL.md +339 -0
  118. package/plugins/ima-claude/skills/mcp-context7/SKILL.md +109 -0
  119. package/plugins/ima-claude/skills/mcp-memory/SKILL.md +182 -0
  120. package/plugins/ima-claude/skills/mcp-qdrant/SKILL.md +233 -0
  121. package/plugins/ima-claude/skills/mcp-sequential/SKILL.md +149 -0
  122. package/plugins/ima-claude/skills/mcp-serena/SKILL.md +174 -0
  123. package/plugins/ima-claude/skills/mcp-tavily/SKILL.md +118 -0
  124. package/plugins/ima-claude/skills/mcp-vestige/SKILL.md +259 -0
  125. package/plugins/ima-claude/skills/php-authnet/SKILL.md +275 -0
  126. package/plugins/ima-claude/skills/php-authnet/references/api-reference.md +624 -0
  127. package/plugins/ima-claude/skills/php-authnet/references/sandbox-testing.md +424 -0
  128. package/plugins/ima-claude/skills/php-fp/SKILL.md +333 -0
  129. package/plugins/ima-claude/skills/php-fp/examples/pure-functions.php +403 -0
  130. package/plugins/ima-claude/skills/php-fp/examples/tests/PureFunctionsTest.php +515 -0
  131. package/plugins/ima-claude/skills/php-fp/references/core-principles.md +277 -0
  132. package/plugins/ima-claude/skills/php-fp/references/testing-patterns.md +374 -0
  133. package/plugins/ima-claude/skills/php-fp-wordpress/SKILL.md +216 -0
  134. package/plugins/ima-claude/skills/php-fp-wordpress/references/fp-patterns.md +275 -0
  135. package/plugins/ima-claude/skills/php-fp-wordpress/references/plugin-architecture.md +295 -0
  136. package/plugins/ima-claude/skills/php-fp-wordpress/references/security-examples.md +203 -0
  137. package/plugins/ima-claude/skills/php-fp-wordpress/references/testing-strategy.md +259 -0
  138. package/plugins/ima-claude/skills/phpunit-wp/SKILL.md +716 -0
  139. package/plugins/ima-claude/skills/playwright/SKILL.md +434 -0
  140. package/plugins/ima-claude/skills/playwright/references/accessibility-testing.md +153 -0
  141. package/plugins/ima-claude/skills/playwright/references/ci-cd.md +268 -0
  142. package/plugins/ima-claude/skills/playwright/references/network-mocking.md +270 -0
  143. package/plugins/ima-claude/skills/playwright/references/visual-regression.md +215 -0
  144. package/plugins/ima-claude/skills/py-fp/SKILL.md +663 -0
  145. package/plugins/ima-claude/skills/py-fp/examples/pure-functions.py +185 -0
  146. package/plugins/ima-claude/skills/py-fp/examples/tests/test_pure_functions.py +244 -0
  147. package/plugins/ima-claude/skills/py-fp/references/core-principles.md +381 -0
  148. package/plugins/ima-claude/skills/py-fp/references/testing-patterns.md +283 -0
  149. package/plugins/ima-claude/skills/quasar-fp/SKILL.md +327 -0
  150. package/plugins/ima-claude/skills/quasar-fp/metadata.json +85 -0
  151. package/plugins/ima-claude/skills/quasar-fp/references/component-patterns.md +257 -0
  152. package/plugins/ima-claude/skills/quasar-fp/references/theme-integration.md +233 -0
  153. package/plugins/ima-claude/skills/quasar-fp/references/utility-classes.md +237 -0
  154. package/plugins/ima-claude/skills/quickstart/SKILL.md +129 -0
  155. package/plugins/ima-claude/skills/rails/SKILL.md +359 -0
  156. package/plugins/ima-claude/skills/resume-session/SKILL.md +68 -0
  157. package/plugins/ima-claude/skills/rg/SKILL.md +205 -0
  158. package/plugins/ima-claude/skills/ruby-fp/SKILL.md +336 -0
  159. package/plugins/ima-claude/skills/save-session/SKILL.md +81 -0
  160. package/plugins/ima-claude/skills/scorecard/SKILL.md +96 -0
  161. package/plugins/ima-claude/skills/skill-analyzer/SKILL.md +127 -0
  162. package/plugins/ima-claude/skills/skill-analyzer/references/advanced-checklist.md +44 -0
  163. package/plugins/ima-claude/skills/skill-analyzer/references/core-checklist.md +60 -0
  164. package/plugins/ima-claude/skills/skill-analyzer/scripts/analyze_skill.py +418 -0
  165. package/plugins/ima-claude/skills/skill-creator/LICENSE.txt +202 -0
  166. package/plugins/ima-claude/skills/skill-creator/SKILL.md +343 -0
  167. package/plugins/ima-claude/skills/skill-creator/references/output-patterns.md +82 -0
  168. package/plugins/ima-claude/skills/skill-creator/references/workflows.md +28 -0
  169. package/plugins/ima-claude/skills/skill-creator/scripts/init_skill.py +303 -0
  170. package/plugins/ima-claude/skills/skill-creator/scripts/package_skill.py +110 -0
  171. package/plugins/ima-claude/skills/skill-creator/scripts/quick_validate.py +103 -0
  172. package/plugins/ima-claude/skills/task-master/SKILL.md +51 -0
  173. package/plugins/ima-claude/skills/task-planner/SKILL.md +228 -0
  174. package/plugins/ima-claude/skills/task-runner/SKILL.md +192 -0
  175. package/plugins/ima-claude/skills/unit-testing/SKILL.md +198 -0
  176. package/plugins/ima-claude/skills/unit-testing/references/mock-patterns.md +181 -0
  177. package/plugins/ima-claude/skills/unit-testing/references/tdd-workflow.md +177 -0
  178. package/plugins/ima-claude/skills/unit-testing/references/test-strategy.md +126 -0
  179. package/plugins/ima-claude/skills/wp-local/SKILL.md +246 -0
  180. package/plugins/ima-claude/skills/wp-local/references/configuration.md +198 -0
  181. package/plugins/ima-claude/skills/wp-local/references/wp-cli-reference.md +406 -0
  182. package/plugins/ima-claude/skills/wp-local/scripts/wp-local.sh +61 -0
@@ -0,0 +1,301 @@
1
+ ---
2
+ name: "js-fp-wordpress"
3
+ description: "FP patterns for JavaScript in WordPress/Bootstrap context - ecosystem-native patterns, jQuery guidance, pure business logic"
4
+ ---
5
+
6
+ # JavaScript FP - WordPress/Bootstrap
7
+
8
+ Functional programming patterns for JavaScript in WordPress environments where jQuery is already loaded and Bootstrap is the UI framework.
9
+
10
+ ## When to Use This Skill
11
+
12
+ - Building WordPress plugin/theme JavaScript
13
+ - Need guidance on jQuery vs Vanilla JS decisions
14
+ - Implementing pure business logic in browser JavaScript
15
+ - Working with Gravity Forms, ACF, or other jQuery-dependent plugins
16
+ - Creating form handlers, AJAX operations, or DOM interactions
17
+
18
+ ## Core Philosophy
19
+
20
+ **"Use what's simple and native to the ecosystem. In WordPress, jQuery IS native."**
21
+
22
+ **Key Insight**: The js-fp principle "Native patterns > FP utilities" targets AI-generated abstractions like custom `pipe()` and `curry()` functions - it does NOT mean "avoid established ecosystem libraries like jQuery."
23
+
24
+ **Foundation**: This skill builds on `js-fp` core principles. Reference `../js-fp/SKILL.md` for purity, composition, dependency injection, and testing patterns.
25
+
26
+ ## TL;DR Decision Matrix
27
+
28
+ | Context | Recommendation | Rationale |
29
+ |---------|---------------|-----------|
30
+ | **New isolated component** | Vanilla JS | No jQuery event coupling needed |
31
+ | **AJAX operations** | jQuery `$.ajax` | Cleaner than `fetch` + error handling |
32
+ | **DOM event delegation** | Either | Both work well |
33
+ | **Integrating with WP plugins** | jQuery | Match ecosystem patterns |
34
+ | **Animation** | CSS transitions | Neither jQuery nor vanilla JS |
35
+ | **Pure business logic** | Vanilla JS | No DOM, fully testable |
36
+
37
+ ## Critical Context: WordPress Reality Check
38
+
39
+ **jQuery IS guaranteed available** in WordPress because:
40
+ 1. WordPress core depends on jQuery
41
+ 2. Bootstrap 5 JavaScript works with or without jQuery
42
+ 3. Gravity Forms, ACF, and most plugins use jQuery
43
+ 4. The overhead argument is **irrelevant** - it's already loaded (0 additional bytes)
44
+
45
+ ### Arguments That DON'T Apply Here
46
+
47
+ | Common Argument | Why It Doesn't Apply |
48
+ |-----------------|---------------------|
49
+ | "jQuery adds bundle size" | Already loaded - 0 additional bytes |
50
+ | "jQuery is a dependency" | Already a core WordPress dependency |
51
+ | "Modern browsers don't need jQuery" | True, but jQuery is still there |
52
+ | "jQuery is slower" | Negligible for DOM operations |
53
+
54
+ ## Practical Guidelines
55
+
56
+ ### 1. Don't Rewrite Working jQuery Code
57
+
58
+ **YAGNI applies**. If existing code works, leave it:
59
+
60
+ ```javascript
61
+ // KEEP: Working jQuery AJAX handler
62
+ (function($) {
63
+ 'use strict';
64
+
65
+ $('.ima-form').on('submit', function(e) {
66
+ e.preventDefault();
67
+ var $form = $(this);
68
+
69
+ $.ajax({
70
+ url: imaAjax.url,
71
+ type: 'POST',
72
+ data: $form.serialize(),
73
+ success: function(response) {
74
+ $form.find('.ima-response').html(response.message);
75
+ }
76
+ });
77
+ });
78
+
79
+ })(jQuery);
80
+
81
+ // DON'T: Rewrite to vanilla "just because" - No benefit, adds risk
82
+ ```
83
+
84
+ ### 2. New Code: Choose Based on Context
85
+
86
+ ```javascript
87
+ // jQuery: When integrating with WordPress plugins
88
+ (function($) {
89
+ 'use strict';
90
+
91
+ // Gravity Forms event - MUST use jQuery
92
+ $(document).on('gform_post_render', function(event, formId) {
93
+ initImaFields($('#gform_' + formId));
94
+ });
95
+
96
+ })(jQuery);
97
+
98
+ // Vanilla JS: Isolated component with no WP plugin interaction
99
+ (function() {
100
+ 'use strict';
101
+
102
+ class RepeaterController {
103
+ constructor(element) {
104
+ this.container = element;
105
+ this.template = element.querySelector('[data-repeater-template]');
106
+ this.init();
107
+ }
108
+
109
+ init() {
110
+ this.container.addEventListener('click', this.handleClick.bind(this));
111
+ }
112
+
113
+ // Pure method - no DOM side effects
114
+ generateRowId() {
115
+ return 'row_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
116
+ }
117
+ }
118
+
119
+ document.querySelectorAll('[data-repeater-container]').forEach(function(el) {
120
+ new RepeaterController(el);
121
+ });
122
+
123
+ })();
124
+ ```
125
+
126
+ ### 3. Prefer Consistency Within Files
127
+
128
+ ```javascript
129
+ // AVOID: Mixing jQuery and vanilla in same file
130
+ (function($) {
131
+ document.querySelectorAll('.foo').forEach(function(el) { // Vanilla
132
+ $(el).on('click', handler); // jQuery - inconsistent!
133
+ });
134
+ })(jQuery);
135
+
136
+ // GOOD: Consistent jQuery throughout
137
+ (function($) {
138
+ 'use strict';
139
+ $('.foo').each(function() {
140
+ $(this).on('click', handler);
141
+ });
142
+ })(jQuery);
143
+
144
+ // GOOD: Consistent vanilla throughout
145
+ (function() {
146
+ 'use strict';
147
+ document.querySelectorAll('.foo').forEach(function(el) {
148
+ el.addEventListener('click', handler);
149
+ });
150
+ })();
151
+ ```
152
+
153
+ ## Pure Business Logic Pattern
154
+
155
+ **Rule**: Extract pure JavaScript functions from DOM-dependent code.
156
+
157
+ ```javascript
158
+ (function($) {
159
+ 'use strict';
160
+
161
+ // Pure business logic (testable without DOM)
162
+ function calculatePricing(quantity, unitPrice, discountPercent) {
163
+ var subtotal = Math.max(0, quantity) * Math.max(0, unitPrice);
164
+ var discountAmount = subtotal * (Math.min(100, Math.max(0, discountPercent)) / 100);
165
+ return {
166
+ subtotal: subtotal,
167
+ discountAmount: discountAmount,
168
+ total: subtotal - discountAmount
169
+ };
170
+ }
171
+
172
+ function formatCurrency(amount) {
173
+ return '$' + amount.toFixed(2);
174
+ }
175
+
176
+ // DOM wrapper (side effects isolated here)
177
+ function PriceCalculator($container) {
178
+ this.$container = $container;
179
+ this.$container.on('change', 'input', this.update.bind(this));
180
+ }
181
+
182
+ PriceCalculator.prototype.update = function() {
183
+ var values = {
184
+ quantity: parseInt(this.$container.find('#quantity').val()) || 0,
185
+ unitPrice: parseFloat(this.$container.find('#unit-price').val()) || 0,
186
+ discount: parseFloat(this.$container.find('#discount').val()) || 0
187
+ };
188
+ var pricing = calculatePricing(values.quantity, values.unitPrice, values.discount);
189
+ this.$container.find('#total').text(formatCurrency(pricing.total));
190
+ };
191
+
192
+ // Export for testing
193
+ if (typeof module !== 'undefined' && module.exports) {
194
+ module.exports = { calculatePricing: calculatePricing, formatCurrency: formatCurrency };
195
+ }
196
+
197
+ })(jQuery);
198
+ ```
199
+
200
+ ## Anti-Patterns (AVOID)
201
+
202
+ ### Rewriting Working jQuery for No Benefit
203
+
204
+ ```javascript
205
+ // DON'T: Same functionality, more code, no benefit
206
+ // Before (working): $('.btn').on('click', handler);
207
+ // After (unnecessary):
208
+ document.querySelectorAll('.btn').forEach(function(btn) {
209
+ btn.addEventListener('click', handler);
210
+ });
211
+ ```
212
+
213
+ ### Fighting the WordPress Ecosystem
214
+
215
+ ```javascript
216
+ // DON'T: Ignore GF jQuery events (this won't work!)
217
+ document.addEventListener('gform_post_render', function() {});
218
+
219
+ // DO: Use jQuery for GF integration
220
+ $(document).on('gform_post_render', function(event, formId) {});
221
+ ```
222
+
223
+ ### Custom FP Utilities
224
+
225
+ ```javascript
226
+ // NEVER: Create custom FP utilities
227
+ const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x)
228
+
229
+ // INSTEAD: Direct function calls
230
+ function processFormData(data) {
231
+ var sanitized = sanitizeData(data);
232
+ var validated = validateData(sanitized);
233
+ return formatData(validated);
234
+ }
235
+ ```
236
+
237
+ ## Quality Gates
238
+
239
+ Before implementing JavaScript in WordPress:
240
+
241
+ 1. **Ecosystem check**: Does this need to interact with jQuery-based plugins (GF, ACF)?
242
+ 2. **Existing code**: Is there working code that just needs enhancement?
243
+ 3. **Pure logic**: Is business logic separated from DOM operations?
244
+ 4. **Consistency**: Is the file using one approach consistently?
245
+ 5. **Testability**: Can pure functions be tested without DOM?
246
+ 6. **YAGNI**: Are we adding complexity without clear benefit?
247
+
248
+ ## Reference Files
249
+
250
+ Load these as needed for detailed patterns:
251
+
252
+ ### AJAX Patterns
253
+ **File**: [references/ajax-patterns.md](references/ajax-patterns.md)
254
+ **When**: Need AJAX implementation patterns
255
+ **Contains**: jQuery $.ajax, vanilla fetch, error handling, retry patterns
256
+
257
+ ### Event Patterns
258
+ **File**: [references/event-patterns.md](references/event-patterns.md)
259
+ **When**: Need event delegation or DOMContentLoaded patterns
260
+ **Contains**: jQuery delegation, vanilla delegation, document ready patterns
261
+
262
+ ### WordPress Integration
263
+ **File**: [references/wp-integration.md](references/wp-integration.md)
264
+ **When**: Integrating with Gravity Forms, ACF, or WordPress admin
265
+ **Contains**: GF hooks, ACF hooks, admin JS, pure logic extraction, testing
266
+
267
+ ### PHP Integration
268
+ **File**: `../php-fp-wordpress/SKILL.md`
269
+ **When**: Need server-side integration patterns
270
+ **Contains**: WordPress AJAX handlers, security practices, PHP/JS coordination
271
+
272
+ ### Core FP Principles
273
+ **File**: `../js-fp/SKILL.md`
274
+ **When**: Need foundational FP patterns
275
+ **Contains**: Purity, composition, dependency injection, immutability, testing
276
+
277
+ ## File Organization
278
+
279
+ ```
280
+ plugin-name/
281
+ └── assets/
282
+ └── js/
283
+ ├── plugin-base.js # jQuery - AJAX, GF integration
284
+ ├── plugin-admin.js # jQuery - Admin UI interactions
285
+ ├── plugin-repeater.js # Vanilla - Isolated component
286
+ └── pure/
287
+ ├── formatting.js # Pure functions (testable)
288
+ └── calculations.js # Pure functions (testable)
289
+ ```
290
+
291
+ ## Success Metrics
292
+
293
+ - **Ecosystem Fit**: JavaScript integrates smoothly with WordPress/plugins
294
+ - **Consistency**: Files use one approach throughout
295
+ - **Testability**: Pure business logic has unit tests
296
+ - **Maintainability**: Clear separation of concerns
297
+ - **Pragmatism**: Working code not rewritten without benefit
298
+
299
+ ## Philosophy
300
+
301
+ *"In WordPress, jQuery IS native. Use what's simple and matches the ecosystem. Separate pure business logic for testability, but don't fight the platform. Working code > ideological purity."*
@@ -0,0 +1,192 @@
1
+ # AJAX Patterns for WordPress
2
+
3
+ WordPress AJAX patterns with jQuery and vanilla JS approaches.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [jQuery AJAX (Recommended)](#jquery-ajax-recommended)
8
+ 2. [Vanilla fetch Alternative](#vanilla-fetch-alternative)
9
+ 3. [Error Handling Patterns](#error-handling-patterns)
10
+
11
+ ---
12
+
13
+ ## jQuery AJAX (Recommended)
14
+
15
+ Standard WordPress AJAX pattern with jQuery:
16
+
17
+ ```javascript
18
+ (function($) {
19
+ 'use strict';
20
+
21
+ function submitForm($form, successCallback, errorCallback) {
22
+ $.ajax({
23
+ url: imaAjax.url,
24
+ type: 'POST',
25
+ data: {
26
+ action: 'ima_process_form',
27
+ nonce: imaAjax.nonce,
28
+ form_data: $form.serialize()
29
+ },
30
+ beforeSend: function() {
31
+ $form.find('button[type="submit"]').prop('disabled', true);
32
+ $form.find('.ima-loading').show();
33
+ },
34
+ success: function(response) {
35
+ if (response.success) {
36
+ successCallback(response.data);
37
+ } else {
38
+ errorCallback(response.data || 'Unknown error');
39
+ }
40
+ },
41
+ error: function(xhr, status, error) {
42
+ errorCallback('Network error: ' + error);
43
+ },
44
+ complete: function() {
45
+ $form.find('button[type="submit"]').prop('disabled', false);
46
+ $form.find('.ima-loading').hide();
47
+ }
48
+ });
49
+ }
50
+
51
+ // Usage
52
+ $('.ima-ajax-form').on('submit', function(e) {
53
+ e.preventDefault();
54
+ var $form = $(this);
55
+
56
+ submitForm(
57
+ $form,
58
+ function(data) {
59
+ $form.find('.ima-response').html(data.message).removeClass('error').addClass('success');
60
+ },
61
+ function(error) {
62
+ $form.find('.ima-response').html(error).removeClass('success').addClass('error');
63
+ }
64
+ );
65
+ });
66
+
67
+ })(jQuery);
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Vanilla fetch Alternative
73
+
74
+ Use when building isolated components without WP plugin interaction:
75
+
76
+ ```javascript
77
+ (function() {
78
+ 'use strict';
79
+
80
+ // Pure function - formats data for WordPress AJAX
81
+ function buildFormData(action, nonce, data) {
82
+ var formData = new FormData();
83
+ formData.append('action', action);
84
+ formData.append('nonce', nonce);
85
+
86
+ Object.keys(data).forEach(function(key) {
87
+ formData.append(key, data[key]);
88
+ });
89
+
90
+ return formData;
91
+ }
92
+
93
+ // Wrapper with side effects
94
+ function submitToWordPress(action, data) {
95
+ return fetch(imaAjax.url, {
96
+ method: 'POST',
97
+ credentials: 'same-origin',
98
+ body: buildFormData(action, imaAjax.nonce, data)
99
+ })
100
+ .then(function(response) {
101
+ if (!response.ok) {
102
+ throw new Error('Network response was not ok');
103
+ }
104
+ return response.json();
105
+ })
106
+ .then(function(data) {
107
+ if (!data.success) {
108
+ throw new Error(data.data || 'Unknown error');
109
+ }
110
+ return data.data;
111
+ });
112
+ }
113
+
114
+ // Usage
115
+ document.querySelectorAll('.ima-fetch-form').forEach(function(form) {
116
+ form.addEventListener('submit', function(e) {
117
+ e.preventDefault();
118
+
119
+ var formData = new FormData(form);
120
+ var data = {};
121
+ formData.forEach(function(value, key) {
122
+ data[key] = value;
123
+ });
124
+
125
+ submitToWordPress('ima_process_form', data)
126
+ .then(function(result) {
127
+ form.querySelector('.ima-response').textContent = result.message;
128
+ })
129
+ .catch(function(error) {
130
+ form.querySelector('.ima-response').textContent = error.message;
131
+ });
132
+ });
133
+ });
134
+
135
+ })();
136
+ ```
137
+
138
+ ---
139
+
140
+ ## Error Handling Patterns
141
+
142
+ ### Centralized Error Handler
143
+
144
+ ```javascript
145
+ (function($) {
146
+ 'use strict';
147
+
148
+ var AjaxHandler = {
149
+ handleError: function(error, $container) {
150
+ var message = typeof error === 'string' ? error : 'An error occurred';
151
+ $container.find('.ima-response')
152
+ .html(message)
153
+ .removeClass('success')
154
+ .addClass('error');
155
+ },
156
+
157
+ handleSuccess: function(data, $container) {
158
+ $container.find('.ima-response')
159
+ .html(data.message || 'Success')
160
+ .removeClass('error')
161
+ .addClass('success');
162
+ }
163
+ };
164
+
165
+ window.ImaAjaxHandler = AjaxHandler;
166
+
167
+ })(jQuery);
168
+ ```
169
+
170
+ ### Retry Pattern
171
+
172
+ ```javascript
173
+ function ajaxWithRetry($form, maxRetries) {
174
+ var attempts = 0;
175
+
176
+ function attempt() {
177
+ attempts++;
178
+ return $.ajax({
179
+ url: imaAjax.url,
180
+ type: 'POST',
181
+ data: $form.serialize()
182
+ }).fail(function(xhr, status, error) {
183
+ if (attempts < maxRetries && status === 'timeout') {
184
+ return attempt();
185
+ }
186
+ throw error;
187
+ });
188
+ }
189
+
190
+ return attempt();
191
+ }
192
+ ```
@@ -0,0 +1,136 @@
1
+ # Event Delegation Patterns
2
+
3
+ Event handling patterns for WordPress JavaScript.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [jQuery Event Delegation](#jquery-event-delegation)
8
+ 2. [Vanilla Event Delegation](#vanilla-event-delegation)
9
+ 3. [DOMContentLoaded Patterns](#domcontentloaded-patterns)
10
+
11
+ ---
12
+
13
+ ## jQuery Event Delegation
14
+
15
+ ### Document-Level Delegation
16
+
17
+ For dynamically added elements:
18
+
19
+ ```javascript
20
+ (function($) {
21
+ 'use strict';
22
+
23
+ // Delegated events - works with dynamically added elements
24
+ $(document).on('click', '.ima-toggle-btn', function(e) {
25
+ e.preventDefault();
26
+ var $target = $($(this).data('target'));
27
+ $target.toggleClass('is-visible');
28
+ });
29
+
30
+ })(jQuery);
31
+ ```
32
+
33
+ ### Scoped Delegation (More Efficient)
34
+
35
+ ```javascript
36
+ (function($) {
37
+ 'use strict';
38
+
39
+ // Scoped delegation - better performance
40
+ $('.ima-component').on('click', '.ima-action-btn', function(e) {
41
+ e.preventDefault();
42
+ handleAction($(this).data('action'), $(this).closest('.ima-item'));
43
+ });
44
+
45
+ })(jQuery);
46
+ ```
47
+
48
+ ---
49
+
50
+ ## Vanilla Event Delegation
51
+
52
+ ### Document-Level Pattern
53
+
54
+ ```javascript
55
+ (function() {
56
+ 'use strict';
57
+
58
+ // Delegated events using event bubbling
59
+ document.addEventListener('click', function(e) {
60
+ // Toggle button delegation
61
+ if (e.target.matches('.ima-toggle-btn') || e.target.closest('.ima-toggle-btn')) {
62
+ e.preventDefault();
63
+ var btn = e.target.closest('.ima-toggle-btn');
64
+ var target = document.querySelector(btn.dataset.target);
65
+ if (target) {
66
+ target.classList.toggle('is-visible');
67
+ }
68
+ }
69
+ });
70
+
71
+ })();
72
+ ```
73
+
74
+ ### Scoped Delegation Pattern
75
+
76
+ ```javascript
77
+ (function() {
78
+ 'use strict';
79
+
80
+ // Scoped delegation
81
+ document.querySelectorAll('.ima-component').forEach(function(component) {
82
+ component.addEventListener('click', function(e) {
83
+ var actionBtn = e.target.closest('.ima-action-btn');
84
+ if (actionBtn) {
85
+ e.preventDefault();
86
+ var action = actionBtn.dataset.action;
87
+ var item = actionBtn.closest('.ima-item');
88
+ handleAction(action, item);
89
+ }
90
+ });
91
+ });
92
+
93
+ })();
94
+ ```
95
+
96
+ ---
97
+
98
+ ## DOMContentLoaded Patterns
99
+
100
+ ### jQuery Document Ready
101
+
102
+ ```javascript
103
+ // Standard WordPress pattern
104
+ (function($) {
105
+ $(document).ready(function() {
106
+ // DOM is ready
107
+ initComponents();
108
+ });
109
+ })(jQuery);
110
+
111
+ // Shorthand (equivalent)
112
+ jQuery(function($) {
113
+ initComponents();
114
+ });
115
+ ```
116
+
117
+ ### Vanilla DOMContentLoaded
118
+
119
+ ```javascript
120
+ (function() {
121
+ 'use strict';
122
+
123
+ function init() {
124
+ initComponents();
125
+ }
126
+
127
+ // Handle both loading states
128
+ if (document.readyState === 'loading') {
129
+ document.addEventListener('DOMContentLoaded', init);
130
+ } else {
131
+ // DOM already loaded (script loaded with defer or at bottom)
132
+ init();
133
+ }
134
+
135
+ })();
136
+ ```