1 | import {FileImporter, Importer} from './importer';
|
2 | import {Logger} from './logger';
|
3 | import {Value} from './value';
|
4 | import {PromiseOr} from './util/promise_or';
|
5 |
|
6 | /**
|
7 | * Syntaxes supported by Sass:
|
8 | *
|
9 | * - `'scss'` is the [SCSS
|
10 | * syntax](https://sass-lang.com/documentation/syntax#scss).
|
11 | * - `'indented'` is the [indented
|
12 | * syntax](https://sass-lang.com/documentation/syntax#the-indented-syntax)
|
13 | * - `'css'` is plain CSS, which is parsed like SCSS but forbids the use of any
|
14 | * special Sass features.
|
15 | *
|
16 | * @category Options
|
17 | */
|
18 | export type Syntax = 'scss' | 'indented' | 'css';
|
19 |
|
20 | /**
|
21 | * Possible output styles for the compiled CSS:
|
22 | *
|
23 | * - `"expanded"` (the default for Dart Sass) writes each selector and
|
24 | * declaration on its own line.
|
25 | *
|
26 | * - `"compressed"` removes as many extra characters as possible, and writes
|
27 | * the entire stylesheet on a single line.
|
28 | *
|
29 | * @category Options
|
30 | */
|
31 | export type OutputStyle = 'expanded' | 'compressed';
|
32 |
|
33 | /**
|
34 | * A callback that implements a custom Sass function. This can be passed to
|
35 | * [[Options.functions]].
|
36 | *
|
37 | * ```js
|
38 | * const result = sass.compile('style.scss', {
|
39 | * functions: {
|
40 | * "sum($arg1, $arg2)": (args) => {
|
41 | * const value1 = args[0].assertNumber('arg1').value;
|
42 | * const value2 = args[1].assertNumber('arg2')
|
43 | * .convertValueToMatch(arg1, 'arg2', 'arg1');
|
44 | * return new sass.SassNumber(value1 + value2).coerceToMatch(arg1);
|
45 | * }
|
46 | * }
|
47 | * });
|
48 | * ```
|
49 | *
|
50 | * @typeParam sync - A `CustomFunction<'sync'>` must return synchronously, but
|
51 | * in return it can be passed to [[compile]] and [[compileString]] in addition
|
52 | * to [[compileAsync]] and [[compileStringAsync]].
|
53 | *
|
54 | * A `CustomFunction<'async'>` may either return synchronously or
|
55 | * asynchronously, but it can only be used with [[compileAsync]] and
|
56 | * [[compileStringAsync]].
|
57 | *
|
58 | * @param args - An array of arguments passed by the function's caller. If the
|
59 | * function takes [arbitrary
|
60 | * arguments](https://sass-lang.com/documentation/at-rules/function#taking-arbitrary-arguments),
|
61 | * the last element will be a [[SassArgumentList]].
|
62 | *
|
63 | * @returns The function's result. This may be in the form of a `Promise`, but
|
64 | * if it is the function may only be passed to [[compileAsync]] and
|
65 | * [[compileStringAsync]], not [[compile]] or [[compileString]].
|
66 | *
|
67 | * @throws any - This function may throw an error, which the Sass compiler will
|
68 | * treat as the function call failing. If the exception object has a `message`
|
69 | * property, it will be used as the wrapped exception's message; otherwise, the
|
70 | * exception object's `toString()` will be used. This means it's safe for custom
|
71 | * functions to throw plain strings.
|
72 | *
|
73 | * @category Custom Function
|
74 | */
|
75 | export type CustomFunction<sync extends 'sync' | 'async'> = (
|
76 | args: Value[]
|
77 | ) => PromiseOr<Value, sync>;
|
78 |
|
79 | /**
|
80 | * Options that can be passed to [[compile]], [[compileAsync]],
|
81 | * [[compileString]], or [[compileStringAsync]].
|
82 | *
|
83 | * @typeParam sync - This lets the TypeScript checker verify that asynchronous
|
84 | * [[Importer]]s, [[FileImporter]]s, and [[CustomFunction]]s aren't passed to
|
85 | * [[compile]] or [[compileString]].
|
86 | *
|
87 | * @category Options
|
88 | */
|
89 | export interface Options<sync extends 'sync' | 'async'> {
|
90 | /**
|
91 | * If this is `true`, the compiler will exclusively use ASCII characters in
|
92 | * its error and warning messages. Otherwise, it may use non-ASCII Unicode
|
93 | * characters as well.
|
94 | *
|
95 | * @defaultValue `false`
|
96 | * @category Messages
|
97 | */
|
98 | alertAscii?: boolean;
|
99 |
|
100 | /**
|
101 | * If this is `true`, the compiler will use ANSI color escape codes in its
|
102 | * error and warning messages. If it's `false`, it won't use these. If it's
|
103 | * undefined, the compiler will determine whether or not to use colors
|
104 | * depending on whether the user is using an interactive terminal.
|
105 | *
|
106 | * @category Messages
|
107 | */
|
108 | alertColor?: boolean;
|
109 |
|
110 | /**
|
111 | * Additional built-in Sass functions that are available in all stylesheets.
|
112 | * This option takes an object whose keys are Sass function signatures like
|
113 | * you'd write for the [`@function
|
114 | * rule`](https://sass-lang.com/documentation/at-rules/function) and whose
|
115 | * values are [[CustomFunction]]s.
|
116 | *
|
117 | * Functions are passed JavaScript representations of [Sass value
|
118 | * types](https://sass-lang.com/documentation/js-api#value-types), and must
|
119 | * return the same.
|
120 | *
|
121 | * When writing custom functions, it's important to make them as user-friendly
|
122 | * and as close to the standards set by Sass's core functions as possible. Some
|
123 | * good guidelines to follow include:
|
124 | *
|
125 | * * Use `Value.assert*` methods, like [[Value.assertString]], to cast untyped
|
126 | * `Value` objects to more specific types. For values that were passed
|
127 | * directly as arguments, pass in the argument name as well. This ensures
|
128 | * that the user gets good error messages when they pass in the wrong type
|
129 | * to your function.
|
130 | *
|
131 | * * Individual classes may have more specific `assert*` methods, like
|
132 | * [[SassNumber.assertInt]], which should be used when possible.
|
133 | *
|
134 | * * In Sass, every value counts as a list. Rather than trying to detect the
|
135 | * [[SassList]] type, you should use [[Value.asList]] to treat all values as
|
136 | * lists.
|
137 | *
|
138 | * * When manipulating values like lists, strings, and numbers that have
|
139 | * metadata (comma versus space separated, bracketed versus unbracketed,
|
140 | * quoted versus unquoted, units), the output metadata should match the
|
141 | * input metadata.
|
142 | *
|
143 | * * When in doubt, lists should default to comma-separated, strings should
|
144 | * default to quoted, and numbers should default to unitless.
|
145 | *
|
146 | * * In Sass, lists and strings use one-based indexing and use negative
|
147 | * indices to index from the end of value. Functions should follow these
|
148 | * conventions. [[Value.sassIndexToListIndex]] and
|
149 | * [[SassString.sassIndexToStringIndex]] can be used to do this
|
150 | * automatically.
|
151 | *
|
152 | * * String indexes in Sass refer to Unicode code points while JavaScript
|
153 | * string indices refer to UTF-16 code units. For example, the character
|
154 | * U+1F60A SMILING FACE WITH SMILING EYES is a single Unicode code point but
|
155 | * is represented in UTF-16 as two code units (`0xD83D` and `0xDE0A`). So in
|
156 | * JavaScript, `"a😊b".charCodeAt(1)` returns `0xD83D`, whereas in Sass
|
157 | * `str-slice("a😊b", 1, 1)` returns `"😊"`. Functions should follow Sass's
|
158 | * convention. [[SassString.sassIndexToStringIndex]] can be used to do this
|
159 | * automatically, and the [[SassString.sassLength]] getter can be used to
|
160 | * access a string's length in code points.
|
161 | *
|
162 | * @example
|
163 | *
|
164 | * ```js
|
165 | * sass.compileString(`
|
166 | * h1 {
|
167 | * font-size: pow(2, 5) * 1px;
|
168 | * }`, {
|
169 | * functions: {
|
170 | * // Note: in real code, you should use `math.pow()` from the built-in
|
171 | * // `sass:math` module.
|
172 | * 'pow($base, $exponent)': function(args) {
|
173 | * const base = args[0].assertNumber('base').assertNoUnits('base');
|
174 | * const exponent =
|
175 | * args[1].assertNumber('exponent').assertNoUnits('exponent');
|
176 | *
|
177 | * return new sass.SassNumber(Math.pow(base.value, exponent.value));
|
178 | * }
|
179 | * }
|
180 | * });
|
181 | * ```
|
182 | *
|
183 | * @category Plugins
|
184 | */
|
185 | functions?: Record<string, CustomFunction<sync>>;
|
186 |
|
187 | /**
|
188 | * Custom importers that control how Sass resolves loads from rules like
|
189 | * [`@use`](https://sass-lang.com/documentation/at-rules/use) and
|
190 | * [`@import`](https://sass-lang.com/documentation/at-rules/import).
|
191 | *
|
192 | * Loads are resolved by trying, in order:
|
193 | *
|
194 | * - The importer that was used to load the current stylesheet, with the
|
195 | * loaded URL resolved relative to the current stylesheet's canonical URL.
|
196 | *
|
197 | * - Each [[Importer]] or [[FileImporter]] in [[importers]], in order.
|
198 | *
|
199 | * - Each load path in [[loadPaths]], in order.
|
200 | *
|
201 | * If none of these return a Sass file, the load fails and Sass throws an
|
202 | * error.
|
203 | *
|
204 | * @category Plugins
|
205 | */
|
206 | importers?: (Importer<sync> | FileImporter<sync>)[];
|
207 |
|
208 | /**
|
209 | * Paths in which to look for stylesheets loaded by rules like
|
210 | * [`@use`](https://sass-lang.com/documentation/at-rules/use) and
|
211 | * [`@import`](https://sass-lang.com/documentation/at-rules/import).
|
212 | *
|
213 | * A load path `loadPath` is equivalent to the following [[FileImporter]]:
|
214 | *
|
215 | * ```js
|
216 | * {
|
217 | * findFileUrl(url) {
|
218 | * // Load paths only support relative URLs.
|
219 | * if (/^[a-z]+:/i.test(url)) return null;
|
220 | * return new URL(url, pathToFileURL(loadPath));
|
221 | * }
|
222 | * }
|
223 | * ```
|
224 | *
|
225 | * @category Input
|
226 | */
|
227 | loadPaths?: string[];
|
228 |
|
229 | /**
|
230 | * An object to use to handle warnings and/or debug messages from Sass.
|
231 | *
|
232 | * By default, Sass emits warnings and debug messages to standard error, but
|
233 | * if [[Logger.warn]] or [[Logger.debug]] is set, this will invoke them
|
234 | * instead.
|
235 | *
|
236 | * The special value [[Logger.silent]] can be used to easily silence all
|
237 | * messages.
|
238 | *
|
239 | * @category Messages
|
240 | */
|
241 | logger?: Logger;
|
242 |
|
243 | /**
|
244 | * If this option is set to `true`, Sass won’t print warnings that are caused
|
245 | * by dependencies. A “dependency” is defined as any file that’s loaded
|
246 | * through [[loadPaths]] or [[importer]]. Stylesheets that are imported
|
247 | * relative to the entrypoint are not considered dependencies.
|
248 | *
|
249 | * This is useful for silencing deprecation warnings that you can’t fix on
|
250 | * your own. However, please <em>also</em> notify your dependencies of the deprecations
|
251 | * so that they can get fixed as soon as possible!
|
252 | *
|
253 | * **Heads up!** If [[compileString]] or [[compileStringAsync]] is called
|
254 | * without [[StringWithoutImporter.url]], <em>all</em> stylesheets it loads
|
255 | * will be considered dependencies. Since it doesn’t have a path of its own,
|
256 | * everything it loads is coming from a load path rather than a relative
|
257 | * import.
|
258 | *
|
259 | * @defaultValue `false`
|
260 | * @category Messages
|
261 | */
|
262 | quietDeps?: boolean;
|
263 |
|
264 | /**
|
265 | * Whether or not Sass should generate a source map. If it does, the source
|
266 | * map will be available as [[CompileResult.sourceMap]].
|
267 | *
|
268 | * **Heads up!** Sass doesn't automatically add a `sourceMappingURL` comment
|
269 | * to the generated CSS. It's up to callers to do that, since callers have
|
270 | * full knowledge of where the CSS and the source map will exist in relation
|
271 | * to one another and how they'll be served to the browser.
|
272 | *
|
273 | * @defaultValue `false`
|
274 | * @category Output
|
275 | */
|
276 | sourceMap?: boolean;
|
277 |
|
278 | /**
|
279 | * The [[OutputStyle]] of the compiled CSS.
|
280 | *
|
281 | * @example
|
282 | *
|
283 | * ```js
|
284 | * const source = `
|
285 | * h1 {
|
286 | * font-size: 40px;
|
287 | * code {
|
288 | * font-face: Roboto Mono;
|
289 | * }
|
290 | * }`;
|
291 | *
|
292 | * let result = sass.compileString(source, {style: "expanded"});
|
293 | * console.log(result.css.toString());
|
294 | * // h1 {
|
295 | * // font-size: 40px;
|
296 | * // }
|
297 | * // h1 code {
|
298 | * // font-face: Roboto Mono;
|
299 | * // }
|
300 | *
|
301 | * result = sass.compileString(source, {style: "compressed"})
|
302 | * console.log(result.css.toString());
|
303 | * // h1{font-size:40px}h1 code{font-face:Roboto Mono}
|
304 | * ```
|
305 | *
|
306 | * @category Output
|
307 | */
|
308 | style?: OutputStyle;
|
309 |
|
310 | /**
|
311 | * By default, Dart Sass will print only five instances of the same
|
312 | * deprecation warning per compilation to avoid deluging users in console
|
313 | * noise. If you set `verbose` to `true`, it will instead print every
|
314 | * deprecation warning it encounters.
|
315 | *
|
316 | * @defaultValue `false`
|
317 | * @category Messages
|
318 | */
|
319 | verbose?: boolean;
|
320 | }
|
321 |
|
322 | /**
|
323 | * Options that can be passed to [[compileString]] or [[compileStringAsync]].
|
324 | *
|
325 | * If the [[StringOptionsWithImporter.importer]] field isn't passed, the
|
326 | * entrypoint file can't load files relative to itself and the [[url]] field is
|
327 | * optional.
|
328 | *
|
329 | * @typeParam sync - This lets the TypeScript checker verify that asynchronous
|
330 | * [[Importer]]s, [[FileImporter]]s, and [[CustomFunction]]s aren't passed to
|
331 | * [[compile]] or [[compileString]].
|
332 | *
|
333 | * @category Options
|
334 | */
|
335 | export interface StringOptionsWithoutImporter<sync extends 'sync' | 'async'>
|
336 | extends Options<sync> {
|
337 | /**
|
338 | * The [[Syntax]] to use to parse the entrypoint stylesheet.
|
339 | *
|
340 | * @default `'scss'`
|
341 | *
|
342 | * @category Input
|
343 | */
|
344 | syntax?: Syntax;
|
345 |
|
346 | /**
|
347 | * The canonical URL of the entrypoint stylesheet. If this isn't passed along
|
348 | * with [[StringOptionsWithoutImporter.importer]], it's optional and only used
|
349 | * for error reporting.
|
350 | *
|
351 | * @category Input
|
352 | */
|
353 | url?: URL;
|
354 | }
|
355 |
|
356 | /**
|
357 | * Options that can be passed to [[compileString]] or [[compileStringAsync]].
|
358 | *
|
359 | * If the [[StringOptionsWithImporter.importer]] field is passed, the entrypoint
|
360 | * file uses it to load files relative to itself and the [[url]] field is
|
361 | * mandatory.
|
362 | *
|
363 | * @typeParam sync - This lets the TypeScript checker verify that asynchronous
|
364 | * [[Importer]]s, [[FileImporter]]s, and [[CustomFunction]]s aren't passed to
|
365 | * [[compile]] or [[compileString]].
|
366 | *
|
367 | * @category Options
|
368 | */
|
369 | export interface StringOptionsWithImporter<sync extends 'sync' | 'async'>
|
370 | extends StringOptionsWithoutImporter<sync> {
|
371 | /**
|
372 | * The importer to use to handle loads that are relative to the entrypoint
|
373 | * stylesheet.
|
374 | *
|
375 | * A relative load's URL is first resolved relative to [[url]], then passed to
|
376 | * [[importer]]. If the importer doesn't recognize it, it's then passed to
|
377 | * [[importers]] and [[loadPaths]].
|
378 | *
|
379 | * @category Input
|
380 | */
|
381 | importer: Importer<sync> | FileImporter<sync>;
|
382 |
|
383 | /**
|
384 | * The canonical URL of the entrypoint stylesheet. If this is passed along
|
385 | * with [[importer]], it's used to resolve relative loads in the entrypoint
|
386 | * stylesheet.
|
387 | *
|
388 | * @category Input
|
389 | */
|
390 | url: URL;
|
391 | }
|
392 |
|
393 | /**
|
394 | * Options that can be passed to [[compileString]] or [[compileStringAsync]].
|
395 | *
|
396 | * This is a [[StringOptionsWithImporter]] if it has a
|
397 | * [[StringOptionsWithImporter.importer]] field, and a
|
398 | * [[StringOptionsWithoutImporter]] otherwise.
|
399 | *
|
400 | * @typeParam sync - This lets the TypeScript checker verify that asynchronous
|
401 | * [[Importer]]s, [[FileImporter]]s, and [[CustomFunction]]s aren't passed to
|
402 | * [[compile]] or [[compileString]].
|
403 | *
|
404 | * @category Options
|
405 | */
|
406 | export type StringOptions<sync extends 'sync' | 'async'> =
|
407 | | StringOptionsWithImporter<sync>
|
408 | | StringOptionsWithoutImporter<sync>;
|