@smartsoft001/pro-claude-plugins 0.2.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.
- package/.claude-plugin/marketplace.json +26 -0
- package/README.md +56 -0
- package/package.json +14 -0
- package/plugins/flow/.claude-plugin/README.md +91 -0
- package/plugins/flow/.claude-plugin/merge-permissions.js +115 -0
- package/plugins/flow/.claude-plugin/plugin.json +5 -0
- package/plugins/flow/.claude-plugin/settings.template.json +86 -0
- package/plugins/flow/agents/angular-component-scaffolder.md +176 -0
- package/plugins/flow/agents/angular-directive-builder.md +154 -0
- package/plugins/flow/agents/angular-guard-builder.md +244 -0
- package/plugins/flow/agents/angular-jest-test-writer.md +475 -0
- package/plugins/flow/agents/angular-pipe-builder.md +170 -0
- package/plugins/flow/agents/angular-resolver-builder.md +287 -0
- package/plugins/flow/agents/angular-service-builder.md +162 -0
- package/plugins/flow/agents/angular-signal-state-builder.md +340 -0
- package/plugins/flow/agents/angular-test-diagnostician.md +279 -0
- package/plugins/flow/agents/angular-testbed-configurator.md +315 -0
- package/plugins/flow/agents/arch-scaffolder.md +278 -0
- package/plugins/flow/agents/e2e-data-testid-injector.md +195 -0
- package/plugins/flow/agents/e2e-project-scaffolder.md +194 -0
- package/plugins/flow/agents/e2e-test-writer.md +357 -0
- package/plugins/flow/agents/shared-agent-evolver.md +294 -0
- package/plugins/flow/agents/shared-build-verifier.md +160 -0
- package/plugins/flow/agents/shared-config-updater.md +310 -0
- package/plugins/flow/agents/shared-coverage-enforcer.md +184 -0
- package/plugins/flow/agents/shared-error-handler.md +217 -0
- package/plugins/flow/agents/shared-file-creator.md +344 -0
- package/plugins/flow/agents/shared-impl-orchestrator.md +312 -0
- package/plugins/flow/agents/shared-impl-reporter.md +368 -0
- package/plugins/flow/agents/shared-impl-teammate.md +201 -0
- package/plugins/flow/agents/shared-linear-subtask-iterator.md +337 -0
- package/plugins/flow/agents/shared-logic-implementer.md +244 -0
- package/plugins/flow/agents/shared-maia-api.md +26 -0
- package/plugins/flow/agents/shared-parallelization-analyzer.md +343 -0
- package/plugins/flow/agents/shared-performance-validator.md +168 -0
- package/plugins/flow/agents/shared-plan-perspective.md +271 -0
- package/plugins/flow/agents/shared-project-standardizer.md +205 -0
- package/plugins/flow/agents/shared-report-synthesizer.md +188 -0
- package/plugins/flow/agents/shared-review-teammate.md +189 -0
- package/plugins/flow/agents/shared-security-scanner.md +186 -0
- package/plugins/flow/agents/shared-style-enforcer.md +230 -0
- package/plugins/flow/agents/shared-subtask-dependency-analyzer.md +189 -0
- package/plugins/flow/agents/shared-tdd-developer.md +350 -0
- package/plugins/flow/agents/shared-team-coordinator.md +192 -0
- package/plugins/flow/agents/shared-test-fixer.md +186 -0
- package/plugins/flow/agents/shared-test-runner.md +191 -0
- package/plugins/flow/agents/shared-ui-classifier.md +263 -0
- package/plugins/flow/agents/shared-verification-orchestrator.md +194 -0
- package/plugins/flow/agents/shared-verification-runner.md +140 -0
- package/plugins/flow/agents/ui-a11y-validator.md +305 -0
- package/plugins/flow/agents/ui-screenshot-reporter.md +329 -0
- package/plugins/flow/agents/ui-web-designer.md +214 -0
- package/plugins/flow/scripts/compute-session-tokens.sh +39 -0
- package/plugins/flow/skills/a11y-audit/SKILL.md +214 -0
- package/plugins/flow/skills/angular-patterns/SKILL.md +191 -0
- package/plugins/flow/skills/browser-capture/SKILL.md +238 -0
- package/plugins/flow/skills/commit/SKILL.md +259 -0
- package/plugins/flow/skills/debug-helper/SKILL.md +375 -0
- package/plugins/flow/skills/impl/SKILL.md +992 -0
- package/plugins/flow/skills/karpathy-guidelines/SKILL.md +72 -0
- package/plugins/flow/skills/linear-suggestion/SKILL.md +132 -0
- package/plugins/flow/skills/maia-files-delete/SKILL.md +59 -0
- package/plugins/flow/skills/maia-files-upload/SKILL.md +57 -0
- package/plugins/flow/skills/nx-conventions/SKILL.md +326 -0
- package/plugins/flow/skills/plan/SKILL.md +1033 -0
- package/plugins/flow/skills/push/SKILL.md +759 -0
- package/plugins/flow/skills/review/SKILL.md +443 -0
- package/plugins/flow/skills/test-e2e/SKILL.md +164 -0
- package/plugins/flow/skills/test-unit/SKILL.md +456 -0
- package/plugins/flow-external/.claude-plugin/README.md +146 -0
- package/plugins/flow-external/.claude-plugin/merge-permissions.js +94 -0
- package/plugins/flow-external/.claude-plugin/plugin.json +5 -0
- package/plugins/flow-external/.claude-plugin/settings.template.json +78 -0
- package/plugins/flow-external/agents/angular-component-scaffolder.md +271 -0
- package/plugins/flow-external/agents/angular-directive-builder.md +134 -0
- package/plugins/flow-external/agents/angular-guard-builder.md +73 -0
- package/plugins/flow-external/agents/angular-pipe-builder.md +90 -0
- package/plugins/flow-external/agents/angular-resolver-builder.md +79 -0
- package/plugins/flow-external/agents/angular-service-builder.md +168 -0
- package/plugins/flow-external/agents/angular-state-builder.md +263 -0
- package/plugins/flow-external/agents/shared-build-verifier.md +67 -0
- package/plugins/flow-external/agents/shared-impl-orchestrator.md +90 -0
- package/plugins/flow-external/agents/shared-impl-reporter.md +135 -0
- package/plugins/flow-external/agents/shared-linear-subtask-iterator.md +70 -0
- package/plugins/flow-external/agents/shared-ui-classifier.md +38 -0
- package/plugins/flow-external/agents/ui-web-designer.md +203 -0
- package/plugins/flow-external/scripts/compute-session-tokens.sh +39 -0
- package/plugins/flow-external/skills/a11y-audit/SKILL.md +97 -0
- package/plugins/flow-external/skills/angular-cli-conventions/SKILL.md +268 -0
- package/plugins/flow-external/skills/angular-patterns/SKILL.md +182 -0
- package/plugins/flow-external/skills/browser-capture/SKILL.md +74 -0
- package/plugins/flow-external/skills/commit/SKILL.md +114 -0
- package/plugins/flow-external/skills/debug-helper/SKILL.md +135 -0
- package/plugins/flow-external/skills/impl/SKILL.md +218 -0
- package/plugins/flow-external/skills/karpathy-guidelines/SKILL.md +72 -0
- package/plugins/flow-external/skills/linear-suggestion/SKILL.md +62 -0
- package/plugins/flow-external/skills/maia-files-delete/SKILL.md +34 -0
- package/plugins/flow-external/skills/maia-files-upload/SKILL.md +41 -0
- package/plugins/flow-external/skills/plan/SKILL.md +334 -0
- package/plugins/flow-external/skills/push/SKILL.md +232 -0
- package/plugins/flow-legacy/.claude-plugin/README.md +143 -0
- package/plugins/flow-legacy/.claude-plugin/merge-permissions.js +94 -0
- package/plugins/flow-legacy/.claude-plugin/plugin.json +5 -0
- package/plugins/flow-legacy/.claude-plugin/settings.template.json +79 -0
- package/plugins/flow-legacy/agents/angular-component-scaffolder.md +327 -0
- package/plugins/flow-legacy/agents/angular-directive-builder.md +253 -0
- package/plugins/flow-legacy/agents/angular-guard-builder.md +326 -0
- package/plugins/flow-legacy/agents/angular-pipe-builder.md +238 -0
- package/plugins/flow-legacy/agents/angular-resolver-builder.md +339 -0
- package/plugins/flow-legacy/agents/angular-service-builder.md +271 -0
- package/plugins/flow-legacy/agents/angular-state-builder.md +480 -0
- package/plugins/flow-legacy/agents/shared-impl-orchestrator.md +174 -0
- package/plugins/flow-legacy/agents/shared-impl-reporter.md +232 -0
- package/plugins/flow-legacy/agents/shared-linear-subtask-iterator.md +198 -0
- package/plugins/flow-legacy/agents/shared-tdd-developer.md +307 -0
- package/plugins/flow-legacy/agents/shared-test-runner.md +133 -0
- package/plugins/flow-legacy/agents/shared-ui-classifier.md +145 -0
- package/plugins/flow-legacy/scripts/compute-session-tokens.sh +39 -0
- package/plugins/flow-legacy/skills/a11y-audit/SKILL.md +214 -0
- package/plugins/flow-legacy/skills/angular-patterns/SKILL.md +346 -0
- package/plugins/flow-legacy/skills/browser-capture/SKILL.md +238 -0
- package/plugins/flow-legacy/skills/commit/SKILL.md +215 -0
- package/plugins/flow-legacy/skills/debug-helper/SKILL.md +395 -0
- package/plugins/flow-legacy/skills/impl/SKILL.md +710 -0
- package/plugins/flow-legacy/skills/karpathy-guidelines/SKILL.md +72 -0
- package/plugins/flow-legacy/skills/linear-suggestion/SKILL.md +132 -0
- package/plugins/flow-legacy/skills/maia-files-delete/SKILL.md +59 -0
- package/plugins/flow-legacy/skills/maia-files-upload/SKILL.md +57 -0
- package/plugins/flow-legacy/skills/nx-conventions/SKILL.md +368 -0
- package/plugins/flow-legacy/skills/plan/SKILL.md +742 -0
- package/plugins/flow-legacy/skills/push/SKILL.md +645 -0
- package/plugins/flow-legacy/skills/test-unit/SKILL.md +500 -0
- package/plugins/smart-pro/.claude-plugin/README.md +115 -0
- package/plugins/smart-pro/.claude-plugin/merge-permissions.js +129 -0
- package/plugins/smart-pro/.claude-plugin/plugin.json +5 -0
- package/plugins/smart-pro/.claude-plugin/settings.template.json +94 -0
- package/plugins/smart-pro/agents/angular-components/AGENT.md +214 -0
- package/plugins/smart-pro/hooks/CONFIG.md +198 -0
- package/plugins/smart-pro/hooks/README.md +139 -0
- package/plugins/smart-pro/hooks/audit_logger.py +107 -0
- package/plugins/smart-pro/hooks/auto_format.sh +11 -0
- package/plugins/smart-pro/hooks/hooks.json +79 -0
- package/plugins/smart-pro/hooks/safety_validator.py +129 -0
- package/plugins/smart-pro/hooks/sensitive_file_blocker.py +58 -0
- package/plugins/smart-pro/hooks/skill_validator.py +220 -0
- package/plugins/smart-pro/skills/angular-components-action-panel/SKILL.md +159 -0
- package/plugins/smart-pro/skills/angular-components-avatar/SKILL.md +142 -0
- package/plugins/smart-pro/skills/angular-components-badge/SKILL.md +110 -0
- package/plugins/smart-pro/skills/angular-components-breadcrumbs/SKILL.md +91 -0
- package/plugins/smart-pro/skills/angular-components-button/SKILL.md +146 -0
- package/plugins/smart-pro/skills/angular-components-button-group/SKILL.md +121 -0
- package/plugins/smart-pro/skills/angular-components-calendar/SKILL.md +78 -0
- package/plugins/smart-pro/skills/angular-components-card/SKILL.md +110 -0
- package/plugins/smart-pro/skills/angular-components-card-heading/SKILL.md +105 -0
- package/plugins/smart-pro/skills/angular-components-command-palette/SKILL.md +168 -0
- package/plugins/smart-pro/skills/angular-components-container/SKILL.md +93 -0
- package/plugins/smart-pro/skills/angular-components-description-list/SKILL.md +102 -0
- package/plugins/smart-pro/skills/angular-components-details/SKILL.md +70 -0
- package/plugins/smart-pro/skills/angular-components-divider/SKILL.md +110 -0
- package/plugins/smart-pro/skills/angular-components-drawer/SKILL.md +136 -0
- package/plugins/smart-pro/skills/angular-components-dropdown/SKILL.md +131 -0
- package/plugins/smart-pro/skills/angular-components-empty-state/SKILL.md +103 -0
- package/plugins/smart-pro/skills/angular-components-feed/SKILL.md +110 -0
- package/plugins/smart-pro/skills/angular-components-form/SKILL.md +77 -0
- package/plugins/smart-pro/skills/angular-components-grid-list/SKILL.md +91 -0
- package/plugins/smart-pro/skills/angular-components-input/SKILL.md +118 -0
- package/plugins/smart-pro/skills/angular-components-list/SKILL.md +75 -0
- package/plugins/smart-pro/skills/angular-components-list-container/SKILL.md +106 -0
- package/plugins/smart-pro/skills/angular-components-media-object/SKILL.md +133 -0
- package/plugins/smart-pro/skills/angular-components-modal/SKILL.md +159 -0
- package/plugins/smart-pro/skills/angular-components-multi-column-layout/SKILL.md +84 -0
- package/plugins/smart-pro/skills/angular-components-navbar/SKILL.md +93 -0
- package/plugins/smart-pro/skills/angular-components-notification/SKILL.md +147 -0
- package/plugins/smart-pro/skills/angular-components-page/SKILL.md +162 -0
- package/plugins/smart-pro/skills/angular-components-page-heading/SKILL.md +96 -0
- package/plugins/smart-pro/skills/angular-components-paging/SKILL.md +86 -0
- package/plugins/smart-pro/skills/angular-components-progress-bars/SKILL.md +94 -0
- package/plugins/smart-pro/skills/angular-components-searchbar/SKILL.md +113 -0
- package/plugins/smart-pro/skills/angular-components-section-heading/SKILL.md +156 -0
- package/plugins/smart-pro/skills/angular-components-select-menu/SKILL.md +101 -0
- package/plugins/smart-pro/skills/angular-components-sidebar-layout/SKILL.md +121 -0
- package/plugins/smart-pro/skills/angular-components-sidebar-navigation/SKILL.md +80 -0
- package/plugins/smart-pro/skills/angular-components-sign-in-form/SKILL.md +91 -0
- package/plugins/smart-pro/skills/angular-components-stacked-layout/SKILL.md +114 -0
- package/plugins/smart-pro/skills/angular-components-stacked-list/SKILL.md +93 -0
- package/plugins/smart-pro/skills/angular-components-stats/SKILL.md +87 -0
- package/plugins/smart-pro/skills/angular-components-table/SKILL.md +98 -0
- package/plugins/smart-pro/skills/angular-components-tabs/SKILL.md +99 -0
- package/plugins/smart-pro/skills/angular-components-textarea/SKILL.md +111 -0
- package/plugins/smart-pro/skills/angular-components-toggle/SKILL.md +109 -0
- package/plugins/smart-pro/skills/angular-components-vertical-navigation/SKILL.md +139 -0
- package/plugins/smart-pro/skills/audit-log/SKILL.md +82 -0
- package/plugins/smart-pro/skills/format-code/SKILL.md +46 -0
- package/plugins/smart-pro/skills/project-conventions/SKILL.md +90 -0
- package/plugins/smart-pro/skills/safety-check/SKILL.md +0 -0
- package/src/index.d.ts +6 -0
- package/src/index.js +7 -0
- package/src/index.js.map +1 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: a11y-audit
|
|
3
|
+
description: Run accessibility audits on web pages. Ensures dev server is running, navigates to pages, captures accessibility snapshots, and runs axe-core tests.
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Bash
|
|
6
|
+
- Read
|
|
7
|
+
- Glob
|
|
8
|
+
- mcp__playwright__browser_navigate
|
|
9
|
+
- mcp__playwright__browser_snapshot
|
|
10
|
+
- mcp__playwright__browser_evaluate
|
|
11
|
+
- mcp__playwright__browser_close
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Accessibility Audit Skill
|
|
15
|
+
|
|
16
|
+
Run accessibility audits on web pages using Playwright and axe-core. Automatically ensures the development server is running before auditing.
|
|
17
|
+
|
|
18
|
+
## Capabilities
|
|
19
|
+
|
|
20
|
+
1. **Server Management**: Check if dev server is running, start if needed
|
|
21
|
+
2. **Page Navigation**: Navigate to specified URLs using Playwright
|
|
22
|
+
3. **Accessibility Snapshot**: Capture accessibility tree for analysis
|
|
23
|
+
4. **Axe-core Testing**: Run automated accessibility tests
|
|
24
|
+
|
|
25
|
+
## Server Management
|
|
26
|
+
|
|
27
|
+
### Read Port Configuration
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Default port location (Nx 14 / Angular 14 project)
|
|
31
|
+
grep -o '"port":[^,}]*' apps/web/project.json | head -1
|
|
32
|
+
# Default: 4200
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Check if Server is Running
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
lsof -i :4200 -t
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- If returns PID -> server is running
|
|
42
|
+
- If returns nothing -> server needs to be started
|
|
43
|
+
|
|
44
|
+
### Start Server if Needed
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Start in background (Nx 14 / @nrwl)
|
|
48
|
+
npm start &
|
|
49
|
+
|
|
50
|
+
# Wait for server to be ready
|
|
51
|
+
for i in {1..15}; do
|
|
52
|
+
curl -s http://localhost:4200 > /dev/null && break
|
|
53
|
+
sleep 2
|
|
54
|
+
done
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Audit Process
|
|
58
|
+
|
|
59
|
+
### 1. Ensure Server is Running
|
|
60
|
+
|
|
61
|
+
Before any audit:
|
|
62
|
+
|
|
63
|
+
1. Read port from `apps/web/project.json` (default: 4200)
|
|
64
|
+
2. Check if port is occupied: `lsof -i :PORT -t`
|
|
65
|
+
3. If not running: `npm start &` and wait ~15 seconds
|
|
66
|
+
|
|
67
|
+
### 2. Navigate to Page
|
|
68
|
+
|
|
69
|
+
Use `mcp__playwright__browser_navigate` to open the target URL.
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
URL format: http://localhost:{port}/{path}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 3. Capture Accessibility Snapshot
|
|
76
|
+
|
|
77
|
+
Use `mcp__playwright__browser_snapshot` to get the accessibility tree.
|
|
78
|
+
|
|
79
|
+
This provides:
|
|
80
|
+
|
|
81
|
+
- Element roles and names
|
|
82
|
+
- ARIA attributes
|
|
83
|
+
- Focus states
|
|
84
|
+
- Interactive element information
|
|
85
|
+
|
|
86
|
+
### 4. Run Axe-core Audit
|
|
87
|
+
|
|
88
|
+
Use `mcp__playwright__browser_evaluate` to inject and run axe-core:
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
// Example evaluation code
|
|
92
|
+
async () => {
|
|
93
|
+
// Load axe-core from CDN
|
|
94
|
+
const script = document.createElement('script');
|
|
95
|
+
script.src =
|
|
96
|
+
'https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.8.2/axe.min.js';
|
|
97
|
+
document.head.appendChild(script);
|
|
98
|
+
|
|
99
|
+
await new Promise((resolve) => (script.onload = resolve));
|
|
100
|
+
|
|
101
|
+
// Run audit
|
|
102
|
+
const results = await axe.run();
|
|
103
|
+
return {
|
|
104
|
+
violations: results.violations,
|
|
105
|
+
passes: results.passes.length,
|
|
106
|
+
incomplete: results.incomplete,
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Usage Examples
|
|
112
|
+
|
|
113
|
+
### Full Page Audit
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
Input: { path: "/articles" }
|
|
117
|
+
|
|
118
|
+
Process:
|
|
119
|
+
1. Check server running on port 4200
|
|
120
|
+
2. Start if needed, wait for ready
|
|
121
|
+
3. Navigate to http://localhost:4200/articles
|
|
122
|
+
4. Capture accessibility snapshot
|
|
123
|
+
5. Run axe-core audit
|
|
124
|
+
6. Return violations and recommendations
|
|
125
|
+
|
|
126
|
+
Output:
|
|
127
|
+
{
|
|
128
|
+
"url": "http://localhost:4200/articles",
|
|
129
|
+
"snapshot": { ... accessibility tree ... },
|
|
130
|
+
"violations": [
|
|
131
|
+
{
|
|
132
|
+
"id": "image-alt",
|
|
133
|
+
"impact": "critical",
|
|
134
|
+
"description": "Images must have alternate text",
|
|
135
|
+
"nodes": [...]
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
"passes": 45,
|
|
139
|
+
"incomplete": 2
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Quick Check
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
Input: { path: "/", snapshotOnly: true }
|
|
147
|
+
|
|
148
|
+
Output:
|
|
149
|
+
{
|
|
150
|
+
"url": "http://localhost:4200/",
|
|
151
|
+
"snapshot": { ... accessibility tree ... }
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Report Format
|
|
156
|
+
|
|
157
|
+
When generating reports, use this structure:
|
|
158
|
+
|
|
159
|
+
```markdown
|
|
160
|
+
## Accessibility Audit Report
|
|
161
|
+
|
|
162
|
+
**Page**: [URL]
|
|
163
|
+
**Date**: [Date]
|
|
164
|
+
**Standard**: WCAG 2.1 Level AA
|
|
165
|
+
|
|
166
|
+
### Critical Issues (Must Fix)
|
|
167
|
+
|
|
168
|
+
| Issue | Elements | WCAG | Fix |
|
|
169
|
+
| ----------- | -------- | ----- | ------------------------ |
|
|
170
|
+
| Missing alt | 3 images | 1.1.1 | Add descriptive alt text |
|
|
171
|
+
|
|
172
|
+
### Serious Issues (Should Fix)
|
|
173
|
+
|
|
174
|
+
| Issue | Elements | WCAG | Fix |
|
|
175
|
+
| ------------ | ---------- | ----- | ---------------- |
|
|
176
|
+
| Low contrast | 2 elements | 1.4.3 | Use darker color |
|
|
177
|
+
|
|
178
|
+
### Passed Checks
|
|
179
|
+
|
|
180
|
+
- [x] Page has lang attribute
|
|
181
|
+
- [x] Headings in correct order
|
|
182
|
+
- [x] Form inputs have labels
|
|
183
|
+
|
|
184
|
+
### Summary
|
|
185
|
+
|
|
186
|
+
- Violations: X critical, Y serious, Z minor
|
|
187
|
+
- Passed: N checks
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Error Handling
|
|
191
|
+
|
|
192
|
+
### Server Won't Start
|
|
193
|
+
|
|
194
|
+
If server fails to start after 30 seconds:
|
|
195
|
+
|
|
196
|
+
1. Check for port conflicts
|
|
197
|
+
2. Check npm logs for errors
|
|
198
|
+
3. Report error and skip audit
|
|
199
|
+
|
|
200
|
+
### Axe-core Load Fails
|
|
201
|
+
|
|
202
|
+
If axe-core fails to load:
|
|
203
|
+
|
|
204
|
+
1. Check network connectivity
|
|
205
|
+
2. Try alternative CDN
|
|
206
|
+
3. Fall back to snapshot-only audit
|
|
207
|
+
|
|
208
|
+
### Navigation Fails
|
|
209
|
+
|
|
210
|
+
If page doesn't load:
|
|
211
|
+
|
|
212
|
+
1. Verify URL is correct
|
|
213
|
+
2. Check for JavaScript errors
|
|
214
|
+
3. Report partial results
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: angular-patterns
|
|
3
|
+
description: Angular 14 legacy patterns including *ngIf/*ngFor directives, constructor DI, and @Input/@Output decorators
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Angular 14 Legacy Patterns
|
|
7
|
+
|
|
8
|
+
This skill provides guidance on Angular 14 patterns for legacy projects.
|
|
9
|
+
|
|
10
|
+
## CRITICAL: Use Legacy Patterns ONLY
|
|
11
|
+
|
|
12
|
+
**DO NOT use modern Angular features (Angular 16+):**
|
|
13
|
+
|
|
14
|
+
| Feature | CORRECT (Angular 14) | WRONG (Modern) |
|
|
15
|
+
| ------------ | ------------------------------- | ------------------------ |
|
|
16
|
+
| Control flow | `*ngIf`, `*ngFor`, `[ngSwitch]` | `@if`, `@for`, `@switch` |
|
|
17
|
+
| DI | Constructor injection | `inject()` |
|
|
18
|
+
| Inputs | `@Input()` decorator | `input()` function |
|
|
19
|
+
| Outputs | `@Output()` decorator | `output()` function |
|
|
20
|
+
| Two-way | `@Input()` + `@Output()` | `model()` |
|
|
21
|
+
| State | BehaviorSubject, Observable | signals, `signal()` |
|
|
22
|
+
| Derived | `pipe(map())` | `computed()` |
|
|
23
|
+
| Side effects | `subscribe()` | `effect()` |
|
|
24
|
+
| Components | NgModule-based | standalone |
|
|
25
|
+
|
|
26
|
+
## 1. Control Flow Syntax (`*ngIf`, `*ngFor`, `[ngSwitch]`)
|
|
27
|
+
|
|
28
|
+
### Conditional Rendering
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<!-- *ngIf with else -->
|
|
32
|
+
<div *ngIf="isLoading; else loadedContent">
|
|
33
|
+
<app-spinner></app-spinner>
|
|
34
|
+
</div>
|
|
35
|
+
<ng-template #loadedContent>
|
|
36
|
+
<div *ngIf="error; else dataContent">
|
|
37
|
+
<app-error [message]="error?.message"></app-error>
|
|
38
|
+
</div>
|
|
39
|
+
</ng-template>
|
|
40
|
+
<ng-template #dataContent>
|
|
41
|
+
<ul>
|
|
42
|
+
<li *ngFor="let item of items; trackBy: trackById">{{ item.name }}</li>
|
|
43
|
+
</ul>
|
|
44
|
+
<p *ngIf="items.length === 0">No data</p>
|
|
45
|
+
</ng-template>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Iteration
|
|
49
|
+
|
|
50
|
+
```html
|
|
51
|
+
<!-- *ngFor with index and trackBy -->
|
|
52
|
+
<ul>
|
|
53
|
+
<li *ngFor="let item of items; let i = index; trackBy: trackById">
|
|
54
|
+
{{ i + 1 }}. {{ item.name }}
|
|
55
|
+
</li>
|
|
56
|
+
</ul>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// trackBy function in component
|
|
61
|
+
trackById(index: number, item: Item): string {
|
|
62
|
+
return item.id;
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Switch Statement
|
|
67
|
+
|
|
68
|
+
```html
|
|
69
|
+
<div [ngSwitch]="status">
|
|
70
|
+
<span *ngSwitchCase="'pending'" class="text-yellow-500">Pending</span>
|
|
71
|
+
<span *ngSwitchCase="'active'" class="text-green-500">Active</span>
|
|
72
|
+
<span *ngSwitchDefault class="text-gray-500">Unknown</span>
|
|
73
|
+
</div>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 2. BehaviorSubject for State Management
|
|
77
|
+
|
|
78
|
+
### When to Use
|
|
79
|
+
|
|
80
|
+
| Pattern | Use Case |
|
|
81
|
+
| ------------------ | --------------------------------------- |
|
|
82
|
+
| `BehaviorSubject` | Local, mutable state with initial value |
|
|
83
|
+
| `ReplaySubject(1)` | State without initial value |
|
|
84
|
+
| `pipe(map())` | Derived/computed values |
|
|
85
|
+
| `combineLatest` | Combine multiple observables |
|
|
86
|
+
|
|
87
|
+
### BehaviorSubject Examples
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { BehaviorSubject } from 'rxjs';
|
|
91
|
+
import { map } from 'rxjs/operators';
|
|
92
|
+
|
|
93
|
+
@Injectable({
|
|
94
|
+
providedIn: 'root',
|
|
95
|
+
})
|
|
96
|
+
export class StateService {
|
|
97
|
+
// Private BehaviorSubject
|
|
98
|
+
private readonly _items = new BehaviorSubject<Item[]>([]);
|
|
99
|
+
private readonly _isLoading = new BehaviorSubject<boolean>(false);
|
|
100
|
+
private readonly _filter = new BehaviorSubject<string>('');
|
|
101
|
+
|
|
102
|
+
// Public Observable (read-only)
|
|
103
|
+
readonly items$ = this._items.asObservable();
|
|
104
|
+
readonly isLoading$ = this._isLoading.asObservable();
|
|
105
|
+
readonly filter$ = this._filter.asObservable();
|
|
106
|
+
|
|
107
|
+
// Derived state using pipe(map())
|
|
108
|
+
readonly filtered$ = combineLatest([this._items, this._filter]).pipe(
|
|
109
|
+
map(([items, filter]) => {
|
|
110
|
+
const f = filter.toLowerCase();
|
|
111
|
+
return items.filter((i) => i.name.toLowerCase().includes(f));
|
|
112
|
+
}),
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
readonly count$ = this._items.pipe(map((items) => items.length));
|
|
116
|
+
|
|
117
|
+
// Methods to update state
|
|
118
|
+
setItems(items: Item[]): void {
|
|
119
|
+
this._items.next(items);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
setLoading(loading: boolean): void {
|
|
123
|
+
this._isLoading.next(loading);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
setFilter(filter: string): void {
|
|
127
|
+
this._filter.next(filter);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Get current value
|
|
131
|
+
get currentItems(): Item[] {
|
|
132
|
+
return this._items.getValue();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## 3. Dependency Injection via Constructor
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import { Component, OnInit, OnDestroy } from '@angular/core';
|
|
141
|
+
import { Subject } from 'rxjs';
|
|
142
|
+
import { takeUntil } from 'rxjs/operators';
|
|
143
|
+
|
|
144
|
+
@Component({
|
|
145
|
+
selector: 'app-my-component',
|
|
146
|
+
templateUrl: './my-component.component.html',
|
|
147
|
+
styleUrls: ['./my-component.component.scss'],
|
|
148
|
+
})
|
|
149
|
+
export class MyComponent implements OnInit, OnDestroy {
|
|
150
|
+
items: Item[] = [];
|
|
151
|
+
|
|
152
|
+
private readonly destroy$ = new Subject<void>();
|
|
153
|
+
|
|
154
|
+
// Constructor injection (NOT inject())
|
|
155
|
+
constructor(
|
|
156
|
+
private readonly http: HttpClient,
|
|
157
|
+
private readonly router: Router,
|
|
158
|
+
private readonly myService: MyService,
|
|
159
|
+
@Optional() private readonly optionalService: OptionalService,
|
|
160
|
+
) {}
|
|
161
|
+
|
|
162
|
+
ngOnInit(): void {
|
|
163
|
+
this.myService.items$.pipe(takeUntil(this.destroy$)).subscribe((items) => {
|
|
164
|
+
this.items = items;
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
ngOnDestroy(): void {
|
|
169
|
+
this.destroy$.next();
|
|
170
|
+
this.destroy$.complete();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Rules
|
|
176
|
+
|
|
177
|
+
- Place dependencies in constructor
|
|
178
|
+
- Use `private readonly` for services
|
|
179
|
+
- Use `@Optional()` for optional dependencies
|
|
180
|
+
- Always implement `OnDestroy` with `takeUntil` pattern
|
|
181
|
+
|
|
182
|
+
## 4. Input/Output APIs: `@Input()`, `@Output()`, `EventEmitter`
|
|
183
|
+
|
|
184
|
+
### Decorator Patterns
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
import {
|
|
188
|
+
Component,
|
|
189
|
+
Input,
|
|
190
|
+
Output,
|
|
191
|
+
EventEmitter,
|
|
192
|
+
OnChanges,
|
|
193
|
+
SimpleChanges,
|
|
194
|
+
} from '@angular/core';
|
|
195
|
+
|
|
196
|
+
@Component({
|
|
197
|
+
selector: 'app-form-field',
|
|
198
|
+
templateUrl: './form-field.component.html',
|
|
199
|
+
})
|
|
200
|
+
export class FormFieldComponent implements OnChanges {
|
|
201
|
+
// Required input (validate in ngOnChanges)
|
|
202
|
+
@Input() label!: string;
|
|
203
|
+
|
|
204
|
+
// Optional input with default
|
|
205
|
+
@Input() disabled = false;
|
|
206
|
+
|
|
207
|
+
// Input with setter for transformation
|
|
208
|
+
@Input()
|
|
209
|
+
set count(value: string | number) {
|
|
210
|
+
this._count = typeof value === 'string' ? parseInt(value, 10) : value;
|
|
211
|
+
}
|
|
212
|
+
get count(): number {
|
|
213
|
+
return this._count;
|
|
214
|
+
}
|
|
215
|
+
private _count = 0;
|
|
216
|
+
|
|
217
|
+
// Output event
|
|
218
|
+
@Output() changed = new EventEmitter<string>();
|
|
219
|
+
|
|
220
|
+
// Two-way binding (banana-in-a-box)
|
|
221
|
+
@Input() value = '';
|
|
222
|
+
@Output() valueChange = new EventEmitter<string>();
|
|
223
|
+
|
|
224
|
+
ngOnChanges(changes: SimpleChanges): void {
|
|
225
|
+
if (changes['label'] && !this.label) {
|
|
226
|
+
throw new Error('label is required');
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
onInputChange(newValue: string): void {
|
|
231
|
+
this.value = newValue;
|
|
232
|
+
this.valueChange.emit(newValue);
|
|
233
|
+
this.changed.emit(newValue);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Usage in Templates
|
|
239
|
+
|
|
240
|
+
```html
|
|
241
|
+
<!-- Parent template -->
|
|
242
|
+
<app-form-field
|
|
243
|
+
label="Name"
|
|
244
|
+
[disabled]="isDisabled"
|
|
245
|
+
[(value)]="name"
|
|
246
|
+
(changed)="onChanged($event)"
|
|
247
|
+
></app-form-field>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## 5. NgModule-based Components
|
|
251
|
+
|
|
252
|
+
All components must be declared in a module:
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
// feature.module.ts
|
|
256
|
+
import { NgModule } from '@angular/core';
|
|
257
|
+
import { CommonModule } from '@angular/common';
|
|
258
|
+
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
259
|
+
|
|
260
|
+
import { FeatureComponent } from './feature.component';
|
|
261
|
+
import { FeatureListComponent } from './feature-list/feature-list.component';
|
|
262
|
+
import { FeatureItemComponent } from './feature-item/feature-item.component';
|
|
263
|
+
import { SharedModule } from '@shared/shared.module';
|
|
264
|
+
|
|
265
|
+
@NgModule({
|
|
266
|
+
declarations: [FeatureComponent, FeatureListComponent, FeatureItemComponent],
|
|
267
|
+
imports: [CommonModule, FormsModule, ReactiveFormsModule, SharedModule],
|
|
268
|
+
exports: [FeatureComponent],
|
|
269
|
+
})
|
|
270
|
+
export class FeatureModule {}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
// feature.component.ts
|
|
275
|
+
@Component({
|
|
276
|
+
selector: 'app-feature',
|
|
277
|
+
templateUrl: './feature.component.html',
|
|
278
|
+
styleUrls: ['./feature.component.scss'],
|
|
279
|
+
})
|
|
280
|
+
export class FeatureComponent implements OnInit, OnDestroy {
|
|
281
|
+
// ... component logic
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## 6. Async Pipe Usage
|
|
286
|
+
|
|
287
|
+
Always prefer `async` pipe over manual subscriptions in templates:
|
|
288
|
+
|
|
289
|
+
```html
|
|
290
|
+
<!-- Using async pipe -->
|
|
291
|
+
<div *ngIf="isLoading$ | async; else content">
|
|
292
|
+
<app-spinner></app-spinner>
|
|
293
|
+
</div>
|
|
294
|
+
<ng-template #content>
|
|
295
|
+
<ul>
|
|
296
|
+
<li *ngFor="let item of items$ | async; trackBy: trackById">
|
|
297
|
+
{{ item.name }}
|
|
298
|
+
</li>
|
|
299
|
+
</ul>
|
|
300
|
+
</ng-template>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
@Component({...})
|
|
305
|
+
export class ListComponent {
|
|
306
|
+
readonly isLoading$ = this.stateService.isLoading$;
|
|
307
|
+
readonly items$ = this.stateService.items$;
|
|
308
|
+
|
|
309
|
+
constructor(private readonly stateService: StateService) {}
|
|
310
|
+
|
|
311
|
+
trackById(index: number, item: Item): string {
|
|
312
|
+
return item.id;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## 7. Performance Guidelines
|
|
318
|
+
|
|
319
|
+
- Every `*ngFor` must have a `trackBy` function
|
|
320
|
+
- Extract complex logic from templates to component methods
|
|
321
|
+
- Use `OnPush` change detection when appropriate
|
|
322
|
+
- Avoid function calls in templates (use getters or properties)
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
@Component({
|
|
326
|
+
selector: 'app-optimized',
|
|
327
|
+
templateUrl: './optimized.component.html',
|
|
328
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
329
|
+
})
|
|
330
|
+
export class OptimizedComponent {
|
|
331
|
+
// ...
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## 8. PR Checklist (Angular 14 Legacy)
|
|
336
|
+
|
|
337
|
+
- [ ] Using `*ngIf`/`*ngFor` (NOT `@if`/`@for`)
|
|
338
|
+
- [ ] Using `[ngSwitch]` (NOT `@switch`)
|
|
339
|
+
- [ ] Every `*ngFor` has `trackBy` function
|
|
340
|
+
- [ ] Using constructor DI (NOT `inject()`)
|
|
341
|
+
- [ ] Using `@Input()`/`@Output()` decorators (NOT `input()`/`output()`)
|
|
342
|
+
- [ ] Using BehaviorSubject for state (NOT signals)
|
|
343
|
+
- [ ] Using `pipe(map())` for derived state (NOT `computed()`)
|
|
344
|
+
- [ ] Component declared in NgModule (NOT standalone)
|
|
345
|
+
- [ ] Using `async` pipe in templates
|
|
346
|
+
- [ ] Implementing `OnDestroy` with `takeUntil` pattern
|