create-tampermonkey-typescript 1.2.3 → 1.2.5

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/README.md CHANGED
@@ -32,6 +32,8 @@ and bundled into the output script, then injected into the page at runtime — n
32
32
  at build time and only the CSS you actually use is injected into your userscript.
33
33
 
34
34
  ✨ **Prettier** — Sets up Prettier with a pre-configured `.prettierrc` and `.prettierignore` for consistent formatting.
35
+ If Tailwind is enabled, there is also a prompt to enable the `prettier-plugin-classnames` and `prettier-plugin-tailwindcss`
36
+ plugins which organize class names and automatically wraps the `className` string if it exceeds print width.
35
37
 
36
38
  🚀 **GitHub Actions workflows** — Includes CI/CD workflows that automatically create Git tags when
37
39
  `package.json` version changes, and publish GitHub Releases with the built script attached.
package/dist/cli.js CHANGED
@@ -5,10 +5,10 @@ import prompts from 'prompts';
5
5
  import kleur from 'kleur';
6
6
  import { execSync } from 'node:child_process';
7
7
  import { fileURLToPath } from 'url';
8
- const __FILENAME = fileURLToPath(import.meta.url);
9
- const __DIRNAME = path.dirname(__FILENAME);
10
- const TEMPLATES_DIR = path.join(__DIRNAME, '../templates');
11
- const defaultDevDeps = [
8
+ export const __FILENAME = fileURLToPath(import.meta.url);
9
+ export const __DIRNAME = path.dirname(__FILENAME);
10
+ export const TEMPLATES_DIR = path.join(__DIRNAME, '../templates');
11
+ export const defaultDevDeps = [
12
12
  'typescript', //
13
13
  'vite',
14
14
  'vite-plugin-banner',
@@ -16,10 +16,10 @@ const defaultDevDeps = [
16
16
  'ts-node',
17
17
  '@types/tampermonkey',
18
18
  ];
19
- const defaultDeps = [];
20
- const baseTsConfig = {
19
+ export const defaultDeps = [];
20
+ export const baseTsConfig = {
21
21
  compilerOptions: {
22
- types: ['vite/client', 'node'],
22
+ types: ['vite/client', 'node', 'tampermonkey'],
23
23
  target: 'ES2022',
24
24
  module: 'ESNext',
25
25
  moduleResolution: 'bundler',
@@ -37,7 +37,20 @@ const baseTsConfig = {
37
37
  },
38
38
  include: ['src'],
39
39
  };
40
- const availableFeatures = [
40
+ export const basePrettierRc = {
41
+ trailingComma: 'es5',
42
+ tabWidth: 2,
43
+ semi: false,
44
+ singleQuote: true,
45
+ printWidth: 120,
46
+ plugins: [],
47
+ };
48
+ export const prettierTailwindPlugins = [
49
+ 'prettier-plugin-tailwindcss',
50
+ 'prettier-plugin-classnames',
51
+ 'prettier-plugin-merge',
52
+ ];
53
+ export const availableFeatures = [
41
54
  {
42
55
  name: 'React',
43
56
  description: 'Adds react support to the project',
@@ -55,9 +68,17 @@ const availableFeatures = [
55
68
  name: 'Prettier',
56
69
  description: 'Adds Prettier with default .prettierrc and .prettierignore files',
57
70
  directory: path.join(TEMPLATES_DIR, 'prettier'),
71
+ devDependencies: ['prettier'],
58
72
  hook: (params) => {
59
- renameDotFiles(params, 'prettierrc', 'prettierignore');
60
- execInProjectDir('npm install --save-dev --save-exact prettier', params);
73
+ if (params.prettierTailwindPlugins) {
74
+ installDependencies(params, prettierTailwindPlugins, '-D');
75
+ }
76
+ const prettierRc = {
77
+ ...basePrettierRc,
78
+ ...(params.prettierTailwindPlugins ? { plugins: prettierTailwindPlugins } : {}),
79
+ };
80
+ writeObjectToJsonFile(prettierRc, '.prettierrc', params);
81
+ renameDotFiles(params, 'prettierignore');
61
82
  },
62
83
  },
63
84
  {
@@ -75,7 +96,7 @@ const availableFeatures = [
75
96
  directory: path.join(TEMPLATES_DIR, 'github-workflows'),
76
97
  },
77
98
  ];
78
- const availablePackageManagers = [
99
+ export const availablePackageManagers = [
79
100
  {
80
101
  name: 'npm',
81
102
  exists: () => commandExists('npm --version'),
@@ -123,7 +144,7 @@ async function main() {
123
144
  // Initialize package.json
124
145
  logWithPrefix(`Creating ${kleur.yellow('package.json')}`);
125
146
  const packageJson = createPackageJson(params);
126
- writeObjectToFile(packageJson, 'package.json', params);
147
+ writeObjectToJsonFile(packageJson, 'package.json', params);
127
148
  // Initialize the lock file
128
149
  logWithPrefix(`Initializing lock file`);
129
150
  execInProjectDir(`${params.packageManager.installCmd}`, params);
@@ -134,13 +155,13 @@ async function main() {
134
155
  if (devDeps.length > 0) {
135
156
  logWithPrefix('Installing dev dependencies');
136
157
  console.log(` ${kleur.dim(devDeps.join(', '))}`);
137
- execInProjectDir(`${params.packageManager.addDependencyCmd} -D ${devDeps.join(' ')}`, params);
158
+ installDependencies(params, devDeps, '-D');
138
159
  }
139
160
  // Install dependencies
140
161
  if (deps.length > 0) {
141
162
  logWithPrefix('Installing dependencies');
142
163
  console.log(` ${kleur.dim(deps.join(', '))}`);
143
- execInProjectDir(`${params.packageManager.addDependencyCmd} ${deps.join(' ')}`, params);
164
+ installDependencies(params, deps, '-D');
144
165
  }
145
166
  // Handle tsconfig.json
146
167
  const tsConfig = { ...baseTsConfig };
@@ -150,7 +171,7 @@ async function main() {
150
171
  }
151
172
  }
152
173
  logWithPrefix(`Creating ${kleur.yellow('tsconfig.json')}`);
153
- writeObjectToFile(tsConfig, 'tsconfig.json', params);
174
+ writeObjectToJsonFile(tsConfig, 'tsconfig.json', params);
154
175
  // Copy files
155
176
  logWithPrefix('Copying project files');
156
177
  // Base files
@@ -179,7 +200,7 @@ async function main() {
179
200
  function logWithPrefix(message) {
180
201
  console.log(`${kleur.cyan('-')} ${kleur.white(message)}`);
181
202
  }
182
- function commandExists(cmd) {
203
+ export function commandExists(cmd) {
183
204
  try {
184
205
  execSync(cmd, { stdio: 'ignore' });
185
206
  return true;
@@ -188,7 +209,7 @@ function commandExists(cmd) {
188
209
  return false;
189
210
  }
190
211
  }
191
- function checkCwdAccess() {
212
+ export function checkCwdAccess() {
192
213
  try {
193
214
  fs.accessSync(process.cwd(), fs.constants.W_OK | fs.constants.R_OK);
194
215
  }
@@ -198,7 +219,7 @@ function checkCwdAccess() {
198
219
  }
199
220
  return true;
200
221
  }
201
- function findValidPackageManager() {
222
+ export function findValidPackageManager() {
202
223
  if (!availablePackageManagers.find((pm) => pm.exists())) {
203
224
  console.log(kleur.red('Could not find any valid package manager: '));
204
225
  console.log(kleur.yellow(`(${availablePackageManagers.map((pm) => pm.name).join(', ')})`));
@@ -206,7 +227,7 @@ function findValidPackageManager() {
206
227
  }
207
228
  return true;
208
229
  }
209
- function validateProjectName(projectName) {
230
+ export function validateProjectName(projectName) {
210
231
  if (!projectName || projectName.length === 0)
211
232
  return 'Project name cannot be empty';
212
233
  if (projectName.includes(' '))
@@ -260,11 +281,16 @@ async function promptForParams() {
260
281
  message: 'Select features:',
261
282
  choices: availableFeatures.map((f) => ({ title: f.name, value: f.name, description: f.description })),
262
283
  },
284
+ {
285
+ type: (prev) => (prev.includes('Prettier') && prev.includes('TailwindCSS') ? 'confirm' : null),
286
+ name: 'prettierTailwindPlugins',
287
+ message: 'Install prettier-plugin-tailwindcss (auto-sorts classes) and prettier-plugin-classnames (wraps long class strings)?',
288
+ },
263
289
  ], {
264
290
  onCancel: () => process.exit(0),
265
291
  });
266
292
  }
267
- async function createProjectDirectory(path) {
293
+ export async function createProjectDirectory(path) {
268
294
  try {
269
295
  fs.mkdirSync(path, { recursive: true });
270
296
  return true;
@@ -276,7 +302,7 @@ async function createProjectDirectory(path) {
276
302
  return 'Unknown error.';
277
303
  }
278
304
  }
279
- function createPackageJson(params) {
305
+ export function createPackageJson(params) {
280
306
  return {
281
307
  name: params.projectName,
282
308
  description: params.description,
@@ -289,7 +315,7 @@ function createPackageJson(params) {
289
315
  },
290
316
  };
291
317
  }
292
- function writeObjectToFile(object, fileName, params) {
318
+ export function writeObjectToJsonFile(object, fileName, params) {
293
319
  const filePath = path.join(params.projectPath, fileName);
294
320
  const jsonString = JSON.stringify(object, null, 2);
295
321
  fs.writeFileSync(filePath, jsonString);
@@ -297,9 +323,15 @@ function writeObjectToFile(object, fileName, params) {
297
323
  function execInProjectDir(command, params) {
298
324
  execSync(command, { stdio: 'inherit', cwd: params.projectPath });
299
325
  }
300
- function renameDotFiles(params, ...fileNames) {
326
+ function installDependencies(params, dependencies, flags = '') {
327
+ execInProjectDir(`${params.packageManager.addDependencyCmd} ${flags} ${dependencies.join(' ')}`, params);
328
+ }
329
+ export function renameDotFiles(params, ...fileNames) {
301
330
  for (const fileName of fileNames) {
302
331
  fs.renameSync(path.join(params.projectPath, `_${fileName}`), path.join(params.projectPath, `.${fileName}`));
303
332
  }
304
333
  }
305
- main().then(() => { }, (e) => console.error(kleur.red(e.message || e)));
334
+ const isDirectRun = process.argv[1]?.endsWith('cli.ts') || process.argv[1]?.endsWith('cli.js');
335
+ if (isDirectRun) {
336
+ main().then(() => { }, (e) => console.error(kleur.red(e.message || e)));
337
+ }
package/package.json CHANGED
@@ -1,51 +1,53 @@
1
- {
2
- "name": "create-tampermonkey-typescript",
3
- "version": "1.2.3",
4
- "description": "CLI tool for generating a TamperMonkey script project written in typescript which is transpiled to JavaScript to be ran in the browser",
5
- "license": "MIT",
6
- "homepage": "https://github.com/neth392/create-tampermonkey-typescript",
7
- "author": "neth392",
8
- "keywords": [
9
- "tampermonkey",
10
- "typescript",
11
- "template"
12
- ],
13
- "publishConfig": {
14
- "access": "public",
15
- "registry": "https://registry.npmjs.org/"
16
- },
17
- "files": [
18
- "dist",
19
- "templates"
20
- ],
21
- "type": "module",
22
- "bin": {
23
- "create-tampermonkey-typescript": "dist/cli.js"
24
- },
25
- "scripts": {
26
- "build": "tsc",
27
- "dev": "ts-node src/cli.ts"
28
- },
29
- "devDependencies": {
30
- "@tailwindcss/vite": "^4.1.18",
31
- "@types/node": "^24.0.10",
32
- "@types/prompts": "^2.4.9",
33
- "@types/react": "^19.1.8",
34
- "@types/react-dom": "^19.1.6",
35
- "@types/tampermonkey": "^5.0.4",
36
- "prettier": "^3.6.1",
37
- "react": "^19.1.0",
38
- "react-dom": "^19.1.0",
39
- "tailwindcss": "^4.1.18",
40
- "ts-node": "^10.9.2",
41
- "type-fest": "^5.4.4",
42
- "typescript": "^5.8.3",
43
- "vite": "^7.0.0",
44
- "vite-plugin-banner": "^0.8.1",
45
- "vite-plugin-css-injected-by-js": "^3.5.2"
46
- },
47
- "dependencies": {
48
- "kleur": "^4.1.5",
49
- "prompts": "^2.4.2"
50
- }
51
- }
1
+ {
2
+ "name": "create-tampermonkey-typescript",
3
+ "version": "1.2.5",
4
+ "description": "CLI tool for generating a TamperMonkey script project written in typescript which is transpiled to JavaScript to be ran in the browser",
5
+ "license": "MIT",
6
+ "homepage": "https://github.com/neth392/create-tampermonkey-typescript",
7
+ "author": "neth392",
8
+ "keywords": [
9
+ "tampermonkey",
10
+ "typescript",
11
+ "template"
12
+ ],
13
+ "publishConfig": {
14
+ "access": "public",
15
+ "registry": "https://registry.npmjs.org/"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "templates"
20
+ ],
21
+ "type": "module",
22
+ "bin": {
23
+ "create-tampermonkey-typescript": "dist/cli.js"
24
+ },
25
+ "scripts": {
26
+ "build": "tsc",
27
+ "test": "vitest run",
28
+ "test:watch": "vitest"
29
+ },
30
+ "devDependencies": {
31
+ "@tailwindcss/vite": "^4.1.18",
32
+ "@types/node": "^24.0.10",
33
+ "@types/prompts": "^2.4.9",
34
+ "@types/react": "^19.1.8",
35
+ "@types/react-dom": "^19.1.6",
36
+ "@types/tampermonkey": "^5.0.4",
37
+ "prettier": "^3.6.1",
38
+ "react": "^19.1.0",
39
+ "react-dom": "^19.1.0",
40
+ "tailwindcss": "^4.1.18",
41
+ "ts-node": "^10.9.2",
42
+ "type-fest": "^5.4.4",
43
+ "typescript": "^5.8.3",
44
+ "vite": "^7.0.0",
45
+ "vite-plugin-banner": "^0.8.1",
46
+ "vite-plugin-css-injected-by-js": "^3.5.2",
47
+ "vitest": "^4.1.0"
48
+ },
49
+ "dependencies": {
50
+ "kleur": "^4.1.5",
51
+ "prompts": "^2.4.2"
52
+ }
53
+ }
@@ -86,6 +86,10 @@ You should customize this file to include directives specific to your script, su
86
86
  - All imported CSS is combined and injected as an inline `<style>` element at runtime
87
87
  - The userscript header from `userscript.txt` is prepended
88
88
 
89
+ ### Removing JSDoc/Comments in Final Script
90
+ The `vite.config.ts` file has a section that can be uncommented which will remove JSDoc and comments from the final
91
+ script, reducing the output file size.
92
+
89
93
  ---
90
94
 
91
95
  ## CSS
@@ -211,7 +215,21 @@ const App = () => (
211
215
 
212
216
  ```
213
217
 
214
- For more information, see the [Tailwind CSS docs](https://tailwindcss.com/docs).
218
+ ### IMPORTANT
219
+ There is a chance that simply using `@import "tailwindcss";` in your styles will break the page's native styling.
220
+ In order to prevent this and utilize tailwind's utilities in your script's own UI, you can scope tailwind to your
221
+ root container like so in `styles.css` (only applicable in v4).
222
+
223
+ ```css
224
+ @layer theme, base, components, utilities;
225
+ @import "tailwindcss/theme.css" layer(theme);
226
+
227
+ #your-root-id {
228
+ @tailwind utilities;
229
+ }
230
+ ```
231
+
232
+ For more information on Tailwind, see the [Tailwind CSS docs](https://tailwindcss.com/docs).
215
233
 
216
234
  ---
217
235
 
@@ -219,6 +237,10 @@ For more information, see the [Tailwind CSS docs](https://tailwindcss.com/docs).
219
237
 
220
238
  Prettier is included with a pre-configured `.prettierrc` and `.prettierignore` file. Feel free to change them to best fit your programming style.
221
239
 
240
+ ### Prettier & Tailwind
241
+ Optionally enabled are the `prettier-plugin-tailwindcss` and `prettier-plugin-classnames` plugins to assist in
242
+ formatting when using class names. `prettier-plugin-merge` is used to fix incompatibility between the two.
243
+
222
244
  ---
223
245
 
224
246
  ## GitHub Workflows
@@ -39,9 +39,22 @@ export default defineConfig({
39
39
  },
40
40
  },
41
41
  plugins: [
42
- ...(hasTailwind ? [(await import('@tailwindcss/vite')).default()] : []),
42
+ ...(hasTailwind
43
+ ? [
44
+ (await import('@tailwindcss/vite')).default({
45
+ optimize: { minify: true },
46
+ }),
47
+ ]
48
+ : []),
43
49
  cssInjectedByJsPlugin({ topExecutionPriority: true }),
44
50
  banner({ content: meta, verify: false }),
51
+ // Uncomment below to remove comments & JSDoc from the final script.
52
+ // {
53
+ // name: 'strip-comments',
54
+ // renderChunk(code) {
55
+ // return code.replace(/\/\*\*[\s\S]*?\*\//g, '').replace(/\/\*[^!][\s\S]*?\*\//g, '')
56
+ // },
57
+ // },
45
58
  ],
46
59
  build: {
47
60
  cssCodeSplit: false,
@@ -1,2 +1,15 @@
1
- /* Add all styles here, keep tailwindcss import for using tailwind */
2
- @import 'tailwindcss';
1
+ /* Add all styles in this file, or create multiple files and be sure to import them all in your script. */
2
+ @import 'tailwindcss';
3
+
4
+
5
+ /* (For Tailwind v4) If just using tailwind utilities, it is recommended to replace the above with this. */
6
+ /* It will prevent tailwind's preflight from breaking the css of the page outside of your script's scope. */
7
+ /* Simply delete the above, uncomment below, and replace #your-root-element-id with your own. */
8
+
9
+ /*@layer theme, base, components, utilities;*/
10
+ /*@import "tailwindcss/theme.css" layer(theme);*/
11
+ /*@custom-variant dark (&:is(.dark-mode *));*/
12
+
13
+ /*#your-root-element-id {*/
14
+ /* @tailwind utilities;*/
15
+ /*}*/
@@ -1,7 +0,0 @@
1
- {
2
- "trailingComma": "es5",
3
- "tabWidth": 2,
4
- "semi": false,
5
- "singleQuote": true,
6
- "printWidth": 120
7
- }