beathers 5.0.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/dist/css/beathers-icons.min.css +1 -0
- package/dist/css/beathers-icons.min.css.map +1 -0
- package/dist/css/beathers.min.css +4 -0
- package/dist/css/beathers.min.css.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/scripts/BuildScssVariables.d.ts +2 -0
- package/dist/scripts/BuildScssVariables.js +111 -0
- package/dist/scripts/BuildTheme.d.ts +1 -0
- package/dist/scripts/BuildTheme.js +99 -0
- package/dist/scripts/CallNewVariables.d.ts +1 -0
- package/dist/scripts/CallNewVariables.js +17 -0
- package/dist/scripts/LoadUserConfigs.d.ts +2 -0
- package/dist/scripts/LoadUserConfigs.js +42 -0
- package/dist/scripts/Merge.d.ts +2 -0
- package/dist/scripts/Merge.js +26 -0
- package/dist/scripts/ReadDefaultValues.d.ts +2 -0
- package/dist/scripts/ReadDefaultValues.js +168 -0
- package/dist/scripts/cli.d.ts +2 -0
- package/dist/scripts/cli.js +14 -0
- package/dist/scripts/types.d.ts +57 -0
- package/dist/scripts/types.js +1 -0
- package/package.json +84 -0
- package/readme.md +235 -0
- package/src/scss/_variables.scss +305 -0
- package/src/scss/beathers-icons.min.scss +265 -0
- package/src/scss/beathers.min.scss +13 -0
- package/src/scss/functions/_colors.scss +232 -0
- package/src/scss/functions/_mediaQueries.scss +128 -0
- package/src/scss/functions/_others.scss +83 -0
- package/src/scss/functions/_typographic.scss +125 -0
- package/src/scss/functions/_validations.scss +256 -0
- package/src/scss/settings/_configs.scss +366 -0
- package/src/scss/settings/_defaults.scss +251 -0
- package/src/scss/settings/_index.scss +68 -0
- package/src/scss/settings/_resets.scss +103 -0
- package/src/scss/style/_colors.scss +139 -0
- package/src/scss/style/_grid.scss +92 -0
- package/src/scss/style/_shaping.scss +372 -0
- package/src/scss/style/_typographic.scss +304 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
export function BuildScssVariables(theme) {
|
|
2
|
+
const { colors, roles, settings, typography } = theme;
|
|
3
|
+
let scss = '// Generated by BuildTheme.ts\n // Do not edit this file directly\n\n';
|
|
4
|
+
if (colors) {
|
|
5
|
+
scss += '\n\n// --- Colors ---\n';
|
|
6
|
+
scss += '$colors: (\n';
|
|
7
|
+
for (const [name, modes] of Object.entries(colors)) {
|
|
8
|
+
scss += `"${name}": (\n`;
|
|
9
|
+
for (const [mode, value] of Object.entries(modes)) {
|
|
10
|
+
scss += `"${mode}": ${value},\n`;
|
|
11
|
+
}
|
|
12
|
+
scss += `),\n`;
|
|
13
|
+
}
|
|
14
|
+
scss += ');\n';
|
|
15
|
+
}
|
|
16
|
+
if (typography) {
|
|
17
|
+
scss += '\n\n// --- Typography ---\n';
|
|
18
|
+
if (typography?.defaultFontFamilies?.length)
|
|
19
|
+
scss += `$defaultFontFamilies: ${typography.defaultFontFamilies.join(', ').replace(/"/g, '')};\n`;
|
|
20
|
+
if (typography?.fontMainPath)
|
|
21
|
+
scss += `$fontMainPath: "${typography.fontMainPath}";\n`;
|
|
22
|
+
if (typography?.fontFormat)
|
|
23
|
+
scss += `$fontFormat: "${typography.fontFormat}";\n`;
|
|
24
|
+
if (typography?.fontWeights)
|
|
25
|
+
scss += `$fontWeights: (${typography.fontWeights.map((fW) => `"${fW}"`).join(', ')});\n`;
|
|
26
|
+
if (typography?.fontStyles?.length)
|
|
27
|
+
scss += `$fontStyles: (${typography.fontStyles.map((fS) => `"${fS}"`).join(', ')});\n`;
|
|
28
|
+
if (typography?.fontSizes) {
|
|
29
|
+
scss += '$fontSizes: (\n';
|
|
30
|
+
for (const [name, value] of Object.entries(typography.fontSizes)) {
|
|
31
|
+
scss += `"${name}": ${value},\n`;
|
|
32
|
+
}
|
|
33
|
+
scss += ');\n';
|
|
34
|
+
}
|
|
35
|
+
if (typography?.textTruncate)
|
|
36
|
+
scss += `$textTruncate: ${typography.textTruncate};\n`;
|
|
37
|
+
if (typography?.fonts) {
|
|
38
|
+
scss += '$fonts: (\n';
|
|
39
|
+
for (const [name, font] of Object.entries(typography.fonts)) {
|
|
40
|
+
scss += `"${name}": (\n`;
|
|
41
|
+
if (font?.weights)
|
|
42
|
+
scss += `"weights": (${font.weights.join(', ')}),\n`;
|
|
43
|
+
if (font?.styles)
|
|
44
|
+
scss += `"styles": (${font.styles.join(', ')}),\n`;
|
|
45
|
+
if (font?.variants) {
|
|
46
|
+
scss += `"variants": (\n`;
|
|
47
|
+
for (const [lang, variant] of Object.entries(font.variants)) {
|
|
48
|
+
scss += `"${lang}": (\n`;
|
|
49
|
+
if (variant?.title)
|
|
50
|
+
scss += `"title": ${variant.title.replace(/"/g, '')},\n`;
|
|
51
|
+
if (variant?.unicode)
|
|
52
|
+
scss += `"unicode": "${variant.unicode}",\n`;
|
|
53
|
+
if (variant?.format)
|
|
54
|
+
scss += `"format": "${variant.format}",\n`;
|
|
55
|
+
if (variant?.isLocal)
|
|
56
|
+
scss += `"isLocal": ${variant.isLocal},\n`;
|
|
57
|
+
if (variant?.url)
|
|
58
|
+
scss += `"url": "${variant.url}",\n`;
|
|
59
|
+
scss += '),\n';
|
|
60
|
+
}
|
|
61
|
+
scss += '),\n';
|
|
62
|
+
}
|
|
63
|
+
scss += '),\n';
|
|
64
|
+
}
|
|
65
|
+
scss += ');\n';
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (settings) {
|
|
69
|
+
scss += '\n\n// --- Settings ---\n';
|
|
70
|
+
if (settings?.axisDivisions)
|
|
71
|
+
scss += `$axisDivisions: ${settings.axisDivisions};\n`;
|
|
72
|
+
if (settings?.opacities)
|
|
73
|
+
scss += `$opacities: (${settings.opacities.join(', ')});\n`;
|
|
74
|
+
if (settings?.blurValues)
|
|
75
|
+
scss += `$blurValues: (${settings.blurValues.join(', ')});\n`;
|
|
76
|
+
if (settings?.insetValues)
|
|
77
|
+
scss += `$insetValues: (${settings.insetValues.join(', ')});\n`;
|
|
78
|
+
if (settings?.bordersValue)
|
|
79
|
+
scss += `$bordersValue: ${settings.bordersValue};\n`;
|
|
80
|
+
if (settings?.radiuses)
|
|
81
|
+
scss += `$radiuses: (${settings.radiuses.join(', ')});\n`;
|
|
82
|
+
if (settings?.breakpoints) {
|
|
83
|
+
scss += `$breakpoints: (\n`;
|
|
84
|
+
for (const [key, value] of Object.entries(settings.breakpoints)) {
|
|
85
|
+
scss += `${key}: ${value},\n`;
|
|
86
|
+
}
|
|
87
|
+
scss += `);\n`;
|
|
88
|
+
}
|
|
89
|
+
if (settings?.wrappers) {
|
|
90
|
+
scss += `$wrappers: (\n`;
|
|
91
|
+
for (const [key, wrapper] of Object.entries(settings.wrappers)) {
|
|
92
|
+
scss += `${key}: ${wrapper.width} ${wrapper.padding ?? ''},\n`;
|
|
93
|
+
}
|
|
94
|
+
scss += `);\n`;
|
|
95
|
+
}
|
|
96
|
+
if (settings?.guttersValues) {
|
|
97
|
+
scss += `$guttersValues: (\n`;
|
|
98
|
+
for (const [key, value] of Object.entries(settings.guttersValues)) {
|
|
99
|
+
scss += `${key}: ${value},\n`;
|
|
100
|
+
}
|
|
101
|
+
scss += `);\n`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (roles) {
|
|
105
|
+
scss += '\n\n// --- Roles ---\n';
|
|
106
|
+
for (const [key, condition] of Object.entries(roles)) {
|
|
107
|
+
scss += `$${key}: ${condition};\n`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return scss;
|
|
111
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function BuildTheme(): Promise<void>;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { LoadUserConfigs } from './LoadUserConfigs.js';
|
|
5
|
+
import { DeepMerge } from './Merge.js';
|
|
6
|
+
import { ReadDefaultValues } from './ReadDefaultValues.js';
|
|
7
|
+
import { BuildScssVariables } from './BuildScssVariables.js';
|
|
8
|
+
import { CallNewVariables } from './CallNewVariables.js';
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
const projectRoot = path.resolve(__dirname, '../..');
|
|
12
|
+
const variablesPath = path.join(projectRoot, 'src', 'scss', '_variables.scss');
|
|
13
|
+
async function defaultTheme() {
|
|
14
|
+
let values = null;
|
|
15
|
+
try {
|
|
16
|
+
values = await ReadDefaultValues([
|
|
17
|
+
path.join(projectRoot, 'src', 'scss', 'settings', '_defaults.scss'),
|
|
18
|
+
path.join(projectRoot, 'src', 'scss', 'settings', '_configs.scss'),
|
|
19
|
+
path.join(projectRoot, 'src', 'scss', 'settings', '_index.scss'),
|
|
20
|
+
], [
|
|
21
|
+
'colors',
|
|
22
|
+
'fonts',
|
|
23
|
+
'fontMainPath',
|
|
24
|
+
'fontFormat',
|
|
25
|
+
'fontWeights',
|
|
26
|
+
'fontStyles',
|
|
27
|
+
'textTruncate',
|
|
28
|
+
'defaultFontFamilies',
|
|
29
|
+
'fontSizes',
|
|
30
|
+
'axisDivisions',
|
|
31
|
+
'breakpoints',
|
|
32
|
+
'wrappers',
|
|
33
|
+
'opacities',
|
|
34
|
+
'blurValues',
|
|
35
|
+
'insetValues',
|
|
36
|
+
'guttersValues',
|
|
37
|
+
'bordersValue',
|
|
38
|
+
'radiuses',
|
|
39
|
+
'useMediaQueries',
|
|
40
|
+
'useIcons',
|
|
41
|
+
'useFontFamilies',
|
|
42
|
+
'useFontSizes',
|
|
43
|
+
'useFontShapes',
|
|
44
|
+
'useTextAligns',
|
|
45
|
+
'useTextTruncate',
|
|
46
|
+
'useColors',
|
|
47
|
+
'useColorsOpacities',
|
|
48
|
+
'useColorsLightMode',
|
|
49
|
+
'useColorsDarkMode',
|
|
50
|
+
'useCurrentColors',
|
|
51
|
+
'useRootColors',
|
|
52
|
+
'useGrid',
|
|
53
|
+
'useFlex',
|
|
54
|
+
'useTransitions',
|
|
55
|
+
'useWrappers',
|
|
56
|
+
'useShadows',
|
|
57
|
+
'useDisplays',
|
|
58
|
+
'useOverflows',
|
|
59
|
+
'useOpacities',
|
|
60
|
+
'useBlur',
|
|
61
|
+
'useObjectFits',
|
|
62
|
+
'usePositions',
|
|
63
|
+
'useInsets',
|
|
64
|
+
'useSizes',
|
|
65
|
+
'useGutters',
|
|
66
|
+
'useBorders',
|
|
67
|
+
'useTextBorders',
|
|
68
|
+
'useRadius',
|
|
69
|
+
]);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
// eslint-disable-next-line no-console
|
|
73
|
+
console.error('❌ buildCustomTheme failed:', error instanceof Error ? error.message : error);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
return values;
|
|
77
|
+
}
|
|
78
|
+
export async function BuildTheme() {
|
|
79
|
+
try {
|
|
80
|
+
const defaults = await defaultTheme();
|
|
81
|
+
const userConfigs = await LoadUserConfigs();
|
|
82
|
+
const theme = DeepMerge(defaults, userConfigs);
|
|
83
|
+
const variablesString = BuildScssVariables(theme);
|
|
84
|
+
await fs.writeFile(variablesPath, variablesString, { flag: 'w' });
|
|
85
|
+
await CallNewVariables(projectRoot);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
// eslint-disable-next-line no-console
|
|
89
|
+
console.error('Error during custom theme build:', error);
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// For backward compatibility when run directly
|
|
94
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
95
|
+
BuildTheme().catch((error) => {
|
|
96
|
+
console.error(error);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function CallNewVariables(projectRoot: string): Promise<void>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
export async function CallNewVariables(projectRoot) {
|
|
4
|
+
const scssFilePath = path.join(projectRoot, 'src', 'scss', 'beathers.min.scss');
|
|
5
|
+
if (!await fs.pathExists(scssFilePath))
|
|
6
|
+
return;
|
|
7
|
+
let scssContent = await fs.readFile(scssFilePath, 'utf8');
|
|
8
|
+
if (scssContent.includes('@use "./variables"'))
|
|
9
|
+
return;
|
|
10
|
+
const styleCommentIndex = scssContent.indexOf('// Style');
|
|
11
|
+
if (styleCommentIndex === -1)
|
|
12
|
+
return;
|
|
13
|
+
const beforeComment = scssContent.slice(0, styleCommentIndex);
|
|
14
|
+
const afterComment = scssContent.slice(styleCommentIndex);
|
|
15
|
+
scssContent = beforeComment + '@use "./variables";\n\n' + afterComment;
|
|
16
|
+
await fs.writeFile(scssFilePath, scssContent, 'utf8');
|
|
17
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
const userConfigFiles = ['beathers.configs.js', 'beathers.configs.ts', 'beathers.configs.json'];
|
|
4
|
+
function findConfigFile(basePath) {
|
|
5
|
+
for (const filename of userConfigFiles) {
|
|
6
|
+
const fullPath = path.join(basePath, filename);
|
|
7
|
+
if (fs.existsSync(fullPath))
|
|
8
|
+
return fullPath;
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
async function loadJsOrTsConfig(filePath) {
|
|
13
|
+
try {
|
|
14
|
+
const absolutePath = path.resolve(filePath);
|
|
15
|
+
const module = await import(absolutePath);
|
|
16
|
+
return module.default || module;
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
throw new Error(`Failed to load config from ${filePath}: ${error}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function loadJsonConfig(filePath) {
|
|
23
|
+
try {
|
|
24
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
25
|
+
return JSON.parse(content);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
throw new Error(`Failed to parse JSON config from ${filePath}: ${error}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function LoadUserConfigs(projectPath) {
|
|
32
|
+
const basePath = projectPath || process.cwd();
|
|
33
|
+
const configFilePath = findConfigFile(basePath);
|
|
34
|
+
if (!configFilePath)
|
|
35
|
+
return null;
|
|
36
|
+
const extension = path.extname(configFilePath);
|
|
37
|
+
if (extension === '.json')
|
|
38
|
+
return loadJsonConfig(configFilePath);
|
|
39
|
+
if (['.js', '.ts'].includes(extension))
|
|
40
|
+
return await loadJsOrTsConfig(configFilePath);
|
|
41
|
+
throw new Error(`Unsupported config file format: ${extension}`);
|
|
42
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function DeepMerge(defaults, configs) {
|
|
2
|
+
if (!configs)
|
|
3
|
+
return defaults;
|
|
4
|
+
const { colors: tColors, roles: tRoles, settings: tSettings, typography: tTypography } = defaults ?? {};
|
|
5
|
+
const { colors: sColors, roles: sRoles, settings: sSettings, typography: sTypography } = configs ?? {};
|
|
6
|
+
const colors = { ...tColors, ...sColors };
|
|
7
|
+
const roles = { ...tRoles, ...sRoles };
|
|
8
|
+
const settings = {
|
|
9
|
+
...tSettings,
|
|
10
|
+
...sSettings,
|
|
11
|
+
...(tSettings?.breakpoints ||
|
|
12
|
+
(sSettings?.breakpoints && { breakpoints: { ...tSettings?.breakpoints, ...sSettings?.breakpoints } })),
|
|
13
|
+
...(tSettings?.wrappers ||
|
|
14
|
+
(sSettings?.wrappers && { wrappers: { ...tSettings?.wrappers, ...sSettings?.wrappers } })),
|
|
15
|
+
...(tSettings?.guttersValues ||
|
|
16
|
+
(sSettings?.guttersValues && { guttersValues: { ...tSettings?.guttersValues, ...sSettings?.guttersValues } })),
|
|
17
|
+
};
|
|
18
|
+
const typography = {
|
|
19
|
+
...tTypography,
|
|
20
|
+
...sTypography,
|
|
21
|
+
...(tTypography?.fontSizes ||
|
|
22
|
+
(sTypography?.fontSizes && { fontSizes: { ...tTypography?.fontSizes, ...sTypography?.fontSizes } })),
|
|
23
|
+
...(tTypography?.fonts || (sTypography?.fonts && { fonts: { ...tTypography?.fonts, ...sTypography?.fonts } })),
|
|
24
|
+
};
|
|
25
|
+
return { colors, roles, settings, typography };
|
|
26
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
function sanitize(val) {
|
|
4
|
+
if (typeof val === 'string') {
|
|
5
|
+
const trimmed = val.trim();
|
|
6
|
+
if (trimmed === 'true')
|
|
7
|
+
return true;
|
|
8
|
+
if (trimmed === 'false')
|
|
9
|
+
return false;
|
|
10
|
+
if (!isNaN(Number(trimmed)))
|
|
11
|
+
return Number(trimmed);
|
|
12
|
+
return trimmed;
|
|
13
|
+
}
|
|
14
|
+
if (typeof val === 'object' && val !== null)
|
|
15
|
+
return Object.fromEntries(Object.entries(val).map(([k, v]) => [sanitize(k), sanitize(v)]));
|
|
16
|
+
return val;
|
|
17
|
+
}
|
|
18
|
+
function cleanString(value) {
|
|
19
|
+
let result = value;
|
|
20
|
+
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'")))
|
|
21
|
+
result = value.slice(1, -1);
|
|
22
|
+
return result.trim();
|
|
23
|
+
}
|
|
24
|
+
function cleanNumber(value) {
|
|
25
|
+
let result = null;
|
|
26
|
+
const num = Number(value);
|
|
27
|
+
if (!isNaN(num) && num.toString() === value)
|
|
28
|
+
result = num;
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
function buildArray(value) {
|
|
32
|
+
if (!value.includes(',') && !value.startsWith('(') && !value.endsWith(')'))
|
|
33
|
+
return [];
|
|
34
|
+
let raw = value;
|
|
35
|
+
if (value.startsWith('(') && value.endsWith(')'))
|
|
36
|
+
raw = value.slice(1, -1);
|
|
37
|
+
return raw.split(',').map((part) => cleanNumber(part.trim()) ?? cleanString(part.trim()));
|
|
38
|
+
}
|
|
39
|
+
function buildJson(value) {
|
|
40
|
+
const raw = value
|
|
41
|
+
.replace(/\(/g, '{')
|
|
42
|
+
.replace(/\)/g, '}')
|
|
43
|
+
.replace(/'/g, '"')
|
|
44
|
+
.replace(/([a-zA-Z0-9_]+):/g, '"$1":')
|
|
45
|
+
.replace(/:\s*"?([0-9]+)"?\.(\d+)(rem)?/g, ':"$1.$2$3"')
|
|
46
|
+
.replace(/:\s*([a-zA-Z0-9_]+)/g, ': "$1"')
|
|
47
|
+
.replace(/,\s*}/g, '\n}');
|
|
48
|
+
const parsed = JSON.parse(raw);
|
|
49
|
+
const sanitized = sanitize(parsed);
|
|
50
|
+
return sanitized;
|
|
51
|
+
}
|
|
52
|
+
function buildColors(value) {
|
|
53
|
+
const raw = value
|
|
54
|
+
.replace(/\(/g, '{')
|
|
55
|
+
.replace(/\)/g, '}')
|
|
56
|
+
.replace(/#([0-9a-fA-F]{3,6})/g, '"#$1"')
|
|
57
|
+
.replace(/,\s*}/g, '}');
|
|
58
|
+
const parsed = JSON.parse(raw);
|
|
59
|
+
return parsed;
|
|
60
|
+
}
|
|
61
|
+
function buildWrappers(value) {
|
|
62
|
+
const raw = value
|
|
63
|
+
.replace(/\(/g, '{')
|
|
64
|
+
.replace(/\)/g, '}')
|
|
65
|
+
.replace(/([a-zA-Z0-9_]+):\s*([0-9%px]+)\s+([0-9.]+rem)/g, '"$1": {"size": "$2", "padding": "$3"}')
|
|
66
|
+
.replace(/,\s*}/g, '}');
|
|
67
|
+
const parsed = JSON.parse(raw);
|
|
68
|
+
return parsed;
|
|
69
|
+
}
|
|
70
|
+
export async function ReadDefaultValues(files, VariableNames) {
|
|
71
|
+
const theme = {};
|
|
72
|
+
const variables = {};
|
|
73
|
+
for (const file of files) {
|
|
74
|
+
const content = await fs.readFile(file, 'utf8');
|
|
75
|
+
for (const name of VariableNames) {
|
|
76
|
+
const variableRegex = new RegExp(`^\\s*\\$${name}\\s*:\\s*([\\s\\S]*?)\\s*!default\\s*;?`, 'm');
|
|
77
|
+
const match = variableRegex.exec(content);
|
|
78
|
+
if (match) {
|
|
79
|
+
const value = match[1].trim();
|
|
80
|
+
let result;
|
|
81
|
+
if (name === 'colors')
|
|
82
|
+
result = buildColors(value);
|
|
83
|
+
else if (name === 'fonts')
|
|
84
|
+
result = buildJson(value);
|
|
85
|
+
else if (name === 'fontSizes')
|
|
86
|
+
result = buildJson(value);
|
|
87
|
+
else if (name === 'breakpoints')
|
|
88
|
+
result = buildJson(value);
|
|
89
|
+
else if (name === 'wrappers')
|
|
90
|
+
result = buildWrappers(value);
|
|
91
|
+
else if (name === 'guttersValues')
|
|
92
|
+
result = buildJson(value);
|
|
93
|
+
else if (['true', 'false'].includes(value))
|
|
94
|
+
result = value === 'true';
|
|
95
|
+
else if ([
|
|
96
|
+
'fontWeights',
|
|
97
|
+
'fontStyles',
|
|
98
|
+
'opacities',
|
|
99
|
+
'blurValues',
|
|
100
|
+
'radiuses',
|
|
101
|
+
'defaultFontFamilies',
|
|
102
|
+
'insetValues',
|
|
103
|
+
].includes(name))
|
|
104
|
+
result = buildArray(value);
|
|
105
|
+
else if (['textTruncate', 'axisDivisions', 'bordersValue'].includes(name))
|
|
106
|
+
result = cleanNumber(value);
|
|
107
|
+
else
|
|
108
|
+
result = cleanString(value);
|
|
109
|
+
variables[name] = result;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
theme.colors = variables?.colors;
|
|
114
|
+
theme.typography = {
|
|
115
|
+
fontMainPath: variables?.fontMainPath,
|
|
116
|
+
fontFormat: variables?.fontFormat,
|
|
117
|
+
fontWeights: variables?.fontWeights,
|
|
118
|
+
fontStyles: variables?.fontStyles,
|
|
119
|
+
textTruncate: variables?.textTruncate,
|
|
120
|
+
defaultFontFamilies: variables?.defaultFontFamilies,
|
|
121
|
+
fonts: variables?.fonts,
|
|
122
|
+
fontSizes: variables?.fontSizes,
|
|
123
|
+
};
|
|
124
|
+
theme.settings = {
|
|
125
|
+
axisDivisions: variables?.axisDivisions,
|
|
126
|
+
opacities: variables?.opacities,
|
|
127
|
+
blurValues: variables?.blurValues,
|
|
128
|
+
insetValues: variables?.insetValues,
|
|
129
|
+
bordersValue: variables?.bordersValue,
|
|
130
|
+
radiuses: variables?.radiuses,
|
|
131
|
+
breakpoints: variables.breakpoints,
|
|
132
|
+
wrappers: variables.wrappers,
|
|
133
|
+
guttersValues: variables.guttersValues,
|
|
134
|
+
};
|
|
135
|
+
theme.roles = {
|
|
136
|
+
useMediaQueries: variables?.useMediaQueries,
|
|
137
|
+
useIcons: variables?.useIcons,
|
|
138
|
+
useFontFamilies: variables?.useFontFamilies,
|
|
139
|
+
useFontSizes: variables?.useFontSizes,
|
|
140
|
+
useFontShapes: variables?.useFontShapes,
|
|
141
|
+
useTextAligns: variables?.useTextAligns,
|
|
142
|
+
useTextTruncate: variables?.useTextTruncate,
|
|
143
|
+
useColors: variables?.useColors,
|
|
144
|
+
useColorsOpacities: variables?.useColorsOpacities,
|
|
145
|
+
useColorsLightMode: variables?.useColorsLightMode,
|
|
146
|
+
useColorsDarkMode: variables?.useColorsDarkMode,
|
|
147
|
+
useCurrentColors: variables?.useCurrentColors,
|
|
148
|
+
useRootColors: variables?.useRootColors,
|
|
149
|
+
useGrid: variables?.useGrid,
|
|
150
|
+
useFlex: variables?.useFlex,
|
|
151
|
+
useTransitions: variables?.useTransitions,
|
|
152
|
+
useWrappers: variables?.useWrappers,
|
|
153
|
+
useShadows: variables?.useShadows,
|
|
154
|
+
useDisplays: variables?.useDisplays,
|
|
155
|
+
useOverflows: variables?.useOverflows,
|
|
156
|
+
useOpacities: variables?.useOpacities,
|
|
157
|
+
useBlur: variables?.useBlur,
|
|
158
|
+
useObjectFits: variables?.useObjectFits,
|
|
159
|
+
usePositions: variables?.usePositions,
|
|
160
|
+
useInsets: variables?.useInsets,
|
|
161
|
+
useSizes: variables?.useSizes,
|
|
162
|
+
useGutters: variables?.useGutters,
|
|
163
|
+
useBorders: variables?.useBorders,
|
|
164
|
+
useTextBorders: variables?.useTextBorders,
|
|
165
|
+
useRadius: variables?.useRadius,
|
|
166
|
+
};
|
|
167
|
+
return theme;
|
|
168
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { BuildTheme } from './BuildTheme.js';
|
|
3
|
+
async function main() {
|
|
4
|
+
try {
|
|
5
|
+
console.log('🎨 Building Beathers theme...');
|
|
6
|
+
await BuildTheme();
|
|
7
|
+
console.log('✅ Theme built successfully!');
|
|
8
|
+
}
|
|
9
|
+
catch (error) {
|
|
10
|
+
console.error('❌ Error building theme:', error);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
main();
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export type ColorType = Record<string, {
|
|
2
|
+
light: `#${string}`;
|
|
3
|
+
dark: `#${string}`;
|
|
4
|
+
}>;
|
|
5
|
+
export type FontWeight = 'thin' | 'extra-light' | 'light' | 'regular' | 'medium' | 'semibold' | 'bold' | 'extra-bold' | 'black';
|
|
6
|
+
export type FontStyle = 'normal' | 'italic' | 'oblique';
|
|
7
|
+
export type FontSize = `${number}px` | `${number}rem` | `${number}em`;
|
|
8
|
+
export interface FontVariant {
|
|
9
|
+
title: string;
|
|
10
|
+
unicode?: string;
|
|
11
|
+
format?: 'woff' | 'woff2';
|
|
12
|
+
isLocal?: boolean;
|
|
13
|
+
url?: `https://${string}` | `http://${string}`;
|
|
14
|
+
}
|
|
15
|
+
export type FontType = {
|
|
16
|
+
weights?: FontWeight[];
|
|
17
|
+
styles?: FontStyle[];
|
|
18
|
+
variants?: FontVariant[];
|
|
19
|
+
};
|
|
20
|
+
export interface Typography {
|
|
21
|
+
defaultFontFamilies?: string[];
|
|
22
|
+
fontMainPath?: string;
|
|
23
|
+
fontFormat?: 'woff' | 'woff2';
|
|
24
|
+
fontWeights?: FontWeight[];
|
|
25
|
+
fontStyles?: FontStyle[];
|
|
26
|
+
fontSizes?: {
|
|
27
|
+
[sizeName: string]: FontSize;
|
|
28
|
+
};
|
|
29
|
+
textTruncate?: number;
|
|
30
|
+
fonts?: Record<string, FontType>;
|
|
31
|
+
}
|
|
32
|
+
export type Breakpoints = Record<'sm' | 'md' | 'lg' | 'xl' | 'xxl', `${number}px` | `${number}rem` | `${number}em`>;
|
|
33
|
+
export type Wrappers = Record<'sm' | 'md' | 'lg' | 'xl' | 'xxl', {
|
|
34
|
+
width: `${number}px` | `${number}rem` | `${number}em`;
|
|
35
|
+
padding?: `${number}px` | `${number}rem` | `${number}em`;
|
|
36
|
+
}>;
|
|
37
|
+
export type GutterValues = Record<'auto' | number, `${number}px` | `${number}rem` | `${number}em`>;
|
|
38
|
+
export interface Settings {
|
|
39
|
+
axisDivisions?: number;
|
|
40
|
+
opacities?: number[];
|
|
41
|
+
blurValues?: number[];
|
|
42
|
+
insetValues?: number[];
|
|
43
|
+
bordersValue?: number;
|
|
44
|
+
radiuses?: number[];
|
|
45
|
+
breakpoints?: Breakpoints;
|
|
46
|
+
wrappers?: Wrappers;
|
|
47
|
+
guttersValues?: GutterValues;
|
|
48
|
+
}
|
|
49
|
+
type RoleKeys = 'useMediaQueries' | 'useIcons' | 'useFontFamilies' | 'useFontSizes' | 'useFontShapes' | 'useTextAligns' | 'useTextTruncate' | 'useColors' | 'useColorsOpacities' | 'useColorsLightMode' | 'useColorsDarkMode' | 'useCurrentColors' | 'useRootColors' | 'useGrid' | 'useFlex' | 'useTransitions' | 'useWrappers' | 'useShadows' | 'useDisplays' | 'useOverflows' | 'useOpacities' | 'useBlur' | 'useObjectFits' | 'usePositions' | 'useInsets' | 'useSizes' | 'useGutters' | 'useBorders' | 'useTextBorders' | 'useRadius';
|
|
50
|
+
export type Roles = Partial<Record<RoleKeys, boolean>>;
|
|
51
|
+
export interface Theme {
|
|
52
|
+
colors?: ColorType;
|
|
53
|
+
typography?: Typography;
|
|
54
|
+
settings?: Settings;
|
|
55
|
+
roles?: Roles;
|
|
56
|
+
}
|
|
57
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "beathers",
|
|
3
|
+
"version": "5.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Beather is a lightweight SCSS library that serves as a comprehensive design system for your projects. It offers a structured and consistent approach to manage colors, fonts, and other design related variables, making it easier to maintain a cohesive visual identity across your application.",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"beathers": "dist/scripts/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"watch": "nodemon --watch src/scss/ --ext scss --exec \"npm-run-all build\"",
|
|
13
|
+
"watch:expanded": " nodemon --watch src/scss/ --ext scss --exec \"npm-run-all build:expanded\"",
|
|
14
|
+
"build": "sass --style compressed --source-map --embed-sources --no-error-css src/scss/:dist/css/",
|
|
15
|
+
"build:expanded": "sass --style expanded --source-map --embed-sources --no-error-css src/scss/:dist/css/expanded/",
|
|
16
|
+
"build:clean": "rimraf dist",
|
|
17
|
+
"build:lib": "tsc",
|
|
18
|
+
"build:all": "rimraf dist && npm run build:lib && npm run build",
|
|
19
|
+
"build:with-configs": "tsx src/scripts/BuildTheme.ts",
|
|
20
|
+
"watch:with-configs": "nodemon --watch src --ext ts --exec \"tsx src/scripts/BuildTheme.ts\"",
|
|
21
|
+
"prepublishOnly": "npm run build:all",
|
|
22
|
+
"lint": "eslint . && stylelint \"**/*.scss\"",
|
|
23
|
+
"lint:fix": "eslint . --fix && stylelint \"**/*.scss\" --fix",
|
|
24
|
+
"lint:scss": "stylelint \"**/*.scss\"",
|
|
25
|
+
"lint:scss:fix": "stylelint \"**/*.scss\" --fix",
|
|
26
|
+
"format:check": "prettier --check --ignore-path .gitignore .",
|
|
27
|
+
"format:fix": "prettier --write --ignore-path .gitignore . && pnpm lint"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"Design-system",
|
|
31
|
+
"Bhoenix",
|
|
32
|
+
"Feather",
|
|
33
|
+
"Beathers",
|
|
34
|
+
"SCSS",
|
|
35
|
+
"CSS",
|
|
36
|
+
"responsive",
|
|
37
|
+
"front-end",
|
|
38
|
+
"framework",
|
|
39
|
+
"web"
|
|
40
|
+
],
|
|
41
|
+
"author": "Bhoenix studio",
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/BhoenixStudio/Beathers.git"
|
|
46
|
+
},
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/BhoenixStudio/Beathers/issues"
|
|
49
|
+
},
|
|
50
|
+
"homepage": "https://github.com/BhoenixStudio/Beathers#readme",
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"fs-extra": "^11.3.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@eslint/js": "^9.26.0",
|
|
56
|
+
"@types/fs-extra": "^11.0.4",
|
|
57
|
+
"@types/node": "^22.15.21",
|
|
58
|
+
"@types/scss-parser": "^1.0.4",
|
|
59
|
+
"autoprefixer": "^10.4.21",
|
|
60
|
+
"eslint": "^9.26.0",
|
|
61
|
+
"eslint-plugin-css": "^0.11.0",
|
|
62
|
+
"eslint-plugin-import": "^2.31.0",
|
|
63
|
+
"globals": "^16.1.0",
|
|
64
|
+
"nodemon": "^3.1.10",
|
|
65
|
+
"npm-run-all": "^4.1.5",
|
|
66
|
+
"postcss": "^8.5.3",
|
|
67
|
+
"postcss-cli": "^11.0.1",
|
|
68
|
+
"postcss-scss": "^4.0.9",
|
|
69
|
+
"prettier": "^3.5.3",
|
|
70
|
+
"rimraf": "^6.0.1",
|
|
71
|
+
"sass": "^1.88.0",
|
|
72
|
+
"stylelint": "^16.19.1",
|
|
73
|
+
"stylelint-config-standard-scss": "^15.0.0",
|
|
74
|
+
"tsx": "^4.19.4",
|
|
75
|
+
"typescript": "^5.8.3",
|
|
76
|
+
"typescript-eslint": "^8.32.1"
|
|
77
|
+
},
|
|
78
|
+
"files": [
|
|
79
|
+
"dist/css/**/*.{css,map}",
|
|
80
|
+
"dist/**/*.{js,d.ts}",
|
|
81
|
+
"src/scss/**/*.scss",
|
|
82
|
+
"readme.md"
|
|
83
|
+
]
|
|
84
|
+
}
|