source: frontend/node_modules/tailwindcss/src/cli/index.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 6.0 KB
Line 
1#!/usr/bin/env node
2
3import path from 'path'
4import arg from 'arg'
5import fs from 'fs'
6
7import { build } from './build'
8import { help } from './help'
9import { init } from './init'
10
11function oneOf(...options) {
12 return Object.assign(
13 (value = true) => {
14 for (let option of options) {
15 let parsed = option(value)
16 if (parsed === value) {
17 return parsed
18 }
19 }
20
21 throw new Error('...')
22 },
23 { manualParsing: true }
24 )
25}
26
27let commands = {
28 init: {
29 run: init,
30 args: {
31 '--esm': { type: Boolean, description: `Initialize configuration file as ESM` },
32 '--ts': { type: Boolean, description: `Initialize configuration file as TypeScript` },
33 '--postcss': { type: Boolean, description: `Initialize a \`postcss.config.js\` file` },
34 '--full': {
35 type: Boolean,
36 description: `Include the default values for all options in the generated configuration file`,
37 },
38 '-f': '--full',
39 '-p': '--postcss',
40 },
41 },
42 build: {
43 run: build,
44 args: {
45 '--input': { type: String, description: 'Input file' },
46 '--output': { type: String, description: 'Output file' },
47 '--watch': {
48 type: oneOf(String, Boolean),
49 description: 'Watch for changes and rebuild as needed',
50 },
51 '--poll': {
52 type: Boolean,
53 description: 'Use polling instead of filesystem events when watching',
54 },
55 '--content': {
56 type: String,
57 description: 'Content paths to use for removing unused classes',
58 },
59 '--purge': {
60 type: String,
61 deprecated: true,
62 },
63 '--postcss': {
64 type: oneOf(String, Boolean),
65 description: 'Load custom PostCSS configuration',
66 },
67 '--minify': { type: Boolean, description: 'Minify the output' },
68 '--config': {
69 type: String,
70 description: 'Path to a custom config file',
71 },
72 '--no-autoprefixer': {
73 type: Boolean,
74 description: 'Disable autoprefixer',
75 },
76 '-c': '--config',
77 '-i': '--input',
78 '-o': '--output',
79 '-m': '--minify',
80 '-w': '--watch',
81 '-p': '--poll',
82 },
83 },
84}
85
86let sharedFlags = {
87 '--help': { type: Boolean, description: 'Display usage information' },
88 '-h': '--help',
89}
90
91if (
92 process.stdout.isTTY /* Detect redirecting output to a file */ &&
93 (process.argv[2] === undefined ||
94 process.argv.slice(2).every((flag) => sharedFlags[flag] !== undefined))
95) {
96 help({
97 usage: [
98 'tailwindcss [--input input.css] [--output output.css] [--watch] [options...]',
99 'tailwindcss init [--full] [--postcss] [options...]',
100 ],
101 commands: Object.keys(commands)
102 .filter((command) => command !== 'build')
103 .map((command) => `${command} [options]`),
104 options: { ...commands.build.args, ...sharedFlags },
105 })
106 process.exit(0)
107}
108
109let command = ((arg = '') => (arg.startsWith('-') ? undefined : arg))(process.argv[2]) || 'build'
110
111if (commands[command] === undefined) {
112 if (fs.existsSync(path.resolve(command))) {
113 // TODO: Deprecate this in future versions
114 // Check if non-existing command, might be a file.
115 command = 'build'
116 } else {
117 help({
118 message: `Invalid command: ${command}`,
119 usage: ['tailwindcss <command> [options]'],
120 commands: Object.keys(commands)
121 .filter((command) => command !== 'build')
122 .map((command) => `${command} [options]`),
123 options: sharedFlags,
124 })
125 process.exit(1)
126 }
127}
128
129// Execute command
130let { args: flags, run } = commands[command]
131let args = (() => {
132 try {
133 let result = arg(
134 Object.fromEntries(
135 Object.entries({ ...flags, ...sharedFlags })
136 .filter(([_key, value]) => !value?.type?.manualParsing)
137 .map(([key, value]) => [key, typeof value === 'object' ? value.type : value])
138 ),
139 { permissive: true }
140 )
141
142 // Manual parsing of flags to allow for special flags like oneOf(Boolean, String)
143 for (let i = result['_'].length - 1; i >= 0; --i) {
144 let flag = result['_'][i]
145 if (!flag.startsWith('-')) continue
146
147 let [flagName, flagValue] = flag.split('=')
148 let handler = flags[flagName]
149
150 // Resolve flagName & handler
151 while (typeof handler === 'string') {
152 flagName = handler
153 handler = flags[handler]
154 }
155
156 if (!handler) continue
157
158 let args = []
159 let offset = i + 1
160
161 // --flag value syntax was used so we need to pull `value` from `args`
162 if (flagValue === undefined) {
163 // Parse args for current flag
164 while (result['_'][offset] && !result['_'][offset].startsWith('-')) {
165 args.push(result['_'][offset++])
166 }
167
168 // Cleanup manually parsed flags + args
169 result['_'].splice(i, 1 + args.length)
170
171 // No args were provided, use default value defined in handler
172 // One arg was provided, use that directly
173 // Multiple args were provided so pass them all in an array
174 flagValue = args.length === 0 ? undefined : args.length === 1 ? args[0] : args
175 } else {
176 // Remove the whole flag from the args array
177 result['_'].splice(i, 1)
178 }
179
180 // Set the resolved value in the `result` object
181 result[flagName] = handler.type(flagValue, flagName)
182 }
183
184 // Ensure that the `command` is always the first argument in the `args`.
185 // This is important so that we don't have to check if a default command
186 // (build) was used or not from within each plugin.
187 //
188 // E.g.: tailwindcss input.css -> _: ['build', 'input.css']
189 // E.g.: tailwindcss build input.css -> _: ['build', 'input.css']
190 if (result['_'][0] !== command) {
191 result['_'].unshift(command)
192 }
193
194 return result
195 } catch (err) {
196 if (err.code === 'ARG_UNKNOWN_OPTION') {
197 help({
198 message: err.message,
199 usage: ['tailwindcss <command> [options]'],
200 options: sharedFlags,
201 })
202 process.exit(1)
203 }
204 throw err
205 }
206})()
207
208if (args['--help']) {
209 help({
210 options: { ...flags, ...sharedFlags },
211 usage: [`tailwindcss ${command} [options]`],
212 })
213 process.exit(0)
214}
215
216run(args)
Note: See TracBrowser for help on using the repository browser.