@sebgroup/green-core 2.37.1 → 2.37.3
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/bin/context-cli/index.js +5 -0
- package/bin/context-cli/migrate/engine.d.ts +48 -0
- package/bin/context-cli/migrate/engine.js +111 -0
- package/bin/context-cli/migrate/index.d.ts +15 -0
- package/bin/context-cli/migrate/index.js +232 -0
- package/bin/context-cli/migrate/registry.d.ts +43 -0
- package/bin/context-cli/migrate/registry.js +75 -0
- package/bin/context-cli/migrate/types.d.ts +135 -0
- package/bin/context-cli/migrate/types.js +0 -0
- package/bin/context-cli/migrate/units/0/example.d.ts +52 -0
- package/bin/context-cli/migrate/units/0/example.js +146 -0
- package/components/pagination/pagination.component.js +14 -3
- package/custom-elements.json +969 -707
- package/gds-element.js +1 -1
- package/generated/mcp/components.json +1 -1
- package/generated/mcp/guides/migration.md +5 -0
- package/generated/mcp/icons.json +1 -1
- package/generated/mcp/index.json +1 -1
- package/package.json +1 -1
- package/utils/helpers/custom-element-scoping.js +1 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example migration unit — template for creating new units.
|
|
3
|
+
*
|
|
4
|
+
* This file is a documented reference for how to build a migration unit.
|
|
5
|
+
* It has `enabled: false`, so it will not appear in `green-core-context
|
|
6
|
+
* migrate list` or be executed during `migrate run`.
|
|
7
|
+
*
|
|
8
|
+
* ## How to create a new migration unit
|
|
9
|
+
*
|
|
10
|
+
* 1. Create a file under `units/<major>/` (e.g. `units/3/my-migration.ts`)
|
|
11
|
+
* 2. Export a `MigrationUnit` object as `export const unit`
|
|
12
|
+
* 3. The registry auto-discovers it from the directory structure — no
|
|
13
|
+
* manual registration needed
|
|
14
|
+
*
|
|
15
|
+
* ## Multi-framework / multi-syntax coverage
|
|
16
|
+
*
|
|
17
|
+
* A single migration unit should cover ONE semantic change across ALL
|
|
18
|
+
* syntax variants. We cannot determine framework from file extension —
|
|
19
|
+
* an Angular template may live inside a `.ts` file, plain HTML may live
|
|
20
|
+
* in a `.html` file that is not Angular, and React JSX uses `.tsx`.
|
|
21
|
+
*
|
|
22
|
+
* Instead, define variant patterns for every known syntax form of the
|
|
23
|
+
* same attribute/property rename:
|
|
24
|
+
*
|
|
25
|
+
* - HTML attribute: `gds-theme="dark"`
|
|
26
|
+
* - Angular property: `[gdsTheme]="expr"`
|
|
27
|
+
* - Angular attr binding: `[attr.gds-theme]="expr"`
|
|
28
|
+
* - React JSX prop: `gdsTheme="dark"` or `gdsTheme={expr}`
|
|
29
|
+
* - JS property assignment: `.gdsTheme = value`
|
|
30
|
+
* - JS setAttribute call: `setAttribute('gds-theme', value)`
|
|
31
|
+
*
|
|
32
|
+
* All patterns are applied to ALL files. This means the unit will find
|
|
33
|
+
* Angular bindings in a `.tsx` file too — that is intentional and harmless.
|
|
34
|
+
* False positives are better than missed migrations.
|
|
35
|
+
*
|
|
36
|
+
* ## Guidelines
|
|
37
|
+
*
|
|
38
|
+
* - Keep regex patterns simple and well-commented
|
|
39
|
+
* - Use non-capturing groups `(?:...)` unless capture is needed
|
|
40
|
+
* - Reset `lastIndex` before reusing a regex with the `g` flag
|
|
41
|
+
* - In `detect()`, always set `file` to `filePath` — the engine
|
|
42
|
+
* normalises it to a relative path afterwards
|
|
43
|
+
* - In `apply()`, return `null` if nothing changed
|
|
44
|
+
* - Mark matches as `manualReview: true` when auto-fix isn't safe
|
|
45
|
+
* - Prefer line-by-line scanning for readable detect logic
|
|
46
|
+
* - Always provide `exampleBefore` / `exampleAfter` — they are used by
|
|
47
|
+
* coding models as context when applying changes manually
|
|
48
|
+
*
|
|
49
|
+
* @module migrate/units/0/example
|
|
50
|
+
*/
|
|
51
|
+
import type { MigrationUnit } from '../../types.js';
|
|
52
|
+
export declare const unit: MigrationUnit;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import "../../../../../chunks/chunk.QU3DSPNU.js";
|
|
2
|
+
const VARIANTS = [
|
|
3
|
+
// ----- HTML attribute (plain HTML, web component, Angular template) -----
|
|
4
|
+
{
|
|
5
|
+
label: "HTML attribute",
|
|
6
|
+
pattern: /\bgds-theme\s*=\s*["']([^"']*)["']/g,
|
|
7
|
+
replace: (_match, value) => `gds-mode="${value}"`,
|
|
8
|
+
message: (m) => `Replace gds-theme="${m[1]}" with gds-mode="${m[1]}"`,
|
|
9
|
+
safe: true
|
|
10
|
+
},
|
|
11
|
+
// ----- Angular property binding: [gdsTheme]="expr" -----
|
|
12
|
+
{
|
|
13
|
+
label: "Angular property binding",
|
|
14
|
+
pattern: /\[gdsTheme\]\s*=\s*"([^"]*)"/g,
|
|
15
|
+
replace: (_match, expr) => `[gdsMode]="${expr}"`,
|
|
16
|
+
message: (m) => `Replace [gdsTheme]="${m[1]}" with [gdsMode]="${m[1]}"`,
|
|
17
|
+
safe: true
|
|
18
|
+
},
|
|
19
|
+
// ----- Angular explicit attr binding: [attr.gds-theme]="expr" -----
|
|
20
|
+
{
|
|
21
|
+
label: "Angular attr binding",
|
|
22
|
+
pattern: /\[attr\.gds-theme\]\s*=\s*"([^"]*)"/g,
|
|
23
|
+
replace: (_match, expr) => `[attr.gds-mode]="${expr}"`,
|
|
24
|
+
message: (m) => `Replace [attr.gds-theme]="${m[1]}" with [attr.gds-mode]="${m[1]}"`,
|
|
25
|
+
safe: true
|
|
26
|
+
},
|
|
27
|
+
// ----- React JSX prop: gdsTheme="value" or gdsTheme={expr} -----
|
|
28
|
+
// Negative lookbehind (?<!\.) excludes JS property access like el.gdsTheme
|
|
29
|
+
{
|
|
30
|
+
label: "React JSX prop (string)",
|
|
31
|
+
pattern: /(?<!\.)\bgdsTheme\s*=\s*"([^"]*)"/g,
|
|
32
|
+
replace: (_match, value) => `gdsMode="${value}"`,
|
|
33
|
+
message: (m) => `Replace gdsTheme="${m[1]}" with gdsMode="${m[1]}"`,
|
|
34
|
+
safe: true
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
label: "React JSX prop (expression)",
|
|
38
|
+
pattern: /(?<!\.)\bgdsTheme\s*=\s*\{([^}]*)\}/g,
|
|
39
|
+
replace: (_match, expr) => `gdsMode={${expr}}`,
|
|
40
|
+
message: (m) => `Replace gdsTheme={${m[1]}} with gdsMode={${m[1]}}`,
|
|
41
|
+
safe: true
|
|
42
|
+
},
|
|
43
|
+
// ----- JS/TS property assignment: .gdsTheme = value -----
|
|
44
|
+
{
|
|
45
|
+
label: "JS property assignment",
|
|
46
|
+
pattern: /\.gdsTheme\s*=/g,
|
|
47
|
+
replace: ".gdsMode =",
|
|
48
|
+
message: () => `Replace .gdsTheme = with .gdsMode =`,
|
|
49
|
+
safe: true
|
|
50
|
+
},
|
|
51
|
+
// ----- JS/TS setAttribute call: setAttribute('gds-theme', ...) -----
|
|
52
|
+
{
|
|
53
|
+
label: "setAttribute call",
|
|
54
|
+
pattern: /setAttribute\(\s*['"]gds-theme['"]/g,
|
|
55
|
+
replace: `setAttribute('gds-mode'`,
|
|
56
|
+
message: () => `Replace setAttribute('gds-theme', ...) with setAttribute('gds-mode', ...)`,
|
|
57
|
+
safe: true
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
function detectVariants(filePath, content, variants) {
|
|
61
|
+
const matches = [];
|
|
62
|
+
const lines = content.split("\n");
|
|
63
|
+
for (let i = 0; i < lines.length; i++) {
|
|
64
|
+
const line = lines[i];
|
|
65
|
+
for (const variant of variants) {
|
|
66
|
+
variant.pattern.lastIndex = 0;
|
|
67
|
+
let m;
|
|
68
|
+
while ((m = variant.pattern.exec(line)) !== null) {
|
|
69
|
+
matches.push({
|
|
70
|
+
file: filePath,
|
|
71
|
+
line: i + 1,
|
|
72
|
+
match: m[0],
|
|
73
|
+
message: variant.message(m),
|
|
74
|
+
manualReview: !variant.safe
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return matches;
|
|
80
|
+
}
|
|
81
|
+
function applyVariants(content, variants) {
|
|
82
|
+
let result = content;
|
|
83
|
+
for (const variant of variants) {
|
|
84
|
+
if (!variant.safe) continue;
|
|
85
|
+
variant.pattern.lastIndex = 0;
|
|
86
|
+
result = result.replace(variant.pattern, variant.replace);
|
|
87
|
+
}
|
|
88
|
+
return result !== content ? result : null;
|
|
89
|
+
}
|
|
90
|
+
const unit = {
|
|
91
|
+
id: "theme-to-mode",
|
|
92
|
+
enabled: false,
|
|
93
|
+
// Example only — not a real migration
|
|
94
|
+
summary: "[Example] Replace deprecated gds-theme / gdsTheme with gds-mode / gdsMode",
|
|
95
|
+
exampleBefore: [
|
|
96
|
+
"<!-- HTML attribute -->",
|
|
97
|
+
'<div gds-theme="dark"><gds-button>Click</gds-button></div>',
|
|
98
|
+
"",
|
|
99
|
+
"<!-- Angular property binding -->",
|
|
100
|
+
'<gds-card [gdsTheme]="theme"></gds-card>',
|
|
101
|
+
"",
|
|
102
|
+
"<!-- Angular explicit attr binding -->",
|
|
103
|
+
'<gds-card [attr.gds-theme]="theme"></gds-card>',
|
|
104
|
+
"",
|
|
105
|
+
"<!-- React JSX prop -->",
|
|
106
|
+
'<GdsCard gdsTheme="dark" />',
|
|
107
|
+
"<GdsCard gdsTheme={theme} />",
|
|
108
|
+
"",
|
|
109
|
+
"// JS property assignment",
|
|
110
|
+
'el.gdsTheme = "dark"',
|
|
111
|
+
"",
|
|
112
|
+
"// JS setAttribute",
|
|
113
|
+
"el.setAttribute('gds-theme', 'dark')"
|
|
114
|
+
].join("\n"),
|
|
115
|
+
exampleAfter: [
|
|
116
|
+
"<!-- HTML attribute -->",
|
|
117
|
+
'<div gds-mode="dark"><gds-button>Click</gds-button></div>',
|
|
118
|
+
"",
|
|
119
|
+
"<!-- Angular property binding -->",
|
|
120
|
+
'<gds-card [gdsMode]="theme"></gds-card>',
|
|
121
|
+
"",
|
|
122
|
+
"<!-- Angular explicit attr binding -->",
|
|
123
|
+
'<gds-card [attr.gds-mode]="theme"></gds-card>',
|
|
124
|
+
"",
|
|
125
|
+
"<!-- React JSX prop -->",
|
|
126
|
+
'<GdsCard gdsMode="dark" />',
|
|
127
|
+
"<GdsCard gdsMode={theme} />",
|
|
128
|
+
"",
|
|
129
|
+
"// JS property assignment",
|
|
130
|
+
'el.gdsMode = "dark"',
|
|
131
|
+
"",
|
|
132
|
+
"// JS setAttribute",
|
|
133
|
+
"el.setAttribute('gds-mode', 'dark')"
|
|
134
|
+
].join("\n"),
|
|
135
|
+
fileExtensions: [".html", ".ts", ".tsx"],
|
|
136
|
+
safe: true,
|
|
137
|
+
detect(filePath, content) {
|
|
138
|
+
return detectVariants(filePath, content, VARIANTS);
|
|
139
|
+
},
|
|
140
|
+
apply(_filePath, content) {
|
|
141
|
+
return applyVariants(content, VARIANTS);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
export {
|
|
145
|
+
unit
|
|
146
|
+
};
|
|
@@ -88,7 +88,10 @@ let GdsPagination = class extends withMarginProps(
|
|
|
88
88
|
this._isMobile = matches;
|
|
89
89
|
}
|
|
90
90
|
render() {
|
|
91
|
-
|
|
91
|
+
const pageCount = __privateGet(this, _GdsPagination_instances, pageCount_get);
|
|
92
|
+
const showNavigation = pageCount > 1;
|
|
93
|
+
const pageSizeMenu = __privateMethod(this, _GdsPagination_instances, renderPageSizeMenu_fn).call(this);
|
|
94
|
+
if (!showNavigation && !pageSizeMenu) return nothing;
|
|
92
95
|
return html`
|
|
93
96
|
<gds-flex
|
|
94
97
|
align-items="center"
|
|
@@ -97,8 +100,16 @@ let GdsPagination = class extends withMarginProps(
|
|
|
97
100
|
gap="${__privateGet(this, _GdsPagination_instances, config_get).gap}"
|
|
98
101
|
>
|
|
99
102
|
${__privateMethod(this, _GdsPagination_instances, renderLabel_fn).call(this)}
|
|
100
|
-
<gds-flex
|
|
101
|
-
|
|
103
|
+
<gds-flex
|
|
104
|
+
aling-items="center"
|
|
105
|
+
gap="${__privateGet(this, _GdsPagination_instances, config_get).gap}"
|
|
106
|
+
flex="1"
|
|
107
|
+
justify-content="${showNavigation ? "space-between" : "flex-end"}"
|
|
108
|
+
>
|
|
109
|
+
${[
|
|
110
|
+
when(showNavigation, () => __privateMethod(this, _GdsPagination_instances, renderNavigationControls_fn).call(this)),
|
|
111
|
+
pageSizeMenu
|
|
112
|
+
]}
|
|
102
113
|
</gds-flex>
|
|
103
114
|
</gds-flex>
|
|
104
115
|
`;
|