joys-fonts 0.1.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.
Files changed (106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +105 -0
  3. package/bin/cli.js +250 -0
  4. package/fonts/joys-inter/joys-inter.css +47 -0
  5. package/fonts/joys-inter/woff2/joys-inter-300.woff2 +0 -0
  6. package/fonts/joys-inter/woff2/joys-inter-400.woff2 +0 -0
  7. package/fonts/joys-inter/woff2/joys-inter-500.woff2 +0 -0
  8. package/fonts/joys-inter/woff2/joys-inter-600.woff2 +0 -0
  9. package/fonts/joys-inter/woff2/joys-inter-700.woff2 +0 -0
  10. package/fonts/joys-inter/woff2/joys-inter-800.woff2 +0 -0
  11. package/fonts/joys-iran-sans-x/joys-iran-sans-x.css +201 -0
  12. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-100.woff2 +0 -0
  13. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-200.woff2 +0 -0
  14. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-300.woff2 +0 -0
  15. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-400.woff2 +0 -0
  16. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-500.woff2 +0 -0
  17. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-600.woff2 +0 -0
  18. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-700.woff2 +0 -0
  19. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-800.woff2 +0 -0
  20. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-900.woff2 +0 -0
  21. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-fanum-100.woff2 +0 -0
  22. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-fanum-200.woff2 +0 -0
  23. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-fanum-300.woff2 +0 -0
  24. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-fanum-400.woff2 +0 -0
  25. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-fanum-500.woff2 +0 -0
  26. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-fanum-600.woff2 +0 -0
  27. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-fanum-700.woff2 +0 -0
  28. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-fanum-800.woff2 +0 -0
  29. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-fanum-900.woff2 +0 -0
  30. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-noen-100.woff2 +0 -0
  31. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-noen-200.woff2 +0 -0
  32. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-noen-300.woff2 +0 -0
  33. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-noen-400.woff2 +0 -0
  34. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-noen-500.woff2 +0 -0
  35. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-noen-600.woff2 +0 -0
  36. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-noen-700.woff2 +0 -0
  37. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-noen-800.woff2 +0 -0
  38. package/fonts/joys-iran-sans-x/woff2/joys-iran-sans-x-noen-900.woff2 +0 -0
  39. package/fonts/joys-iran-yekan-x/joys-iran-yekan-x.css +81 -0
  40. package/fonts/joys-iran-yekan-x/woff2/joys-iran-yekan-x-100.woff2 +0 -0
  41. package/fonts/joys-iran-yekan-x/woff2/joys-iran-yekan-x-1000.woff2 +0 -0
  42. package/fonts/joys-iran-yekan-x/woff2/joys-iran-yekan-x-200.woff2 +0 -0
  43. package/fonts/joys-iran-yekan-x/woff2/joys-iran-yekan-x-300.woff2 +0 -0
  44. package/fonts/joys-iran-yekan-x/woff2/joys-iran-yekan-x-400.woff2 +0 -0
  45. package/fonts/joys-iran-yekan-x/woff2/joys-iran-yekan-x-500.woff2 +0 -0
  46. package/fonts/joys-iran-yekan-x/woff2/joys-iran-yekan-x-600.woff2 +0 -0
  47. package/fonts/joys-iran-yekan-x/woff2/joys-iran-yekan-x-700.woff2 +0 -0
  48. package/fonts/joys-iran-yekan-x/woff2/joys-iran-yekan-x-800.woff2 +0 -0
  49. package/fonts/joys-iran-yekan-x/woff2/joys-iran-yekan-x-900.woff2 +0 -0
  50. package/fonts/joys-iran-yekan-x/woff2/joys-iran-yekan-x-950.woff2 +0 -0
  51. package/fonts/joys-kalameh/joys-kalameh.css +201 -0
  52. package/fonts/joys-kalameh/woff2/joys-kalameh-100.woff2 +0 -0
  53. package/fonts/joys-kalameh/woff2/joys-kalameh-200.woff2 +0 -0
  54. package/fonts/joys-kalameh/woff2/joys-kalameh-300.woff2 +0 -0
  55. package/fonts/joys-kalameh/woff2/joys-kalameh-400.woff2 +0 -0
  56. package/fonts/joys-kalameh/woff2/joys-kalameh-500.woff2 +0 -0
  57. package/fonts/joys-kalameh/woff2/joys-kalameh-600.woff2 +0 -0
  58. package/fonts/joys-kalameh/woff2/joys-kalameh-700.woff2 +0 -0
  59. package/fonts/joys-kalameh/woff2/joys-kalameh-800.woff2 +0 -0
  60. package/fonts/joys-kalameh/woff2/joys-kalameh-900.woff2 +0 -0
  61. package/fonts/joys-kalameh/woff2/joys-kalameh-fanum-100.woff2 +0 -0
  62. package/fonts/joys-kalameh/woff2/joys-kalameh-fanum-200.woff2 +0 -0
  63. package/fonts/joys-kalameh/woff2/joys-kalameh-fanum-300.woff2 +0 -0
  64. package/fonts/joys-kalameh/woff2/joys-kalameh-fanum-400.woff2 +0 -0
  65. package/fonts/joys-kalameh/woff2/joys-kalameh-fanum-500.woff2 +0 -0
  66. package/fonts/joys-kalameh/woff2/joys-kalameh-fanum-600.woff2 +0 -0
  67. package/fonts/joys-kalameh/woff2/joys-kalameh-fanum-700.woff2 +0 -0
  68. package/fonts/joys-kalameh/woff2/joys-kalameh-fanum-800.woff2 +0 -0
  69. package/fonts/joys-kalameh/woff2/joys-kalameh-fanum-900.woff2 +0 -0
  70. package/fonts/joys-kalameh/woff2/joys-kalameh-noen-100.woff2 +0 -0
  71. package/fonts/joys-kalameh/woff2/joys-kalameh-noen-200.woff2 +0 -0
  72. package/fonts/joys-kalameh/woff2/joys-kalameh-noen-300.woff2 +0 -0
  73. package/fonts/joys-kalameh/woff2/joys-kalameh-noen-400.woff2 +0 -0
  74. package/fonts/joys-kalameh/woff2/joys-kalameh-noen-500.woff2 +0 -0
  75. package/fonts/joys-kalameh/woff2/joys-kalameh-noen-600.woff2 +0 -0
  76. package/fonts/joys-kalameh/woff2/joys-kalameh-noen-700.woff2 +0 -0
  77. package/fonts/joys-kalameh/woff2/joys-kalameh-noen-800.woff2 +0 -0
  78. package/fonts/joys-kalameh/woff2/joys-kalameh-noen-900.woff2 +0 -0
  79. package/fonts/joys-morabba/joys-morabba.css +77 -0
  80. package/fonts/joys-morabba/woff2/joys-morabba-200.woff2 +0 -0
  81. package/fonts/joys-morabba/woff2/joys-morabba-300.woff2 +0 -0
  82. package/fonts/joys-morabba/woff2/joys-morabba-400.woff2 +0 -0
  83. package/fonts/joys-morabba/woff2/joys-morabba-500.woff2 +0 -0
  84. package/fonts/joys-morabba/woff2/joys-morabba-600.woff2 +0 -0
  85. package/fonts/joys-morabba/woff2/joys-morabba-700.woff2 +0 -0
  86. package/fonts/joys-morabba/woff2/joys-morabba-800.woff2 +0 -0
  87. package/fonts/joys-morabba/woff2/joys-morabba-900.woff2 +0 -0
  88. package/fonts/joys-morabba/woff2/joys-morabba-950.woff2 +0 -0
  89. package/fonts/joys-vazir/joys-vazir.css +68 -0
  90. package/fonts/joys-vazir/woff2/joys-vazir-100.woff2 +0 -0
  91. package/fonts/joys-vazir/woff2/joys-vazir-200.woff2 +0 -0
  92. package/fonts/joys-vazir/woff2/joys-vazir-300.woff2 +0 -0
  93. package/fonts/joys-vazir/woff2/joys-vazir-400.woff2 +0 -0
  94. package/fonts/joys-vazir/woff2/joys-vazir-500.woff2 +0 -0
  95. package/fonts/joys-vazir/woff2/joys-vazir-600.woff2 +0 -0
  96. package/fonts/joys-vazir/woff2/joys-vazir-700.woff2 +0 -0
  97. package/fonts/joys-vazir/woff2/joys-vazir-800.woff2 +0 -0
  98. package/fonts/joys-vazir/woff2/joys-vazir-900.woff2 +0 -0
  99. package/fonts/joys-yekan-bakh/joys-yekan-bakh.css +48 -0
  100. package/fonts/joys-yekan-bakh/woff2/joys-yekan-bakh-fanum-vf.woff2 +0 -0
  101. package/fonts/joys-yekan-bakh/woff2/joys-yekan-bakh-noen-vf.woff2 +0 -0
  102. package/fonts/joys-yekan-bakh/woff2/joys-yekan-bakh-vf.woff2 +0 -0
  103. package/fonts.manifest.json +734 -0
  104. package/package.json +35 -0
  105. package/src/index.d.ts +42 -0
  106. package/src/index.js +189 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 joys
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # Joys Fonts
2
+
3
+ Joys Fonts is a modern platform and CLI utility designed to package and install Persian web fonts into Tailwind CSS projects (specifically targeting **Tailwind CSS v4+**).
4
+
5
+ Instead of manual setup or adding the entire font collection as a dependency, the Joys Fonts CLI allows you to download and configure only the specific fonts you need.
6
+
7
+ ---
8
+
9
+ ## Features
10
+
11
+ - **Tailwind CSS v4+ Native**: Automatically updates your main CSS file, injecting `@import` statements and registering theme variables inside the Tailwind `@theme` block.
12
+ - **Zero-Dependency CLI**: Written in native Node.js ES Modules. Extremely fast and lightweight.
13
+ - **WOFF2 Optimized**: Only keeps modern, optimized WOFF2 font assets for maximum web performance.
14
+ - **Supports Static & Variable Fonts**: Installs and maps font weights (including custom axes) appropriately.
15
+
16
+ ---
17
+
18
+ ## Installation & Usage
19
+
20
+ You don't need to install this package. You can run the installer CLI in the root of your project using your preferred package manager:
21
+
22
+ ### npm
23
+ ```bash
24
+ npx joys-fonts add <font-slug>
25
+ ```
26
+
27
+ ### pnpm
28
+ ```bash
29
+ pnpm dlx joys-fonts add <font-slug>
30
+ ```
31
+
32
+ ### yarn
33
+ ```bash
34
+ yarn dlx joys-fonts add <font-slug>
35
+ ```
36
+
37
+ ### bun
38
+ ```bash
39
+ bunx joys-fonts add <font-slug>
40
+ ```
41
+
42
+ For example, to install the `joys-iran-sans-x` font using pnpm:
43
+
44
+ ```bash
45
+ pnpm dlx joys-fonts add joys-iran-sans-x
46
+ ```
47
+
48
+ ### Options
49
+
50
+ The CLI can be run non-interactively using options for automation and CI/CD:
51
+
52
+ ```bash
53
+ npx joys-fonts add <font-slug> [options]
54
+ ```
55
+
56
+ - `-d, --dest <path>`: Specify the directory where the font files should be copied.
57
+ - `-c, --css <path>`: Specify your project's global/Tailwind CSS stylesheet to update.
58
+ - `-y, --yes`: Auto-confirm all prompts with default settings.
59
+
60
+ ---
61
+
62
+ ## How It Works
63
+
64
+ When you run `npx joys-fonts add joys-iran-sans-x`, the CLI will:
65
+ 1. Copy the font's WOFF2 files and its stylesheet (`joys-iran-sans-x.css`) to your project (e.g., `./src/fonts/joys-iran-sans-x`).
66
+ 2. Inject the stylesheet `@import` at the top of your global CSS:
67
+ ```css
68
+ @import "./fonts/joys-iran-sans-x/joys-iran-sans-x.css";
69
+ ```
70
+ 3. Update your Tailwind CSS v4 `@theme` block to declare the corresponding CSS font-family variables:
71
+ ```css
72
+ @theme {
73
+ --font-iran-sans-x: "JoysIranSansX", sans-serif;
74
+ --font-iran-sans-x-fanum: "JoysIranSansXFaNum", sans-serif;
75
+ --font-iran-sans-x-noen: "JoysIranSansXNoEn", sans-serif;
76
+ }
77
+ ```
78
+ 4. Now, you can use standard Tailwind classes anywhere in your HTML or React code:
79
+ - `font-iran-sans-x` (Default Regular weight)
80
+ - `font-iran-sans-x-fanum` (Persian numbers version)
81
+ - `font-iran-sans-x-noen` (No English letters version)
82
+
83
+ ---
84
+
85
+ ## Available Fonts
86
+
87
+ The following fonts are packaged and available for installation:
88
+
89
+ - `joys-iran-sans-x`
90
+ - `joys-iran-yekan-x`
91
+ - `joys-kalameh`
92
+ - `joys-morabba`
93
+ - `joys-yekan-bakh`
94
+
95
+ ---
96
+
97
+ ## Contributing & Adding Fonts
98
+
99
+ If you want to contribute, add new Persian fonts, or edit existing ones, please follow our step-by-step guidelines in [CONTRIBUTING.md](./CONTRIBUTING.md) to keep the repository clean and standardized.
100
+
101
+ ---
102
+
103
+ ## License
104
+
105
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,250 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Joys Fonts Installer CLI
4
+ * Usage:
5
+ * npx joys-fonts [command] [options]
6
+ * node bin/cli.js [command] [options]
7
+ *
8
+ * Commands:
9
+ * add <font-slug> Install a font into your project
10
+ * list, ls List all available fonts
11
+ * help, -h, --help Show help screen
12
+ *
13
+ * Options:
14
+ * -d, --dest <path> Install destination directory
15
+ * -c, --css <path> Global CSS file path to update
16
+ * -y, --yes Auto-confirm with default options
17
+ */
18
+
19
+ import fs from 'fs';
20
+ import path from 'path';
21
+ import readline from 'readline/promises';
22
+ import { stdin as input, stdout as output } from 'process';
23
+ import { manifest, installFont, detectTailwindVersion } from '../src/index.js';
24
+
25
+ // Parse command line arguments
26
+ function parseArgs(args) {
27
+ const options = {
28
+ command: null,
29
+ slug: null,
30
+ dest: null,
31
+ css: null,
32
+ yes: false,
33
+ help: false
34
+ };
35
+
36
+ const positionals = [];
37
+ for (let i = 0; i < args.length; i++) {
38
+ const arg = args[i];
39
+ if (arg === '--dest' || arg === '-d') {
40
+ options.dest = args[++i];
41
+ } else if (arg === '--css' || arg === '-c') {
42
+ options.css = args[++i];
43
+ } else if (arg === '--yes' || arg === '-y') {
44
+ options.yes = true;
45
+ } else if (arg === '--help' || arg === '-h' || arg === 'help') {
46
+ options.help = true;
47
+ } else {
48
+ positionals.push(arg);
49
+ }
50
+ }
51
+
52
+ if (options.help) {
53
+ options.command = 'help';
54
+ } else if (positionals[0] === 'list' || positionals[0] === 'ls') {
55
+ options.command = 'list';
56
+ } else if (positionals[0] === 'add') {
57
+ options.command = 'add';
58
+ options.slug = positionals[1] || null;
59
+ } else if (positionals[0]) {
60
+ options.command = 'add';
61
+ options.slug = positionals[0];
62
+ }
63
+
64
+ return options;
65
+ }
66
+
67
+ function printHelp() {
68
+ console.log(`
69
+ \x1b[35m=======================================\x1b[0m
70
+ \x1b[36m\x1b[1m Joys Fonts Installer CLI\x1b[0m
71
+ \x1b[35m=======================================\x1b[0m
72
+
73
+ Usage:
74
+ npx joys-fonts [command] [options]
75
+
76
+ Commands:
77
+ \x1b[32madd <font-slug>\x1b[0m Install a specific font
78
+ \x1b[32mlist, ls\x1b[0m List all available fonts
79
+ \x1b[32mhelp, -h, --help\x1b[0m Show this help screen
80
+
81
+ Options:
82
+ \x1b[33m-d, --dest <path>\x1b[0m Install destination directory
83
+ \x1b[33m-c, --css <path>\x1b[0m Global CSS file path to update
84
+ \x1b[33m-y, --yes\x1b[0m Auto-confirm with default options
85
+
86
+ Examples:
87
+ npx joys-fonts add joys-iran-sans-x
88
+ pnpm dlx joys-fonts list
89
+ yarn dlx joys-fonts add joys-kalameh --yes
90
+ `);
91
+ }
92
+
93
+ function printList() {
94
+ console.log('\n\x1b[36mAvailable fonts in Joys Fonts:\x1b[0m');
95
+ console.log('\x1b[90m---------------------------------------\x1b[0m');
96
+ manifest.forEach((f, idx) => {
97
+ const families = f.families.map(fa => fa.family).join(', ');
98
+ console.log(` ${idx + 1}. \x1b[32m\x1b[1m${f.slug}\x1b[0m`);
99
+ console.log(` Families: \x1b[37m${families}\x1b[0m`);
100
+ console.log(` CSS Path: \x1b[90m${f.css}\x1b[0m`);
101
+ console.log('\x1b[90m---------------------------------------\x1b[0m');
102
+ });
103
+ }
104
+
105
+ async function main() {
106
+ const options = parseArgs(process.argv.slice(2));
107
+
108
+ if (options.command === 'help') {
109
+ printHelp();
110
+ process.exit(0);
111
+ }
112
+
113
+ if (options.command === 'list') {
114
+ printList();
115
+ process.exit(0);
116
+ }
117
+
118
+ let slug = options.slug;
119
+ const rl = readline.createInterface({ input, output });
120
+
121
+ // If no slug is specified, prompt interactively
122
+ if (!slug) {
123
+ console.log('\n\x1b[35m=======================================\x1b[0m');
124
+ console.log('\x1b[36m\x1b[1m Joys Fonts Installer CLI\x1b[0m');
125
+ console.log('\x1b[35m=======================================\x1b[0m\n');
126
+ console.log('Available fonts:');
127
+ manifest.forEach((f, idx) => {
128
+ console.log(` [${idx + 1}] \x1b[32m${f.slug}\x1b[0m (${f.families.map(fa => fa.family).join(', ')})`);
129
+ });
130
+
131
+ const choice = await rl.question('\nSelect a font number or type slug (e.g. joys-kalameh): ');
132
+ const idxChoice = parseInt(choice, 10);
133
+ let selected = null;
134
+
135
+ if (!isNaN(idxChoice) && idxChoice >= 1 && idxChoice <= manifest.length) {
136
+ selected = manifest[idxChoice - 1];
137
+ } else {
138
+ const cleanChoice = choice.trim();
139
+ selected = manifest.find(f => f.slug === cleanChoice || f.slug === `joys-${cleanChoice}`);
140
+ }
141
+
142
+ if (!selected) {
143
+ console.error('\x1b[31m❌ Invalid selection.\x1b[0m');
144
+ rl.close();
145
+ process.exit(1);
146
+ }
147
+ slug = selected.slug;
148
+ }
149
+
150
+ const fontEntry = manifest.find(f => f.slug === slug);
151
+ if (!fontEntry) {
152
+ console.error(`\x1b[31m❌ Font slug "${slug}" not found in manifest.\x1b[0m`);
153
+ console.log(`Run \x1b[32mnpx joys-fonts list\x1b[0m to see all available fonts.`);
154
+ rl.close();
155
+ process.exit(1);
156
+ }
157
+
158
+ console.log(`\nSelected font: \x1b[36m${fontEntry.slug}\x1b[0m`);
159
+
160
+ // Determine default destination
161
+ let defaultDest = `./fonts/${slug}`;
162
+ if (fs.existsSync('src') && fs.statSync('src').isDirectory()) {
163
+ defaultDest = `./src/fonts/${slug}`;
164
+ } else if (fs.existsSync('app') && fs.statSync('app').isDirectory()) {
165
+ defaultDest = `./app/fonts/${slug}`;
166
+ }
167
+
168
+ let chosenDest = '';
169
+ if (options.dest) {
170
+ chosenDest = options.dest;
171
+ } else if (options.yes) {
172
+ chosenDest = defaultDest;
173
+ } else {
174
+ const destPathInput = await rl.question(`Install destination [\x1b[32m${defaultDest}\x1b[0m]: `);
175
+ chosenDest = destPathInput.trim() || defaultDest;
176
+ }
177
+ const destPath = path.resolve(chosenDest);
178
+
179
+ // Detect main CSS file
180
+ const commonCssPaths = [
181
+ 'src/index.css',
182
+ 'src/app.css',
183
+ 'src/global.css',
184
+ 'src/main.css',
185
+ 'app/globals.css',
186
+ 'app/global.css',
187
+ 'index.css',
188
+ 'global.css'
189
+ ];
190
+ let defaultCss = '';
191
+ for (const p of commonCssPaths) {
192
+ if (fs.existsSync(p)) {
193
+ defaultCss = p;
194
+ break;
195
+ }
196
+ }
197
+
198
+ let chosenCss = '';
199
+ if (options.css) {
200
+ chosenCss = options.css;
201
+ } else if (options.yes) {
202
+ chosenCss = defaultCss;
203
+ } else {
204
+ const cssPathInput = await rl.question(`Tailwind/Global CSS file path to update${defaultCss ? ` [\x1b[32m${defaultCss}\x1b[0m]` : ''} (press Enter to skip): `);
205
+ chosenCss = cssPathInput.trim() || defaultCss;
206
+ }
207
+
208
+ let mainCssPath = null;
209
+ if (chosenCss) {
210
+ const resolvedCss = path.resolve(chosenCss);
211
+ if (fs.existsSync(resolvedCss)) {
212
+ mainCssPath = resolvedCss;
213
+ } else {
214
+ console.log(`\x1b[33m⚠️ Warning: File "${chosenCss}" does not exist. CSS/Tailwind configuration will be skipped.\x1b[0m`);
215
+ }
216
+ }
217
+
218
+ rl.close();
219
+
220
+ console.log('\nInstalling font files...');
221
+ try {
222
+ const tailwindVersion = detectTailwindVersion();
223
+
224
+ await installFont({
225
+ slug,
226
+ destPath,
227
+ cssPath: mainCssPath || undefined,
228
+ tailwindVersion
229
+ });
230
+
231
+ console.log(`\x1b[32m✅ Copied font files to: ${chosenDest}\x1b[0m`);
232
+
233
+ if (mainCssPath) {
234
+ console.log(`\x1b[32m✅ Successfully updated CSS configuration in ${path.relative(process.cwd(), mainCssPath)}\x1b[0m`);
235
+ if (tailwindVersion === 3) {
236
+ console.log(`\x1b[32m✅ Successfully extended fontFamily in tailwind.config file\x1b[0m`);
237
+ }
238
+ }
239
+
240
+ console.log(`\n\x1b[32m\x1b[1m🎉 Font ${slug} successfully installed! You can now use it in your project.\x1b[0m`);
241
+ } catch (err) {
242
+ console.error(`\x1b[31m❌ Installation failed: ${err.message}\x1b[0m`);
243
+ process.exit(1);
244
+ }
245
+ }
246
+
247
+ main().catch(err => {
248
+ console.error(`\x1b[31m❌ Unexpected error: ${err.message}\x1b[0m`);
249
+ process.exit(1);
250
+ });
@@ -0,0 +1,47 @@
1
+ @font-face {
2
+ font-family: 'JoysInter';
3
+ src: url('./woff2/joys-inter-300.woff2') format('woff2');
4
+ font-weight: 300;
5
+ font-style: normal;
6
+ font-display: swap;
7
+ }
8
+ @font-face {
9
+ font-family: 'JoysInter';
10
+ src: url('./woff2/joys-inter-400.woff2') format('woff2');
11
+ font-weight: 400;
12
+ font-style: normal;
13
+ font-display: swap;
14
+ }
15
+ @font-face {
16
+ font-family: 'JoysInter';
17
+ src: url('./woff2/joys-inter-500.woff2') format('woff2');
18
+ font-weight: 500;
19
+ font-style: normal;
20
+ font-display: swap;
21
+ }
22
+ @font-face {
23
+ font-family: 'JoysInter';
24
+ src: url('./woff2/joys-inter-600.woff2') format('woff2');
25
+ font-weight: 600;
26
+ font-style: normal;
27
+ font-display: swap;
28
+ }
29
+ @font-face {
30
+ font-family: 'JoysInter';
31
+ src: url('./woff2/joys-inter-700.woff2') format('woff2');
32
+ font-weight: 700;
33
+ font-style: normal;
34
+ font-display: swap;
35
+ }
36
+ @font-face {
37
+ font-family: 'JoysInter';
38
+ src: url('./woff2/joys-inter-800.woff2') format('woff2');
39
+ font-weight: 800;
40
+ font-style: normal;
41
+ font-display: swap;
42
+ }
43
+
44
+ .font-inter {
45
+ font-family: 'JoysInter', sans-serif;
46
+ font-weight: 400;
47
+ }
@@ -0,0 +1,201 @@
1
+ @font-face {
2
+ font-family: 'JoysIranSansX';
3
+ src: url('./woff2/joys-iran-sans-x-100.woff2') format('woff2');
4
+ font-weight: 100;
5
+ font-style: normal;
6
+ font-display: swap;
7
+ }
8
+ @font-face {
9
+ font-family: 'JoysIranSansX';
10
+ src: url('./woff2/joys-iran-sans-x-200.woff2') format('woff2');
11
+ font-weight: 200;
12
+ font-style: normal;
13
+ font-display: swap;
14
+ }
15
+ @font-face {
16
+ font-family: 'JoysIranSansX';
17
+ src: url('./woff2/joys-iran-sans-x-300.woff2') format('woff2');
18
+ font-weight: 300;
19
+ font-style: normal;
20
+ font-display: swap;
21
+ }
22
+ @font-face {
23
+ font-family: 'JoysIranSansX';
24
+ src: url('./woff2/joys-iran-sans-x-400.woff2') format('woff2');
25
+ font-weight: 400;
26
+ font-style: normal;
27
+ font-display: swap;
28
+ }
29
+ @font-face {
30
+ font-family: 'JoysIranSansX';
31
+ src: url('./woff2/joys-iran-sans-x-500.woff2') format('woff2');
32
+ font-weight: 500;
33
+ font-style: normal;
34
+ font-display: swap;
35
+ }
36
+ @font-face {
37
+ font-family: 'JoysIranSansX';
38
+ src: url('./woff2/joys-iran-sans-x-600.woff2') format('woff2');
39
+ font-weight: 600;
40
+ font-style: normal;
41
+ font-display: swap;
42
+ }
43
+ @font-face {
44
+ font-family: 'JoysIranSansX';
45
+ src: url('./woff2/joys-iran-sans-x-700.woff2') format('woff2');
46
+ font-weight: 700;
47
+ font-style: normal;
48
+ font-display: swap;
49
+ }
50
+ @font-face {
51
+ font-family: 'JoysIranSansX';
52
+ src: url('./woff2/joys-iran-sans-x-800.woff2') format('woff2');
53
+ font-weight: 800;
54
+ font-style: normal;
55
+ font-display: swap;
56
+ }
57
+ @font-face {
58
+ font-family: 'JoysIranSansX';
59
+ src: url('./woff2/joys-iran-sans-x-900.woff2') format('woff2');
60
+ font-weight: 900;
61
+ font-style: normal;
62
+ font-display: swap;
63
+ }
64
+ @font-face {
65
+ font-family: 'JoysIranSansXFaNum';
66
+ src: url('./woff2/joys-iran-sans-x-fanum-100.woff2') format('woff2');
67
+ font-weight: 100;
68
+ font-style: normal;
69
+ font-display: swap;
70
+ }
71
+ @font-face {
72
+ font-family: 'JoysIranSansXFaNum';
73
+ src: url('./woff2/joys-iran-sans-x-fanum-200.woff2') format('woff2');
74
+ font-weight: 200;
75
+ font-style: normal;
76
+ font-display: swap;
77
+ }
78
+ @font-face {
79
+ font-family: 'JoysIranSansXFaNum';
80
+ src: url('./woff2/joys-iran-sans-x-fanum-300.woff2') format('woff2');
81
+ font-weight: 300;
82
+ font-style: normal;
83
+ font-display: swap;
84
+ }
85
+ @font-face {
86
+ font-family: 'JoysIranSansXFaNum';
87
+ src: url('./woff2/joys-iran-sans-x-fanum-400.woff2') format('woff2');
88
+ font-weight: 400;
89
+ font-style: normal;
90
+ font-display: swap;
91
+ }
92
+ @font-face {
93
+ font-family: 'JoysIranSansXFaNum';
94
+ src: url('./woff2/joys-iran-sans-x-fanum-500.woff2') format('woff2');
95
+ font-weight: 500;
96
+ font-style: normal;
97
+ font-display: swap;
98
+ }
99
+ @font-face {
100
+ font-family: 'JoysIranSansXFaNum';
101
+ src: url('./woff2/joys-iran-sans-x-fanum-600.woff2') format('woff2');
102
+ font-weight: 600;
103
+ font-style: normal;
104
+ font-display: swap;
105
+ }
106
+ @font-face {
107
+ font-family: 'JoysIranSansXFaNum';
108
+ src: url('./woff2/joys-iran-sans-x-fanum-700.woff2') format('woff2');
109
+ font-weight: 700;
110
+ font-style: normal;
111
+ font-display: swap;
112
+ }
113
+ @font-face {
114
+ font-family: 'JoysIranSansXFaNum';
115
+ src: url('./woff2/joys-iran-sans-x-fanum-800.woff2') format('woff2');
116
+ font-weight: 800;
117
+ font-style: normal;
118
+ font-display: swap;
119
+ }
120
+ @font-face {
121
+ font-family: 'JoysIranSansXFaNum';
122
+ src: url('./woff2/joys-iran-sans-x-fanum-900.woff2') format('woff2');
123
+ font-weight: 900;
124
+ font-style: normal;
125
+ font-display: swap;
126
+ }
127
+ @font-face {
128
+ font-family: 'JoysIranSansXNoEn';
129
+ src: url('./woff2/joys-iran-sans-x-noen-100.woff2') format('woff2');
130
+ font-weight: 100;
131
+ font-style: normal;
132
+ font-display: swap;
133
+ }
134
+ @font-face {
135
+ font-family: 'JoysIranSansXNoEn';
136
+ src: url('./woff2/joys-iran-sans-x-noen-200.woff2') format('woff2');
137
+ font-weight: 200;
138
+ font-style: normal;
139
+ font-display: swap;
140
+ }
141
+ @font-face {
142
+ font-family: 'JoysIranSansXNoEn';
143
+ src: url('./woff2/joys-iran-sans-x-noen-300.woff2') format('woff2');
144
+ font-weight: 300;
145
+ font-style: normal;
146
+ font-display: swap;
147
+ }
148
+ @font-face {
149
+ font-family: 'JoysIranSansXNoEn';
150
+ src: url('./woff2/joys-iran-sans-x-noen-400.woff2') format('woff2');
151
+ font-weight: 400;
152
+ font-style: normal;
153
+ font-display: swap;
154
+ }
155
+ @font-face {
156
+ font-family: 'JoysIranSansXNoEn';
157
+ src: url('./woff2/joys-iran-sans-x-noen-500.woff2') format('woff2');
158
+ font-weight: 500;
159
+ font-style: normal;
160
+ font-display: swap;
161
+ }
162
+ @font-face {
163
+ font-family: 'JoysIranSansXNoEn';
164
+ src: url('./woff2/joys-iran-sans-x-noen-600.woff2') format('woff2');
165
+ font-weight: 600;
166
+ font-style: normal;
167
+ font-display: swap;
168
+ }
169
+ @font-face {
170
+ font-family: 'JoysIranSansXNoEn';
171
+ src: url('./woff2/joys-iran-sans-x-noen-700.woff2') format('woff2');
172
+ font-weight: 700;
173
+ font-style: normal;
174
+ font-display: swap;
175
+ }
176
+ @font-face {
177
+ font-family: 'JoysIranSansXNoEn';
178
+ src: url('./woff2/joys-iran-sans-x-noen-800.woff2') format('woff2');
179
+ font-weight: 800;
180
+ font-style: normal;
181
+ font-display: swap;
182
+ }
183
+ @font-face {
184
+ font-family: 'JoysIranSansXNoEn';
185
+ src: url('./woff2/joys-iran-sans-x-noen-900.woff2') format('woff2');
186
+ font-weight: 900;
187
+ font-style: normal;
188
+ font-display: swap;
189
+ }
190
+ .font-iran-sans-x {
191
+ font-family: 'JoysIranSansX', sans-serif;
192
+ font-weight: 400;
193
+ }
194
+ .font-iran-sans-x-fanum {
195
+ font-family: 'JoysIranSansXFaNum', sans-serif;
196
+ font-weight: 400;
197
+ }
198
+ .font-iran-sans-x-noen {
199
+ font-family: 'JoysIranSansXNoEn', sans-serif;
200
+ font-weight: 400;
201
+ }