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/lib/index.cjs +245 -0
- package/lib/index.js +214 -4
- package/lib/options.d.ts +21 -0
- package/lib/types.d.ts +93 -28
- package/package.json +12 -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.map +0 -1
- package/lib/loader.js +0 -99
- package/lib/loader.js.map +0 -1
- 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.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/src/types.ts +0 -359
- 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/lib/index.cjs
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
//#endregion
|
|
24
|
+
let cosmiconfig = require("cosmiconfig");
|
|
25
|
+
let picomatch = require("picomatch");
|
|
26
|
+
picomatch = __toESM(picomatch);
|
|
27
|
+
let path = require("path");
|
|
28
|
+
path = __toESM(path);
|
|
29
|
+
//#region src/loader.ts
|
|
30
|
+
const explorer = (0, cosmiconfig.cosmiconfig)("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
|
+
".mts": cosmiconfig.defaultLoadersSync[".ts"],
|
|
41
|
+
".cts": cosmiconfig.defaultLoadersSync[".ts"],
|
|
42
|
+
".mjs": cosmiconfig.defaultLoadersSync[".js"],
|
|
43
|
+
".cjs": cosmiconfig.defaultLoadersSync[".cjs"]
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
const explorerSync = (0, cosmiconfig.cosmiconfigSync)("styles", {
|
|
47
|
+
searchPlaces: [
|
|
48
|
+
"styles.config.ts",
|
|
49
|
+
"styles.config.js",
|
|
50
|
+
"styles.config.mts",
|
|
51
|
+
"styles.config.mjs",
|
|
52
|
+
"styles.config.cjs",
|
|
53
|
+
"styles.config.cts"
|
|
54
|
+
],
|
|
55
|
+
loaders: {
|
|
56
|
+
".mts": cosmiconfig.defaultLoadersSync[".ts"],
|
|
57
|
+
".cts": cosmiconfig.defaultLoadersSync[".ts"],
|
|
58
|
+
".mjs": cosmiconfig.defaultLoadersSync[".js"],
|
|
59
|
+
".cjs": cosmiconfig.defaultLoadersSync[".cjs"]
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
/**
|
|
63
|
+
* Load styles configuration from the file system (async)
|
|
64
|
+
* @param searchFrom - Directory to search from (defaults to process.cwd())
|
|
65
|
+
* @returns Configuration object or null if not found
|
|
66
|
+
*/
|
|
67
|
+
async function loadConfig(searchFrom) {
|
|
68
|
+
const result = await explorer.search(searchFrom);
|
|
69
|
+
return result?.config ? normalizeConfig(result.config) : null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Load styles configuration from the file system (sync)
|
|
73
|
+
* @param searchFrom - Directory to search from (defaults to process.cwd())
|
|
74
|
+
* @returns Configuration object or empty object if not found
|
|
75
|
+
*/
|
|
76
|
+
function loadConfigSync(searchFrom) {
|
|
77
|
+
const result = explorerSync.search(searchFrom);
|
|
78
|
+
return result?.config ? normalizeConfig(result.config) : {};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Load styles configuration with metadata (sync).
|
|
82
|
+
* Includes config file path when a config file is discovered.
|
|
83
|
+
*/
|
|
84
|
+
function loadConfigSyncWithMeta(searchFrom) {
|
|
85
|
+
const result = explorerSync.search(searchFrom);
|
|
86
|
+
return {
|
|
87
|
+
config: result?.config ? normalizeConfig(result.config) : {},
|
|
88
|
+
configFilePath: result?.filepath
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Load styles configuration from a specific file path (async)
|
|
93
|
+
* @param filePath - Path to the config file
|
|
94
|
+
* @returns Configuration object or null if not found
|
|
95
|
+
*/
|
|
96
|
+
async function loadConfigFromPath(filePath) {
|
|
97
|
+
const result = await explorer.load(filePath);
|
|
98
|
+
return result?.config ? normalizeConfig(result.config) : null;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Load styles configuration from a specific file path (sync)
|
|
102
|
+
* @param filePath - Path to the config file
|
|
103
|
+
* @returns Configuration object or empty object if not found
|
|
104
|
+
*/
|
|
105
|
+
function loadConfigFromPathSync(filePath) {
|
|
106
|
+
const result = explorerSync.load(filePath);
|
|
107
|
+
return result?.config ? normalizeConfig(result.config) : {};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Normalize config object - handle default exports and ensure proper type
|
|
111
|
+
*/
|
|
112
|
+
function isStylesConfig(value) {
|
|
113
|
+
return typeof value === "object" && value !== null;
|
|
114
|
+
}
|
|
115
|
+
function normalizeConfig(config) {
|
|
116
|
+
if (isStylesConfig(config) && "default" in config) return normalizeConfig(config.default);
|
|
117
|
+
if (isStylesConfig(config)) return config;
|
|
118
|
+
return {};
|
|
119
|
+
}
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/options.ts
|
|
122
|
+
/**
|
|
123
|
+
* Expand the `strict` convenience preset. When `strict` is truthy, fills the
|
|
124
|
+
* strict bundle for any governed option left `undefined` — an explicitly set
|
|
125
|
+
* option always wins. Modeled after `tsconfig`'s `strict`: it only *sets*
|
|
126
|
+
* semantic options, it is not itself a mode. Sets the strictest value of each
|
|
127
|
+
* governed axis (`equalityMode: 'exact'` is the no-coercion dialect).
|
|
128
|
+
*
|
|
129
|
+
* Returns a new object (never mutates the input); a no-op when `strict` is falsy.
|
|
130
|
+
*/
|
|
131
|
+
function applyStrictPreset(opts) {
|
|
132
|
+
if (!opts?.strict) return opts;
|
|
133
|
+
const filled = { ...opts };
|
|
134
|
+
filled.unitMode ??= "strict";
|
|
135
|
+
filled.equalityMode ??= "exact";
|
|
136
|
+
filled.leakyScope ??= false;
|
|
137
|
+
filled.allowOverloadedImport ??= false;
|
|
138
|
+
return filled;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Map of file extensions to language keys
|
|
142
|
+
*/
|
|
143
|
+
const extensionToLanguage = new Map([
|
|
144
|
+
[".less", "less"],
|
|
145
|
+
[".scss", "scss"],
|
|
146
|
+
[".sass", "scss"],
|
|
147
|
+
[".jess", "jess"],
|
|
148
|
+
[".css", "css"]
|
|
149
|
+
]);
|
|
150
|
+
/**
|
|
151
|
+
* Infer language from a file path's extension
|
|
152
|
+
*/
|
|
153
|
+
function inferLanguage(filePath) {
|
|
154
|
+
if (!filePath) return;
|
|
155
|
+
const ext = path.default.extname(filePath).toLowerCase();
|
|
156
|
+
return extensionToLanguage.get(ext);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Check if a file path matches a pattern (exact path, relative path, or glob)
|
|
160
|
+
*/
|
|
161
|
+
function matchesFile(pattern, filePath) {
|
|
162
|
+
if (!pattern || !filePath) return false;
|
|
163
|
+
const normalizedPattern = path.default.normalize(pattern);
|
|
164
|
+
const normalizedFile = path.default.normalize(filePath);
|
|
165
|
+
if (normalizedPattern === normalizedFile) return true;
|
|
166
|
+
if (path.default.basename(normalizedFile) === normalizedPattern) return true;
|
|
167
|
+
const isMatch = (0, picomatch.default)(pattern, { dot: true });
|
|
168
|
+
return isMatch(filePath) || isMatch(normalizedFile);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Get matching options from an array of file-based options.
|
|
172
|
+
* Returns merged options from:
|
|
173
|
+
* 1. All entries without a `file` property (defaults)
|
|
174
|
+
* 2. All entries whose `file` pattern matches the given path
|
|
175
|
+
*
|
|
176
|
+
* Later entries override earlier ones.
|
|
177
|
+
*/
|
|
178
|
+
function getMatchingOptions(options, filePath) {
|
|
179
|
+
if (!options) return {};
|
|
180
|
+
const optionsArray = Array.isArray(options) ? options : [options];
|
|
181
|
+
let result = {};
|
|
182
|
+
for (const opt of optionsArray) if (!opt.file || filePath && matchesFile(opt.file, filePath)) {
|
|
183
|
+
const { file, ...rest } = opt;
|
|
184
|
+
result = {
|
|
185
|
+
...result,
|
|
186
|
+
...rest
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get merged options by combining compile, language, input, and output settings.
|
|
193
|
+
*
|
|
194
|
+
* Merge priority (later wins):
|
|
195
|
+
* 1. compile options (base)
|
|
196
|
+
* 2. language-specific options (inferred from input extension or explicitly specified)
|
|
197
|
+
* 3. matched input options (if input path provided and matches)
|
|
198
|
+
* 4. matched output options (if output path provided and matches)
|
|
199
|
+
*
|
|
200
|
+
* @param config - The styles configuration object
|
|
201
|
+
* @param params - Options specifying language, input file, and output file
|
|
202
|
+
* @returns Merged options object
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* // Get Less options for a specific input/output (language inferred from .less extension)
|
|
206
|
+
* const options = getOptions(config, {
|
|
207
|
+
* input: 'src/styles/main.less',
|
|
208
|
+
* output: 'dist/main.css'
|
|
209
|
+
* });
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* // Explicitly specify language
|
|
213
|
+
* const options = getOptions(config, { language: 'less' });
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* // Get base options without language-specific settings
|
|
217
|
+
* const options = getOptions(config);
|
|
218
|
+
*/
|
|
219
|
+
function getOptions(config = {}, params = {}) {
|
|
220
|
+
const { input: inputFile, output: outputFile } = params;
|
|
221
|
+
const { compile = {}, input, output, language: languageConfig = {} } = config;
|
|
222
|
+
const language = params.language ?? inferLanguage(inputFile);
|
|
223
|
+
const languageOptions = language ? languageConfig[language] ?? {} : {};
|
|
224
|
+
const matchedInput = getMatchingOptions(input, inputFile);
|
|
225
|
+
const matchedOutput = getMatchingOptions(output, outputFile);
|
|
226
|
+
return {
|
|
227
|
+
mathMode: compile.mathMode,
|
|
228
|
+
unitMode: compile.unitMode,
|
|
229
|
+
equalityMode: compile.equalityMode,
|
|
230
|
+
allowExtendSelectors: compile.allowExtendSelectors,
|
|
231
|
+
disableScriptModules: compile.disableScriptModules ?? compile.disablePluginRule,
|
|
232
|
+
paths: compile.searchPaths,
|
|
233
|
+
...languageOptions,
|
|
234
|
+
...matchedInput,
|
|
235
|
+
...matchedOutput
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
//#endregion
|
|
239
|
+
exports.applyStrictPreset = applyStrictPreset;
|
|
240
|
+
exports.getOptions = getOptions;
|
|
241
|
+
exports.loadConfig = loadConfig;
|
|
242
|
+
exports.loadConfigFromPath = loadConfigFromPath;
|
|
243
|
+
exports.loadConfigFromPathSync = loadConfigFromPathSync;
|
|
244
|
+
exports.loadConfigSync = loadConfigSync;
|
|
245
|
+
exports.loadConfigSyncWithMeta = loadConfigSyncWithMeta;
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,214 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
//#
|
|
1
|
+
import { cosmiconfig, cosmiconfigSync, defaultLoadersSync } from "cosmiconfig";
|
|
2
|
+
import picomatch from "picomatch";
|
|
3
|
+
import path from "path";
|
|
4
|
+
//#region src/loader.ts
|
|
5
|
+
const explorer = cosmiconfig("styles", {
|
|
6
|
+
searchPlaces: [
|
|
7
|
+
"styles.config.ts",
|
|
8
|
+
"styles.config.js",
|
|
9
|
+
"styles.config.mts",
|
|
10
|
+
"styles.config.mjs",
|
|
11
|
+
"styles.config.cjs",
|
|
12
|
+
"styles.config.cts"
|
|
13
|
+
],
|
|
14
|
+
loaders: {
|
|
15
|
+
".mts": defaultLoadersSync[".ts"],
|
|
16
|
+
".cts": defaultLoadersSync[".ts"],
|
|
17
|
+
".mjs": defaultLoadersSync[".js"],
|
|
18
|
+
".cjs": defaultLoadersSync[".cjs"]
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
const explorerSync = cosmiconfigSync("styles", {
|
|
22
|
+
searchPlaces: [
|
|
23
|
+
"styles.config.ts",
|
|
24
|
+
"styles.config.js",
|
|
25
|
+
"styles.config.mts",
|
|
26
|
+
"styles.config.mjs",
|
|
27
|
+
"styles.config.cjs",
|
|
28
|
+
"styles.config.cts"
|
|
29
|
+
],
|
|
30
|
+
loaders: {
|
|
31
|
+
".mts": defaultLoadersSync[".ts"],
|
|
32
|
+
".cts": defaultLoadersSync[".ts"],
|
|
33
|
+
".mjs": defaultLoadersSync[".js"],
|
|
34
|
+
".cjs": defaultLoadersSync[".cjs"]
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
/**
|
|
38
|
+
* Load styles configuration from the file system (async)
|
|
39
|
+
* @param searchFrom - Directory to search from (defaults to process.cwd())
|
|
40
|
+
* @returns Configuration object or null if not found
|
|
41
|
+
*/
|
|
42
|
+
async function loadConfig(searchFrom) {
|
|
43
|
+
const result = await explorer.search(searchFrom);
|
|
44
|
+
return result?.config ? normalizeConfig(result.config) : null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Load styles configuration from the file system (sync)
|
|
48
|
+
* @param searchFrom - Directory to search from (defaults to process.cwd())
|
|
49
|
+
* @returns Configuration object or empty object if not found
|
|
50
|
+
*/
|
|
51
|
+
function loadConfigSync(searchFrom) {
|
|
52
|
+
const result = explorerSync.search(searchFrom);
|
|
53
|
+
return result?.config ? normalizeConfig(result.config) : {};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Load styles configuration with metadata (sync).
|
|
57
|
+
* Includes config file path when a config file is discovered.
|
|
58
|
+
*/
|
|
59
|
+
function loadConfigSyncWithMeta(searchFrom) {
|
|
60
|
+
const result = explorerSync.search(searchFrom);
|
|
61
|
+
return {
|
|
62
|
+
config: result?.config ? normalizeConfig(result.config) : {},
|
|
63
|
+
configFilePath: result?.filepath
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Load styles configuration from a specific file path (async)
|
|
68
|
+
* @param filePath - Path to the config file
|
|
69
|
+
* @returns Configuration object or null if not found
|
|
70
|
+
*/
|
|
71
|
+
async function loadConfigFromPath(filePath) {
|
|
72
|
+
const result = await explorer.load(filePath);
|
|
73
|
+
return result?.config ? normalizeConfig(result.config) : null;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Load styles configuration from a specific file path (sync)
|
|
77
|
+
* @param filePath - Path to the config file
|
|
78
|
+
* @returns Configuration object or empty object if not found
|
|
79
|
+
*/
|
|
80
|
+
function loadConfigFromPathSync(filePath) {
|
|
81
|
+
const result = explorerSync.load(filePath);
|
|
82
|
+
return result?.config ? normalizeConfig(result.config) : {};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Normalize config object - handle default exports and ensure proper type
|
|
86
|
+
*/
|
|
87
|
+
function isStylesConfig(value) {
|
|
88
|
+
return typeof value === "object" && value !== null;
|
|
89
|
+
}
|
|
90
|
+
function normalizeConfig(config) {
|
|
91
|
+
if (isStylesConfig(config) && "default" in config) return normalizeConfig(config.default);
|
|
92
|
+
if (isStylesConfig(config)) return config;
|
|
93
|
+
return {};
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/options.ts
|
|
97
|
+
/**
|
|
98
|
+
* Expand the `strict` convenience preset. When `strict` is truthy, fills the
|
|
99
|
+
* strict bundle for any governed option left `undefined` — an explicitly set
|
|
100
|
+
* option always wins. Modeled after `tsconfig`'s `strict`: it only *sets*
|
|
101
|
+
* semantic options, it is not itself a mode. Sets the strictest value of each
|
|
102
|
+
* governed axis (`equalityMode: 'exact'` is the no-coercion dialect).
|
|
103
|
+
*
|
|
104
|
+
* Returns a new object (never mutates the input); a no-op when `strict` is falsy.
|
|
105
|
+
*/
|
|
106
|
+
function applyStrictPreset(opts) {
|
|
107
|
+
if (!opts?.strict) return opts;
|
|
108
|
+
const filled = { ...opts };
|
|
109
|
+
filled.unitMode ??= "strict";
|
|
110
|
+
filled.equalityMode ??= "exact";
|
|
111
|
+
filled.leakyScope ??= false;
|
|
112
|
+
filled.allowOverloadedImport ??= false;
|
|
113
|
+
return filled;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Map of file extensions to language keys
|
|
117
|
+
*/
|
|
118
|
+
const extensionToLanguage = new Map([
|
|
119
|
+
[".less", "less"],
|
|
120
|
+
[".scss", "scss"],
|
|
121
|
+
[".sass", "scss"],
|
|
122
|
+
[".jess", "jess"],
|
|
123
|
+
[".css", "css"]
|
|
124
|
+
]);
|
|
125
|
+
/**
|
|
126
|
+
* Infer language from a file path's extension
|
|
127
|
+
*/
|
|
128
|
+
function inferLanguage(filePath) {
|
|
129
|
+
if (!filePath) return;
|
|
130
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
131
|
+
return extensionToLanguage.get(ext);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check if a file path matches a pattern (exact path, relative path, or glob)
|
|
135
|
+
*/
|
|
136
|
+
function matchesFile(pattern, filePath) {
|
|
137
|
+
if (!pattern || !filePath) return false;
|
|
138
|
+
const normalizedPattern = path.normalize(pattern);
|
|
139
|
+
const normalizedFile = path.normalize(filePath);
|
|
140
|
+
if (normalizedPattern === normalizedFile) return true;
|
|
141
|
+
if (path.basename(normalizedFile) === normalizedPattern) return true;
|
|
142
|
+
const isMatch = picomatch(pattern, { dot: true });
|
|
143
|
+
return isMatch(filePath) || isMatch(normalizedFile);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get matching options from an array of file-based options.
|
|
147
|
+
* Returns merged options from:
|
|
148
|
+
* 1. All entries without a `file` property (defaults)
|
|
149
|
+
* 2. All entries whose `file` pattern matches the given path
|
|
150
|
+
*
|
|
151
|
+
* Later entries override earlier ones.
|
|
152
|
+
*/
|
|
153
|
+
function getMatchingOptions(options, filePath) {
|
|
154
|
+
if (!options) return {};
|
|
155
|
+
const optionsArray = Array.isArray(options) ? options : [options];
|
|
156
|
+
let result = {};
|
|
157
|
+
for (const opt of optionsArray) if (!opt.file || filePath && matchesFile(opt.file, filePath)) {
|
|
158
|
+
const { file, ...rest } = opt;
|
|
159
|
+
result = {
|
|
160
|
+
...result,
|
|
161
|
+
...rest
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get merged options by combining compile, language, input, and output settings.
|
|
168
|
+
*
|
|
169
|
+
* Merge priority (later wins):
|
|
170
|
+
* 1. compile options (base)
|
|
171
|
+
* 2. language-specific options (inferred from input extension or explicitly specified)
|
|
172
|
+
* 3. matched input options (if input path provided and matches)
|
|
173
|
+
* 4. matched output options (if output path provided and matches)
|
|
174
|
+
*
|
|
175
|
+
* @param config - The styles configuration object
|
|
176
|
+
* @param params - Options specifying language, input file, and output file
|
|
177
|
+
* @returns Merged options object
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* // Get Less options for a specific input/output (language inferred from .less extension)
|
|
181
|
+
* const options = getOptions(config, {
|
|
182
|
+
* input: 'src/styles/main.less',
|
|
183
|
+
* output: 'dist/main.css'
|
|
184
|
+
* });
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* // Explicitly specify language
|
|
188
|
+
* const options = getOptions(config, { language: 'less' });
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* // Get base options without language-specific settings
|
|
192
|
+
* const options = getOptions(config);
|
|
193
|
+
*/
|
|
194
|
+
function getOptions(config = {}, params = {}) {
|
|
195
|
+
const { input: inputFile, output: outputFile } = params;
|
|
196
|
+
const { compile = {}, input, output, language: languageConfig = {} } = config;
|
|
197
|
+
const language = params.language ?? inferLanguage(inputFile);
|
|
198
|
+
const languageOptions = language ? languageConfig[language] ?? {} : {};
|
|
199
|
+
const matchedInput = getMatchingOptions(input, inputFile);
|
|
200
|
+
const matchedOutput = getMatchingOptions(output, outputFile);
|
|
201
|
+
return {
|
|
202
|
+
mathMode: compile.mathMode,
|
|
203
|
+
unitMode: compile.unitMode,
|
|
204
|
+
equalityMode: compile.equalityMode,
|
|
205
|
+
allowExtendSelectors: compile.allowExtendSelectors,
|
|
206
|
+
disableScriptModules: compile.disableScriptModules ?? compile.disablePluginRule,
|
|
207
|
+
paths: compile.searchPaths,
|
|
208
|
+
...languageOptions,
|
|
209
|
+
...matchedInput,
|
|
210
|
+
...matchedOutput
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
//#endregion
|
|
214
|
+
export { applyStrictPreset, getOptions, loadConfig, loadConfigFromPath, loadConfigFromPathSync, loadConfigSync, loadConfigSyncWithMeta };
|
package/lib/options.d.ts
CHANGED
|
@@ -1,4 +1,25 @@
|
|
|
1
1
|
import type { StylesConfig } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Options bag the `strict` preset can expand. Any bag carrying a `strict` flag
|
|
4
|
+
* plus the semantic modes it governs.
|
|
5
|
+
*/
|
|
6
|
+
export interface StrictPresetOptions {
|
|
7
|
+
strict?: boolean;
|
|
8
|
+
unitMode?: 'loose' | 'preserve' | 'strict';
|
|
9
|
+
equalityMode?: 'less' | 'sass' | 'exact';
|
|
10
|
+
leakyScope?: boolean;
|
|
11
|
+
allowOverloadedImport?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Expand the `strict` convenience preset. When `strict` is truthy, fills the
|
|
15
|
+
* strict bundle for any governed option left `undefined` — an explicitly set
|
|
16
|
+
* option always wins. Modeled after `tsconfig`'s `strict`: it only *sets*
|
|
17
|
+
* semantic options, it is not itself a mode. Sets the strictest value of each
|
|
18
|
+
* governed axis (`equalityMode: 'exact'` is the no-coercion dialect).
|
|
19
|
+
*
|
|
20
|
+
* Returns a new object (never mutates the input); a no-op when `strict` is falsy.
|
|
21
|
+
*/
|
|
22
|
+
export declare function applyStrictPreset<T extends StrictPresetOptions>(opts: T): T;
|
|
2
23
|
/**
|
|
3
24
|
* Options for retrieving merged configuration
|
|
4
25
|
*/
|
package/lib/types.d.ts
CHANGED
|
@@ -7,36 +7,39 @@ export type MathMode = 'always' | 'parens-division' | 'parens' | 'strict';
|
|
|
7
7
|
*/
|
|
8
8
|
export type UnitMode = 'loose' | 'preserve' | 'strict';
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Function-call resolution modes — mirrors {@link UnitMode}. Governs an optional
|
|
11
|
+
* (global) function call that matched a registered function but couldn't be
|
|
12
|
+
* evaluated: `preserve` renders it as-is (+ warning), `error` throws.
|
|
11
13
|
*/
|
|
12
|
-
export type
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
allowNetHosts?: string[];
|
|
23
|
-
/**
|
|
24
|
-
* Optional explicit filesystem root for script reads.
|
|
25
|
-
* If omitted, compiler resolves using entry/config roots.
|
|
26
|
-
*/
|
|
27
|
-
jsReadRoot?: string;
|
|
28
|
-
}
|
|
29
|
-
export type CompileJavaScriptOption = true | JavaScriptSandboxConfig;
|
|
14
|
+
export type FunctionMode = 'preserve' | 'error';
|
|
15
|
+
/**
|
|
16
|
+
* Equality dialects for guard comparisons — named by dialect (Less 4.x and Sass
|
|
17
|
+
* diverge in opposite directions), not by strictness:
|
|
18
|
+
* - `less`: Less 4.x equality (numeric coercion; quoted vs unquoted distinct)
|
|
19
|
+
* - `sass`: Dart Sass equality (unit-strict; quote-insensitive strings)
|
|
20
|
+
* - `exact`: no coercion — operands must be the same node type
|
|
21
|
+
*/
|
|
22
|
+
export type EqualityMode = 'less' | 'sass' | 'exact';
|
|
23
|
+
export type ExtendSelectorKind = 'simple' | 'basic' | 'pseudo' | 'complex' | 'compound';
|
|
30
24
|
/**
|
|
31
25
|
* Less compiler options
|
|
32
26
|
* Based on less.js default-options.js and bin/lessc
|
|
33
27
|
*/
|
|
34
28
|
export interface LessOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Restrict which selector shapes are allowed in extend targets.
|
|
31
|
+
* When set, any other selector kind is a parse error.
|
|
32
|
+
*/
|
|
33
|
+
allowExtendSelectors?: ExtendSelectorKind[];
|
|
35
34
|
/**
|
|
36
35
|
* Inline Javascript - @plugin still allowed
|
|
37
36
|
* @default false
|
|
38
37
|
*/
|
|
39
38
|
javascriptEnabled?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* @deprecated Use `disableScriptModules` instead.
|
|
41
|
+
*/
|
|
42
|
+
disablePluginRule?: boolean;
|
|
40
43
|
/**
|
|
41
44
|
* Outputs a makefile import dependency list to stdout.
|
|
42
45
|
* @default false
|
|
@@ -124,11 +127,21 @@ export interface LessOptions {
|
|
|
124
127
|
* @default 'preserve'
|
|
125
128
|
*/
|
|
126
129
|
unitMode?: UnitMode;
|
|
130
|
+
/**
|
|
131
|
+
* How to handle an optional/global function call that matched a registered
|
|
132
|
+
* function but couldn't be evaluated (no matching signature, or it threw) —
|
|
133
|
+
* e.g. `unit(80/16)`, `color("x")`. Mirrors {@link unitMode}.
|
|
134
|
+
* - 'preserve': render the call as-is (like an unknown CSS function) + warn
|
|
135
|
+
* - 'error': throw the underlying function error (Less 4.x behavior)
|
|
136
|
+
* Unknown function names always render as-is regardless.
|
|
137
|
+
* @default 'preserve'
|
|
138
|
+
*/
|
|
139
|
+
functionMode?: FunctionMode;
|
|
127
140
|
/**
|
|
128
141
|
* How to handle equality/coercion in guards and comparisons.
|
|
129
|
-
* - '
|
|
142
|
+
* - 'loose': Less-compatible loose (coercive) equality (JS '==')
|
|
130
143
|
* - 'strict': type-strict behavior
|
|
131
|
-
* @default '
|
|
144
|
+
* @default 'loose'
|
|
132
145
|
*/
|
|
133
146
|
equalityMode?: EqualityMode;
|
|
134
147
|
/**
|
|
@@ -201,6 +214,26 @@ export interface LessOptions {
|
|
|
201
214
|
* @default false
|
|
202
215
|
*/
|
|
203
216
|
quiet?: boolean;
|
|
217
|
+
/**
|
|
218
|
+
* Convenience preset. When `true`, sets the strict bundle for any of the
|
|
219
|
+
* following left `undefined` (individual options always win):
|
|
220
|
+
* - `unitMode: 'strict'`
|
|
221
|
+
* - `equalityMode: 'exact'` (the no-coercion dialect)
|
|
222
|
+
* - `leakyScope: false`
|
|
223
|
+
* - `allowOverloadedImport: false`
|
|
224
|
+
*
|
|
225
|
+
* Modeled after `tsconfig` `strict`: it only *sets* semantic options, it is not
|
|
226
|
+
* itself a mode.
|
|
227
|
+
* @default false
|
|
228
|
+
*/
|
|
229
|
+
strict?: boolean;
|
|
230
|
+
/**
|
|
231
|
+
* Whether re-importing a file/namespace may contribute *overloaded* (duplicated,
|
|
232
|
+
* additively-merged) definitions rather than being de-duplicated like Less's
|
|
233
|
+
* `@import (once)`. `strict` sets this to `false`.
|
|
234
|
+
* @default true
|
|
235
|
+
*/
|
|
236
|
+
allowOverloadedImport?: boolean;
|
|
204
237
|
/**
|
|
205
238
|
* @deprecated This is legacy Less behavior.
|
|
206
239
|
*
|
|
@@ -212,7 +245,7 @@ export interface LessOptions {
|
|
|
212
245
|
* - Both mixins and detached rulesets: Mixin and VarDeclaration nodes are 'private'
|
|
213
246
|
* @default true
|
|
214
247
|
*/
|
|
215
|
-
|
|
248
|
+
leakyScope?: boolean;
|
|
216
249
|
/**
|
|
217
250
|
* Whether to collapse nested selectors (Less 1.x-4.x style flattening)
|
|
218
251
|
* When true, nested selectors like `.parent { .child { } }` are flattened to `.parent .child { }`
|
|
@@ -228,6 +261,13 @@ export interface LessOptions {
|
|
|
228
261
|
*/
|
|
229
262
|
bubbleRootAtRules?: boolean;
|
|
230
263
|
}
|
|
264
|
+
export interface ScssOptions {
|
|
265
|
+
allowExtendSelectors?: ExtendSelectorKind[];
|
|
266
|
+
unitMode?: UnitMode;
|
|
267
|
+
equalityMode?: EqualityMode;
|
|
268
|
+
collapseNesting?: boolean;
|
|
269
|
+
[key: string]: any;
|
|
270
|
+
}
|
|
231
271
|
/**
|
|
232
272
|
* Base interface for file-matching options
|
|
233
273
|
*/
|
|
@@ -244,9 +284,17 @@ export interface FileMatchOptions {
|
|
|
244
284
|
export interface InputOptions extends FileMatchOptions {
|
|
245
285
|
mathMode?: MathMode;
|
|
246
286
|
unitMode?: UnitMode;
|
|
287
|
+
functionMode?: FunctionMode;
|
|
247
288
|
equalityMode?: EqualityMode;
|
|
289
|
+
strict?: boolean;
|
|
290
|
+
allowOverloadedImport?: boolean;
|
|
291
|
+
allowExtendSelectors?: ExtendSelectorKind[];
|
|
292
|
+
disableScriptModules?: boolean;
|
|
293
|
+
/**
|
|
294
|
+
* @deprecated Use `disableScriptModules` instead.
|
|
295
|
+
*/
|
|
296
|
+
disablePluginRule?: boolean;
|
|
248
297
|
searchPaths?: string[];
|
|
249
|
-
enableJavaScript?: boolean;
|
|
250
298
|
javascriptEnabled?: boolean;
|
|
251
299
|
paths?: string[];
|
|
252
300
|
globalVars?: Record<string, string> | null;
|
|
@@ -254,7 +302,7 @@ export interface InputOptions extends FileMatchOptions {
|
|
|
254
302
|
strictImports?: boolean | 'error';
|
|
255
303
|
rewriteUrls?: boolean | 'all' | 'local' | 'off';
|
|
256
304
|
rootpath?: string;
|
|
257
|
-
|
|
305
|
+
leakyScope?: boolean;
|
|
258
306
|
collapseNesting?: boolean;
|
|
259
307
|
bubbleRootAtRules?: boolean;
|
|
260
308
|
/** Allow additional language-specific options */
|
|
@@ -292,11 +340,28 @@ export interface StylesConfig {
|
|
|
292
340
|
*/
|
|
293
341
|
plugins?: Array<any | string>;
|
|
294
342
|
searchPaths?: string[];
|
|
295
|
-
enableJavaScript?: boolean;
|
|
296
|
-
javascript?: CompileJavaScriptOption;
|
|
297
343
|
mathMode?: MathMode;
|
|
298
344
|
unitMode?: UnitMode;
|
|
345
|
+
functionMode?: FunctionMode;
|
|
299
346
|
equalityMode?: EqualityMode;
|
|
347
|
+
/** See {@link LessOptions.strict}. Expanded onto the other compile modes. */
|
|
348
|
+
strict?: boolean;
|
|
349
|
+
/** See {@link LessOptions.allowOverloadedImport}. */
|
|
350
|
+
allowOverloadedImport?: boolean;
|
|
351
|
+
/** See {@link LessOptions.leakyScope}. */
|
|
352
|
+
leakyScope?: boolean;
|
|
353
|
+
allowExtendSelectors?: ExtendSelectorKind[];
|
|
354
|
+
disableScriptModules?: boolean;
|
|
355
|
+
/**
|
|
356
|
+
* @deprecated Use `disableScriptModules` instead.
|
|
357
|
+
*/
|
|
358
|
+
disablePluginRule?: boolean;
|
|
359
|
+
/**
|
|
360
|
+
* Filesystem root that Less `@plugin` / script-module scripts are allowed to
|
|
361
|
+
* be read from. When set, it overrides the default (the entry file's
|
|
362
|
+
* directory). Paths outside this root are rejected by @jesscss/plugin-js.
|
|
363
|
+
*/
|
|
364
|
+
jsReadRoot?: string;
|
|
300
365
|
};
|
|
301
366
|
/**
|
|
302
367
|
* Input file options. Can be a single object for defaults, or an array
|
|
@@ -312,9 +377,9 @@ export interface StylesConfig {
|
|
|
312
377
|
output?: OutputOptions | OutputOptions[];
|
|
313
378
|
language?: {
|
|
314
379
|
less?: LessOptions;
|
|
315
|
-
scss?:
|
|
380
|
+
scss?: ScssOptions;
|
|
316
381
|
css?: Record<string, any>;
|
|
317
382
|
jess?: Record<string, any>;
|
|
318
|
-
[key: string]: LessOptions | Record<string, any> | undefined;
|
|
383
|
+
[key: string]: LessOptions | ScssOptions | Record<string, any> | undefined;
|
|
319
384
|
};
|
|
320
385
|
}
|