styles-config 2.0.0-alpha.5 → 2.0.0-alpha.7

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/src/types.ts DELETED
@@ -1,359 +0,0 @@
1
- /**
2
- * Math processing modes
3
- */
4
- export type MathMode = 'always' | 'parens-division' | 'parens' | 'strict';
5
-
6
- /**
7
- * Unit conversion modes
8
- */
9
- export type UnitMode = 'loose' | 'preserve' | 'strict';
10
-
11
- /**
12
- * Equality/coercion modes for guard comparisons.
13
- */
14
- export type EqualityMode = 'coerce' | 'strict';
15
-
16
- export interface JavaScriptSandboxConfig {
17
- /**
18
- * Allow network access for script execution runtime.
19
- * @default false
20
- */
21
- allowHttp?: boolean;
22
- /**
23
- * Optional host allowlist when `allowHttp` is enabled.
24
- */
25
- allowNetHosts?: string[];
26
- /**
27
- * Optional explicit filesystem root for script reads.
28
- * If omitted, compiler resolves using entry/config roots.
29
- */
30
- jsReadRoot?: string;
31
- }
32
-
33
- export type CompileJavaScriptOption = true | JavaScriptSandboxConfig;
34
-
35
- /**
36
- * Less compiler options
37
- * Based on less.js default-options.js and bin/lessc
38
- */
39
- export interface LessOptions {
40
- /**
41
- * Inline Javascript - @plugin still allowed
42
- * @default false
43
- */
44
- javascriptEnabled?: boolean;
45
-
46
- /**
47
- * Outputs a makefile import dependency list to stdout.
48
- * @default false
49
- */
50
- depends?: boolean;
51
-
52
- /**
53
- * @deprecated Compress using less built-in compression.
54
- * This does an okay job but does not utilise all the tricks of
55
- * dedicated css compression.
56
- * @default false
57
- */
58
- compress?: boolean;
59
-
60
- /**
61
- * Runs the less parser and just reports errors without any output.
62
- * @default false
63
- */
64
- lint?: boolean;
65
-
66
- /**
67
- * Sets available include paths.
68
- * If the file in an @import rule does not exist at that exact location,
69
- * less will look for it at the location(s) passed to this option.
70
- * @default []
71
- */
72
- paths?: string[];
73
-
74
- /**
75
- * Color output in the terminal
76
- * @default true
77
- */
78
- color?: boolean;
79
-
80
- /**
81
- * @deprecated This option has confusing behavior and may be removed in a future version.
82
- *
83
- * Controls how @import statements for .less files are handled inside selector blocks (rulesets).
84
- *
85
- * Behavior:
86
- * - @import at root level: Always processed
87
- * - @import inside @-rules (@media, @supports, etc.): Processed (these are not selector blocks)
88
- * - @import inside selector blocks (.class, #id, etc.): Behavior depends on this option
89
- *
90
- * Options:
91
- * - `false` (default): All @import statements are processed regardless of context.
92
- * - `true`: @import statements inside selector blocks are silently ignored and not output.
93
- * - `'error'`: @import statements inside selector blocks will throw an error instead of being silently ignored.
94
- *
95
- * Note: Only affects .less file imports. CSS imports (url(...) or .css files) are
96
- * always output as CSS @import statements regardless of this setting.
97
- *
98
- * @see https://github.com/less/less.js/issues/656
99
- * @default false
100
- */
101
- strictImports?: boolean | 'error';
102
-
103
- /**
104
- * Allow Imports from Insecure HTTPS Hosts
105
- * @default false
106
- */
107
- insecure?: boolean;
108
-
109
- /**
110
- * Allows you to add a path to every generated import and url in your css.
111
- * This does not affect less import statements that are processed, just ones
112
- * that are left in the output css.
113
- * @default ''
114
- */
115
- rootpath?: string;
116
-
117
- /**
118
- * By default URLs are kept as-is, so if you import a file in a sub-directory
119
- * that references an image, exactly the same URL will be output in the css.
120
- * This option allows you to re-write URL's in imported files so that the
121
- * URL is always relative to the base imported file
122
- * @default false
123
- */
124
- rewriteUrls?: boolean | 'all' | 'local' | 'off';
125
-
126
- /**
127
- * How to process math operations
128
- * - 'always': eagerly try to solve all operations
129
- * - 'parens-division': require parens for division "/"
130
- * - 'parens' or 'strict': require parens for all operations
131
- * @default 'parens-division'
132
- */
133
- mathMode?: MathMode;
134
-
135
- /**
136
- * How to handle unit conversions in math operations
137
- * - 'loose': Less's default 1.x-4.x behavior
138
- * - 'preserve': Create calc() expressions for unit errors
139
- * - 'strict': strict unit mode
140
- * @default 'preserve'
141
- */
142
- unitMode?: UnitMode;
143
-
144
- /**
145
- * How to handle equality/coercion in guards and comparisons.
146
- * - 'coerce': Less-compatible coercion behavior
147
- * - 'strict': type-strict behavior
148
- * @default 'coerce'
149
- */
150
- equalityMode?: EqualityMode;
151
-
152
- /**
153
- * @deprecated Use `mathMode` instead. This option maps to `mathMode` as follows:
154
- * - 0 or 'always' → 'always'
155
- * - 1 or 'parens-division' → 'parens-division'
156
- * - 2 or 'parens' or 'strict' → 'parens'
157
- * - 3 or 'strict-legacy' → 'parens' (removed, will default to 'strict)
158
- * @default undefined (uses mathMode if provided, otherwise 'parens-division')
159
- */
160
- math?: 0 | 1 | 2 | 3 | MathMode | 'strict-legacy';
161
-
162
- /**
163
- * @deprecated Use `unitMode` instead. If `true`, sets `unitMode` to 'strict'.
164
- * If `false`, sets the unitMode to 'loose.
165
- * If undefined, uses the `unitMode` value (defaults to 'preserve').
166
- * @default false
167
- */
168
- strictUnits?: boolean;
169
-
170
- /**
171
- * Effectively the declaration is put at the top of your base Less file,
172
- * meaning it can be used but it also can be overridden if this variable
173
- * is defined in the file.
174
- * @default null
175
- */
176
- globalVars?: Record<string, string> | null;
177
-
178
- /**
179
- * As opposed to the global variable option, this puts the declaration at the
180
- * end of your base file, meaning it will override anything defined in your Less file.
181
- * @default null
182
- */
183
- modifyVars?: Record<string, string> | null;
184
-
185
- /**
186
- * This option allows you to specify a argument to go on to every URL.
187
- * @default ''
188
- */
189
- urlArgs?: string;
190
-
191
- /**
192
- * @removed The dumpLineNumbers option is not useful nor supported in browsers. Use sourcemaps instead.
193
- *
194
- * @default undefined
195
- */
196
- dumpLineNumbers?: string;
197
-
198
- /**
199
- * Source map options
200
- * @default undefined
201
- */
202
- sourceMap?: boolean | {
203
- sourceMapFullFilename?: string;
204
- sourceMapRootpath?: string;
205
- sourceMapBasepath?: string;
206
- sourceMapURL?: string;
207
- sourceMapFileInline?: boolean;
208
- outputSourceFiles?: boolean;
209
- disableSourcemapAnnotation?: boolean;
210
- sourceMapOutputFilename?: string;
211
- sourceMapFilename?: string;
212
- };
213
-
214
- /**
215
- * Verbose output
216
- * @default false
217
- */
218
- verbose?: boolean;
219
-
220
- /**
221
- * Silent mode (suppress errors)
222
- * @default false
223
- */
224
- silent?: boolean;
225
-
226
- /**
227
- * Quiet mode (suppress warnings)
228
- * @default false
229
- */
230
- quiet?: boolean;
231
-
232
- /**
233
- * @deprecated This is legacy Less behavior.
234
- *
235
- * Controls whether mixins and detached rulesets "leak" their inner rules.
236
- * When true:
237
- * - Mixins: Mixin and VarDeclaration nodes are 'public' and 'optional' respectively
238
- * - Detached rulesets: Mixin and VarDeclaration nodes are 'public' and 'private' respectively
239
- * When false:
240
- * - Both mixins and detached rulesets: Mixin and VarDeclaration nodes are 'private'
241
- * @default true
242
- */
243
- leakyRules?: boolean;
244
-
245
- /**
246
- * Whether to collapse nested selectors (Less 1.x-4.x style flattening)
247
- * When true, nested selectors like `.parent { .child { } }` are flattened to `.parent .child { }`
248
- * @default false
249
- */
250
- collapseNesting?: boolean;
251
-
252
- /**
253
- * @deprecated This is legacy Less behavior.
254
- *
255
- * Whether to bubble root-only at-rules (@font-face, @keyframes, etc.) to the root
256
- * when they are nested inside rulesets. Modern CSS supports nesting these at-rules.
257
- * @default true
258
- */
259
- bubbleRootAtRules?: boolean;
260
- }
261
-
262
- /**
263
- * Base interface for file-matching options
264
- */
265
- export interface FileMatchOptions {
266
- /**
267
- * File path, relative path, or glob pattern for matching.
268
- * If omitted, the options serve as defaults.
269
- */
270
- file?: string;
271
- }
272
-
273
- /**
274
- * Input file options - can override compile and language settings per input file
275
- */
276
- export interface InputOptions extends FileMatchOptions {
277
- // Compile-level options that can be overridden per-input
278
- mathMode?: MathMode;
279
- unitMode?: UnitMode;
280
- equalityMode?: EqualityMode;
281
- searchPaths?: string[];
282
- enableJavaScript?: boolean;
283
-
284
- // Less-specific options that can be overridden per-input
285
- javascriptEnabled?: boolean;
286
- paths?: string[];
287
- globalVars?: Record<string, string> | null;
288
- modifyVars?: Record<string, string> | null;
289
- strictImports?: boolean | 'error';
290
- rewriteUrls?: boolean | 'all' | 'local' | 'off';
291
- rootpath?: string;
292
- leakyRules?: boolean;
293
- collapseNesting?: boolean;
294
- bubbleRootAtRules?: boolean;
295
-
296
- /** Allow additional language-specific options */
297
- [key: string]: any;
298
- }
299
-
300
- /**
301
- * Output file options - can override output settings per output file
302
- */
303
- export interface OutputOptions extends FileMatchOptions {
304
- collapseNesting?: boolean;
305
- compress?: boolean;
306
- sourceMap?: boolean | {
307
- sourceMapFullFilename?: string;
308
- sourceMapRootpath?: string;
309
- sourceMapBasepath?: string;
310
- sourceMapURL?: string;
311
- sourceMapFileInline?: boolean;
312
- outputSourceFiles?: boolean;
313
- disableSourcemapAnnotation?: boolean;
314
- sourceMapOutputFilename?: string;
315
- sourceMapFilename?: string;
316
- };
317
-
318
- /** Allow additional options */
319
- [key: string]: any;
320
- }
321
-
322
- export interface StylesConfig {
323
- compile?: {
324
- /**
325
- * Plugins can be specified as:
326
- * - Plugin instances (PluginInterface from @jesscss/core)
327
- * - String keys (plugin names that get resolved elsewhere)
328
- *
329
- * @note - Using `any` here to avoid circular dependency with @jesscss/core.
330
- * The actual type is PluginInterface from @jesscss/core.
331
- */
332
- plugins?: Array<any | string>;
333
- searchPaths?: string[];
334
- enableJavaScript?: boolean;
335
- javascript?: CompileJavaScriptOption;
336
- mathMode?: MathMode;
337
- unitMode?: UnitMode;
338
- equalityMode?: EqualityMode;
339
- };
340
- /**
341
- * Input file options. Can be a single object for defaults, or an array
342
- * where entries can have a `file` property (path or glob) to match specific inputs.
343
- * Entries without a `file` property serve as defaults.
344
- */
345
- input?: InputOptions | InputOptions[];
346
- /**
347
- * Output file options. Can be a single object for defaults, or an array
348
- * where entries can have a `file` property (path or glob) to match specific outputs.
349
- * Entries without a `file` property serve as defaults.
350
- */
351
- output?: OutputOptions | OutputOptions[];
352
- language?: {
353
- less?: LessOptions;
354
- scss?: Record<string, any>;
355
- css?: Record<string, any>;
356
- jess?: Record<string, any>;
357
- [key: string]: LessOptions | Record<string, any> | undefined;
358
- };
359
- }
@@ -1,256 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { getOptions } from '../src/options.js';
3
- import type { StylesConfig } from '../src/types.js';
4
-
5
- describe('getOptions', () => {
6
- describe('language inference from input extension', () => {
7
- it('should infer language from .less extension', () => {
8
- const config: StylesConfig = {
9
- language: {
10
- less: { leakyRules: true }
11
- }
12
- };
13
- const options = getOptions(config, { input: 'src/styles.less' });
14
- expect(options.leakyRules).toBe(true);
15
- });
16
-
17
- it('should infer language from .scss extension', () => {
18
- const config: StylesConfig = {
19
- language: {
20
- scss: { precision: 10 }
21
- }
22
- };
23
- const options = getOptions(config, { input: 'src/styles.scss' });
24
- expect(options.precision).toBe(10);
25
- });
26
-
27
- it('should infer language from .sass extension', () => {
28
- const config: StylesConfig = {
29
- language: {
30
- scss: { indentedSyntax: true }
31
- }
32
- };
33
- const options = getOptions(config, { input: 'src/styles.sass' });
34
- expect(options.indentedSyntax).toBe(true);
35
- });
36
-
37
- it('should infer language from .jess extension', () => {
38
- const config: StylesConfig = {
39
- language: {
40
- jess: { customOption: 'value' }
41
- }
42
- };
43
- const options = getOptions(config, { input: 'src/styles.jess' });
44
- expect(options.customOption).toBe('value');
45
- });
46
-
47
- it('should allow explicit language to override inferred', () => {
48
- const config: StylesConfig = {
49
- language: {
50
- less: { leakyRules: true },
51
- scss: { precision: 10 }
52
- }
53
- };
54
- // File is .less but we explicitly request scss options
55
- const options = getOptions(config, { language: 'scss', input: 'src/styles.less' });
56
- expect(options.precision).toBe(10);
57
- expect(options.leakyRules).toBeUndefined();
58
- });
59
- });
60
-
61
- describe('merge priority', () => {
62
- it('should merge compile options as base', () => {
63
- const config: StylesConfig = {
64
- compile: {
65
- mathMode: 'parens-division',
66
- unitMode: 'loose',
67
- equalityMode: 'coerce'
68
- }
69
- };
70
- const options = getOptions(config);
71
- expect(options.mathMode).toBe('parens-division');
72
- expect(options.unitMode).toBe('loose');
73
- expect(options.equalityMode).toBe('coerce');
74
- });
75
-
76
- it('should override compile options with language options', () => {
77
- const config: StylesConfig = {
78
- compile: {
79
- mathMode: 'parens-division'
80
- },
81
- language: {
82
- less: { mathMode: 'strict' }
83
- }
84
- };
85
- const options = getOptions(config, { language: 'less' });
86
- expect(options.mathMode).toBe('strict');
87
- });
88
-
89
- it('should override language options with matched input options', () => {
90
- const config: StylesConfig = {
91
- language: {
92
- less: { mathMode: 'parens-division', leakyRules: true }
93
- },
94
- input: [
95
- { mathMode: 'strict' }
96
- ]
97
- };
98
- const options = getOptions(config, { input: 'src/styles.less' });
99
- expect(options.mathMode).toBe('strict');
100
- expect(options.leakyRules).toBe(true); // from language.less
101
- });
102
-
103
- it('should override input options with matched output options', () => {
104
- const config: StylesConfig = {
105
- input: [
106
- { compress: false }
107
- ],
108
- output: [
109
- { compress: true }
110
- ]
111
- };
112
- const options = getOptions(config, { input: 'src/styles.less', output: 'dist/styles.css' });
113
- expect(options.compress).toBe(true);
114
- });
115
-
116
- it('should apply full merge priority chain', () => {
117
- const config: StylesConfig = {
118
- compile: {
119
- mathMode: 'always',
120
- unitMode: 'loose',
121
- equalityMode: 'coerce'
122
- },
123
- language: {
124
- less: {
125
- mathMode: 'parens-division',
126
- leakyRules: true
127
- }
128
- },
129
- input: [
130
- { mathMode: 'strict', collapseNesting: false }
131
- ],
132
- output: [
133
- { compress: true, sourceMap: true }
134
- ]
135
- };
136
- const options = getOptions(config, { input: 'src/styles.less', output: 'dist/styles.css' });
137
- expect(options.unitMode).toBe('loose'); // from compile
138
- expect(options.equalityMode).toBe('coerce'); // from compile
139
- expect(options.leakyRules).toBe(true); // from language.less
140
- expect(options.mathMode).toBe('strict'); // from input (overrides language)
141
- expect(options.collapseNesting).toBe(false); // from input
142
- expect(options.compress).toBe(true); // from output
143
- expect(options.sourceMap).toBe(true); // from output
144
- });
145
- });
146
-
147
- describe('file matching', () => {
148
- it('should match entries without file property as defaults', () => {
149
- const config: StylesConfig = {
150
- input: [
151
- { leakyRules: true }
152
- ]
153
- };
154
- const options = getOptions(config, { input: 'any/file.less' });
155
- expect(options.leakyRules).toBe(true);
156
- });
157
-
158
- it('should match exact file paths', () => {
159
- const config: StylesConfig = {
160
- input: [
161
- { leakyRules: false },
162
- { file: 'src/legacy.less', leakyRules: true }
163
- ]
164
- };
165
- const options = getOptions(config, { input: 'src/legacy.less' });
166
- expect(options.leakyRules).toBe(true);
167
- });
168
-
169
- it('should match basename patterns', () => {
170
- const config: StylesConfig = {
171
- input: [
172
- { leakyRules: false },
173
- { file: 'legacy.less', leakyRules: true }
174
- ]
175
- };
176
- const options = getOptions(config, { input: '/path/to/legacy.less' });
177
- expect(options.leakyRules).toBe(true);
178
- });
179
-
180
- it('should match glob patterns', () => {
181
- const config: StylesConfig = {
182
- input: [
183
- { leakyRules: false },
184
- { file: 'legacy/**/*.less', leakyRules: true }
185
- ]
186
- };
187
- const options = getOptions(config, { input: 'legacy/old/styles.less' });
188
- expect(options.leakyRules).toBe(true);
189
- });
190
-
191
- it('should not match when glob does not match', () => {
192
- const config: StylesConfig = {
193
- input: [
194
- { leakyRules: false },
195
- { file: 'legacy/**/*.less', leakyRules: true }
196
- ]
197
- };
198
- const options = getOptions(config, { input: 'modern/styles.less' });
199
- expect(options.leakyRules).toBe(false);
200
- });
201
-
202
- it('should merge multiple matching entries in order', () => {
203
- const config: StylesConfig = {
204
- input: [
205
- { mathMode: 'always', leakyRules: false },
206
- { file: '**/*.less', mathMode: 'parens-division' },
207
- { file: 'legacy/**/*.less', leakyRules: true }
208
- ]
209
- };
210
- const options = getOptions(config, { input: 'legacy/old.less' });
211
- expect(options.mathMode).toBe('parens-division'); // from **/*.less
212
- expect(options.leakyRules).toBe(true); // from legacy/**/*.less
213
- });
214
-
215
- it('should match output files with glob patterns', () => {
216
- const config: StylesConfig = {
217
- output: [
218
- { compress: false },
219
- { file: '**/*.min.css', compress: true }
220
- ]
221
- };
222
- const options = getOptions(config, { output: 'dist/styles.min.css' });
223
- expect(options.compress).toBe(true);
224
- });
225
- });
226
-
227
- describe('single object vs array', () => {
228
- it('should handle single input object', () => {
229
- const config: StylesConfig = {
230
- input: { leakyRules: true }
231
- };
232
- const options = getOptions(config, { input: 'src/styles.less' });
233
- expect(options.leakyRules).toBe(true);
234
- });
235
-
236
- it('should handle single output object', () => {
237
- const config: StylesConfig = {
238
- output: { compress: true }
239
- };
240
- const options = getOptions(config, { output: 'dist/styles.css' });
241
- expect(options.compress).toBe(true);
242
- });
243
- });
244
-
245
- describe('no config', () => {
246
- it('should return empty-ish object with no config', () => {
247
- const options = getOptions();
248
- expect(options).toBeDefined();
249
- });
250
-
251
- it('should return empty-ish object with empty config', () => {
252
- const options = getOptions({});
253
- expect(options).toBeDefined();
254
- });
255
- });
256
- });
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "./lib",
5
- "rootDir": "./src",
6
- "noEmit": false
7
- },
8
- "include": ["src/**/*"]
9
- }
10
-