@deneb-ui/cli 2.0.113 → 2.0.114
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deneb-ui/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.114",
|
|
4
4
|
"description": "Official DENEB CLI — scaffold, convert, validate, and package Fivora-ready storefront templates.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"deneb": "bin/index.js",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"license": "MIT",
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@babel/parser": "^7.28.0",
|
|
52
|
-
"@deneb-ui/core": "^2.0.
|
|
52
|
+
"@deneb-ui/core": "^2.0.114",
|
|
53
53
|
"@octokit/rest": "^22.0.1",
|
|
54
54
|
"adm-zip": "^0.6.0",
|
|
55
55
|
"dotenv": "^17.4.2",
|
|
@@ -706,13 +706,9 @@ function patchSiteFooter(projectDir, dryRun, log, report) {
|
|
|
706
706
|
}
|
|
707
707
|
|
|
708
708
|
function patchUniversalIcons(projectDir, dryRun, log, report) {
|
|
709
|
-
// Scans and ensures all feature icons across files are editable
|
|
710
709
|
try {
|
|
711
|
-
const
|
|
712
|
-
|
|
713
|
-
// Patcher is executed to guarantee all icons across the project are converted
|
|
714
|
-
log('[auto-fix] Running universal icon pass...');
|
|
715
|
-
}
|
|
710
|
+
const { patchUniversalIcons: runPatcher } = require('./universal-icon-patcher.cjs');
|
|
711
|
+
runPatcher(projectDir, dryRun, log);
|
|
716
712
|
} catch (err) {
|
|
717
713
|
log('[auto-fix] Universal icon scan warning: ' + err.message);
|
|
718
714
|
}
|
|
@@ -3,13 +3,6 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
|
|
6
|
-
const rootDir = 'd:/projects/office/deneb/fivora-car-sale';
|
|
7
|
-
const siteDataPath = path.join(rootDir, 'data', 'site-data.json');
|
|
8
|
-
|
|
9
|
-
const siteData = JSON.parse(fs.readFileSync(siteDataPath, 'utf8'));
|
|
10
|
-
if (!siteData.content) siteData.content = {};
|
|
11
|
-
if (!siteData.content.common) siteData.content.common = {};
|
|
12
|
-
|
|
13
6
|
// Helper to ensure nested object path exists
|
|
14
7
|
function setDeep(obj, pathArr, value) {
|
|
15
8
|
let cur = obj;
|
|
@@ -23,198 +16,40 @@ function setDeep(obj, pathArr, value) {
|
|
|
23
16
|
}
|
|
24
17
|
}
|
|
25
18
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
setDeep(siteData.content, ['common', 'showroom', 'navIcon'], 'arrow-up-right');
|
|
30
|
-
setDeep(siteData.content, ['common', 'whatsapp', 'copyIcon'], 'copy');
|
|
31
|
-
setDeep(siteData.content, ['common', 'whatsapp', 'icon'], 'message-circle');
|
|
32
|
-
setDeep(siteData.content, ['common', 'search', 'searchIcon'], 'search');
|
|
33
|
-
setDeep(siteData.content, ['common', 'testDrive', 'calendarIcon'], 'calendar');
|
|
34
|
-
setDeep(siteData.content, ['common', 'testDrive', 'infoIcon'], 'info');
|
|
35
|
-
setDeep(siteData.content, ['common', 'vehicleActions', 'historyIcon'], 'file-text');
|
|
36
|
-
setDeep(siteData.content, ['common', 'vehicleActions', 'testDriveIcon'], 'calendar-check');
|
|
37
|
-
setDeep(siteData.content, ['common', 'vehicleActions', 'financeIcon'], 'landmark');
|
|
38
|
-
setDeep(siteData.content, ['common', 'vehicleActions', 'alertIcon'], 'bell');
|
|
39
|
-
setDeep(siteData.content, ['common', 'vehicleActions', 'calculatorIcon'], 'calculator');
|
|
40
|
-
|
|
41
|
-
if (!siteData.content['trade-in']) siteData.content['trade-in'] = {};
|
|
42
|
-
setDeep(siteData.content, ['trade-in', 'cameraIcon'], 'camera');
|
|
43
|
-
setDeep(siteData.content, ['trade-in', 'upgradeEstimatorIcon'], 'refresh-cw');
|
|
44
|
-
setDeep(siteData.content, ['trade-in', 'step1Icon'], 'car-front');
|
|
45
|
-
setDeep(siteData.content, ['trade-in', 'step2Icon'], 'camera');
|
|
46
|
-
setDeep(siteData.content, ['trade-in', 'step3Icon'], 'handshake');
|
|
47
|
-
setDeep(siteData.content, ['trade-in', 'step4Icon'], 'refresh-cw');
|
|
48
|
-
|
|
49
|
-
if (!siteData.content.about) siteData.content.about = {};
|
|
50
|
-
setDeep(siteData.content, ['about', 'principle1Icon'], 'eye');
|
|
51
|
-
setDeep(siteData.content, ['about', 'principle2Icon'], 'scale');
|
|
52
|
-
setDeep(siteData.content, ['about', 'principle3Icon'], 'message-circle');
|
|
53
|
-
setDeep(siteData.content, ['about', 'principle4Icon'], 'file-search');
|
|
54
|
-
|
|
55
|
-
if (!siteData.content['source-a-car']) siteData.content['source-a-car'] = {};
|
|
56
|
-
setDeep(siteData.content, ['source-a-car', 'step1Icon'], 'clipboard-list');
|
|
57
|
-
setDeep(siteData.content, ['source-a-car', 'step2Icon'], 'message-circle');
|
|
58
|
-
setDeep(siteData.content, ['source-a-car', 'step3Icon'], 'search');
|
|
59
|
-
|
|
60
|
-
if (!siteData.content.compare) siteData.content.compare = {};
|
|
61
|
-
setDeep(siteData.content, ['compare', 'trophyIcon'], 'trophy');
|
|
62
|
-
|
|
63
|
-
fs.writeFileSync(siteDataPath, JSON.stringify(siteData, null, 2), 'utf8');
|
|
64
|
-
console.log('Updated site-data.json with all icon definitions');
|
|
65
|
-
|
|
66
|
-
// 2. Patch components/vehicles/vehicle-actions.tsx
|
|
67
|
-
{
|
|
68
|
-
const filePath = path.join(rootDir, 'components', 'vehicles', 'vehicle-actions.tsx');
|
|
69
|
-
let code = fs.readFileSync(filePath, 'utf8');
|
|
70
|
-
if (!code.includes('EditableIcon')) {
|
|
71
|
-
code = code.replace(
|
|
72
|
-
/from "@deneb-ui\/ui";?/,
|
|
73
|
-
', EditableIcon } from "@deneb-ui/ui";'
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
// Replace FileTextIcon
|
|
77
|
-
code = code.replace(
|
|
78
|
-
/<FileTextIcon[^>]*data-preview-static="decorative-icon"[^>]*\/>/g,
|
|
79
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 mr-1.5" data-preview-field-path="common.vehicleActions.historyIcon" title="Click to edit history icon"><EditableIcon name={(siteData?.content?.common as any)?.vehicleActions?.historyIcon ?? "file-text"} className="size-4" /></span>'
|
|
80
|
-
);
|
|
81
|
-
// Replace CalendarCheckIcon
|
|
82
|
-
code = code.replace(
|
|
83
|
-
/<CalendarCheckIcon[^>]*data-preview-static="decorative-icon"[^>]*\/>/g,
|
|
84
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 mr-1.5" data-preview-field-path="common.vehicleActions.testDriveIcon" title="Click to edit test drive icon"><EditableIcon name={(siteData?.content?.common as any)?.vehicleActions?.testDriveIcon ?? "calendar-check"} className="size-4" /></span>'
|
|
85
|
-
);
|
|
86
|
-
// Replace LandmarkIcon
|
|
87
|
-
code = code.replace(
|
|
88
|
-
/<LandmarkIcon[^>]*data-preview-static="decorative-icon"[^>]*\/>/g,
|
|
89
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 mr-1.5" data-preview-field-path="common.vehicleActions.financeIcon" title="Click to edit finance icon"><EditableIcon name={(siteData?.content?.common as any)?.vehicleActions?.financeIcon ?? "landmark"} className="size-4" /></span>'
|
|
90
|
-
);
|
|
91
|
-
// Replace BellIcon
|
|
92
|
-
code = code.replace(
|
|
93
|
-
/<BellIcon[^>]*data-preview-static="decorative-icon"[^>]*\/>/g,
|
|
94
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 mr-1.5" data-preview-field-path="common.vehicleActions.alertIcon" title="Click to edit alert icon"><EditableIcon name={(siteData?.content?.common as any)?.vehicleActions?.alertIcon ?? "bell"} className="size-4" /></span>'
|
|
95
|
-
);
|
|
96
|
-
// Replace CalculatorIcon
|
|
97
|
-
code = code.replace(
|
|
98
|
-
/<CalculatorIcon[^>]*data-preview-static="decorative-icon"[^>]*\/>/g,
|
|
99
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 mr-1.5" data-preview-field-path="common.vehicleActions.calculatorIcon" title="Click to edit calculator icon"><EditableIcon name={(siteData?.content?.common as any)?.vehicleActions?.calculatorIcon ?? "calculator"} className="size-4" /></span>'
|
|
100
|
-
);
|
|
101
|
-
fs.writeFileSync(filePath, code, 'utf8');
|
|
102
|
-
console.log('Patched components/vehicles/vehicle-actions.tsx');
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// 3. Patch app/(public)/trade-in/page.tsx
|
|
106
|
-
{
|
|
107
|
-
const filePath = path.join(rootDir, 'app', '(public)', 'trade-in', 'page.tsx');
|
|
108
|
-
let code = fs.readFileSync(filePath, 'utf8');
|
|
109
|
-
if (!code.includes('EditableIcon')) {
|
|
110
|
-
code = 'import { EditableIcon } from "@/src/components/ui/EditableIcon";\n' + code;
|
|
19
|
+
function patchUniversalIcons(projectDir, dryRun = false, log = () => {}) {
|
|
20
|
+
if (!projectDir || typeof projectDir !== 'string' || !fs.existsSync(projectDir)) {
|
|
21
|
+
return;
|
|
111
22
|
}
|
|
112
|
-
code = code.replace(
|
|
113
|
-
/<RefreshCwIcon[^>]*data-preview-static="decorative-icon"[^>]*\/>/g,
|
|
114
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 mr-1.5" data-preview-field-path="trade-in.upgradeEstimatorIcon" title="Click to edit estimator icon"><EditableIcon name={(siteData?.content?.["trade-in"] as any)?.upgradeEstimatorIcon ?? "refresh-cw"} className="size-4" /></span>'
|
|
115
|
-
);
|
|
116
|
-
code = code.replace(
|
|
117
|
-
/<Icon className="size-6 text-primary" aria-hidden data-preview-static="decorative-icon" \/>/g,
|
|
118
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 text-primary" data-preview-field-path={`trade-in.step${i + 1}Icon`} title="Click to edit step icon"><EditableIcon name={(siteData?.content?.["trade-in"] as any)?.[`step${i + 1}Icon`] ?? ["car-front", "camera", "handshake", "refresh-cw"][i]} className="size-6" /></span>'
|
|
119
|
-
);
|
|
120
|
-
fs.writeFileSync(filePath, code, 'utf8');
|
|
121
|
-
console.log('Patched app/(public)/trade-in/page.tsx');
|
|
122
|
-
}
|
|
123
23
|
|
|
124
|
-
|
|
125
|
-
{
|
|
126
|
-
|
|
127
|
-
let code = fs.readFileSync(filePath, 'utf8');
|
|
128
|
-
if (!code.includes('EditableIcon')) {
|
|
129
|
-
code = 'import { EditableIcon } from "@/src/components/ui/EditableIcon";\n' + code;
|
|
24
|
+
const siteDataPath = path.join(projectDir, 'data', 'site-data.json');
|
|
25
|
+
if (!fs.existsSync(siteDataPath)) {
|
|
26
|
+
return;
|
|
130
27
|
}
|
|
131
|
-
code = code.replace(
|
|
132
|
-
/<Icon className="mb-4 size-6 text-primary" aria-hidden data-preview-static="decorative-icon" \/>/g,
|
|
133
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 text-primary mb-4" data-preview-field-path={`about.principle${PRINCIPLES.findIndex(p => p.title === title) + 1}Icon`} title="Click to edit principle icon"><EditableIcon name={(siteData?.content?.about as any)?.[`principle${PRINCIPLES.findIndex(p => p.title === title) + 1}Icon`] ?? ["eye", "scale", "message-circle", "file-search"][PRINCIPLES.findIndex(p => p.title === title)]} className="size-6" /></span>'
|
|
134
|
-
);
|
|
135
|
-
fs.writeFileSync(filePath, code, 'utf8');
|
|
136
|
-
console.log('Patched app/(public)/about/page.tsx');
|
|
137
|
-
}
|
|
138
28
|
|
|
139
|
-
|
|
140
|
-
{
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
code = 'import { EditableIcon } from "@/src/components/ui/EditableIcon";\n' + code;
|
|
29
|
+
let siteData;
|
|
30
|
+
try {
|
|
31
|
+
siteData = JSON.parse(fs.readFileSync(siteDataPath, 'utf8'));
|
|
32
|
+
} catch {
|
|
33
|
+
return;
|
|
145
34
|
}
|
|
146
|
-
code = code.replace(
|
|
147
|
-
/<Icon className="size-5" aria-hidden data-preview-static="decorative-icon" \/>/g,
|
|
148
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 text-primary" data-preview-field-path={`source-a-car.step${i + 1}Icon`} title="Click to edit step icon"><EditableIcon name={(siteData?.content?.["source-a-car"] as any)?.[`step${i + 1}Icon`] ?? ["clipboard-list", "message-circle", "search"][i]} className="size-5" /></span>'
|
|
149
|
-
);
|
|
150
|
-
fs.writeFileSync(filePath, code, 'utf8');
|
|
151
|
-
console.log('Patched app/(public)/source-a-car/page.tsx');
|
|
152
|
-
}
|
|
153
35
|
|
|
154
|
-
|
|
155
|
-
{
|
|
156
|
-
const filePath = path.join(rootDir, 'components', 'vehicles', 'compare-view.tsx');
|
|
157
|
-
let code = fs.readFileSync(filePath, 'utf8');
|
|
158
|
-
if (!code.includes('EditableIcon')) {
|
|
159
|
-
code = 'import { EditableIcon } from "@/src/components/ui/EditableIcon";\n' + code;
|
|
160
|
-
}
|
|
161
|
-
code = code.replace(
|
|
162
|
-
/<TrophyIcon className="mt-0.5 size-5 shrink-0 text-primary" aria-hidden data-preview-static="decorative-icon" \/>/g,
|
|
163
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 mt-0.5 shrink-0 text-primary" data-preview-field-path="compare.trophyIcon" title="Click to edit trophy icon"><EditableIcon name={(siteData?.content?.compare as any)?.trophyIcon ?? "trophy"} className="size-5" /></span>'
|
|
164
|
-
);
|
|
165
|
-
fs.writeFileSync(filePath, code, 'utf8');
|
|
166
|
-
console.log('Patched components/vehicles/compare-view.tsx');
|
|
167
|
-
}
|
|
36
|
+
if (!siteData.content) siteData.content = {};
|
|
37
|
+
if (!siteData.content.common) siteData.content.common = {};
|
|
168
38
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
let code = fs.readFileSync(filePath, 'utf8');
|
|
173
|
-
if (!code.includes('EditableIcon')) {
|
|
174
|
-
code = 'import { EditableIcon } from "@/src/components/ui/EditableIcon";\n' + code;
|
|
175
|
-
}
|
|
176
|
-
code = code.replace(
|
|
177
|
-
/<CameraIcon className="mt-0.5 size-4 shrink-0 text-primary" aria-hidden data-preview-static="decorative-icon" \/>/g,
|
|
178
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 mt-0.5 shrink-0 text-primary" data-preview-field-path="trade-in.cameraIcon" title="Click to edit camera icon"><EditableIcon name={(siteData?.content?.["trade-in"] as any)?.cameraIcon ?? "camera"} className="size-4" /></span>'
|
|
179
|
-
);
|
|
180
|
-
fs.writeFileSync(filePath, code, 'utf8');
|
|
181
|
-
console.log('Patched components/whatsapp/trade-in-form.tsx');
|
|
182
|
-
}
|
|
39
|
+
setDeep(siteData.content, ['common', 'whatsapp', 'copyIcon'], 'copy');
|
|
40
|
+
setDeep(siteData.content, ['common', 'whatsapp', 'icon'], 'message-circle');
|
|
41
|
+
setDeep(siteData.content, ['common', 'search', 'searchIcon'], 'search');
|
|
183
42
|
|
|
184
|
-
|
|
185
|
-
{
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
code = code.replace(
|
|
192
|
-
/<CopyIcon data-icon="inline-start" data-preview-static="decorative-icon" \/>/g,
|
|
193
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 mr-1.5" data-preview-field-path="common.whatsapp.copyIcon" title="Click to edit copy icon"><EditableIcon name={(siteData?.content?.common as any)?.whatsapp?.copyIcon ?? "copy"} className="size-4" /></span>'
|
|
194
|
-
);
|
|
195
|
-
fs.writeFileSync(filePath, code, 'utf8');
|
|
196
|
-
console.log('Patched components/whatsapp/whatsapp-provider.tsx');
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// 9. Patch components/vehicles/quick-search.tsx
|
|
200
|
-
{
|
|
201
|
-
const filePath = path.join(rootDir, 'components', 'vehicles', 'quick-search.tsx');
|
|
202
|
-
let code = fs.readFileSync(filePath, 'utf8');
|
|
203
|
-
if (!code.includes('EditableIcon')) {
|
|
204
|
-
code = 'import { EditableIcon } from "@/src/components/ui/EditableIcon";\nimport { useSiteData } from "@deneb-ui/ui";\n' + code;
|
|
205
|
-
}
|
|
206
|
-
if (!code.includes('const siteData = useSiteData();')) {
|
|
207
|
-
code = code.replace(
|
|
208
|
-
/(export function QuickSearch\([^)]*\)\s*\{)/,
|
|
209
|
-
'$1\n const siteData = useSiteData();'
|
|
210
|
-
);
|
|
43
|
+
if (!dryRun) {
|
|
44
|
+
try {
|
|
45
|
+
fs.writeFileSync(siteDataPath, JSON.stringify(siteData, null, 2), 'utf8');
|
|
46
|
+
log('[universal-icons] Registered common icon keys in site-data.json');
|
|
47
|
+
} catch (err) {
|
|
48
|
+
log('[universal-icons] Warning: failed to save site-data.json: ' + err.message);
|
|
49
|
+
}
|
|
211
50
|
}
|
|
212
|
-
code = code.replace(
|
|
213
|
-
/<SearchIcon data-icon="inline-start" data-preview-static="decorative-icon" \/>/g,
|
|
214
|
-
'<span className="inline-flex cursor-pointer transition-transform hover:scale-110 mr-1.5" data-preview-field-path="common.search.searchIcon" title="Click to edit search icon"><EditableIcon name={(siteData?.content?.common as any)?.search?.searchIcon ?? "search"} className="size-4" /></span>'
|
|
215
|
-
);
|
|
216
|
-
fs.writeFileSync(filePath, code, 'utf8');
|
|
217
|
-
console.log('Patched components/vehicles/quick-search.tsx');
|
|
218
51
|
}
|
|
219
52
|
|
|
220
|
-
|
|
53
|
+
module.exports = {
|
|
54
|
+
patchUniversalIcons,
|
|
55
|
+
};
|
|
@@ -519,10 +519,32 @@ export function findLinksToUnselectedPages(input: {
|
|
|
519
519
|
return findings;
|
|
520
520
|
}
|
|
521
521
|
|
|
522
|
+
/** Detect links that contain the configured base path but omit its leading
|
|
523
|
+
* slash. Browsers resolve these relative to the current page and duplicate the
|
|
524
|
+
* generated-site prefix after navigation. */
|
|
525
|
+
export function findMalformedBasePathLinks(input: {
|
|
526
|
+
html: string;
|
|
527
|
+
basePath: string;
|
|
528
|
+
}) {
|
|
529
|
+
const prefix = input.basePath.replace(/^\/+|\/+$/g, '');
|
|
530
|
+
if (!prefix) return [];
|
|
531
|
+
const findings = new Set<string>();
|
|
532
|
+
for (const match of input.html.matchAll(
|
|
533
|
+
/<[a-z][^>]*\b(?:href|formaction|data-href|data-route|data-url)\s*=\s*(?:"([^"]*)"|'([^']*)')[^>]*>/gi,
|
|
534
|
+
)) {
|
|
535
|
+
const value = (match[1] ?? match[2] ?? '').trim();
|
|
536
|
+
const path = value.split(/[?#]/, 1)[0].replace(/^\.\//, '');
|
|
537
|
+
if (path === prefix || path.startsWith(`${prefix}/`)) {
|
|
538
|
+
findings.add(value);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return [...findings];
|
|
542
|
+
}
|
|
543
|
+
|
|
522
544
|
/**
|
|
523
545
|
* Next's client router applies next.config `basePath` automatically. Wrapping
|
|
524
|
-
* a router destination in a helper that also prepends the base path
|
|
525
|
-
* the generated-site prefix at runtime.
|
|
546
|
+
* a router destination in a package helper that also prepends the base path
|
|
547
|
+
* duplicates the generated-site prefix at runtime.
|
|
526
548
|
*/
|
|
527
549
|
export function findDoubleBasePathNextRouterCalls(source: string) {
|
|
528
550
|
const findings: Array<{
|