styles-config 2.0.0-alpha.4 → 2.0.0-alpha.6
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/lib/index.cjs +226 -0
- package/{src/types.ts → lib/index.d.cts} +115 -51
- package/lib/index.d.ts +423 -3
- package/lib/index.js +196 -4
- package/package.json +13 -7
- package/eslint.config.mjs +0 -6
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/loader.d.ts +0 -34
- package/lib/loader.d.ts.map +0 -1
- package/lib/loader.js +0 -99
- package/lib/loader.js.map +0 -1
- package/lib/options.d.ts +0 -49
- package/lib/options.d.ts.map +0 -1
- package/lib/options.js +0 -128
- package/lib/options.js.map +0 -1
- package/lib/types.d.ts +0 -320
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js +0 -2
- package/lib/types.js.map +0 -1
- package/src/index.ts +0 -3
- package/src/loader.ts +0 -112
- package/src/options.ts +0 -172
- package/test/options.test.ts +0 -256
- package/tsconfig.build.json +0 -10
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.json +0 -10
- package/tsconfig.tsbuildinfo +0 -1
package/src/loader.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { cosmiconfig, cosmiconfigSync, defaultLoadersSync } from 'cosmiconfig';
|
|
2
|
-
import type { StylesConfig } from './types.js';
|
|
3
|
-
|
|
4
|
-
export interface LoadedConfigMeta {
|
|
5
|
-
config: StylesConfig;
|
|
6
|
-
configFilePath?: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const explorer = cosmiconfig('styles', {
|
|
10
|
-
searchPlaces: [
|
|
11
|
-
'styles.config.ts',
|
|
12
|
-
'styles.config.js',
|
|
13
|
-
'styles.config.mts',
|
|
14
|
-
'styles.config.mjs',
|
|
15
|
-
'styles.config.cjs',
|
|
16
|
-
'styles.config.cts'
|
|
17
|
-
],
|
|
18
|
-
loaders: {
|
|
19
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
20
|
-
'.mts': defaultLoadersSync['.ts'],
|
|
21
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
22
|
-
'.cts': defaultLoadersSync['.ts'],
|
|
23
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
24
|
-
'.mjs': defaultLoadersSync['.js'],
|
|
25
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
26
|
-
'.cjs': defaultLoadersSync['.cjs']
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const explorerSync = cosmiconfigSync('styles', {
|
|
31
|
-
searchPlaces: [
|
|
32
|
-
'styles.config.ts',
|
|
33
|
-
'styles.config.js',
|
|
34
|
-
'styles.config.mts',
|
|
35
|
-
'styles.config.mjs',
|
|
36
|
-
'styles.config.cjs',
|
|
37
|
-
'styles.config.cts'
|
|
38
|
-
],
|
|
39
|
-
loaders: {
|
|
40
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
41
|
-
'.mts': defaultLoadersSync['.ts'],
|
|
42
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
43
|
-
'.cts': defaultLoadersSync['.ts'],
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
45
|
-
'.mjs': defaultLoadersSync['.js'],
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
47
|
-
'.cjs': defaultLoadersSync['.cjs']
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Load styles configuration from the file system (async)
|
|
53
|
-
* @param searchFrom - Directory to search from (defaults to process.cwd())
|
|
54
|
-
* @returns Configuration object or null if not found
|
|
55
|
-
*/
|
|
56
|
-
export async function loadConfig(searchFrom?: string): Promise<StylesConfig | null> {
|
|
57
|
-
const result = await explorer.search(searchFrom);
|
|
58
|
-
return result?.config ? normalizeConfig(result.config) : null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Load styles configuration from the file system (sync)
|
|
63
|
-
* @param searchFrom - Directory to search from (defaults to process.cwd())
|
|
64
|
-
* @returns Configuration object or empty object if not found
|
|
65
|
-
*/
|
|
66
|
-
export function loadConfigSync(searchFrom?: string): StylesConfig {
|
|
67
|
-
const result = explorerSync.search(searchFrom);
|
|
68
|
-
return result?.config ? normalizeConfig(result.config) : {};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Load styles configuration with metadata (sync).
|
|
73
|
-
* Includes config file path when a config file is discovered.
|
|
74
|
-
*/
|
|
75
|
-
export function loadConfigSyncWithMeta(searchFrom?: string): LoadedConfigMeta {
|
|
76
|
-
const result = explorerSync.search(searchFrom);
|
|
77
|
-
return {
|
|
78
|
-
config: result?.config ? normalizeConfig(result.config) : {},
|
|
79
|
-
configFilePath: result?.filepath
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Load styles configuration from a specific file path (async)
|
|
85
|
-
* @param filePath - Path to the config file
|
|
86
|
-
* @returns Configuration object or null if not found
|
|
87
|
-
*/
|
|
88
|
-
export async function loadConfigFromPath(filePath: string): Promise<StylesConfig | null> {
|
|
89
|
-
const result = await explorer.load(filePath);
|
|
90
|
-
return result?.config ? normalizeConfig(result.config) : null;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Load styles configuration from a specific file path (sync)
|
|
95
|
-
* @param filePath - Path to the config file
|
|
96
|
-
* @returns Configuration object or empty object if not found
|
|
97
|
-
*/
|
|
98
|
-
export function loadConfigFromPathSync(filePath: string): StylesConfig {
|
|
99
|
-
const result = explorerSync.load(filePath);
|
|
100
|
-
return result?.config ? normalizeConfig(result.config) : {};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Normalize config object - handle default exports and ensure proper type
|
|
105
|
-
*/
|
|
106
|
-
function normalizeConfig(config: any): StylesConfig {
|
|
107
|
-
// Handle default export (common in ES modules)
|
|
108
|
-
if (typeof config === 'object' && config !== null && 'default' in config) {
|
|
109
|
-
return config.default as StylesConfig;
|
|
110
|
-
}
|
|
111
|
-
return config as StylesConfig;
|
|
112
|
-
}
|
package/src/options.ts
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import type { StylesConfig, FileMatchOptions } from './types.js';
|
|
2
|
-
import picomatch from 'picomatch';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Options for retrieving merged configuration
|
|
7
|
-
*/
|
|
8
|
-
export interface GetOptionsParams {
|
|
9
|
-
/**
|
|
10
|
-
* Language key to get options for (e.g., 'less', 'scss', 'jess').
|
|
11
|
-
* If omitted but `input` is provided, language is inferred from the file extension.
|
|
12
|
-
*/
|
|
13
|
-
language?: string;
|
|
14
|
-
/**
|
|
15
|
-
* Input file path to match against input options.
|
|
16
|
-
* Also used to infer language if `language` is not specified.
|
|
17
|
-
*/
|
|
18
|
-
input?: string;
|
|
19
|
-
/**
|
|
20
|
-
* Output file path to match against output options
|
|
21
|
-
*/
|
|
22
|
-
output?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Map of file extensions to language keys
|
|
27
|
-
*/
|
|
28
|
-
const extensionToLanguage = new Map<string, string>([
|
|
29
|
-
['.less', 'less'],
|
|
30
|
-
['.scss', 'scss'],
|
|
31
|
-
['.sass', 'scss'],
|
|
32
|
-
['.jess', 'jess'],
|
|
33
|
-
['.css', 'css']
|
|
34
|
-
]);
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Infer language from a file path's extension
|
|
38
|
-
*/
|
|
39
|
-
function inferLanguage(filePath: string | undefined): string | undefined {
|
|
40
|
-
if (!filePath) {
|
|
41
|
-
return undefined;
|
|
42
|
-
}
|
|
43
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
44
|
-
return extensionToLanguage.get(ext);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Check if a file path matches a pattern (exact path, relative path, or glob)
|
|
49
|
-
*/
|
|
50
|
-
function matchesFile(pattern: string | undefined, filePath: string | undefined): boolean {
|
|
51
|
-
if (!pattern || !filePath) {
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Normalize paths for comparison
|
|
56
|
-
const normalizedPattern = path.normalize(pattern);
|
|
57
|
-
const normalizedFile = path.normalize(filePath);
|
|
58
|
-
|
|
59
|
-
// Try exact match first
|
|
60
|
-
if (normalizedPattern === normalizedFile) {
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Try basename match (e.g., pattern "styles.less" matches "/path/to/styles.less")
|
|
65
|
-
if (path.basename(normalizedFile) === normalizedPattern) {
|
|
66
|
-
return true;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Try glob/pattern match using picomatch
|
|
70
|
-
const isMatch = picomatch(pattern, { dot: true });
|
|
71
|
-
return isMatch(filePath) || isMatch(normalizedFile);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Get matching options from an array of file-based options.
|
|
76
|
-
* Returns merged options from:
|
|
77
|
-
* 1. All entries without a `file` property (defaults)
|
|
78
|
-
* 2. All entries whose `file` pattern matches the given path
|
|
79
|
-
*
|
|
80
|
-
* Later entries override earlier ones.
|
|
81
|
-
*/
|
|
82
|
-
function getMatchingOptions<T extends FileMatchOptions>(
|
|
83
|
-
options: T | T[] | undefined,
|
|
84
|
-
filePath?: string
|
|
85
|
-
): Partial<T> {
|
|
86
|
-
if (!options) {
|
|
87
|
-
return {};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const optionsArray = Array.isArray(options) ? options : [options];
|
|
91
|
-
let result: Partial<T> = {};
|
|
92
|
-
|
|
93
|
-
for (const opt of optionsArray) {
|
|
94
|
-
// Include if: no file pattern (default), or file pattern matches
|
|
95
|
-
if (!opt.file || (filePath && matchesFile(opt.file, filePath))) {
|
|
96
|
-
// Merge this entry's options, excluding the 'file' property
|
|
97
|
-
const rest = { ...opt } as Record<string, unknown>;
|
|
98
|
-
delete rest.file;
|
|
99
|
-
result = { ...result, ...rest };
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Get merged options by combining compile, language, input, and output settings.
|
|
107
|
-
*
|
|
108
|
-
* Merge priority (later wins):
|
|
109
|
-
* 1. compile options (base)
|
|
110
|
-
* 2. language-specific options (inferred from input extension or explicitly specified)
|
|
111
|
-
* 3. matched input options (if input path provided and matches)
|
|
112
|
-
* 4. matched output options (if output path provided and matches)
|
|
113
|
-
*
|
|
114
|
-
* @param config - The styles configuration object
|
|
115
|
-
* @param params - Options specifying language, input file, and output file
|
|
116
|
-
* @returns Merged options object
|
|
117
|
-
*
|
|
118
|
-
* @example
|
|
119
|
-
* // Get Less options for a specific input/output (language inferred from .less extension)
|
|
120
|
-
* const options = getOptions(config, {
|
|
121
|
-
* input: 'src/styles/main.less',
|
|
122
|
-
* output: 'dist/main.css'
|
|
123
|
-
* });
|
|
124
|
-
*
|
|
125
|
-
* @example
|
|
126
|
-
* // Explicitly specify language
|
|
127
|
-
* const options = getOptions(config, { language: 'less' });
|
|
128
|
-
*
|
|
129
|
-
* @example
|
|
130
|
-
* // Get base options without language-specific settings
|
|
131
|
-
* const options = getOptions(config);
|
|
132
|
-
*/
|
|
133
|
-
export function getOptions(
|
|
134
|
-
config: StylesConfig = {},
|
|
135
|
-
params: GetOptionsParams = {}
|
|
136
|
-
): Record<string, any> {
|
|
137
|
-
const { input: inputFile, output: outputFile } = params;
|
|
138
|
-
const { compile = {}, input, output, language: languageConfig = {} } = config;
|
|
139
|
-
|
|
140
|
-
// Determine language: explicit param > inferred from input extension
|
|
141
|
-
const language = params.language ?? inferLanguage(inputFile);
|
|
142
|
-
|
|
143
|
-
// Get language-specific options if language is determined
|
|
144
|
-
const languageOptions = language ? (languageConfig[language] ?? {}) : {};
|
|
145
|
-
|
|
146
|
-
// Get matched input and output options
|
|
147
|
-
const matchedInput = getMatchingOptions(input, inputFile);
|
|
148
|
-
const matchedOutput = getMatchingOptions(output, outputFile);
|
|
149
|
-
|
|
150
|
-
// Build result with proper merge priority:
|
|
151
|
-
// 1. compile (base)
|
|
152
|
-
// 2. language-specific
|
|
153
|
-
// 3. matched input
|
|
154
|
-
// 4. matched output
|
|
155
|
-
return {
|
|
156
|
-
// Start with compile-level settings
|
|
157
|
-
mathMode: compile.mathMode,
|
|
158
|
-
unitMode: compile.unitMode,
|
|
159
|
-
equalityMode: compile.equalityMode,
|
|
160
|
-
paths: compile.searchPaths,
|
|
161
|
-
javascriptEnabled: compile.enableJavaScript,
|
|
162
|
-
|
|
163
|
-
// Override with language-specific settings
|
|
164
|
-
...languageOptions,
|
|
165
|
-
|
|
166
|
-
// Override with matched input settings
|
|
167
|
-
...matchedInput,
|
|
168
|
-
|
|
169
|
-
// Override with matched output settings
|
|
170
|
-
...matchedOutput
|
|
171
|
-
};
|
|
172
|
-
}
|
package/test/options.test.ts
DELETED
|
@@ -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
|
-
});
|