@popina/cli 5.0.1-20260204192447Z โ 5.0.1
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": "@popina/cli",
|
|
3
|
-
"version": "5.0.1
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"description": "Popina CLI",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"author": "Franรงois Veauvy",
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"eslint": "^9.19.0",
|
|
23
|
-
"@pragma/config": "3.
|
|
24
|
-
"@pragma/eslint": "1.3.
|
|
23
|
+
"@pragma/config": "3.1.0",
|
|
24
|
+
"@pragma/eslint": "1.3.6",
|
|
25
25
|
"@pragma/tsconfig": "1.0.2"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import fs from 'fs'
|
|
2
|
+
import { createRequire } from 'module'
|
|
2
3
|
import path from 'path'
|
|
3
4
|
import type { PlopTypes } from '@turbo/gen'
|
|
4
5
|
|
|
6
|
+
const require = createRequire(import.meta.url)
|
|
7
|
+
|
|
5
8
|
export const generatorIcon = (plop: PlopTypes.NodePlopAPI) => {
|
|
9
|
+
const absoluteUiIconsPath = path.resolve(
|
|
10
|
+
plop.getDestBasePath(),
|
|
11
|
+
'../../packages/ui/src/icons',
|
|
12
|
+
)
|
|
13
|
+
const absoluteUiPackageRoot = path.resolve(
|
|
14
|
+
plop.getDestBasePath(),
|
|
15
|
+
'../../packages/ui',
|
|
16
|
+
)
|
|
17
|
+
|
|
6
18
|
plop.setGenerator('icon', {
|
|
7
19
|
description: 'Create a new icon in @pragma/ui',
|
|
8
20
|
prompts: [
|
|
9
|
-
// Prompt the user to choose how to create the icon
|
|
10
21
|
{
|
|
11
22
|
type: 'list',
|
|
12
23
|
name: 'iconSource',
|
|
@@ -16,7 +27,6 @@ export const generatorIcon = (plop: PlopTypes.NodePlopAPI) => {
|
|
|
16
27
|
'๐น Create Custom SVG',
|
|
17
28
|
],
|
|
18
29
|
},
|
|
19
|
-
// Prompt to enter the name of the Lucide icon to import (if chosen)
|
|
20
30
|
{
|
|
21
31
|
type: 'input',
|
|
22
32
|
name: 'importedIconName',
|
|
@@ -25,67 +35,50 @@ export const generatorIcon = (plop: PlopTypes.NodePlopAPI) => {
|
|
|
25
35
|
answers.iconSource ===
|
|
26
36
|
'๐ธ Import Lucide React from "https://lucide.dev/icons/"',
|
|
27
37
|
validate: (input) => {
|
|
28
|
-
if (!input)
|
|
29
|
-
return 'Icon name is required.'
|
|
30
|
-
}
|
|
38
|
+
if (!input) return 'Icon name is required.'
|
|
31
39
|
|
|
32
|
-
// Trim and convert the icon name to PascalCase
|
|
33
40
|
const importedIconName = input.trim()
|
|
34
41
|
const pascalCaseImportedIconName =
|
|
35
42
|
importedIconName[0].toUpperCase() + importedIconName.slice(1)
|
|
36
43
|
const importedIconFileName = `${importedIconName}.js`
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
const importedIconFilePath = path.join(
|
|
40
|
-
plop.getDestBasePath(),
|
|
41
|
-
'/node_modules/lucide-react/dist/esm/icons/' + importedIconFileName,
|
|
42
|
-
)
|
|
43
|
-
const iconIndexFilePath = path.join(
|
|
44
|
-
plop.getDestBasePath(),
|
|
45
|
-
'packages/ui/src/icons/index.tsx',
|
|
46
|
-
)
|
|
45
|
+
const iconIndexFilePath = path.join(absoluteUiIconsPath, 'index.tsx')
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
try {
|
|
48
|
+
require.resolve(
|
|
49
|
+
`lucide-react/dist/esm/icons/${importedIconFileName}`,
|
|
50
|
+
{
|
|
51
|
+
paths: [absoluteUiPackageRoot],
|
|
52
|
+
},
|
|
53
|
+
)
|
|
54
|
+
} catch (error) {
|
|
55
|
+
return `The icon "${importedIconName}" is not found in Lucide React. Verify: https://lucide.dev/icons/`
|
|
51
56
|
}
|
|
52
57
|
|
|
53
|
-
// Check if the Lucide icon name already exists in the index.tsx file
|
|
54
58
|
if (fs.existsSync(iconIndexFilePath)) {
|
|
55
59
|
const iconIndexContent = fs.readFileSync(iconIndexFilePath, 'utf-8')
|
|
56
60
|
const iconIndexPattern = new RegExp(
|
|
57
61
|
`\\b${pascalCaseImportedIconName}\\b`,
|
|
58
62
|
)
|
|
59
|
-
|
|
60
63
|
if (iconIndexPattern.test(iconIndexContent)) {
|
|
61
|
-
return `The icon name "${pascalCaseImportedIconName}" already exists in
|
|
64
|
+
return `The icon name "${pascalCaseImportedIconName}" already exists in index.tsx.`
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
|
-
|
|
65
67
|
return true
|
|
66
68
|
},
|
|
67
69
|
},
|
|
68
|
-
// Prompt to enter the name of the custom SVG icon (if chosen)
|
|
69
70
|
{
|
|
70
71
|
type: 'input',
|
|
71
72
|
name: 'customIconName',
|
|
72
73
|
message: 'What is the name of the icon you want to create?',
|
|
73
74
|
when: (answers) => answers.iconSource === '๐น Create Custom SVG',
|
|
74
75
|
validate: (input) => {
|
|
75
|
-
if (!input)
|
|
76
|
-
return 'Icon name is required.'
|
|
77
|
-
}
|
|
76
|
+
if (!input) return 'Icon name is required.'
|
|
78
77
|
|
|
79
|
-
// Trim and convert the icon name to PascalCase
|
|
80
78
|
const pascalCaseCustomIconName = plop.getHelper('pascalCase')(input)
|
|
81
79
|
|
|
82
|
-
|
|
83
|
-
const customIconFilePath = path.join(
|
|
84
|
-
plop.getDestBasePath(),
|
|
85
|
-
'packages/ui/src/icons/index.tsx',
|
|
86
|
-
)
|
|
80
|
+
const customIconFilePath = path.join(absoluteUiIconsPath, 'index.tsx')
|
|
87
81
|
|
|
88
|
-
// Check if the custom SVG icon file already exists
|
|
89
82
|
if (fs.existsSync(customIconFilePath)) {
|
|
90
83
|
const iconIndexContent = fs.readFileSync(
|
|
91
84
|
customIconFilePath,
|
|
@@ -94,12 +87,10 @@ export const generatorIcon = (plop: PlopTypes.NodePlopAPI) => {
|
|
|
94
87
|
const iconIndexPattern = new RegExp(
|
|
95
88
|
`\\b${pascalCaseCustomIconName}\\b`,
|
|
96
89
|
)
|
|
97
|
-
|
|
98
90
|
if (iconIndexPattern.test(iconIndexContent)) {
|
|
99
|
-
return `The icon name "${pascalCaseCustomIconName}" already exists in
|
|
91
|
+
return `The icon name "${pascalCaseCustomIconName}" already exists in index.tsx.`
|
|
100
92
|
}
|
|
101
93
|
}
|
|
102
|
-
|
|
103
94
|
return true
|
|
104
95
|
},
|
|
105
96
|
},
|
|
@@ -112,16 +103,15 @@ export const generatorIcon = (plop: PlopTypes.NodePlopAPI) => {
|
|
|
112
103
|
const camelCaseCustomName = plop.getHelper('camelCase')(iconName)
|
|
113
104
|
const customIconFileName = `${iconName}.tsx`
|
|
114
105
|
const importStatement = `import { ${iconName} } from './${iconName}'`
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
106
|
+
const finalCustomIconPath = path.join(
|
|
107
|
+
absoluteUiIconsPath,
|
|
108
|
+
customIconFileName,
|
|
118
109
|
)
|
|
119
110
|
|
|
120
|
-
// Add actions for '๐น Create Custom SVG'
|
|
121
111
|
actions.push(
|
|
122
112
|
{
|
|
123
113
|
type: 'add',
|
|
124
|
-
path:
|
|
114
|
+
path: finalCustomIconPath,
|
|
125
115
|
templateFile: 'templates/icon/icon-react.hbs',
|
|
126
116
|
},
|
|
127
117
|
{
|
|
@@ -139,41 +129,38 @@ export const generatorIcon = (plop: PlopTypes.NodePlopAPI) => {
|
|
|
139
129
|
)
|
|
140
130
|
}
|
|
141
131
|
|
|
142
|
-
if (
|
|
143
|
-
answers &&
|
|
144
|
-
answers.iconSource ===
|
|
145
|
-
'๐ธ Import Lucide React from "https://lucide.dev/icons/"'
|
|
146
|
-
) {
|
|
132
|
+
if (answers && answers.iconSource.includes('Import Lucide React')) {
|
|
147
133
|
const importedIconName = answers.importedIconName
|
|
148
|
-
|
|
149
134
|
let pascalCaseImportedIconName: string
|
|
150
135
|
|
|
151
136
|
if (importedIconName.includes('-')) {
|
|
152
|
-
const splittedAnswer: string[] = answers.importedIconName.split('-')
|
|
153
|
-
|
|
137
|
+
const splittedAnswer: string[] = answers.importedIconName.split('-')
|
|
154
138
|
pascalCaseImportedIconName = splittedAnswer.reduce<string>(
|
|
155
|
-
(acc, word) =>
|
|
156
|
-
return acc + word[0].toUpperCase() + word.slice(1)
|
|
157
|
-
},
|
|
139
|
+
(acc, word) => acc + word[0].toUpperCase() + word.slice(1),
|
|
158
140
|
'',
|
|
159
141
|
)
|
|
160
|
-
console.log(pascalCaseImportedIconName)
|
|
161
142
|
} else {
|
|
162
143
|
pascalCaseImportedIconName =
|
|
163
144
|
importedIconName[0].toUpperCase() + importedIconName.slice(1)
|
|
164
145
|
}
|
|
165
146
|
|
|
166
147
|
const importedIconFileName = `${importedIconName}.js`
|
|
167
|
-
const importedIconFilePath = path.join(
|
|
168
|
-
plop.getDestBasePath(),
|
|
169
|
-
'/node_modules/lucide-react/dist/esm/icons/' + importedIconFileName,
|
|
170
|
-
)
|
|
171
148
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
149
|
+
let iconExists = false
|
|
150
|
+
try {
|
|
151
|
+
require.resolve(
|
|
152
|
+
`lucide-react/dist/esm/icons/${importedIconFileName}`,
|
|
153
|
+
{
|
|
154
|
+
paths: [absoluteUiPackageRoot],
|
|
155
|
+
},
|
|
156
|
+
)
|
|
157
|
+
iconExists = true
|
|
158
|
+
} catch (e) {
|
|
159
|
+
iconExists = false
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (iconExists) {
|
|
163
|
+
const importKey = `${pascalCaseImportedIconName[0].toLowerCase()}${pascalCaseImportedIconName.slice(1)}`
|
|
177
164
|
actions.push(
|
|
178
165
|
{
|
|
179
166
|
type: 'modify',
|
|
@@ -188,10 +175,6 @@ export const generatorIcon = (plop: PlopTypes.NodePlopAPI) => {
|
|
|
188
175
|
template: `\n ${importKey}: ${pascalCaseImportedIconName},`,
|
|
189
176
|
},
|
|
190
177
|
)
|
|
191
|
-
} else {
|
|
192
|
-
console.error(
|
|
193
|
-
`The file "${importedIconFileName}" doesn't exist in the specified path.`,
|
|
194
|
-
)
|
|
195
178
|
}
|
|
196
179
|
}
|
|
197
180
|
|
|
@@ -5,15 +5,14 @@ interface {{pascalCase customIconName}}Props extends React.SVGProps<SVGSVGElemen
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
export const {{pascalCase customIconName}} =
|
|
8
|
-
({ ref, className
|
|
8
|
+
({ ref, className }: {{pascalCase customIconName}}Props) => {
|
|
9
9
|
return (
|
|
10
10
|
<svg
|
|
11
11
|
xmlns="http://www.w3.org/2000/svg"
|
|
12
12
|
width="24"
|
|
13
13
|
height="24"
|
|
14
14
|
viewBox="0 0 24 24"
|
|
15
|
-
fill="
|
|
16
|
-
stroke="#f62992"
|
|
15
|
+
fill="currentColor"
|
|
17
16
|
strokeWidth="2"
|
|
18
17
|
strokeLinecap="round"
|
|
19
18
|
strokeLinejoin="round">
|
|
@@ -27,6 +26,6 @@ export const {{pascalCase customIconName}} =
|
|
|
27
26
|
/**
|
|
28
27
|
* TODO: Then add in svg
|
|
29
28
|
* ref={ref}
|
|
30
|
-
* className={
|
|
29
|
+
* className={className}
|
|
31
30
|
* fill="currentColor"
|
|
32
31
|
*/
|