@patternfly/context-for-ai 1.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/README.md +615 -0
- package/codemod/ALL_COMPONENTS_REFERENCE.md +815 -0
- package/codemod/ATTRIBUTE_DECISION_LOGIC.md +320 -0
- package/codemod/README.md +400 -0
- package/codemod/add-semantic-attributes.sh +69 -0
- package/codemod/component-attributes-reference.json +129 -0
- package/codemod/example-after.tsx +51 -0
- package/codemod/example-before.tsx +19 -0
- package/codemod/static-inference.js +5015 -0
- package/codemod/transform.js +1108 -0
- package/dist/components/advanced/index.d.ts +2 -0
- package/dist/components/advanced/index.d.ts.map +1 -0
- package/dist/components/core/Button.d.ts +14 -0
- package/dist/components/core/Button.d.ts.map +1 -0
- package/dist/components/core/Link.d.ts +15 -0
- package/dist/components/core/Link.d.ts.map +1 -0
- package/dist/components/core/StarIcon.d.ts +15 -0
- package/dist/components/core/StarIcon.d.ts.map +1 -0
- package/dist/components/core/index.d.ts +4 -0
- package/dist/components/core/index.d.ts.map +1 -0
- package/dist/components/data-display/Card.d.ts +14 -0
- package/dist/components/data-display/Card.d.ts.map +1 -0
- package/dist/components/data-display/StatusBadge.d.ts +13 -0
- package/dist/components/data-display/StatusBadge.d.ts.map +1 -0
- package/dist/components/data-display/Tbody.d.ts +12 -0
- package/dist/components/data-display/Tbody.d.ts.map +1 -0
- package/dist/components/data-display/Td.d.ts +14 -0
- package/dist/components/data-display/Td.d.ts.map +1 -0
- package/dist/components/data-display/Th.d.ts +14 -0
- package/dist/components/data-display/Th.d.ts.map +1 -0
- package/dist/components/data-display/Thead.d.ts +12 -0
- package/dist/components/data-display/Thead.d.ts.map +1 -0
- package/dist/components/data-display/Tr.d.ts +16 -0
- package/dist/components/data-display/Tr.d.ts.map +1 -0
- package/dist/components/data-display/index.d.ts +8 -0
- package/dist/components/data-display/index.d.ts.map +1 -0
- package/dist/components/feedback/index.d.ts +2 -0
- package/dist/components/feedback/index.d.ts.map +1 -0
- package/dist/components/forms/Checkbox.d.ts +16 -0
- package/dist/components/forms/Checkbox.d.ts.map +1 -0
- package/dist/components/forms/Form.d.ts +12 -0
- package/dist/components/forms/Form.d.ts.map +1 -0
- package/dist/components/forms/Radio.d.ts +32 -0
- package/dist/components/forms/Radio.d.ts.map +1 -0
- package/dist/components/forms/Select.d.ts +33 -0
- package/dist/components/forms/Select.d.ts.map +1 -0
- package/dist/components/forms/Switch.d.ts +31 -0
- package/dist/components/forms/Switch.d.ts.map +1 -0
- package/dist/components/forms/TextArea.d.ts +29 -0
- package/dist/components/forms/TextArea.d.ts.map +1 -0
- package/dist/components/forms/TextInput.d.ts +29 -0
- package/dist/components/forms/TextInput.d.ts.map +1 -0
- package/dist/components/forms/index.d.ts +8 -0
- package/dist/components/forms/index.d.ts.map +1 -0
- package/dist/components/index.d.ts +9 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/layout/Flex.d.ts +16 -0
- package/dist/components/layout/Flex.d.ts.map +1 -0
- package/dist/components/layout/FlexItem.d.ts +16 -0
- package/dist/components/layout/FlexItem.d.ts.map +1 -0
- package/dist/components/layout/index.d.ts +3 -0
- package/dist/components/layout/index.d.ts.map +1 -0
- package/dist/components/navigation/DropdownItem.d.ts +8 -0
- package/dist/components/navigation/DropdownItem.d.ts.map +1 -0
- package/dist/components/navigation/MenuToggle.d.ts +8 -0
- package/dist/components/navigation/MenuToggle.d.ts.map +1 -0
- package/dist/components/navigation/index.d.ts +3 -0
- package/dist/components/navigation/index.d.ts.map +1 -0
- package/dist/components/overlay/Drawer.d.ts +12 -0
- package/dist/components/overlay/Drawer.d.ts.map +1 -0
- package/dist/components/overlay/Modal.d.ts +16 -0
- package/dist/components/overlay/Modal.d.ts.map +1 -0
- package/dist/components/overlay/index.d.ts +3 -0
- package/dist/components/overlay/index.d.ts.map +1 -0
- package/dist/context/SemanticContext.d.ts +28 -0
- package/dist/context/SemanticContext.d.ts.map +1 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/useAccessibility.d.ts +13 -0
- package/dist/hooks/useAccessibility.d.ts.map +1 -0
- package/dist/hooks/useSemanticMetadata.d.ts +9 -0
- package/dist/hooks/useSemanticMetadata.d.ts.map +1 -0
- package/dist/index.d.ts +574 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +1362 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +1426 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +47 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/utils/accessibility.d.ts +16 -0
- package/dist/utils/accessibility.d.ts.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/inference.d.ts +136 -0
- package/dist/utils/inference.d.ts.map +1 -0
- package/dist/utils/metadata.d.ts +17 -0
- package/dist/utils/metadata.d.ts.map +1 -0
- package/package.json +104 -0
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
# Semantic Attributes Codemod
|
|
2
|
+
|
|
3
|
+
This codemod automatically adds standardized `data-*` attributes to all PatternFly components in your codebase, making them more AI-friendly and easier for AI tools to understand.
|
|
4
|
+
|
|
5
|
+
## What It Does
|
|
6
|
+
|
|
7
|
+
The codemod transforms your PatternFly components from:
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
<Card isClickable>
|
|
11
|
+
<CardBody>
|
|
12
|
+
I'm a card
|
|
13
|
+
<Button variant="danger">Cancel</Button>
|
|
14
|
+
</CardBody>
|
|
15
|
+
</Card>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Into:
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
<Card
|
|
22
|
+
isClickable
|
|
23
|
+
data-role="card"
|
|
24
|
+
data-purpose="clickable"
|
|
25
|
+
data-variant="default"
|
|
26
|
+
data-context="default"
|
|
27
|
+
data-state="active"
|
|
28
|
+
>
|
|
29
|
+
<CardBody
|
|
30
|
+
data-role="card-body"
|
|
31
|
+
data-purpose="display"
|
|
32
|
+
data-variant="default"
|
|
33
|
+
data-context="default"
|
|
34
|
+
data-state="default"
|
|
35
|
+
>
|
|
36
|
+
I'm a card
|
|
37
|
+
<Button
|
|
38
|
+
variant="danger"
|
|
39
|
+
data-role="button"
|
|
40
|
+
data-purpose="action"
|
|
41
|
+
data-variant="danger"
|
|
42
|
+
data-context="default"
|
|
43
|
+
data-state="active"
|
|
44
|
+
>
|
|
45
|
+
Cancel
|
|
46
|
+
</Button>
|
|
47
|
+
</CardBody>
|
|
48
|
+
</Card>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Rendered HTML in Browser:**
|
|
52
|
+
```html
|
|
53
|
+
<div class="pf-c-card" data-role="card" data-purpose="clickable" data-variant="default" data-context="default" data-state="active">
|
|
54
|
+
<div class="pf-c-card__body" data-role="card-body" data-purpose="display" data-variant="default" data-context="default" data-state="default">
|
|
55
|
+
I'm a card
|
|
56
|
+
<button class="pf-c-button pf-m-danger" data-role="button" data-purpose="action" data-variant="danger" data-context="default" data-state="active">
|
|
57
|
+
Cancel
|
|
58
|
+
</button>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Standardized Attributes
|
|
64
|
+
|
|
65
|
+
Every PatternFly component gets the same 5 attributes that **appear on the rendered DOM elements**:
|
|
66
|
+
|
|
67
|
+
| Attribute | Description | Example Values |
|
|
68
|
+
|-----------|-------------|----------------|
|
|
69
|
+
| `data-role` | What the component IS | `button`, `card`, `input`, `modal` |
|
|
70
|
+
| `data-purpose` | What it DOES | `action`, `display`, `input`, `navigation` |
|
|
71
|
+
| `data-variant` | How it LOOKS | `primary`, `danger`, `secondary`, `text` |
|
|
72
|
+
| `data-context` | Where it's USED | `form`, `modal`, `table`, `toolbar` |
|
|
73
|
+
| `data-state` | Current STATE | `active`, `disabled`, `selected`, `readonly` |
|
|
74
|
+
|
|
75
|
+
**Important**: These attributes will appear on the actual rendered HTML elements in your browser. React automatically forwards all `data-*` attributes to the underlying DOM elements, and PatternFly components respect this behavior.
|
|
76
|
+
|
|
77
|
+
## Usage
|
|
78
|
+
|
|
79
|
+
### Quick Start
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Transform all files in src/
|
|
83
|
+
./codemod/add-semantic-attributes.sh src/
|
|
84
|
+
|
|
85
|
+
# Transform a specific file
|
|
86
|
+
./codemod/add-semantic-attributes.sh src/components/MyComponent.tsx
|
|
87
|
+
|
|
88
|
+
# Transform current directory
|
|
89
|
+
./codemod/add-semantic-attributes.sh
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Using jscodeshift Directly
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Install jscodeshift globally (if not already installed)
|
|
96
|
+
npm install -g jscodeshift
|
|
97
|
+
|
|
98
|
+
# Run the transform
|
|
99
|
+
jscodeshift -t codemod/transform.js --extensions=ts,tsx,js,jsx --parser=tsx src/
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## How It Works
|
|
103
|
+
|
|
104
|
+
1. **Component Detection**: Scans import statements to identify PatternFly components
|
|
105
|
+
- Recognizes imports from `@patternfly/react-core`, `@patternfly/react-table`, etc.
|
|
106
|
+
- Handles both named and default imports
|
|
107
|
+
- Handles aliased imports (e.g., `import { Button as PFButton }`)
|
|
108
|
+
- **Works for ALL PatternFly components**, not just wrapped ones
|
|
109
|
+
|
|
110
|
+
2. **Static Inference**: Analyzes component props to infer semantic properties
|
|
111
|
+
- **Enhanced inference** for components with specific logic (Button, Card, Modal, Form, Input, Select, etc.)
|
|
112
|
+
- **Generic inference with fallbacks** for other PF components (Alert, Breadcrumb, Tabs, etc.)
|
|
113
|
+
- Reads `variant`, `type`, `onClick`, `isDisabled`, etc.
|
|
114
|
+
- Determines purpose from component name and props
|
|
115
|
+
- Detects parent context for nested components
|
|
116
|
+
|
|
117
|
+
3. **Attribute Injection**: Adds standardized attributes without modifying existing code
|
|
118
|
+
- Preserves all existing props and formatting
|
|
119
|
+
- Skips components that already have semantic attributes (no duplicates)
|
|
120
|
+
- Maintains code style and comments
|
|
121
|
+
|
|
122
|
+
4. **DOM Rendering**: Attributes automatically appear on rendered HTML elements
|
|
123
|
+
- React forwards all `data-*` attributes to DOM elements
|
|
124
|
+
- PatternFly components respect React's attribute forwarding
|
|
125
|
+
- Attributes are queryable in browser DevTools
|
|
126
|
+
|
|
127
|
+
### Inference Quality
|
|
128
|
+
|
|
129
|
+
**Components with Enhanced Inference:**
|
|
130
|
+
- Button, Card, Modal, Form, TextInput, TextArea, Select, Checkbox, Radio, Switch
|
|
131
|
+
- Flex, FlexItem, Table components (Th, Td, Tr, Thead, Tbody)
|
|
132
|
+
- Link, Drawer, MenuToggle, DropdownItem
|
|
133
|
+
- Accordion, ActionList, Alert, Avatar, Banner, Breadcrumb, ClipboardCopy, CodeBlock, Content
|
|
134
|
+
|
|
135
|
+
**Components with Generic Inference:**
|
|
136
|
+
- All other PatternFly components (Breadcrumb, Tabs, Popover, Tooltip, Wizard, etc.)
|
|
137
|
+
- Uses heuristics and fallbacks to provide reasonable defaults
|
|
138
|
+
- Still adds all 7 standardized attributes
|
|
139
|
+
|
|
140
|
+
**Components We Skip:**
|
|
141
|
+
- Static components without meaningful variants, states, or interactive behavior
|
|
142
|
+
- Specifically skipped: Backdrop, BackgroundImage, BackToTop, Brand
|
|
143
|
+
- These components always behave the same and don't benefit from semantic attributes
|
|
144
|
+
|
|
145
|
+
**Components Not Currently Supported:**
|
|
146
|
+
- CodeEditor - Not currently supported (may be added in the future)
|
|
147
|
+
|
|
148
|
+
**Component Nesting Restrictions:**
|
|
149
|
+
- Content - PatternFly recommends using the `component` prop (e.g., `component="h1"`) instead of nesting other components within `<Content>`. The codemod will add semantic attributes to Content components, but developers should follow PatternFly's nesting guidelines.
|
|
150
|
+
|
|
151
|
+
## Supported PatternFly Packages
|
|
152
|
+
|
|
153
|
+
The codemod works with **ALL components** imported from these PatternFly packages:
|
|
154
|
+
|
|
155
|
+
- `@patternfly/react-core` - All core components (Button, Card, Modal, Form, Input, Select, etc.)
|
|
156
|
+
- `@patternfly/react-table` - All table components (Table, Th, Td, Tr, Thead, Tbody, etc.)
|
|
157
|
+
- `@patternfly/react-icons` - Icon components
|
|
158
|
+
- `@patternfly/react-charts` - Chart components
|
|
159
|
+
- `@patternfly/react-topology` - Topology components
|
|
160
|
+
|
|
161
|
+
**Important**: The codemod processes **any component** imported from these packages, not just the ones we've wrapped. It uses intelligent inference with fallbacks for unknown components.
|
|
162
|
+
|
|
163
|
+
## Inference Examples
|
|
164
|
+
|
|
165
|
+
### Button Component
|
|
166
|
+
```tsx
|
|
167
|
+
// Input
|
|
168
|
+
<Button variant="danger" onClick={handleDelete}>Delete</Button>
|
|
169
|
+
|
|
170
|
+
// Output (attributes added)
|
|
171
|
+
<Button
|
|
172
|
+
variant="danger"
|
|
173
|
+
onClick={handleDelete}
|
|
174
|
+
data-role="button"
|
|
175
|
+
data-purpose="action"
|
|
176
|
+
data-variant="danger"
|
|
177
|
+
data-context="default"
|
|
178
|
+
data-state="active"
|
|
179
|
+
>
|
|
180
|
+
Delete
|
|
181
|
+
</Button>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Rendered HTML:**
|
|
185
|
+
```html
|
|
186
|
+
<button
|
|
187
|
+
class="pf-c-button pf-m-danger"
|
|
188
|
+
data-role="button"
|
|
189
|
+
data-purpose="action"
|
|
190
|
+
data-variant="danger"
|
|
191
|
+
data-context="default"
|
|
192
|
+
data-state="active"
|
|
193
|
+
>
|
|
194
|
+
Delete
|
|
195
|
+
</button>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Card Component
|
|
199
|
+
```tsx
|
|
200
|
+
// Input
|
|
201
|
+
<Card isClickable isSelected>
|
|
202
|
+
<CardBody>Content</CardBody>
|
|
203
|
+
</Card>
|
|
204
|
+
|
|
205
|
+
// Output
|
|
206
|
+
<Card
|
|
207
|
+
isClickable
|
|
208
|
+
isSelected
|
|
209
|
+
data-role="card"
|
|
210
|
+
data-purpose="clickable"
|
|
211
|
+
data-variant="default"
|
|
212
|
+
data-context="default"
|
|
213
|
+
data-state="selected"
|
|
214
|
+
>
|
|
215
|
+
<CardBody
|
|
216
|
+
data-role="card-body"
|
|
217
|
+
data-purpose="display"
|
|
218
|
+
data-variant="default"
|
|
219
|
+
data-context="default"
|
|
220
|
+
data-state="default"
|
|
221
|
+
>
|
|
222
|
+
Content
|
|
223
|
+
</CardBody>
|
|
224
|
+
</Card>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Rendered HTML:**
|
|
228
|
+
```html
|
|
229
|
+
<div class="pf-c-card" data-role="card" data-purpose="clickable" data-variant="default" data-context="default" data-state="selected">
|
|
230
|
+
<div class="pf-c-card__body" data-role="card-body" data-purpose="display" data-variant="default" data-context="default" data-state="default">
|
|
231
|
+
Content
|
|
232
|
+
</div>
|
|
233
|
+
</div>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Form Input
|
|
237
|
+
```tsx
|
|
238
|
+
// Input
|
|
239
|
+
<TextInput type="email" isRequired />
|
|
240
|
+
|
|
241
|
+
// Output
|
|
242
|
+
<TextInput
|
|
243
|
+
type="email"
|
|
244
|
+
isRequired
|
|
245
|
+
data-role="text-input"
|
|
246
|
+
data-purpose="input"
|
|
247
|
+
data-variant="email"
|
|
248
|
+
data-context="form"
|
|
249
|
+
data-state="default"
|
|
250
|
+
/>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Rendered HTML:**
|
|
254
|
+
```html
|
|
255
|
+
<input
|
|
256
|
+
type="email"
|
|
257
|
+
class="pf-c-form-control"
|
|
258
|
+
required
|
|
259
|
+
data-role="text-input"
|
|
260
|
+
data-purpose="input"
|
|
261
|
+
data-variant="email"
|
|
262
|
+
data-context="form"
|
|
263
|
+
data-state="default"
|
|
264
|
+
/>
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Limitations
|
|
268
|
+
|
|
269
|
+
### Static Analysis Only
|
|
270
|
+
The codemod uses **static analysis** (what it can see in your source code), not runtime values:
|
|
271
|
+
|
|
272
|
+
✅ **Works:**
|
|
273
|
+
- `variant="danger"` (literal string)
|
|
274
|
+
- `isDisabled={true}` (literal boolean)
|
|
275
|
+
- `onClick={handler}` (prop exists)
|
|
276
|
+
|
|
277
|
+
❌ **Can't Detect:**
|
|
278
|
+
- `variant={someVariable}` (variable value unknown)
|
|
279
|
+
- `onClick={condition ? handler1 : handler2}` (runtime decision)
|
|
280
|
+
- Dynamic props from state or context
|
|
281
|
+
|
|
282
|
+
### Parent Context Detection
|
|
283
|
+
Parent context is detected by analyzing the JSX tree structure, but:
|
|
284
|
+
- Only works for direct parent-child relationships
|
|
285
|
+
- Limited to 10 levels deep (prevents infinite loops)
|
|
286
|
+
- May not detect context from React Context API
|
|
287
|
+
|
|
288
|
+
## Extending the Codemod
|
|
289
|
+
|
|
290
|
+
### Adding New PatternFly Packages
|
|
291
|
+
|
|
292
|
+
Edit `codemod/static-inference.js`:
|
|
293
|
+
|
|
294
|
+
```javascript
|
|
295
|
+
const PF_PACKAGES = [
|
|
296
|
+
'@patternfly/react-core',
|
|
297
|
+
'@patternfly/react-table',
|
|
298
|
+
'@patternfly/react-icons',
|
|
299
|
+
'@patternfly/react-charts',
|
|
300
|
+
'@patternfly/react-topology',
|
|
301
|
+
'@patternfly/react-new-package', // Add here
|
|
302
|
+
];
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Adding New Component Inference Rules
|
|
306
|
+
|
|
307
|
+
Edit `codemod/static-inference.js`:
|
|
308
|
+
|
|
309
|
+
```javascript
|
|
310
|
+
function inferPurpose(componentName, props) {
|
|
311
|
+
// Add your custom logic here
|
|
312
|
+
if (componentName === 'MyNewComponent') {
|
|
313
|
+
return 'custom-purpose';
|
|
314
|
+
}
|
|
315
|
+
// ... existing logic
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Customizing Attributes
|
|
320
|
+
|
|
321
|
+
Edit `codemod/transform.js` to add or modify attributes:
|
|
322
|
+
|
|
323
|
+
```javascript
|
|
324
|
+
const newAttributes = [
|
|
325
|
+
j.jsxAttribute(
|
|
326
|
+
j.jsxIdentifier('data-semantic-role'),
|
|
327
|
+
j.literal(role)
|
|
328
|
+
),
|
|
329
|
+
// Add more attributes here
|
|
330
|
+
j.jsxAttribute(
|
|
331
|
+
j.jsxIdentifier('data-custom-attr'),
|
|
332
|
+
j.literal('custom-value')
|
|
333
|
+
),
|
|
334
|
+
];
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Troubleshooting
|
|
338
|
+
|
|
339
|
+
### Components Not Being Transformed
|
|
340
|
+
|
|
341
|
+
1. **Check imports**: Make sure components are imported from PatternFly packages
|
|
342
|
+
2. **Check file extensions**: Only `.ts`, `.tsx`, `.js`, `.jsx` files are processed
|
|
343
|
+
3. **Check existing attributes**: Components with existing `data-semantic-*` attributes are skipped
|
|
344
|
+
|
|
345
|
+
### Incorrect Inferences
|
|
346
|
+
|
|
347
|
+
The codemod uses heuristics to infer values. If results are incorrect:
|
|
348
|
+
1. Manually add attributes to override inferred values
|
|
349
|
+
2. Update inference logic in `static-inference.js`
|
|
350
|
+
3. Report issues with specific component patterns
|
|
351
|
+
|
|
352
|
+
### Formatting Issues
|
|
353
|
+
|
|
354
|
+
The codemod preserves your existing formatting. If you see formatting changes:
|
|
355
|
+
1. Run your formatter (Prettier, ESLint) after the transform
|
|
356
|
+
2. The codemod uses single quotes and trailing commas by default
|
|
357
|
+
|
|
358
|
+
## Best Practices
|
|
359
|
+
|
|
360
|
+
1. **Run on Clean Code**: Transform before adding custom logic
|
|
361
|
+
2. **Version Control**: Commit before running, review changes after
|
|
362
|
+
3. **Test After**: Verify your app still works after transformation
|
|
363
|
+
4. **Incremental**: Transform one directory at a time for large codebases
|
|
364
|
+
5. **Review Changes**: Use `git diff` to review what was changed
|
|
365
|
+
|
|
366
|
+
## Integration with AI Tools
|
|
367
|
+
|
|
368
|
+
Once attributes are added and rendered, AI tools can query the DOM:
|
|
369
|
+
|
|
370
|
+
- **Query by purpose**: Find all action buttons: `[data-purpose="action"]`
|
|
371
|
+
- **Query by context**: Find all form inputs: `[data-context="form"]`
|
|
372
|
+
- **Query by state**: Find all disabled components: `[data-state="disabled"]`
|
|
373
|
+
- **Query by role**: Find all cards: `[data-role="card"]`
|
|
374
|
+
- **Query by variant**: Find all danger buttons: `[data-variant="danger"]`
|
|
375
|
+
|
|
376
|
+
**Example Browser Queries:**
|
|
377
|
+
```javascript
|
|
378
|
+
// Find all action buttons
|
|
379
|
+
document.querySelectorAll('[data-purpose="action"]')
|
|
380
|
+
|
|
381
|
+
// Find all form inputs
|
|
382
|
+
document.querySelectorAll('[data-context="form"]')
|
|
383
|
+
|
|
384
|
+
// Find all danger variants
|
|
385
|
+
document.querySelectorAll('[data-variant="danger"]')
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## Contributing
|
|
389
|
+
|
|
390
|
+
To improve the codemod:
|
|
391
|
+
|
|
392
|
+
1. Add new inference rules in `static-inference.js`
|
|
393
|
+
2. Add support for new PatternFly components
|
|
394
|
+
3. Improve parent context detection
|
|
395
|
+
4. Add more sophisticated static analysis
|
|
396
|
+
|
|
397
|
+
## License
|
|
398
|
+
|
|
399
|
+
MIT License - same as the main project
|
|
400
|
+
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Add Semantic Attributes to PatternFly Components
|
|
4
|
+
#
|
|
5
|
+
# This script runs a jscodeshift codemod that adds standardized data-* attributes
|
|
6
|
+
# to all PatternFly components in your codebase, making them more AI-friendly.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# ./codemod/add-semantic-attributes.sh [path/to/files]
|
|
10
|
+
#
|
|
11
|
+
# Examples:
|
|
12
|
+
# ./codemod/add-semantic-attributes.sh src/
|
|
13
|
+
# ./codemod/add-semantic-attributes.sh src/components/MyComponent.tsx
|
|
14
|
+
# ./codemod/add-semantic-attributes.sh # transforms current directory
|
|
15
|
+
|
|
16
|
+
set -e
|
|
17
|
+
|
|
18
|
+
# Colors for output
|
|
19
|
+
RED='\033[0;31m'
|
|
20
|
+
GREEN='\033[0;32m'
|
|
21
|
+
YELLOW='\033[1;33m'
|
|
22
|
+
NC='\033[0m' # No Color
|
|
23
|
+
|
|
24
|
+
# Get the directory where this script is located
|
|
25
|
+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
26
|
+
PROJECT_ROOT="$( cd "$SCRIPT_DIR/.." && pwd )"
|
|
27
|
+
|
|
28
|
+
# Default path is current directory if not provided
|
|
29
|
+
TARGET_PATH="${1:-.}"
|
|
30
|
+
|
|
31
|
+
# Check if jscodeshift is installed
|
|
32
|
+
if ! command -v jscodeshift &> /dev/null; then
|
|
33
|
+
echo -e "${RED}Error: jscodeshift is not installed${NC}"
|
|
34
|
+
echo "Installing jscodeshift globally..."
|
|
35
|
+
npm install -g jscodeshift
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# Check if target path exists
|
|
39
|
+
if [ ! -e "$TARGET_PATH" ]; then
|
|
40
|
+
echo -e "${RED}Error: Path '$TARGET_PATH' does not exist${NC}"
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
echo -e "${GREEN}Adding semantic attributes to PatternFly components...${NC}"
|
|
45
|
+
echo "Target: $TARGET_PATH"
|
|
46
|
+
echo ""
|
|
47
|
+
|
|
48
|
+
# Run jscodeshift
|
|
49
|
+
jscodeshift \
|
|
50
|
+
--transform="$SCRIPT_DIR/transform.js" \
|
|
51
|
+
--extensions=ts,tsx,js,jsx \
|
|
52
|
+
--parser=tsx \
|
|
53
|
+
"$TARGET_PATH"
|
|
54
|
+
|
|
55
|
+
echo ""
|
|
56
|
+
echo -e "${GREEN}✓ Transformation complete!${NC}"
|
|
57
|
+
echo ""
|
|
58
|
+
echo "All PatternFly components now have standardized data-* attributes:"
|
|
59
|
+
echo " - data-role (what the component IS)"
|
|
60
|
+
echo " - data-purpose (what it DOES)"
|
|
61
|
+
echo " - data-variant (how it LOOKS)"
|
|
62
|
+
echo " - data-context (where it's USED)"
|
|
63
|
+
echo " - data-state (current STATE)"
|
|
64
|
+
echo ""
|
|
65
|
+
echo "These attributes will appear on the rendered DOM elements in your browser."
|
|
66
|
+
echo "You can verify by inspecting the HTML in DevTools."
|
|
67
|
+
echo ""
|
|
68
|
+
echo "Example: <button class='pf-c-button' data-role='button' data-purpose='action'>"
|
|
69
|
+
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
{
|
|
2
|
+
"TextInputGroup": {
|
|
3
|
+
"data-role": ["text-input-group"],
|
|
4
|
+
"data-purpose": ["input"],
|
|
5
|
+
"data-variant": ["basic", "with-icon", "with-clear-button", "with-label-group"],
|
|
6
|
+
"data-context": ["form", "toolbar", "page"],
|
|
7
|
+
"data-state": ["active", "disabled", "error", "warning"],
|
|
8
|
+
"data-action-type": [],
|
|
9
|
+
"data-size": []
|
|
10
|
+
},
|
|
11
|
+
"Timestamp": {
|
|
12
|
+
"data-role": ["timestamp"],
|
|
13
|
+
"data-purpose": ["display"],
|
|
14
|
+
"data-variant": ["24-hour", "12-hour", "abbreviated-date"],
|
|
15
|
+
"data-context": ["table", "card", "page"],
|
|
16
|
+
"data-state": [],
|
|
17
|
+
"data-action-type": [],
|
|
18
|
+
"data-size": []
|
|
19
|
+
},
|
|
20
|
+
"Title": {
|
|
21
|
+
"data-role": ["title"],
|
|
22
|
+
"data-purpose": ["header"],
|
|
23
|
+
"data-variant": ["h1", "h2", "h3", "h4", "h5", "h6"],
|
|
24
|
+
"data-context": ["page", "modal", "card", "form"],
|
|
25
|
+
"data-state": [],
|
|
26
|
+
"data-action-type": [],
|
|
27
|
+
"data-size": []
|
|
28
|
+
},
|
|
29
|
+
"ToggleGroup": {
|
|
30
|
+
"data-role": ["toggle-group"],
|
|
31
|
+
"data-purpose": ["selection"],
|
|
32
|
+
"data-variant": ["single-select", "multi-select"],
|
|
33
|
+
"data-context": ["toolbar", "page", "form"],
|
|
34
|
+
"data-state": [],
|
|
35
|
+
"data-action-type": ["selection"],
|
|
36
|
+
"data-size": []
|
|
37
|
+
},
|
|
38
|
+
"ToggleItem": {
|
|
39
|
+
"data-role": ["toggle-item"],
|
|
40
|
+
"data-purpose": ["selection"],
|
|
41
|
+
"data-variant": [],
|
|
42
|
+
"data-context": ["toolbar", "page", "form"],
|
|
43
|
+
"data-state": ["selected", "unselected", "disabled"],
|
|
44
|
+
"data-action-type": [],
|
|
45
|
+
"data-size": []
|
|
46
|
+
},
|
|
47
|
+
"Toolbar": {
|
|
48
|
+
"data-role": ["toolbar"],
|
|
49
|
+
"data-purpose": ["action-group"],
|
|
50
|
+
"data-variant": ["basic", "custom", "with-toggle-group", "sticky"],
|
|
51
|
+
"data-context": ["page", "table", "card"],
|
|
52
|
+
"data-state": [],
|
|
53
|
+
"data-action-type": [],
|
|
54
|
+
"data-size": []
|
|
55
|
+
},
|
|
56
|
+
"ToolbarItem": {
|
|
57
|
+
"data-role": ["toolbar-item"],
|
|
58
|
+
"data-purpose": ["action"],
|
|
59
|
+
"data-variant": [],
|
|
60
|
+
"data-context": ["toolbar"],
|
|
61
|
+
"data-state": [],
|
|
62
|
+
"data-action-type": [],
|
|
63
|
+
"data-size": []
|
|
64
|
+
},
|
|
65
|
+
"ToolbarItemGroup": {
|
|
66
|
+
"data-role": ["toolbar-item-group"],
|
|
67
|
+
"data-purpose": ["grouping"],
|
|
68
|
+
"data-variant": [],
|
|
69
|
+
"data-context": ["toolbar"],
|
|
70
|
+
"data-state": [],
|
|
71
|
+
"data-action-type": [],
|
|
72
|
+
"data-size": []
|
|
73
|
+
},
|
|
74
|
+
"Tooltip": {
|
|
75
|
+
"data-role": ["tooltip"],
|
|
76
|
+
"data-purpose": ["guidance"],
|
|
77
|
+
"data-variant": ["default"],
|
|
78
|
+
"data-context": ["form", "table", "page", "toolbar"],
|
|
79
|
+
"data-state": ["open", "closed"],
|
|
80
|
+
"data-action-type": [],
|
|
81
|
+
"data-size": []
|
|
82
|
+
},
|
|
83
|
+
"TreeView": {
|
|
84
|
+
"data-role": ["tree-view"],
|
|
85
|
+
"data-purpose": ["display"],
|
|
86
|
+
"data-variant": ["basic", "with-search", "with-checkboxes", "with-badges", "with-icons", "with-actions", "compact"],
|
|
87
|
+
"data-context": ["wizard", "drawer", "modal", "page"],
|
|
88
|
+
"data-state": [],
|
|
89
|
+
"data-action-type": ["selection"],
|
|
90
|
+
"data-size": []
|
|
91
|
+
},
|
|
92
|
+
"TreeViewItem": {
|
|
93
|
+
"data-role": ["tree-view-item"],
|
|
94
|
+
"data-purpose": ["selection"],
|
|
95
|
+
"data-variant": [],
|
|
96
|
+
"data-context": ["wizard", "drawer", "modal", "page"],
|
|
97
|
+
"data-state": ["selected", "expanded", "collapsed", "disabled"],
|
|
98
|
+
"data-action-type": [],
|
|
99
|
+
"data-size": []
|
|
100
|
+
},
|
|
101
|
+
"Truncate": {
|
|
102
|
+
"data-role": ["truncate"],
|
|
103
|
+
"data-purpose": ["display"],
|
|
104
|
+
"data-variant": ["front-line", "mid-line", "end-line"],
|
|
105
|
+
"data-context": ["table", "card", "page", "alert"],
|
|
106
|
+
"data-state": [],
|
|
107
|
+
"data-action-type": [],
|
|
108
|
+
"data-size": []
|
|
109
|
+
},
|
|
110
|
+
"Wizard": {
|
|
111
|
+
"data-role": ["wizard"],
|
|
112
|
+
"data-purpose": ["form-container"],
|
|
113
|
+
"data-variant": ["modal", "in-page", "progressive", "with-sub-steps", "with-optional-steps", "with-drawer"],
|
|
114
|
+
"data-context": ["overlay", "page"],
|
|
115
|
+
"data-state": [],
|
|
116
|
+
"data-action-type": ["form"],
|
|
117
|
+
"data-size": []
|
|
118
|
+
},
|
|
119
|
+
"WizardNavItem": {
|
|
120
|
+
"data-role": ["wizard-nav-item"],
|
|
121
|
+
"data-purpose": ["navigation"],
|
|
122
|
+
"data-variant": [],
|
|
123
|
+
"data-context": ["wizard"],
|
|
124
|
+
"data-state": ["visited", "current", "disabled"],
|
|
125
|
+
"data-action-type": [],
|
|
126
|
+
"data-size": []
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Example: After running the codemod
|
|
2
|
+
// This is what the output should look like
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Card, CardBody, Button } from '@patternfly/react-core';
|
|
5
|
+
|
|
6
|
+
function ExampleComponent() {
|
|
7
|
+
return (
|
|
8
|
+
<Card
|
|
9
|
+
isClickable
|
|
10
|
+
data-role="card"
|
|
11
|
+
data-purpose="clickable"
|
|
12
|
+
data-variant="default"
|
|
13
|
+
data-context="default"
|
|
14
|
+
data-state="active"
|
|
15
|
+
>
|
|
16
|
+
<CardBody
|
|
17
|
+
data-role="card-body"
|
|
18
|
+
data-purpose="display"
|
|
19
|
+
data-variant="default"
|
|
20
|
+
data-context="default"
|
|
21
|
+
data-state="default"
|
|
22
|
+
>
|
|
23
|
+
I'm a card
|
|
24
|
+
<Button
|
|
25
|
+
variant="danger"
|
|
26
|
+
onClick={() => console.log('Delete')}
|
|
27
|
+
data-role="button"
|
|
28
|
+
data-purpose="action"
|
|
29
|
+
data-variant="danger"
|
|
30
|
+
data-context="default"
|
|
31
|
+
data-state="active"
|
|
32
|
+
>
|
|
33
|
+
Cancel
|
|
34
|
+
</Button>
|
|
35
|
+
</CardBody>
|
|
36
|
+
</Card>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default ExampleComponent;
|
|
41
|
+
|
|
42
|
+
// Rendered HTML in browser will look like:
|
|
43
|
+
// <div class="pf-c-card" data-role="card" data-purpose="clickable" ...>
|
|
44
|
+
// <div class="pf-c-card__body" data-role="card-body" data-purpose="display" ...>
|
|
45
|
+
// I'm a card
|
|
46
|
+
// <button class="pf-c-button pf-m-danger" data-role="button" data-purpose="action" data-variant="danger" ...>
|
|
47
|
+
// Cancel
|
|
48
|
+
// </button>
|
|
49
|
+
// </div>
|
|
50
|
+
// </div>
|
|
51
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Example: Before running the codemod
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Card, CardBody, Button } from '@patternfly/react-core';
|
|
4
|
+
|
|
5
|
+
function ExampleComponent() {
|
|
6
|
+
return (
|
|
7
|
+
<Card isClickable>
|
|
8
|
+
<CardBody>
|
|
9
|
+
I'm a card
|
|
10
|
+
<Button variant="danger" onClick={() => console.log('Delete')}>
|
|
11
|
+
Cancel
|
|
12
|
+
</Button>
|
|
13
|
+
</CardBody>
|
|
14
|
+
</Card>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default ExampleComponent;
|
|
19
|
+
|