UNPKG

20.9 kBTypeScriptView Raw
1import {Logger} from '../logger';
2import {LegacyImporter} from './importer';
3import {LegacyFunction} from './function';
4import {NodePackageImporter} from '../importer';
5
6/**
7 * Options for {@link render} and {@link renderSync} that are shared between
8 * {@link LegacyFileOptions} and {@link LegacyStringOptions}.
9 *
10 * @typeParam sync - This lets the TypeScript checker verify that {@link
11 * LegacyAsyncImporter}s and {@link LegacyAsyncFunction}s aren't passed to
12 * {@link renderSync}.
13 *
14 * @category Legacy
15 * @deprecated This only works with the legacy {@link render} and {@link
16 * renderSync} APIs. Use {@link Options} with {@link compile}, {@link
17 * compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
18 */
19export interface LegacySharedOptions<sync extends 'sync' | 'async'> {
20 /**
21 * This array of strings option provides [load
22 * paths](https://sass-lang.com/documentation/at-rules/import#load-paths) for
23 * Sass to look for stylesheets. Earlier load paths will take precedence over
24 * later ones.
25 *
26 * ```js
27 * sass.renderSync({
28 * file: "style.scss",
29 * includePaths: ["node_modules/bootstrap/dist/css"]
30 * });
31 * ```
32 *
33 * Load paths are also loaded from the `SASS_PATH` environment variable, if
34 * it’s set. This variable should be a list of paths separated by `;` (on
35 * Windows) or `:` (on other operating systems). Load paths from the
36 * `includePaths` option take precedence over load paths from `SASS_PATH`.
37 *
38 * ```sh
39 * $ SASS_PATH=node_modules/bootstrap/dist/css sass style.scss style.css
40 * ```
41 *
42 * @category Input
43 * @compatibility feature: "SASS_PATH", dart: "1.15.0", node: "3.9.0"
44 *
45 * Earlier versions of Dart Sass and Node Sass didn’t support the `SASS_PATH`
46 * environment variable.
47 */
48 includePaths?: string[];
49
50 /**
51 * Whether the generated CSS should use spaces or tabs for indentation.
52 *
53 * ```js
54 * const result = sass.renderSync({
55 * file: "style.scss",
56 * indentType: "tab",
57 * indentWidth: 1
58 * });
59 *
60 * result.css.toString();
61 * // "h1 {\n\tfont-size: 40px;\n}\n"
62 * ```
63 *
64 * @defaultValue `'space'`
65 * @category Output
66 * @compatibility dart: true, node: "3.0.0"
67 */
68 indentType?: 'space' | 'tab';
69
70 /**
71 * How many spaces or tabs (depending on {@link indentType}) should be used
72 * per indentation level in the generated CSS. It must be between 0 and 10
73 * (inclusive).
74 *
75 * @defaultValue `2`
76 * @category Output
77 * @compatibility dart: true, node: "3.0.0"
78 */
79 indentWidth?: number;
80
81 /**
82 * Which character sequence to use at the end of each line in the generated
83 * CSS. It can have the following values:
84 *
85 * * `'lf'` uses U+000A LINE FEED.
86 * * `'lfcr'` uses U+000A LINE FEED followed by U+000D CARRIAGE RETURN.
87 * * `'cr'` uses U+000D CARRIAGE RETURN.
88 * * `'crlf'` uses U+000D CARRIAGE RETURN followed by U+000A LINE FEED.
89 *
90 * @defaultValue `'lf'`
91 * @category Output
92 * @compatibility dart: true, node: "3.0.0"
93 */
94 linefeed?: 'cr' | 'crlf' | 'lf' | 'lfcr';
95
96 /**
97 * If `true`, Sass won't add a link from the generated CSS to the source map.
98 *
99 * ```js
100 * const result = sass.renderSync({
101 * file: "style.scss",
102 * sourceMap: "out.map",
103 * omitSourceMapUrl: true
104 * })
105 * console.log(result.css.toString());
106 * // h1 {
107 * // font-size: 40px;
108 * // }
109 * ```
110 *
111 * @defaultValue `false`
112 * @category Source Maps
113 */
114 omitSourceMapUrl?: boolean;
115
116 /**
117 * The location that Sass expects the generated CSS to be saved to. It’s used
118 * to determine the URL used to link from the generated CSS to the source map,
119 * and from the source map to the Sass source files.
120 *
121 * **Heads up!** Despite the name, Sass does *not* write the CSS output to
122 * this file. The caller must do that themselves.
123 *
124 * ```js
125 * result = sass.renderSync({
126 * file: "style.scss",
127 * sourceMap: true,
128 * outFile: "out.css"
129 * })
130 * console.log(result.css.toString());
131 * // h1 {
132 * // font-size: 40px;
133 * // }
134 * // /*# sourceMappingURL=out.css.map * /
135 * ```
136 *
137 * @category Source Maps
138 */
139 outFile?: string;
140
141 /**
142 * The output style of the compiled CSS. There are four possible output styles:
143 *
144 * * `"expanded"` (the default for Dart Sass) writes each selector and
145 * declaration on its own line.
146 *
147 * * `"compressed"` removes as many extra characters as possible, and writes
148 * the entire stylesheet on a single line.
149 *
150 * * `"nested"` (the default for Node Sass, not supported by Dart Sass)
151 * indents CSS rules to match the nesting of the Sass source.
152 *
153 * * `"compact"` (not supported by Dart Sass) puts each CSS rule on its own single line.
154 *
155 * @example
156 *
157 * ```js
158 * const source = `
159 * h1 {
160 * font-size: 40px;
161 * code {
162 * font-face: Roboto Mono;
163 * }
164 * }`;
165 *
166 * let result = sass.renderSync({
167 * data: source,
168 * outputStyle: "expanded"
169 * });
170 * console.log(result.css.toString());
171 * // h1 {
172 * // font-size: 40px;
173 * // }
174 * // h1 code {
175 * // font-face: Roboto Mono;
176 * // }
177 *
178 * result = sass.renderSync({
179 * data: source,
180 * outputStyle: "compressed"
181 * });
182 * console.log(result.css.toString());
183 * // h1{font-size:40px}h1 code{font-face:Roboto Mono}
184 *
185 * result = sass.renderSync({
186 * data: source,
187 * outputStyle: "nested"
188 * });
189 * console.log(result.css.toString());
190 * // h1 {
191 * // font-size: 40px; }
192 * // h1 code {
193 * // font-face: Roboto Mono; }
194 *
195 * result = sass.renderSync({
196 * data: source,
197 * outputStyle: "compact"
198 * });
199 * console.log(result.css.toString());
200 * // h1 { font-size: 40px; }
201 * // h1 code { font-face: Roboto Mono; }
202 * ```
203 *
204 * @category Output
205 */
206 outputStyle?: 'compressed' | 'expanded' | 'nested' | 'compact';
207
208 /**
209 * Whether or not Sass should generate a source map. If it does, the source
210 * map will be available as {@link LegacyResult.map} (unless {@link
211 * sourceMapEmbed} is `true`).
212 *
213 * If this option is a string, it’s the path that the source map is expected
214 * to be written to, which is used to link to the source map from the
215 * generated CSS and to link *from* the source map to the Sass source files.
216 * Note that if `sourceMap` is a string and {@link outFile} isn’t passed, Sass
217 * assumes that the CSS will be written to the same directory as the file
218 * option if it’s passed.
219 *
220 * If this option is `true`, the path is assumed to be {@link outFile} with
221 * `.map` added to the end. If it’s `true` and {@link outFile} isn’t passed,
222 * it has no effect.
223 *
224 * @example
225 *
226 * ```js
227 * let result = sass.renderSync({
228 * file: "style.scss",
229 * sourceMap: "out.map"
230 * })
231 * console.log(result.css.toString());
232 * // h1 {
233 * // font-size: 40px;
234 * // }
235 * // /*# sourceMappingURL=out.map * /
236 *
237 * result = sass.renderSync({
238 * file: "style.scss",
239 * sourceMap: true,
240 * outFile: "out.css"
241 * })
242 * console.log(result.css.toString());
243 * // h1 {
244 * // font-size: 40px;
245 * // }
246 * // /*# sourceMappingURL=out.css.map * /
247 * ```
248 *
249 * @defaultValue `false`
250 * @category Source Maps
251 */
252 sourceMap?: boolean | string;
253
254 /**
255 * Whether to embed the entire contents of the Sass files that contributed to
256 * the generated CSS in the source map. This may produce very large source
257 * maps, but it guarantees that the source will be available on any computer
258 * no matter how the CSS is served.
259 *
260 * @example
261 *
262 * ```js
263 * sass.renderSync({
264 * file: "style.scss",
265 * sourceMap: "out.map",
266 * sourceMapContents: true
267 * })
268 * ```
269 *
270 * @defaultValue `false`
271 * @category Source Maps
272 */
273 sourceMapContents?: boolean;
274
275 /**
276 * Whether to embed the contents of the source map file in the generated CSS,
277 * rather than creating a separate file and linking to it from the CSS.
278 *
279 * @example
280 *
281 * ```js
282 * sass.renderSync({
283 * file: "style.scss",
284 * sourceMap: "out.map",
285 * sourceMapEmbed: true
286 * });
287 * ```
288 *
289 * @defaultValue `false`
290 * @category Source Maps
291 */
292 sourceMapEmbed?: boolean;
293
294 /**
295 * If this is passed, it's prepended to all the links from the source map to
296 * the Sass source files.
297 *
298 * @category Source Maps
299 */
300 sourceMapRoot?: string;
301
302 /**
303 * Additional handler(s) for loading files when a [`@use`
304 * rule](https://sass-lang.com/documentation/at-rules/use) or an [`@import`
305 * rule](https://sass-lang.com/documentation/at-rules/import) is encountered.
306 * It can either be a single {@link LegacyImporter} function, or an array of
307 * {@link LegacyImporter}s.
308 *
309 * Importers take the URL of the `@import` or `@use` rule and return a {@link
310 * LegacyImporterResult} indicating how to handle that rule. For more details,
311 * see {@link LegacySyncImporter} and {@link LegacyAsyncImporter}.
312 *
313 * Loads are resolved by trying, in order:
314 *
315 * * Loading a file from disk relative to the file in which the `@use` or
316 * `@import` appeared.
317 *
318 * * Each custom importer.
319 *
320 * * Loading a file relative to the current working directory.
321 *
322 * * Each load path in {@link includePaths}.
323 *
324 * * Each load path specified in the `SASS_PATH` environment variable, which
325 * should be semicolon-separated on Windows and colon-separated elsewhere.
326 *
327 * @example
328 *
329 * ```js
330 * sass.render({
331 * file: "style.scss",
332 * importer: [
333 * // This importer uses the synchronous API, and can be passed to either
334 * // renderSync() or render().
335 * function(url, prev) {
336 * // This generates a stylesheet from scratch for `@use "big-headers"`.
337 * if (url != "big-headers") return null;
338 *
339 * return {
340 * contents: `
341 * h1 {
342 * font-size: 40px;
343 * }`
344 * };
345 * },
346 *
347 * // This importer uses the asynchronous API, and can only be passed to
348 * // render().
349 * function(url, prev, done) {
350 * // Convert `@use "foo/bar"` to "node_modules/foo/sass/bar".
351 * const components = url.split('/');
352 * const innerPath = components.slice(1).join('/');
353 * done({
354 * file: `node_modules/${components.first}/sass/${innerPath}`
355 * });
356 * }
357 * ]
358 * }, function(err, result) {
359 * // ...
360 * });
361 * ```
362 *
363 * @category Plugins
364 * @compatibility dart: true, node: "3.0.0"
365 *
366 * Versions of Node Sass before 3.0.0 don’t support arrays of importers, nor
367 * do they support importers that return `Error` objects.
368 *
369 * Versions of Node Sass before 2.0.0 don’t support the `importer` option at
370 * all.
371 *
372 * @compatibility feature: "Import order", dart: "1.20.2", node: false
373 *
374 * Versions of Dart Sass before 1.20.2 preferred resolving imports using
375 * {@link includePaths} before resolving them using custom importers.
376 *
377 * All versions of Node Sass currently pass imports to importers before
378 * loading them relative to the file in which the `@import` appears. This
379 * behavior is considered incorrect and should not be relied on because it
380 * violates the principle of *locality*, which says that it should be possible
381 * to reason about a stylesheet without knowing everything about how the
382 * entire system is set up. If a user tries to import a stylesheet relative to
383 * another stylesheet, that import should *always* work. It shouldn’t be
384 * possible for some configuration somewhere else to break it.
385 */
386 importer?: LegacyImporter<sync> | LegacyImporter<sync>[];
387
388 /**
389 * Additional built-in Sass functions that are available in all stylesheets.
390 * This option takes an object whose keys are Sass function signatures and
391 * whose values are {@link LegacyFunction}s. Each function should take the
392 * same arguments as its signature.
393 *
394 * Functions are passed subclasses of {@link LegacyValue}, and must return the
395 * same.
396 *
397 * **Heads up!** When writing custom functions, it’s important to ensure that
398 * all the arguments are the types you expect. Otherwise, users’ stylesheets
399 * could crash in hard-to-debug ways or, worse, compile to meaningless CSS.
400 *
401 * @example
402 *
403 * ```js
404 * sass.render({
405 * data: `
406 * h1 {
407 * font-size: pow(2, 5) * 1px;
408 * }`,
409 * functions: {
410 * // This function uses the synchronous API, and can be passed to either
411 * // renderSync() or render().
412 * 'pow($base, $exponent)': function(base, exponent) {
413 * if (!(base instanceof sass.types.Number)) {
414 * throw "$base: Expected a number.";
415 * } else if (base.getUnit()) {
416 * throw "$base: Expected a unitless number.";
417 * }
418 *
419 * if (!(exponent instanceof sass.types.Number)) {
420 * throw "$exponent: Expected a number.";
421 * } else if (exponent.getUnit()) {
422 * throw "$exponent: Expected a unitless number.";
423 * }
424 *
425 * return new sass.types.Number(
426 * Math.pow(base.getValue(), exponent.getValue()));
427 * },
428 *
429 * // This function uses the asynchronous API, and can only be passed to
430 * // render().
431 * 'sqrt($number)': function(number, done) {
432 * if (!(number instanceof sass.types.Number)) {
433 * throw "$number: Expected a number.";
434 * } else if (number.getUnit()) {
435 * throw "$number: Expected a unitless number.";
436 * }
437 *
438 * done(new sass.types.Number(Math.sqrt(number.getValue())));
439 * }
440 * }
441 * }, function(err, result) {
442 * console.log(result.css.toString());
443 * // h1 {
444 * // font-size: 32px;
445 * // }
446 * });
447 * ```
448 *
449 * @category Plugins
450 */
451 functions?: {[key: string]: LegacyFunction<sync>};
452
453 /**
454 * By default, if the CSS document contains non-ASCII characters, Sass adds a
455 * `@charset` declaration (in expanded output mode) or a byte-order mark (in
456 * compressed mode) to indicate its encoding to browsers or other consumers.
457 * If `charset` is `false`, these annotations are omitted.
458 *
459 * @category Output
460 * @compatibility dart: "1.39.0", node: false
461 */
462 charset?: boolean;
463
464 /**
465 * If this option is set to `true`, Sass won’t print warnings that are caused
466 * by dependencies. A “dependency” is defined as any file that’s loaded
467 * through {@link includePaths} or {@link importer}. Stylesheets that are
468 * imported relative to the entrypoint are not considered dependencies.
469 *
470 * This is useful for silencing deprecation warnings that you can’t fix on
471 * your own. However, please <em>also</em> notify your dependencies of the deprecations
472 * so that they can get fixed as soon as possible!
473 *
474 * **Heads up!** If {@link render} or {@link renderSync} is called without
475 * {@link LegacyFileOptions.file} or {@link LegacyStringOptions.file},
476 * <em>all</em> stylesheets it loads will be considered dependencies. Since it
477 * doesn’t have a path of its own, everything it loads is coming from a load
478 * path rather than a relative import.
479 *
480 * @defaultValue `false`
481 * @category Messages
482 * @compatibility dart: "1.35.0", node: false
483 */
484 quietDeps?: boolean;
485
486 /**
487 * By default, Dart Sass will print only five instances of the same
488 * deprecation warning per compilation to avoid deluging users in console
489 * noise. If you set `verbose` to `true`, it will instead print every
490 * deprecation warning it encounters.
491 *
492 * @defaultValue `false`
493 * @category Messages
494 * @compatibility dart: "1.35.0", node: false
495 */
496 verbose?: boolean;
497
498 /**
499 * An object to use to handle warnings and/or debug messages from Sass.
500 *
501 * By default, Sass emits warnings and debug messages to standard error, but
502 * if {@link Logger.warn} or {@link Logger.debug} is set, this will invoke
503 * them instead.
504 *
505 * The special value {@link Logger.silent} can be used to easily silence all
506 * messages.
507 *
508 * @category Messages
509 * @compatibility dart: "1.43.0", node: false
510 */
511 logger?: Logger;
512
513 /**
514 * If this option is set to an instance of `NodePackageImporter`, Sass will
515 * use the built-in Node.js package importer to resolve Sass files with a
516 * `pkg:` URL scheme. Details for library authors and users can be found in
517 * the {@link NodePackageImporter} documentation.
518 *
519 * @example
520 * ```js
521 * sass.renderSync({
522 * data: '@use "pkg:vuetify";',
523 * pkgImporter: new sass.NodePackageImporter()
524 * });
525 * ```
526 * @category Plugins
527 * @compatibility dart: "2.0", node: false
528 */
529 pkgImporter?: NodePackageImporter;
530}
531
532/**
533 * If {@link file} is passed without {@link data}, Sass will load the stylesheet
534 * at {@link file} and compile it to CSS.
535 *
536 * @typeParam sync - This lets the TypeScript checker verify that {@link
537 * LegacyAsyncImporter}s and {@link LegacyAsyncFunction}s aren't passed to
538 * {@link renderSync}.
539 */
540export interface LegacyFileOptions<sync extends 'sync' | 'async'>
541 extends LegacySharedOptions<sync> {
542 /**
543 * The path to the file for Sass to load and compile. If the file’s extension
544 * is `.scss`, it will be parsed as SCSS; if it’s `.sass`, it will be parsed
545 * as the indented syntax; and if it’s `.css`, it will be parsed as plain CSS.
546 * If it has no extension, it will be parsed as SCSS.
547 *
548 * @example
549 *
550 * ```js
551 * sass.renderSync({file: "style.scss"});
552 * ```
553 *
554 * @category Input
555 * @compatibility feature: "Plain CSS files", dart: "1.11.0", node: "partial"
556 *
557 * Node Sass and older versions of Dart Sass support loading files with the
558 * extension `.css`, but contrary to the specification they’re treated as SCSS
559 * files rather than being parsed as CSS. This behavior has been deprecated
560 * and should not be relied on. Any files that use Sass features should use
561 * the `.scss` extension.
562 *
563 * All versions of Node Sass and Dart Sass otherwise support the file option
564 * as described below.
565 */
566 file: string;
567
568 /**
569 * See {@link LegacyStringOptions.file} for documentation of passing {@link
570 * file} along with {@link data}.
571 *
572 * @category Input
573 */
574 data?: never;
575}
576
577/**
578 * If {@link data} is passed, Sass will use it as the contents of the stylesheet
579 * to compile.
580 *
581 * @typeParam sync - This lets the TypeScript checker verify that {@link
582 * LegacyAsyncImporter}s and {@link LegacyAsyncFunction}s aren't passed to
583 * {@link renderSync}.
584 *
585 * @category Legacy
586 * @deprecated This only works with the legacy {@link render} and {@link
587 * renderSync} APIs. Use {@link StringOptions} with {@link compile}, {@link
588 * compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
589 */
590export interface LegacyStringOptions<sync extends 'sync' | 'async'>
591 extends LegacySharedOptions<sync> {
592 /**
593 * The contents of the stylesheet to compile. Unless {@link file} is passed as
594 * well, the stylesheet’s URL is set to `"stdin"`.
595 *
596 * By default, this stylesheet is parsed as SCSS. This can be controlled using
597 * {@link indentedSyntax}.
598 *
599 * @example
600 *
601 * ```js
602 * sass.renderSync({
603 * data: `
604 * h1 {
605 * font-size: 40px;
606 * }`
607 * });
608 * ```
609 *
610 * @category Input
611 */
612 data: string;
613
614 /**
615 * If `file` and {@link data} are both passed, `file` is used as the path of
616 * the stylesheet for error reporting, but {@link data} is used as the
617 * contents of the stylesheet. In this case, `file`’s extension is not used to
618 * determine the syntax of the stylesheet.
619 *
620 * @category Input
621 */
622 file?: string;
623
624 /**
625 * This flag controls whether {@link data} is parsed as the indented syntax or
626 * not.
627 *
628 * @example
629 *
630 * ```js
631 * sass.renderSync({
632 * data: `
633 * h1
634 * font-size: 40px`,
635 * indentedSyntax: true
636 * });
637 * ```
638 *
639 * @defaultValue `false`
640 * @category Input
641 */
642 indentedSyntax?: boolean;
643}
644
645/**
646 * Options for {@link render} and {@link renderSync}. This can either be {@link
647 * LegacyFileOptions} to load a file from disk, or {@link LegacyStringOptions}
648 * to compile a string of Sass code.
649 *
650 * See {@link LegacySharedOptions} for options that are shared across both file
651 * and string inputs.
652 *
653 * @category Legacy
654 * @deprecated This only works with the legacy {@link render} and {@link
655 * renderSync} APIs. Use {@link Options} with {@link compile}, {@link
656 * compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
657 */
658export type LegacyOptions<sync extends 'sync' | 'async'> =
659 | LegacyFileOptions<sync>
660 | LegacyStringOptions<sync>;