Skip to content

Commit c8fb459

Browse files
authored
release: version 2025.5.16 (#27)
1 parent c66ea20 commit c8fb459

12 files changed

Lines changed: 203 additions & 97 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ node_modules/
66

77
.DS_Store
88

9+
!.prettierrc.json
910
!.editorconfig
1011
!CONTRIBUTING.md
1112
!LICENSE

.npmignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
*
22

3+
!CONTRIBUTING.md
4+
!LICENSE
35
!main.js
46
!package.json
57
!README.md
6-
!LICENSE
7-
!CONTRIBUTING.md
88

99
!generators/
1010
!generators/**

.prettierrc.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"semi": false,
3+
"singleQuote": true,
4+
"printWidth": 120,
5+
"trailingComma": "all",
6+
"arrowParens": "avoid",
7+
"bracketSpacing": true,
8+
"htmlWhitespaceSensitivity": "ignore"
9+
}

main.js

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env node
22

3-
import fs from 'fs'
4-
import path from 'path'
3+
import { readdirSync, existsSync, readFileSync, writeFileSync } from 'fs'
4+
import { resolve, join } from 'path'
55

66
// packages
77
import chalk from 'chalk'
@@ -12,10 +12,17 @@ import { config } from './utils/config.js'
1212
import { colors } from './utils/colors.js'
1313
import { RGBToHSL, HSLToRGB } from './utils/convert.js'
1414
import { handleSingleColor, handlePaletteRanges } from './utils/palette.js'
15+
import { getProjectRoot } from './utils/getProjectRoot.js'
16+
17+
const projectRoot = getProjectRoot()
1518

1619
async function main() {
1720
console.clear()
18-
console.log('🎨 Welcome to Style-Forge Generator CLI')
21+
22+
console.log(`
23+
${chalk.hex('#00ffff').bold(' ⚡ STYLE-FORGE.COLORS ⚡ ')}
24+
${chalk.hex('#f0f').bold('⚛️ Atomic HSL-based generator')}
25+
`)
1926

2027
const { mode } = await inquirer.prompt([
2128
{
@@ -38,7 +45,7 @@ async function main() {
3845
process.exit(0)
3946
}
4047

41-
let format = config.defaultFormat || 'HSL'
48+
let format = config.modules.colors.defaultFormat || 'HSL'
4249

4350
if (mode === '🎨 Generate CSS file by') {
4451
const formatAnswer = await inquirer.prompt([
@@ -47,7 +54,7 @@ async function main() {
4754
name: 'format',
4855
message: 'Select input format:',
4956
choices: ['HSL', 'RGB', 'HEX'],
50-
default: config.defaultFormat || 'HSL',
57+
default: config.modules.colors.defaultFormat || 'HSL',
5158
},
5259
])
5360
format = formatAnswer.format
@@ -84,7 +91,7 @@ async function main() {
8491
type: 'input',
8592
name: 'hex',
8693
message: 'HEX (e.g. #ff00aa):',
87-
validate: v => /^#?[0-9A-Fa-f]{6}$/.test(v)
94+
validate: v => /^#?[0-9A-Fa-f]{6}$/.test(v),
8895
},
8996
])
9097
const hex = input.hex.replace('#', '')
@@ -101,17 +108,23 @@ async function main() {
101108
await handleSingleColor(H, S, L)
102109
}
103110
if (mode === '📐 Generate from paletteRanges (from config)') {
104-
if (config.paletteRanges && Array.isArray(config.paletteRanges)) {
105-
await handlePaletteRanges(config.paletteRanges)
111+
if (config.modules.colors.paletteRanges && Array.isArray(config.modules.colors.paletteRanges)) {
112+
await handlePaletteRanges(config.modules.colors.paletteRanges)
106113
} else {
107-
console.log('⚠️ No paletteRanges found in config.')
114+
console.log('⚠️ No paletteRanges found in config.modules.colors.paletteRanges')
108115
}
109116
}
110117
if (mode === '🌈 Generate full palette for H / S range') {
111118
const { h, s, step } = await inquirer.prompt([
112119
{ type: 'input', name: 'h', message: 'Hue (0–360):', validate: v => !isNaN(v) && v >= 0 && v <= 360 },
113120
{ type: 'input', name: 's', message: 'Saturation (0–100):', validate: v => !isNaN(v) && v >= 0 && v <= 100 },
114-
{ type: 'input', name: 'step', message: 'Step for Lightness (1–100):', default: 5, validate: v => !isNaN(v) && v > 0 && v <= 100 }
121+
{
122+
type: 'input',
123+
name: 'step',
124+
message: 'Step for Lightness (1–100):',
125+
default: 5,
126+
validate: v => !isNaN(v) && v > 0 && v <= 100,
127+
},
115128
])
116129
const H = parseInt(h)
117130
const S = parseInt(s)
@@ -153,24 +166,23 @@ async function main() {
153166
}
154167
}
155168
if (mode === '🧩 Combine CSS files') {
156-
const outputDir = path.resolve(config.outputDir)
157-
const srcDir = path.resolve(config.outputDir, config.atomicSubDir)
169+
const outputDir = resolve(projectRoot, config.output.dir, config.modules.colors.dir)
170+
const srcDir = resolve(outputDir, config.modules.colors.atomicSubDir)
158171

159-
if (!fs.existsSync(srcDir)) {
172+
if (!existsSync(srcDir)) {
160173
console.log(`❌ Folder "${srcDir}" not found.`)
161174
return
162175
}
163176

164177
const replace = x => x.replace('.css', '').split('.').map(Number)
165178

166-
const allFiles = fs
167-
.readdirSync(srcDir)
168-
.filter(name => name.endsWith('.css') && !name.startsWith('combined'))
169-
.sort((a, b) => {
170-
const [ha, sa, la] = replace(a)
171-
const [hb, sb, lb] = replace(b)
172-
return ha - hb || sa - sb || la - lb
173-
})
179+
const allFiles = readdirSync(srcDir)
180+
.filter(name => name.endsWith('.css') && !name.startsWith('combined'))
181+
.sort((a, b) => {
182+
const [ha, sa, la] = replace(a)
183+
const [hb, sb, lb] = replace(b)
184+
return ha - hb || sa - sb || la - lb
185+
})
174186

175187
if (allFiles.length === 0) {
176188
console.log(`❌ No .css files found in "${srcDir}" — nothing to combine.`)
@@ -207,11 +219,10 @@ async function main() {
207219
validate: input => {
208220
if (!input.trim()) return true
209221
const indexes = input.split(',').map(i => parseInt(i.trim(), 10))
210-
const isValid = indexes.length === selected.length &&
211-
indexes.every(i => i > 0 && i <= selected.length)
222+
const isValid = indexes.length === selected.length && indexes.every(i => i > 0 && i <= selected.length)
212223
return isValid || 'Enter valid sequence using all indexes (e.g. 2,1,3)'
213-
}
214-
}
224+
},
225+
},
215226
])
216227

217228
let orderedFiles = selected
@@ -232,31 +243,26 @@ async function main() {
232243
},
233244
])
234245

235-
const targetPath = path.join(outputDir, `${name}.css`)
246+
const targetPath = join(outputDir, `${name}.css`)
236247
let combined = ''
237248

238249
for (const file of orderedFiles) {
239-
const content = fs.readFileSync(path.join(srcDir, file), 'utf-8')
250+
const content = readFileSync(join(srcDir, file), 'utf-8')
240251
combined += `/* ${file} */\n` + content + '\n\n'
241252
}
242253

243-
fs.writeFileSync(targetPath, combined)
254+
writeFileSync(targetPath, combined)
244255
console.log(`✅ Combined ${orderedFiles.length} files into ${name}.css`)
245256
console.log(`📦 Size: ${(Buffer.byteLength(combined) / 1024).toFixed(2)} KB`)
246257
}
247258
}
248259

249-
(async function loop() {
250-
while (true) {
251-
try {
252-
await main()
253-
} catch (err) {
254-
if (err?.isTtyError || err?.message?.includes('SIGINT') || err.name === 'ExitPromptError') {
255-
console.log('\n👋 Bye!')
256-
break
257-
}
258-
console.error('❌ Unhandled error:', err)
259-
break
260-
}
260+
main().catch(err => {
261+
if (err?.isTtyError || err?.message?.includes('SIGINT') || err.name === 'ExitPromptError') {
262+
console.log('\n👋 Bye!\n')
263+
process.exit(0)
261264
}
262-
})()
265+
266+
console.error('\n❌ Unhandled error:', err)
267+
process.exit(1)
268+
})

package.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "style-forge.colors",
3-
"version": "2025.5.13",
3+
"version": "2025.5.16",
44
"description": "Style-Forge Colors: atomic HSL-based color palette generator and CSS module for scalable design systems.",
55
"type": "module",
66
"bin": {
@@ -38,5 +38,11 @@
3838
"homepage": "https://style-forge.github.io/colors/",
3939
"publishConfig": {
4040
"registry": "https://registry.npmjs.org/"
41+
},
42+
"engines": {
43+
"node": ">=18"
44+
},
45+
"devDependencies": {
46+
"prettier": "2.8.8"
4147
}
4248
}

utils/config.js

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import { existsSync, writeFileSync, readFileSync } from 'fs'
22
import { resolve } from 'path'
33
import stringify from 'json-stringify-pretty-compact'
44

5-
const configPath = resolve('style-forge.colors.config.json')
5+
// Utils
6+
import { getProjectRoot } from './getProjectRoot.js'
67

7-
const defaultConfig = {
8+
const defaultColorsConfig = {
9+
atomicSubDir: 'single',
810
defaultFormat: 'HSL',
9-
outputDir: 'src/assets/styles/colors',
10-
atomicSubDir: "single",
11+
dir: 'colors',
1112
paletteRanges: [
1213
[0, 0, [0]],
1314
[240, 100, [50]],
@@ -17,12 +18,37 @@ const defaultConfig = {
1718
[197, 71, [73]],
1819
[300, 76, [72]],
1920
[60, 100, [50]],
20-
]
21+
],
2122
}
2223

24+
const configPath = resolve(getProjectRoot(), 'styleforgerc.json')
25+
2326
if (!existsSync(configPath)) {
24-
writeFileSync(configPath, stringify(defaultConfig))
25-
console.log('🆕 Created style-forge.colors.config.json with default settings')
27+
writeFileSync(
28+
configPath,
29+
stringify({
30+
output: {
31+
dir: 'src/assets/styles',
32+
name: 'style-forge',
33+
},
34+
modules: {
35+
colors: defaultColorsConfig,
36+
},
37+
}),
38+
)
2639
}
2740

28-
export const config = JSON.parse(readFileSync(configPath, 'utf-8'))
41+
const config = JSON.parse(readFileSync(configPath, 'utf-8'))
42+
43+
config.modules = config.modules || {}
44+
config.modules.colors = config.modules.colors || {}
45+
46+
const target = config.modules.colors
47+
48+
for (const [key, value] of Object.entries(defaultColorsConfig)) {
49+
if (!(key in target)) target[key] = value
50+
}
51+
52+
writeFileSync(configPath, stringify(config, { maxLength: 100 }))
53+
54+
export { config }

0 commit comments

Comments
 (0)