tailwind-lint 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.
- package/LICENSE +21 -0
- package/README.md +205 -0
- package/dist/cli.cjs +200 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/constants-BFubEpZ9.cjs +102 -0
- package/dist/constants-BFubEpZ9.cjs.map +1 -0
- package/dist/constants-Bstz7FuV.cjs +5 -0
- package/dist/linter-QRh7wAZ7.cjs +686 -0
- package/dist/linter-QRh7wAZ7.cjs.map +1 -0
- package/dist/linter.cjs +3 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Philip Stapelfeldt <me@ph1p.dev>
|
|
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,205 @@
|
|
|
1
|
+
# Tailwind CSS Linter (CLI)
|
|
2
|
+
|
|
3
|
+
A command-line tool that uses the Tailwind CSS IntelliSense engine to lint your Tailwind classes.
|
|
4
|
+
|
|
5
|
+
Supports **Tailwind CSS v4** (CSS-based config) and **v3** (JavaScript config, legacy).
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
**Core (v3 & v4):**
|
|
10
|
+
- CSS Conflicts - Detects when multiple classes apply the same CSS properties
|
|
11
|
+
- Invalid @apply Usage - Validates if a class can be used with `@apply`
|
|
12
|
+
- Invalid @screen References - Detects references to non-existent breakpoints
|
|
13
|
+
- Invalid Config Paths - Validates references in `config()` and `theme()` functions
|
|
14
|
+
- Invalid @tailwind Directives - Validates `@tailwind` layer values
|
|
15
|
+
- Recommended Variant Order - Suggests preferred ordering of variants
|
|
16
|
+
- Blocklisted Classes - Detects usage of blocklisted classes
|
|
17
|
+
- Autofix - Automatically fix issues with `--fix` flag
|
|
18
|
+
|
|
19
|
+
**v4-Specific:**
|
|
20
|
+
- Canonical Class Suggestions - Suggests shorthand equivalents for arbitrary values (e.g., `top-[60px]` → `top-15`)
|
|
21
|
+
- Invalid @source Directives - Validates `@source` directive paths
|
|
22
|
+
- Full theme loading - Automatically loads Tailwind's default theme
|
|
23
|
+
|
|
24
|
+
## Requirements
|
|
25
|
+
|
|
26
|
+
- Node.js >= 22.0.0
|
|
27
|
+
- Tailwind CSS v4 or v3 (installed in your project)
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# npm
|
|
33
|
+
npm install -g tailwind-lint
|
|
34
|
+
|
|
35
|
+
# pnpm
|
|
36
|
+
pnpm add -g tailwind-lint
|
|
37
|
+
|
|
38
|
+
# npx (no installation)
|
|
39
|
+
npx tailwind-lint "src/**/*.html"
|
|
40
|
+
|
|
41
|
+
# pnpm dlx (no installation)
|
|
42
|
+
pnpm dlx tailwind-lint "src/**/*.html"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
tailwind-lint [options] [files...]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Options
|
|
52
|
+
|
|
53
|
+
- `-c, --config <path>` - Path to Tailwind config file (default: auto-discover)
|
|
54
|
+
- `-a, --auto` - Auto-discover files from config content patterns (v3 only)
|
|
55
|
+
- `--fix` - Automatically fix problems that can be fixed
|
|
56
|
+
- `-v, --verbose` - Enable verbose logging for debugging
|
|
57
|
+
- `-h, --help` - Show help message
|
|
58
|
+
- `--version` - Show version number
|
|
59
|
+
|
|
60
|
+
### Examples
|
|
61
|
+
|
|
62
|
+
**Tailwind CSS v4:**
|
|
63
|
+
```bash
|
|
64
|
+
# Lint files
|
|
65
|
+
tailwind-lint "src/**/*.{js,jsx,ts,tsx}"
|
|
66
|
+
|
|
67
|
+
# With CSS config
|
|
68
|
+
tailwind-lint "src/**/*.tsx" --config ./app.css
|
|
69
|
+
|
|
70
|
+
# Fix issues (including canonical class suggestions)
|
|
71
|
+
tailwind-lint "src/**/*.html" --fix
|
|
72
|
+
|
|
73
|
+
# Verbose mode for debugging
|
|
74
|
+
tailwind-lint "src/**/*.tsx" --verbose
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Tailwind CSS v3 (Legacy):**
|
|
78
|
+
```bash
|
|
79
|
+
# With JavaScript config
|
|
80
|
+
tailwind-lint --config ./tailwind.config.js
|
|
81
|
+
|
|
82
|
+
# Auto-discover from config content patterns
|
|
83
|
+
tailwind-lint --auto
|
|
84
|
+
|
|
85
|
+
# Fix issues
|
|
86
|
+
tailwind-lint --config ./tailwind.config.js --fix
|
|
87
|
+
|
|
88
|
+
# Debug with verbose logging
|
|
89
|
+
tailwind-lint --auto --verbose
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Configuration
|
|
93
|
+
|
|
94
|
+
### Tailwind CSS v4
|
|
95
|
+
|
|
96
|
+
Create a CSS config file (`app.css`, `index.css`, or `tailwind.css`):
|
|
97
|
+
|
|
98
|
+
```css
|
|
99
|
+
@import "tailwindcss";
|
|
100
|
+
|
|
101
|
+
@theme {
|
|
102
|
+
--color-primary: #3b82f6;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@source "./src/**/*.{js,jsx,ts,tsx,html}";
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The CLI auto-detects configs at: `app.css`, `src/app.css`, `index.css`, `src/index.css`, `tailwind.css`, `src/tailwind.css`
|
|
109
|
+
|
|
110
|
+
### Tailwind CSS v3 (Legacy)
|
|
111
|
+
|
|
112
|
+
Create a JavaScript config file (`tailwind.config.js`):
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
/** @type {import('tailwindcss').Config} */
|
|
116
|
+
module.exports = {
|
|
117
|
+
content: ['./src/**/*.{js,jsx,ts,tsx}'],
|
|
118
|
+
theme: {
|
|
119
|
+
extend: {},
|
|
120
|
+
},
|
|
121
|
+
plugins: [],
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Autofix
|
|
126
|
+
|
|
127
|
+
Use `--fix` to automatically resolve issues:
|
|
128
|
+
|
|
129
|
+
- **Canonical class suggestions** (v4) - Replaces arbitrary values with standard classes
|
|
130
|
+
- **Recommended variant order** (v3 & v4) - Reorders variants correctly
|
|
131
|
+
|
|
132
|
+
Files are written atomically with multiple iterations to ensure all fixes are applied.
|
|
133
|
+
|
|
134
|
+
## Output Examples
|
|
135
|
+
|
|
136
|
+
**Issues found:**
|
|
137
|
+
```
|
|
138
|
+
src/example.html
|
|
139
|
+
10:8 warning 'p-4' applies the same CSS properties as 'px-8' (cssConflict)
|
|
140
|
+
13:8 warning 'text-red-500' applies the same CSS properties as 'text-blue-500' (cssConflict)
|
|
141
|
+
|
|
142
|
+
Found 2 warnings in 1 file
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**With --fix:**
|
|
146
|
+
```
|
|
147
|
+
src/components.html
|
|
148
|
+
✔ Fixed 2 issues
|
|
149
|
+
|
|
150
|
+
✔ Fixed 2 issues
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**With --verbose:**
|
|
154
|
+
```
|
|
155
|
+
→ Running in verbose mode
|
|
156
|
+
Working directory: /path/to/project
|
|
157
|
+
Config path: auto-discover
|
|
158
|
+
Fix mode: false
|
|
159
|
+
Patterns: src/**/*.tsx
|
|
160
|
+
|
|
161
|
+
→ Initializing Tailwind CSS language service...
|
|
162
|
+
Tailwind version: 4.1.18
|
|
163
|
+
Config type: CSS (v4)
|
|
164
|
+
Config path: /path/to/project/app.css
|
|
165
|
+
✓ Loaded v4 design system
|
|
166
|
+
✓ State initialized successfully
|
|
167
|
+
|
|
168
|
+
→ Discovered 15 files to lint
|
|
169
|
+
[1/15] Linting src/components/Button.tsx
|
|
170
|
+
[2/15] Linting src/components/Card.tsx
|
|
171
|
+
...
|
|
172
|
+
|
|
173
|
+
src/components/Button.tsx
|
|
174
|
+
10:8 warning 'p-4' applies the same CSS properties as 'px-8' (cssConflict)
|
|
175
|
+
|
|
176
|
+
Found 1 warning in 1 file
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Development
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Install dependencies
|
|
183
|
+
pnpm install
|
|
184
|
+
|
|
185
|
+
# Build for production
|
|
186
|
+
pnpm build
|
|
187
|
+
|
|
188
|
+
# Development mode (watch)
|
|
189
|
+
pnpm dev
|
|
190
|
+
|
|
191
|
+
# Run tests
|
|
192
|
+
pnpm test
|
|
193
|
+
|
|
194
|
+
# Run tests in watch mode
|
|
195
|
+
pnpm test:watch
|
|
196
|
+
|
|
197
|
+
# Run tests with coverage
|
|
198
|
+
pnpm test:coverage
|
|
199
|
+
|
|
200
|
+
# Format and lint code
|
|
201
|
+
pnpm format
|
|
202
|
+
|
|
203
|
+
# Check code without fixing
|
|
204
|
+
pnpm lint
|
|
205
|
+
```
|
package/dist/cli.cjs
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const require_linter = require('./linter-QRh7wAZ7.cjs');
|
|
3
|
+
const require_constants = require('./constants-BFubEpZ9.cjs');
|
|
4
|
+
let node_path = require("node:path");
|
|
5
|
+
node_path = require_linter.__toESM(node_path);
|
|
6
|
+
let node_fs = require("node:fs");
|
|
7
|
+
node_fs = require_linter.__toESM(node_fs);
|
|
8
|
+
let chalk = require("chalk");
|
|
9
|
+
chalk = require_linter.__toESM(chalk);
|
|
10
|
+
let commander = require("commander");
|
|
11
|
+
|
|
12
|
+
//#region src/cli.ts
|
|
13
|
+
function countDiagnosticsBySeverity(diagnostics) {
|
|
14
|
+
let errors = 0;
|
|
15
|
+
let warnings = 0;
|
|
16
|
+
for (const diagnostic of diagnostics) {
|
|
17
|
+
if (diagnostic.severity === 1) errors++;
|
|
18
|
+
if (diagnostic.severity === 2) warnings++;
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
errors,
|
|
22
|
+
warnings
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function resolveOptions(files, options) {
|
|
26
|
+
const hasConfigFlag = !!options.config;
|
|
27
|
+
const hasAutoFlag = !!options.auto;
|
|
28
|
+
const hasFiles = files.length > 0;
|
|
29
|
+
let cwd = process.cwd();
|
|
30
|
+
let configPath = options.config;
|
|
31
|
+
let patterns = files;
|
|
32
|
+
if (hasConfigFlag && options.config && !hasFiles) {
|
|
33
|
+
const absoluteConfigPath = node_path.isAbsolute(options.config) ? options.config : node_path.resolve(process.cwd(), options.config);
|
|
34
|
+
cwd = node_path.dirname(absoluteConfigPath);
|
|
35
|
+
configPath = node_path.basename(absoluteConfigPath);
|
|
36
|
+
patterns = [require_constants.DEFAULT_FILE_PATTERN];
|
|
37
|
+
}
|
|
38
|
+
const autoDiscover = hasAutoFlag;
|
|
39
|
+
return {
|
|
40
|
+
cwd,
|
|
41
|
+
configPath,
|
|
42
|
+
patterns: autoDiscover ? [] : patterns,
|
|
43
|
+
autoDiscover,
|
|
44
|
+
fix: options.fix || false,
|
|
45
|
+
verbose: options.verbose || false
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function truncateFilename(filename, maxLength) {
|
|
49
|
+
return filename.length > maxLength ? `...${filename.slice(-maxLength)}` : filename;
|
|
50
|
+
}
|
|
51
|
+
async function displayResults(files, fixMode, verbose) {
|
|
52
|
+
let totalErrors = 0;
|
|
53
|
+
let totalWarnings = 0;
|
|
54
|
+
let totalFixed = 0;
|
|
55
|
+
let filesWithIssues = 0;
|
|
56
|
+
let isFirstFile = true;
|
|
57
|
+
for (const file of files) if (file.diagnostics.length > 0 || fixMode && file.fixed) {
|
|
58
|
+
if (isFirstFile && verbose) {
|
|
59
|
+
console.log();
|
|
60
|
+
isFirstFile = false;
|
|
61
|
+
} else if (!isFirstFile) console.log();
|
|
62
|
+
console.log(chalk.default.underline.bold(file.path));
|
|
63
|
+
if (fixMode && file.fixed) {
|
|
64
|
+
const issueText = `${file.fixedCount || 0} issue${file.fixedCount !== 1 ? "s" : ""}`;
|
|
65
|
+
console.log(chalk.default.green(` ✔ Fixed ${issueText}`));
|
|
66
|
+
totalFixed += file.fixedCount || 0;
|
|
67
|
+
}
|
|
68
|
+
const { errors, warnings } = countDiagnosticsBySeverity(file.diagnostics);
|
|
69
|
+
totalErrors += errors;
|
|
70
|
+
totalWarnings += warnings;
|
|
71
|
+
if (file.diagnostics.length > 0) filesWithIssues++;
|
|
72
|
+
for (const diagnostic of file.diagnostics) {
|
|
73
|
+
const line = diagnostic.range.start.line + 1;
|
|
74
|
+
const char = diagnostic.range.start.character + 1;
|
|
75
|
+
const severity = diagnostic.severity === 1 ? "error" : "warning";
|
|
76
|
+
const severityColor = diagnostic.severity === 1 ? chalk.default.red(severity) : chalk.default.yellow(severity);
|
|
77
|
+
const code = diagnostic.code ? chalk.default.dim(` (${diagnostic.code})`) : "";
|
|
78
|
+
console.log(` ${chalk.default.dim(`${line}:${char}`)} ${severityColor} ${diagnostic.message}${code}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
console.log();
|
|
82
|
+
if (totalErrors === 0 && totalWarnings === 0) if (totalFixed > 0) {
|
|
83
|
+
const issueText = `${totalFixed} issue${totalFixed !== 1 ? "s" : ""}`;
|
|
84
|
+
console.log(chalk.default.green.bold(`✔ Fixed ${issueText}`));
|
|
85
|
+
} else console.log(chalk.default.green.bold("✔ No issues found"));
|
|
86
|
+
else {
|
|
87
|
+
const parts = [];
|
|
88
|
+
if (totalErrors > 0) parts.push(`${totalErrors} error${totalErrors !== 1 ? "s" : ""}`);
|
|
89
|
+
if (totalWarnings > 0) parts.push(`${totalWarnings} warning${totalWarnings !== 1 ? "s" : ""}`);
|
|
90
|
+
const fileText = `${filesWithIssues} file${filesWithIssues !== 1 ? "s" : ""}`;
|
|
91
|
+
const summary = `Found ${parts.join(" and ")} in ${fileText}`;
|
|
92
|
+
if (totalFixed > 0) {
|
|
93
|
+
const issueText = `${totalFixed} issue${totalFixed !== 1 ? "s" : ""}`;
|
|
94
|
+
console.log(chalk.default.green.bold(`✔ Fixed ${issueText}`));
|
|
95
|
+
console.log(summary);
|
|
96
|
+
} else console.log(summary);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const program = new commander.Command();
|
|
100
|
+
const getVersion = () => {
|
|
101
|
+
const packageJsonPath = node_path.join(__dirname, "../package.json");
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8")).version || require_constants.DEFAULT_VERSION;
|
|
104
|
+
} catch {
|
|
105
|
+
return require_constants.DEFAULT_VERSION;
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
program.configureHelp({ formatHelp: (cmd, helper) => {
|
|
109
|
+
const termWidth = helper.padWidth(cmd, helper);
|
|
110
|
+
let output = "";
|
|
111
|
+
output += `${chalk.default.bold.cyan("Usage:")} ${helper.commandUsage(cmd)}\n\n`;
|
|
112
|
+
if (cmd.description()) output += `${cmd.description()}\n\n`;
|
|
113
|
+
const args = helper.visibleArguments(cmd);
|
|
114
|
+
if (args.length > 0) {
|
|
115
|
+
output += `${chalk.default.bold.cyan("Arguments:")}\n`;
|
|
116
|
+
args.forEach((arg) => {
|
|
117
|
+
const argName = arg.required ? `<${arg.name()}>` : `[${arg.name()}]`;
|
|
118
|
+
output += ` ${chalk.default.green(argName.padEnd(termWidth))} ${arg.description}\n`;
|
|
119
|
+
});
|
|
120
|
+
output += "\n";
|
|
121
|
+
}
|
|
122
|
+
const options = helper.visibleOptions(cmd);
|
|
123
|
+
if (options.length > 0) {
|
|
124
|
+
output += `${chalk.default.bold.cyan("Options:")}\n`;
|
|
125
|
+
options.forEach((option) => {
|
|
126
|
+
const flags = helper.optionTerm(option);
|
|
127
|
+
const description = helper.optionDescription(option);
|
|
128
|
+
output += ` ${chalk.default.yellow(flags.padEnd(termWidth))} ${description}\n`;
|
|
129
|
+
});
|
|
130
|
+
output += "\n";
|
|
131
|
+
}
|
|
132
|
+
return output;
|
|
133
|
+
} });
|
|
134
|
+
program.name("tailwind-lint").description("A CLI tool for linting Tailwind CSS class usage").version(getVersion()).argument("[files...]", "File patterns to lint (e.g., \"src/**/*.{js,jsx,ts,tsx}\")").option("-c, --config <path>", "Path to Tailwind config file (default: auto-discover)").option("-a, --auto", "Auto-discover files from Tailwind config content patterns").option("--fix", "Automatically fix problems that can be fixed").option("-v, --verbose", "Enable verbose logging for debugging").addHelpText("after", `
|
|
135
|
+
${chalk.default.bold.cyan("Examples:")}
|
|
136
|
+
${chalk.default.dim("$")} tailwind-lint ${chalk.default.green("\"src/**/*.{js,jsx,ts,tsx}\"")}
|
|
137
|
+
${chalk.default.dim("$")} tailwind-lint ${chalk.default.yellow("--auto")}
|
|
138
|
+
${chalk.default.dim("$")} tailwind-lint ${chalk.default.yellow("--config")} ${chalk.default.green("./tailwind.config.js")}
|
|
139
|
+
${chalk.default.dim("$")} tailwind-lint ${chalk.default.green("\"src/**/*.tsx\"")} ${chalk.default.yellow("--fix")}
|
|
140
|
+
${chalk.default.dim("$")} tailwind-lint ${chalk.default.green("\"**/*.vue\"")}
|
|
141
|
+
|
|
142
|
+
${chalk.default.bold.cyan("Notes:")}
|
|
143
|
+
${chalk.default.dim("•")} Use ${chalk.default.yellow("--auto")} to auto-discover files from your Tailwind config (v3 only)
|
|
144
|
+
${chalk.default.dim("•")} Use ${chalk.default.yellow("--config")} alone to lint common file types from that directory
|
|
145
|
+
${chalk.default.dim("•")} Default pattern: ${chalk.default.dim("./**/*.{js,jsx,ts,tsx,html}")}
|
|
146
|
+
${chalk.default.dim("•")} Use ${chalk.default.yellow("--fix")} to automatically resolve fixable issues
|
|
147
|
+
`).action(async (files, options) => {
|
|
148
|
+
const hasConfigFlag = !!options.config;
|
|
149
|
+
const hasAutoFlag = !!options.auto;
|
|
150
|
+
if (!(files.length > 0) && !hasAutoFlag && !hasConfigFlag) {
|
|
151
|
+
console.error("Error: No files specified. Use glob patterns, --auto flag, or --config flag.\n");
|
|
152
|
+
program.help();
|
|
153
|
+
}
|
|
154
|
+
const resolved = resolveOptions(files, options);
|
|
155
|
+
try {
|
|
156
|
+
if (resolved.verbose) {
|
|
157
|
+
console.log(chalk.default.cyan("→ Running in verbose mode"));
|
|
158
|
+
console.log(chalk.default.dim(` Working directory: ${resolved.cwd}`));
|
|
159
|
+
console.log(chalk.default.dim(` Config path: ${resolved.configPath || "auto-discover"}`));
|
|
160
|
+
console.log(chalk.default.dim(` Fix mode: ${resolved.fix}`));
|
|
161
|
+
console.log(chalk.default.dim(` Patterns: ${resolved.patterns.length > 0 ? resolved.patterns.join(", ") : "auto-discover"}`));
|
|
162
|
+
}
|
|
163
|
+
console.log();
|
|
164
|
+
const results = await require_linter.lint({
|
|
165
|
+
...resolved,
|
|
166
|
+
onProgress: (current, total, file) => {
|
|
167
|
+
if (process.stdout.isTTY && !resolved.verbose) {
|
|
168
|
+
const displayFile = truncateFilename(file, 50);
|
|
169
|
+
process.stdout.write(`\rLinting files... (${current}/${total}) ${chalk.default.dim(displayFile)}${" ".repeat(10)}`);
|
|
170
|
+
} else if (resolved.verbose) console.log(chalk.default.dim(` [${current}/${total}] Linting ${file}`));
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
if (process.stdout.isTTY && !resolved.verbose) process.stdout.write("\r\x1B[K");
|
|
174
|
+
if (results.totalFilesProcessed === 0) {
|
|
175
|
+
if (resolved.verbose) console.log();
|
|
176
|
+
console.log(chalk.default.yellow("No files found to lint."));
|
|
177
|
+
process.exit(0);
|
|
178
|
+
}
|
|
179
|
+
if (results.files.length === 0) {
|
|
180
|
+
if (resolved.verbose) console.log();
|
|
181
|
+
console.log(chalk.default.green.bold("✔ No issues found"));
|
|
182
|
+
process.exit(0);
|
|
183
|
+
}
|
|
184
|
+
await displayResults(results.files, resolved.fix, resolved.verbose);
|
|
185
|
+
const hasErrors = results.files.some((file) => file.diagnostics.some((d) => d.severity === 1));
|
|
186
|
+
process.exit(hasErrors ? 1 : 0);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
189
|
+
console.error(chalk.default.red("✖ Error:"), errorMessage);
|
|
190
|
+
if (resolved.verbose && error instanceof Error) {
|
|
191
|
+
console.error(chalk.default.dim("\nStack trace:"));
|
|
192
|
+
console.error(chalk.default.dim(error.stack || error.toString()));
|
|
193
|
+
}
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
program.parse();
|
|
198
|
+
|
|
199
|
+
//#endregion
|
|
200
|
+
//# sourceMappingURL=cli.cjs.map
|
package/dist/cli.cjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.cjs","names":["path","DEFAULT_FILE_PATTERN","Command","fs","DEFAULT_VERSION","lint"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport chalk from \"chalk\";\nimport { Command } from \"commander\";\nimport { DEFAULT_FILE_PATTERN, DEFAULT_VERSION } from \"./constants\";\nimport { lint } from \"./linter\";\nimport type { LintFileResult, SerializedDiagnostic } from \"./types\";\n\nfunction countDiagnosticsBySeverity(diagnostics: SerializedDiagnostic[]): {\n\terrors: number;\n\twarnings: number;\n} {\n\tlet errors = 0;\n\tlet warnings = 0;\n\n\tfor (const diagnostic of diagnostics) {\n\t\tif (diagnostic.severity === 1) errors++;\n\t\tif (diagnostic.severity === 2) warnings++;\n\t}\n\n\treturn { errors, warnings };\n}\n\ninterface ResolvedOptions {\n\tcwd: string;\n\tconfigPath: string | undefined;\n\tpatterns: string[];\n\tautoDiscover: boolean;\n\tfix: boolean;\n\tverbose: boolean;\n}\n\ninterface CliOptions {\n\tconfig?: string;\n\tauto?: boolean;\n\tfix?: boolean;\n\tverbose?: boolean;\n}\n\nfunction resolveOptions(files: string[], options: CliOptions): ResolvedOptions {\n\tconst hasConfigFlag = !!options.config;\n\tconst hasAutoFlag = !!options.auto;\n\tconst hasFiles = files.length > 0;\n\n\tlet cwd = process.cwd();\n\tlet configPath = options.config;\n\tlet patterns = files;\n\n\tif (hasConfigFlag && options.config && !hasFiles) {\n\t\tconst absoluteConfigPath = path.isAbsolute(options.config)\n\t\t\t? options.config\n\t\t\t: path.resolve(process.cwd(), options.config);\n\t\tcwd = path.dirname(absoluteConfigPath);\n\t\tconfigPath = path.basename(absoluteConfigPath);\n\t\tpatterns = [DEFAULT_FILE_PATTERN];\n\t}\n\n\tconst autoDiscover = hasAutoFlag;\n\n\treturn {\n\t\tcwd,\n\t\tconfigPath,\n\t\tpatterns: autoDiscover ? [] : patterns,\n\t\tautoDiscover,\n\t\tfix: options.fix || false,\n\t\tverbose: options.verbose || false,\n\t};\n}\n\nfunction truncateFilename(filename: string, maxLength: number): string {\n\treturn filename.length > maxLength\n\t\t? `...${filename.slice(-maxLength)}`\n\t\t: filename;\n}\n\nasync function displayResults(\n\tfiles: LintFileResult[],\n\tfixMode: boolean,\n\tverbose: boolean,\n): Promise<void> {\n\tlet totalErrors = 0;\n\tlet totalWarnings = 0;\n\tlet totalFixed = 0;\n\tlet filesWithIssues = 0;\n\tlet isFirstFile = true;\n\n\tfor (const file of files) {\n\t\tif (file.diagnostics.length > 0 || (fixMode && file.fixed)) {\n\t\t\tif (isFirstFile && verbose) {\n\t\t\t\tconsole.log();\n\t\t\t\tisFirstFile = false;\n\t\t\t} else if (!isFirstFile) {\n\t\t\t\tconsole.log();\n\t\t\t}\n\t\t\tconsole.log(chalk.underline.bold(file.path));\n\n\t\t\tif (fixMode && file.fixed) {\n\t\t\t\tconst issueText = `${file.fixedCount || 0} issue${file.fixedCount !== 1 ? \"s\" : \"\"}`;\n\t\t\t\tconsole.log(chalk.green(` ✔ Fixed ${issueText}`));\n\t\t\t\ttotalFixed += file.fixedCount || 0;\n\t\t\t}\n\n\t\t\tconst { errors, warnings } = countDiagnosticsBySeverity(file.diagnostics);\n\t\t\ttotalErrors += errors;\n\t\t\ttotalWarnings += warnings;\n\n\t\t\tif (file.diagnostics.length > 0) {\n\t\t\t\tfilesWithIssues++;\n\t\t\t}\n\n\t\t\tfor (const diagnostic of file.diagnostics) {\n\t\t\t\tconst line = diagnostic.range.start.line + 1;\n\t\t\t\tconst char = diagnostic.range.start.character + 1;\n\t\t\t\tconst severity = diagnostic.severity === 1 ? \"error\" : \"warning\";\n\t\t\t\tconst severityColor =\n\t\t\t\t\tdiagnostic.severity === 1\n\t\t\t\t\t\t? chalk.red(severity)\n\t\t\t\t\t\t: chalk.yellow(severity);\n\t\t\t\tconst code = diagnostic.code ? chalk.dim(` (${diagnostic.code})`) : \"\";\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t` ${chalk.dim(`${line}:${char}`)} ${severityColor} ${diagnostic.message}${code}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tconsole.log();\n\n\tif (totalErrors === 0 && totalWarnings === 0) {\n\t\tif (totalFixed > 0) {\n\t\t\tconst issueText = `${totalFixed} issue${totalFixed !== 1 ? \"s\" : \"\"}`;\n\t\t\tconsole.log(chalk.green.bold(`✔ Fixed ${issueText}`));\n\t\t} else {\n\t\t\tconsole.log(chalk.green.bold(\"✔ No issues found\"));\n\t\t}\n\t} else {\n\t\tconst parts = [];\n\t\tif (totalErrors > 0) {\n\t\t\tparts.push(`${totalErrors} error${totalErrors !== 1 ? \"s\" : \"\"}`);\n\t\t}\n\t\tif (totalWarnings > 0) {\n\t\t\tparts.push(`${totalWarnings} warning${totalWarnings !== 1 ? \"s\" : \"\"}`);\n\t\t}\n\n\t\tconst fileText = `${filesWithIssues} file${filesWithIssues !== 1 ? \"s\" : \"\"}`;\n\t\tconst summary = `Found ${parts.join(\" and \")} in ${fileText}`;\n\n\t\tif (totalFixed > 0) {\n\t\t\tconst issueText = `${totalFixed} issue${totalFixed !== 1 ? \"s\" : \"\"}`;\n\t\t\tconsole.log(chalk.green.bold(`✔ Fixed ${issueText}`));\n\t\t\tconsole.log(summary);\n\t\t} else {\n\t\t\tconsole.log(summary);\n\t\t}\n\t}\n}\n\nconst program = new Command();\n\nconst getVersion = (): string => {\n\tconst packageJsonPath = path.join(__dirname, \"../package.json\");\n\ttry {\n\t\tconst pkg = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n\t\treturn pkg.version || DEFAULT_VERSION;\n\t} catch {\n\t\treturn DEFAULT_VERSION;\n\t}\n};\n\nprogram.configureHelp({\n\tformatHelp: (cmd, helper) => {\n\t\tconst termWidth = helper.padWidth(cmd, helper);\n\t\tlet output = \"\";\n\n\t\toutput += `${chalk.bold.cyan(\"Usage:\")} ${helper.commandUsage(cmd)}\\n\\n`;\n\n\t\tif (cmd.description()) {\n\t\t\toutput += `${cmd.description()}\\n\\n`;\n\t\t}\n\n\t\tconst args = helper.visibleArguments(cmd);\n\t\tif (args.length > 0) {\n\t\t\toutput += `${chalk.bold.cyan(\"Arguments:\")}\\n`;\n\t\t\targs.forEach((arg) => {\n\t\t\t\tconst argName = arg.required ? `<${arg.name()}>` : `[${arg.name()}]`;\n\t\t\t\toutput += ` ${chalk.green(argName.padEnd(termWidth))} ${arg.description}\\n`;\n\t\t\t});\n\t\t\toutput += \"\\n\";\n\t\t}\n\n\t\tconst options = helper.visibleOptions(cmd);\n\t\tif (options.length > 0) {\n\t\t\toutput += `${chalk.bold.cyan(\"Options:\")}\\n`;\n\t\t\toptions.forEach((option) => {\n\t\t\t\tconst flags = helper.optionTerm(option);\n\t\t\t\tconst description = helper.optionDescription(option);\n\t\t\t\toutput += ` ${chalk.yellow(flags.padEnd(termWidth))} ${description}\\n`;\n\t\t\t});\n\t\t\toutput += \"\\n\";\n\t\t}\n\n\t\treturn output;\n\t},\n});\n\nprogram\n\t.name(\"tailwind-lint\")\n\t.description(\"A CLI tool for linting Tailwind CSS class usage\")\n\t.version(getVersion())\n\t.argument(\n\t\t\"[files...]\",\n\t\t'File patterns to lint (e.g., \"src/**/*.{js,jsx,ts,tsx}\")',\n\t)\n\t.option(\n\t\t\"-c, --config <path>\",\n\t\t\"Path to Tailwind config file (default: auto-discover)\",\n\t)\n\t.option(\n\t\t\"-a, --auto\",\n\t\t\"Auto-discover files from Tailwind config content patterns\",\n\t)\n\t.option(\"--fix\", \"Automatically fix problems that can be fixed\")\n\t.option(\"-v, --verbose\", \"Enable verbose logging for debugging\")\n\t.addHelpText(\n\t\t\"after\",\n\t\t`\n${chalk.bold.cyan(\"Examples:\")}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.green('\"src/**/*.{js,jsx,ts,tsx}\"')}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.yellow(\"--auto\")}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.yellow(\"--config\")} ${chalk.green(\"./tailwind.config.js\")}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.green('\"src/**/*.tsx\"')} ${chalk.yellow(\"--fix\")}\n ${chalk.dim(\"$\")} tailwind-lint ${chalk.green('\"**/*.vue\"')}\n\n${chalk.bold.cyan(\"Notes:\")}\n ${chalk.dim(\"•\")} Use ${chalk.yellow(\"--auto\")} to auto-discover files from your Tailwind config (v3 only)\n ${chalk.dim(\"•\")} Use ${chalk.yellow(\"--config\")} alone to lint common file types from that directory\n ${chalk.dim(\"•\")} Default pattern: ${chalk.dim(\"./**/*.{js,jsx,ts,tsx,html}\")}\n ${chalk.dim(\"•\")} Use ${chalk.yellow(\"--fix\")} to automatically resolve fixable issues\n`,\n\t)\n\t.action(async (files: string[], options) => {\n\t\tconst hasConfigFlag = !!options.config;\n\t\tconst hasAutoFlag = !!options.auto;\n\t\tconst hasFiles = files.length > 0;\n\n\t\tif (!hasFiles && !hasAutoFlag && !hasConfigFlag) {\n\t\t\tconsole.error(\n\t\t\t\t\"Error: No files specified. Use glob patterns, --auto flag, or --config flag.\\n\",\n\t\t\t);\n\t\t\tprogram.help();\n\t\t}\n\n\t\tconst resolved = resolveOptions(files, options);\n\n\t\ttry {\n\t\t\tif (resolved.verbose) {\n\t\t\t\tconsole.log(chalk.cyan(\"→ Running in verbose mode\"));\n\t\t\t\tconsole.log(chalk.dim(` Working directory: ${resolved.cwd}`));\n\t\t\t\tconsole.log(\n\t\t\t\t\tchalk.dim(` Config path: ${resolved.configPath || \"auto-discover\"}`),\n\t\t\t\t);\n\t\t\t\tconsole.log(chalk.dim(` Fix mode: ${resolved.fix}`));\n\t\t\t\tconsole.log(\n\t\t\t\t\tchalk.dim(\n\t\t\t\t\t\t` Patterns: ${resolved.patterns.length > 0 ? resolved.patterns.join(\", \") : \"auto-discover\"}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconsole.log();\n\n\t\t\tconst results = await lint({\n\t\t\t\t...resolved,\n\t\t\t\tonProgress: (current, total, file) => {\n\t\t\t\t\tif (process.stdout.isTTY && !resolved.verbose) {\n\t\t\t\t\t\tconst displayFile = truncateFilename(file, 50);\n\t\t\t\t\t\tprocess.stdout.write(\n\t\t\t\t\t\t\t`\\rLinting files... (${current}/${total}) ${chalk.dim(displayFile)}${\" \".repeat(10)}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (resolved.verbose) {\n\t\t\t\t\t\tconsole.log(chalk.dim(` [${current}/${total}] Linting ${file}`));\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (process.stdout.isTTY && !resolved.verbose) {\n\t\t\t\tprocess.stdout.write(\"\\r\\x1b[K\");\n\t\t\t}\n\n\t\t\tif (results.totalFilesProcessed === 0) {\n\t\t\t\tif (resolved.verbose) {\n\t\t\t\t\tconsole.log();\n\t\t\t\t}\n\t\t\t\tconsole.log(chalk.yellow(\"No files found to lint.\"));\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\n\t\t\tif (results.files.length === 0) {\n\t\t\t\tif (resolved.verbose) {\n\t\t\t\t\tconsole.log();\n\t\t\t\t}\n\t\t\t\tconsole.log(chalk.green.bold(\"✔ No issues found\"));\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\n\t\t\tawait displayResults(results.files, resolved.fix, resolved.verbose);\n\n\t\t\tconst hasErrors = results.files.some((file) =>\n\t\t\t\tfile.diagnostics.some((d) => d.severity === 1),\n\t\t\t);\n\t\t\tprocess.exit(hasErrors ? 1 : 0);\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error);\n\t\t\tconsole.error(chalk.red(\"✖ Error:\"), errorMessage);\n\n\t\t\tif (resolved.verbose && error instanceof Error) {\n\t\t\t\tconsole.error(chalk.dim(\"\\nStack trace:\"));\n\t\t\t\tconsole.error(chalk.dim(error.stack || error.toString()));\n\t\t\t}\n\t\t\tprocess.exit(1);\n\t\t}\n\t});\n\nprogram.parse();\n"],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/constants.ts
|
|
3
|
+
const DEFAULT_IGNORE_PATTERNS = [
|
|
4
|
+
"**/node_modules/**",
|
|
5
|
+
"**/dist/**",
|
|
6
|
+
"**/build/**",
|
|
7
|
+
"**/.git/**",
|
|
8
|
+
"**/.next/**",
|
|
9
|
+
"**/.nuxt/**",
|
|
10
|
+
"**/coverage/**",
|
|
11
|
+
"**/.vscode/**",
|
|
12
|
+
"**/.idea/**",
|
|
13
|
+
"**/.cache/**",
|
|
14
|
+
"**/.DS_Store/**"
|
|
15
|
+
];
|
|
16
|
+
const DEFAULT_FILE_PATTERN = "./**/*.{js,jsx,ts,tsx,html}";
|
|
17
|
+
const V3_CONFIG_PATHS = [
|
|
18
|
+
"tailwind.config.js",
|
|
19
|
+
"tailwind.config.cjs",
|
|
20
|
+
"tailwind.config.mjs",
|
|
21
|
+
"tailwind.config.ts"
|
|
22
|
+
];
|
|
23
|
+
const V4_CSS_NAMES = [
|
|
24
|
+
"app.css",
|
|
25
|
+
"index.css",
|
|
26
|
+
"tailwind.css",
|
|
27
|
+
"globals.css"
|
|
28
|
+
];
|
|
29
|
+
const V4_CSS_FOLDERS = [
|
|
30
|
+
"./",
|
|
31
|
+
"./src/",
|
|
32
|
+
"./app/",
|
|
33
|
+
"./styles/"
|
|
34
|
+
];
|
|
35
|
+
const DEFAULT_VERSION = "0.0.1";
|
|
36
|
+
const MAX_FIX_ITERATIONS = 10;
|
|
37
|
+
const DEFAULT_TAB_SIZE = 2;
|
|
38
|
+
const DEFAULT_SEPARATOR = ":";
|
|
39
|
+
const DEFAULT_ROOT_FONT_SIZE = 16;
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
Object.defineProperty(exports, 'DEFAULT_FILE_PATTERN', {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function () {
|
|
45
|
+
return DEFAULT_FILE_PATTERN;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, 'DEFAULT_IGNORE_PATTERNS', {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () {
|
|
51
|
+
return DEFAULT_IGNORE_PATTERNS;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(exports, 'DEFAULT_ROOT_FONT_SIZE', {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function () {
|
|
57
|
+
return DEFAULT_ROOT_FONT_SIZE;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(exports, 'DEFAULT_SEPARATOR', {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function () {
|
|
63
|
+
return DEFAULT_SEPARATOR;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
Object.defineProperty(exports, 'DEFAULT_TAB_SIZE', {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function () {
|
|
69
|
+
return DEFAULT_TAB_SIZE;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(exports, 'DEFAULT_VERSION', {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function () {
|
|
75
|
+
return DEFAULT_VERSION;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
Object.defineProperty(exports, 'MAX_FIX_ITERATIONS', {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function () {
|
|
81
|
+
return MAX_FIX_ITERATIONS;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
Object.defineProperty(exports, 'V3_CONFIG_PATHS', {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function () {
|
|
87
|
+
return V3_CONFIG_PATHS;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
Object.defineProperty(exports, 'V4_CSS_FOLDERS', {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
get: function () {
|
|
93
|
+
return V4_CSS_FOLDERS;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
Object.defineProperty(exports, 'V4_CSS_NAMES', {
|
|
97
|
+
enumerable: true,
|
|
98
|
+
get: function () {
|
|
99
|
+
return V4_CSS_NAMES;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
//# sourceMappingURL=constants-BFubEpZ9.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants-BFubEpZ9.cjs","names":[],"sources":["../src/constants.ts"],"sourcesContent":["export const DEFAULT_IGNORE_PATTERNS = [\n\t\"**/node_modules/**\",\n\t\"**/dist/**\",\n\t\"**/build/**\",\n\t\"**/.git/**\",\n\t\"**/.next/**\",\n\t\"**/.nuxt/**\",\n\t\"**/coverage/**\",\n\t\"**/.vscode/**\",\n\t\"**/.idea/**\",\n\t\"**/.cache/**\",\n\t\"**/.DS_Store/**\",\n];\n\nexport const DEFAULT_FILE_PATTERN = \"./**/*.{js,jsx,ts,tsx,html}\";\n\nexport const V3_CONFIG_PATHS = [\n\t\"tailwind.config.js\",\n\t\"tailwind.config.cjs\",\n\t\"tailwind.config.mjs\",\n\t\"tailwind.config.ts\",\n];\n\nexport const V4_CSS_NAMES = [\n\t\"app.css\",\n\t\"index.css\",\n\t\"tailwind.css\",\n\t\"globals.css\",\n];\n\nexport const V4_CSS_FOLDERS = [\"./\", \"./src/\", \"./app/\", \"./styles/\"];\n\nexport const LANGUAGE_MAP: Record<string, string> = {\n\t\".astro\": \"astro\",\n\t\".css\": \"css\",\n\t\".erb\": \"erb\",\n\t\".hbs\": \"handlebars\",\n\t\".htm\": \"html\",\n\t\".html\": \"html\",\n\t\".js\": \"javascript\",\n\t\".jsx\": \"javascriptreact\",\n\t\".less\": \"less\",\n\t\".md\": \"markdown\",\n\t\".mdx\": \"mdx\",\n\t\".php\": \"php\",\n\t\".sass\": \"sass\",\n\t\".scss\": \"scss\",\n\t\".svelte\": \"svelte\",\n\t\".ts\": \"typescript\",\n\t\".tsx\": \"typescriptreact\",\n\t\".twig\": \"twig\",\n\t\".vue\": \"vue\",\n};\n\nexport const DEFAULT_VERSION = \"0.0.1\";\n\nexport const MAX_FIX_ITERATIONS = 10;\n\nexport const DEFAULT_TAB_SIZE = 2;\n\nexport const DEFAULT_SEPARATOR = \":\";\n\nexport const DEFAULT_ROOT_FONT_SIZE = 16;\n"],"mappings":";;AAAA,MAAa,0BAA0B;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AAED,MAAa,uBAAuB;AAEpC,MAAa,kBAAkB;CAC9B;CACA;CACA;CACA;CACA;AAED,MAAa,eAAe;CAC3B;CACA;CACA;CACA;CACA;AAED,MAAa,iBAAiB;CAAC;CAAM;CAAU;CAAU;CAAY;AAwBrE,MAAa,kBAAkB;AAE/B,MAAa,qBAAqB;AAElC,MAAa,mBAAmB;AAEhC,MAAa,oBAAoB;AAEjC,MAAa,yBAAyB"}
|