/// import * as Sass from 'sass'; import * as Webpack from 'webpack'; type ImporterReturnType = | { file: string } | { file?: string | undefined; contents: string } | Error | null | types.Null | types.Error; /** * The context value is a value that is shared for the duration of a single render. * The context object is the implicit `this` for importers and sass functions * that are implemented in javascript. * * A render can be detected as asynchronous if the `callback` property is set on the context object. */ interface Context { options: Options; callback: SassRenderCallback | undefined; [data: string]: any; } interface AsyncContext extends Context { callback: SassRenderCallback; } interface SyncContext extends Context { callback: undefined; } type AsyncImporter = ( this: AsyncContext, url: string, prev: string, done: (data: ImporterReturnType) => void, ) => void; type SyncImporter = (this: SyncContext, url: string, prev: string) => ImporterReturnType; type Importer = AsyncImporter | SyncImporter; // These function types enumerate up to 6 js arguments. More than that will be incorrectly marked by the compiler as an error. // ** Sync Sass functions receiving fixed # of arguments *** type SyncSassFn = (this: SyncContext, ...$args: types.Value[]) => types.ReturnValue; // ** Sync Sass functions receiving variable # of arguments *** type SyncSassVarArgFn1 = (this: SyncContext, $arg1: types.Value[]) => types.ReturnValue; type SyncSassVarArgFn2 = (this: SyncContext, $arg1: types.Value, $arg2: types.Value[]) => types.ReturnValue; type SyncSassVarArgFn3 = ( this: SyncContext, $arg1: types.Value, $arg2: types.Value, $arg3: types.Value[], ) => types.ReturnValue; type SyncSassVarArgFn4 = ( this: SyncContext, $arg1: types.Value, $arg2: types.Value, $arg3: types.Value, $arg4: types.Value[], ) => types.ReturnValue; type SyncSassVarArgFn5 = ( this: SyncContext, $arg1: types.Value, $arg2: types.Value, $arg3: types.Value, $arg4: types.Value, $arg5: types.Value[], ) => types.ReturnValue; type SyncSassVarArgFn6 = ( this: SyncContext, $arg1: types.Value, $arg2: types.Value, $arg3: types.Value, $arg4: types.Value, $arg5: types.Value, $arg6: types.Value[], ) => types.ReturnValue; type SassFunctionCallback = ($result: types.ReturnValue) => void; // ** Async Sass functions receiving fixed # of arguments *** type AsyncSassFn0 = (this: AsyncContext, cb: SassFunctionCallback) => void; type AsyncSassFn1 = (this: AsyncContext, $arg1: types.Value, cb: SassFunctionCallback) => void; type AsyncSassFn2 = ( this: AsyncContext, $arg1: types.Value, $arg2: types.Value, cb: SassFunctionCallback, ) => void; type AsyncSassFn3 = ( this: AsyncContext, $arg1: types.Value, $arg2: types.Value, $arg3: types.Value, cb: SassFunctionCallback, ) => void; type AsyncSassFn4 = ( this: AsyncContext, $arg1: types.Value, $arg2: types.Value, $arg3: types.Value, $arg4: types.Value, cb: SassFunctionCallback, ) => void; type AsyncSassFn5 = ( this: AsyncContext, $arg1: types.Value, $arg2: types.Value, $arg3: types.Value, $arg4: types.Value, $arg5: types.Value, cb: SassFunctionCallback, ) => void; type AsyncSassFn6 = ( this: AsyncContext, $arg1: types.Value, $arg2: types.Value, $arg3: types.Value, $arg4: types.Value, $arg5: types.Value, $arg6: types.Value, cb: SassFunctionCallback, ) => void; // *** Async Sass Functions receiving variable # of arguments *** type AsyncSassVarArgFn1 = (this: AsyncContext, $arg1: types.Value[], cb: SassFunctionCallback) => void; type AsyncSassVarArgFn2 = ( this: AsyncContext, $arg1: types.Value, $arg2: types.Value[], cb: SassFunctionCallback, ) => void; type AsyncSassVarArgFn3 = ( this: AsyncContext, $arg1: types.Value, $arg2: types.Value, $arg3: types.Value[], cb: SassFunctionCallback, ) => void; type AsyncSassVarArgFn4 = ( this: AsyncContext, $arg1: types.Value, $arg2: types.Value, $arg3: types.Value, $arg4: types.Value[], cb: SassFunctionCallback, ) => void; type AsyncSassVarArgFn5 = ( this: AsyncContext, $arg1: types.Value, $arg2: types.Value, $arg3: types.Value, $arg4: types.Value, $arg5: types.Value[], cb: SassFunctionCallback, ) => void; type AsyncSassVarArgFn6 = ( this: AsyncContext, $arg1: types.Value, $arg2: types.Value, $arg3: types.Value, $arg4: types.Value, $arg5: types.Value, $arg6: types.Value[], cb: SassFunctionCallback, ) => void; type SyncSassFunction = | SyncSassFn | SyncSassVarArgFn1 | SyncSassVarArgFn2 | SyncSassVarArgFn3 | SyncSassVarArgFn4 | SyncSassVarArgFn5 | SyncSassVarArgFn6; type AsyncSassFunction = | AsyncSassFn0 | AsyncSassFn1 | AsyncSassFn2 | AsyncSassFn3 | AsyncSassFn4 | AsyncSassFn5 | AsyncSassFn6 | AsyncSassVarArgFn1 | AsyncSassVarArgFn2 | AsyncSassVarArgFn3 | AsyncSassVarArgFn4 | AsyncSassVarArgFn5 | AsyncSassVarArgFn6; type SassFunction = SyncSassFunction | AsyncSassFunction; type FunctionDeclarations = Record; interface Options { file?: string | undefined; data?: string | undefined; importer?: Importer | Importer[] | undefined; functions?: FunctionDeclarations | undefined; includePaths?: string[] | undefined; indentedSyntax?: boolean | undefined; indentType?: string | undefined; indentWidth?: number | undefined; linefeed?: string | undefined; omitSourceMapUrl?: boolean | undefined; outFile?: string | undefined; outputStyle?: "compact" | "compressed" | "expanded" | "nested" | undefined; precision?: number | undefined; sourceComments?: boolean | undefined; sourceMap?: boolean | string | undefined; sourceMapContents?: boolean | undefined; sourceMapEmbed?: boolean | undefined; sourceMapRoot?: string | undefined; [key: string]: any; } /** * The error object returned to javascript by sass's render methods. * * This is not the same thing as types.Error. */ interface SassError extends Error { message: string; line: number; column: number; status: number; file: string; } /** * The result of successfully compiling a Sass file. */ interface Result { css: Buffer; map: Buffer; stats: { entry: string; start: number; end: number; duration: number; includedFiles: string[]; }; } type SassRenderCallback = (err: SassError, result: Result) => any; // Note, most node-sass constructors can be invoked as a function or with a new // operator. The exception: the types Null and Boolean for which new is // forbidden. // // Because of this, the new-able object notation is used here, a class does not // work for these types. declare namespace types { /* tslint:disable:ban-types */ /** * Values that are received from Sass as an argument to a javascript function. */ export type Value = Null | Number | String | Color | Boolean | List | Map; /** * Values that are legal to return to Sass from a javascript function. */ export type ReturnValue = Value | Error; // *** Sass Null *** export interface Null { /** * This property doesn't exist, but its presence forces the typescript * compiler to properly type check this type. Without it, it seems to * allow things that aren't types.Null to match it in case statements and * assignments. */ readonly ___NULL___: unique symbol; } interface NullConstructor { (): Null; NULL: Null; } export const Null: NullConstructor; // *** Sass Number *** export interface Number { getValue(): number; setValue(n: number): void; getUnit(): string; setUnit(u: string): void; } interface NumberConstructor { /** * Constructs a new Sass number. Does not require use of the `new` keyword. */ new(value: number, unit?: string): Number; /** * Constructs a new Sass number. Can also be used with the `new` keyword. */ (value: number, unit?: string): Number; } export const Number: NumberConstructor; // *** Sass String *** export interface String { getValue(): string; setValue(s: string): void; } interface StringConstructor { /** * Constructs a new Sass string. Does not require use of the `new` keyword. */ new(value: string): String; /** * Constructs a new Sass string. Can also be used with the `new` keyword. */ (value: string): String; } export const String: StringConstructor; // *** Sass Color *** export interface Color { /** * Get the red component of the color. * @returns integer between 0 and 255 inclusive; */ getR(): number; /** * Set the red component of the color. * @returns integer between 0 and 255 inclusive; */ setR(r: number): void; /** * Get the green component of the color. * @returns integer between 0 and 255 inclusive; */ getG(): number; /** * Set the green component of the color. * @param g integer between 0 and 255 inclusive; */ setG(g: number): void; /** * Get the blue component of the color. * @returns integer between 0 and 255 inclusive; */ getB(): number; /** * Set the blue component of the color. * @param b integer between 0 and 255 inclusive; */ setB(b: number): void; /** * Get the alpha transparency component of the color. * @returns number between 0 and 1 inclusive; */ getA(): number; /** * Set the alpha component of the color. * @param a number between 0 and 1 inclusive; */ setA(a: number): void; } interface ColorConstructor { /** * Constructs a new Sass color given the RGBA component values. Do not invoke with the `new` keyword. * * @param r integer 0-255 inclusive * @param g integer 0-255 inclusive * @param b integer 0-255 inclusive * @param [a] float 0 - 1 inclusive * @returns a SassColor instance. */ new(r: number, g: number, b: number, a?: number): Color; /** * Constructs a new Sass color given a 4 byte number. Do not invoke with the `new` keyword. * * If a single number is passed it is assumed to be a number that contains * all the components which are extracted using bitmasks and bitshifting. * * @param hexN A number that is usually written in hexadecimal form. E.g. 0xff0088cc. * @returns a Sass Color instance. * @example * // Comparison with byte array manipulation * let a = new ArrayBuffer(4); * let hexN = 0xCCFF0088; // 0xAARRGGBB * let a32 = new Uint32Array(a); // Uint32Array [ 0 ] * a32[0] = hexN; * let a8 = new Uint8Array(a); // Uint8Array [ 136, 0, 255, 204 ] * let componentBytes = [a8[2], a8[1], a8[0], a8[3] / 255] // [ 136, 0, 255, 0.8 ] * let c = sass.types.Color(hexN); * let components = [c.getR(), c.getG(), c.getR(), c.getA()] // [ 136, 0, 255, 0.8 ] * assert.deepEqual(componentBytes, components); // does not raise. */ new(hexN: number): Color; /** * Constructs a new Sass color given the RGBA component values. Do not invoke with the `new` keyword. * * @param r integer 0-255 inclusive * @param g integer 0-255 inclusive * @param b integer 0-255 inclusive * @param [a] float 0 - 1 inclusive * @returns a SassColor instance. */ (r: number, g: number, b: number, a?: number): Color; /** * Constructs a new Sass color given a 4 byte number. Do not invoke with the `new` keyword. * * If a single number is passed it is assumed to be a number that contains * all the components which are extracted using bitmasks and bitshifting. * * @param hexN A number that is usually written in hexadecimal form. E.g. 0xff0088cc. * @returns a Sass Color instance. * @example * // Comparison with byte array manipulation * let a = new ArrayBuffer(4); * let hexN = 0xCCFF0088; // 0xAARRGGBB * let a32 = new Uint32Array(a); // Uint32Array [ 0 ] * a32[0] = hexN; * let a8 = new Uint8Array(a); // Uint8Array [ 136, 0, 255, 204 ] * let componentBytes = [a8[2], a8[1], a8[0], a8[3] / 255] // [ 136, 0, 255, 0.8 ] * let c = sass.types.Color(hexN); * let components = [c.getR(), c.getG(), c.getR(), c.getA()] // [ 136, 0, 255, 0.8 ] * assert.deepEqual(componentBytes, components); // does not raise. */ (hexN: number): Color; } export const Color: ColorConstructor; // *** Sass Boolean *** export interface Boolean { getValue(): boolean; } interface BooleanConstructor { (bool: boolean): Boolean; TRUE: Boolean; FALSE: Boolean; } export const Boolean: BooleanConstructor; // *** Sass List *** export interface Enumerable { getValue(index: number): Value; setValue(index: number, value: Value): void; getLength(): number; } export interface List extends Enumerable { getSeparator(): boolean; setSeparator(isComma: boolean): void; } interface ListConstructor { new(length: number, commaSeparator?: boolean): List; (length: number, commaSeparator?: boolean): List; } export const List: ListConstructor; // *** Sass Map *** export interface Map extends Enumerable { getKey(index: number): Value; setKey(index: number, key: Value): void; } interface MapConstructor { new(length: number): Map; (length: number): Map; } export const Map: MapConstructor; // *** Sass Error *** export interface Error { /** * This property doesn't exist, but its presence forces the typescript * compiler to properly type check this type. Without it, it seems to * allow things that aren't types.Error to match it in case statements and * assignments. */ readonly ___SASS_ERROR___: unique symbol; // why isn't there a getMessage() method? } interface ErrorConstructor { /** * An error return value for async functions. * For synchronous functions, this can be returned or a standard error object can be thrown. */ new(message: string): Error; /** * An error return value for async functions. * For synchronous functions, this can be returned or a standard error object can be thrown. */ (message: string): Error; } export const Error: ErrorConstructor; /* eslint-enable @typescript-eslint/ban-types */ /* tslint:enable:ban-types */ } interface LoaderOptions { /** * The special `implementation` option determines which implementation of Sass * to use. * * By default the loader resolve the implementation based on your dependencies. * Just add required implementation to `package.json` (`node-sass` or `sass` * package) and install dependencies. * * Example where the `sass-loader` loader uses the `sass` (`dart-sass`) * implementation: * * **package.json** * * ```json * { * "devDependencies": { * "sass-loader": "^7.2.0", * "sass": "^1.22.10" * } * } * ``` * * Example where the `sass-loader` loader uses the `node-sass` implementation: * * **package.json** * * ```json * { * "devDependencies": { * "sass-loader": "^7.2.0", * "node-sass": "^4.0.0" * } * } * ``` * * Beware the situation when `node-sass` and `sass` were installed! By default * the `sass-loader` prefers `node-sass`. In order to avoid this situation you * can use the `implementation` option. * * The `implementation` options either accepts `node-sass` or `sass` (`Dart Sass`) * as a module. * * For example, to use Dart Sass, you'd pass: * * ```js * module.exports = { * module: { * rules: [ * { * test: /\.s[ac]ss$/i, * use: [ * 'style-loader', * 'css-loader', * { * loader: 'sass-loader', * options: { * // Prefer `dart-sass` * implementation: require('sass'), * }, * }, * ], * }, * ], * }, * }; * ``` * * Note that when using `sass` (`Dart Sass`), **synchronous compilation is twice * as fast as asynchronous compilation** by default, due to the overhead of * asynchronous callbacks. To avoid this overhead, you can use the [fibers](https://www.npmjs.com/package/fibers) * package to call asynchronous importers from the synchronous code path. * * We automatically inject the [`fibers`](https://github.com/laverdet/node-fibers) * package (setup `sassOptions.fiber`) if is possible (i.e. you need install the * [`fibers`](https://github.com/laverdet/node-fibers) package). * * **package.json** * * ```json * { * "devDependencies": { * "sass-loader": "^7.2.0", * "sass": "^1.22.10", * "fibers": "^4.0.1" * } * } * ``` * * You can disable automatically injecting the [`fibers`](https://github.com/laverdet/node-fibers) * package by passing a `false` value for the `sassOptions.fiber` option. * * **webpack.config.js** * * ```js * module.exports = { * module: { * rules: [ * { * test: /\.s[ac]ss$/i, * use: [ * 'style-loader', * 'css-loader', * { * loader: 'sass-loader', * options: { * implementation: require('sass'), * sassOptions: { * fiber: false, * }, * }, * }, * ], * }, * ], * }, * }; * ``` * * You can also pass the `fiber` value using this code: * * **webpack.config.js** * * ```js * module.exports = { * module: { * rules: [ * { * test: /\.s[ac]ss$/i, * use: [ * 'style-loader', * 'css-loader', * { * loader: 'sass-loader', * options: { * implementation: require('sass'), * sassOptions: { * fiber: require('fibers'), * }, * }, * }, * ], * }, * ], * }, * }; * ``` */ implementation?: any; /** * Options for [Node Sass](https://github.com/sass/node-sass) or [Dart Sass](http://sass-lang.com/dart-sass) * implementation. * * > ℹ️ The `indentedSyntax` option has `true` value for the `sass` extension. * * > ℹ️ Options such as `file` and `outFile` are unavailable. * * > ℹ️ We recommend not to use the `sourceMapContents`, `sourceMapEmbed`, * `sourceMapRoot` options because `sass-loader` automatically sets these * options. * * There is a slight difference between the `node-sass` and `sass` (`Dart Sass`) * options. Please consult documentation before using them: * * - [Node Sass documentation](https://github.com/sass/node-sass/#options) for * all available `node-sass` options. * - [Dart Sass documentation](https://github.com/sass/dart-sass#javascript-api) * for all available `sass` options. * * #### `Object` * * Use and object for the Sass implementation setup. * * **webpack.config.js** * * ```js * module.exports = { * module: { * rules: [ * { * test: /\.s[ac]ss$/i, * use: [ * 'style-loader', * 'css-loader', * { * loader: 'sass-loader', * options: { * sassOptions: { * indentWidth: 4, * includePaths: ['absolute/path/a', 'absolute/path/b'], * }, * }, * }, * ], * }, * ], * }, * }; * ``` * * #### `Function` * * Allows to setup the Sass implementation by setting different options based on * the loader context. * * ```js * module.exports = { * module: { * rules: [ * { * test: /\.s[ac]ss$/i, * use: [ * 'style-loader', * 'css-loader', * { * loader: 'sass-loader', * options: { * sassOptions: (loaderContext) => { * // More information about available properties https://webpack.js.org/api/loaders/ * const { resourcePath, rootContext } = loaderContext; * const relativePath = path.relative(rootContext, resourcePath); * * if (relativePath === 'styles/foo.scss') { * return { * includePaths: ['absolute/path/c', 'absolute/path/d'], * }; * } * * return { * includePaths: ['absolute/path/a', 'absolute/path/b'], * }; * }, * }, * }, * ], * }, * ], * }, * }; * ``` */ sassOptions?: LoaderOptions.SassOptions | LoaderOptions.Callback | undefined; /** * Prepends `Sass`/`SCSS` code before the actual entry file. In this case, the * `sass-loader` will not override the `data` option but just append the entry's * content. * * This is especially useful when some of your Sass variables depend on the * environment: * * > ℹ Since you're injecting code, this will break the source mappings in your * entry file. Often there's a simpler solution than this, like multiple Sass * entry files. * * #### `String` * * ```js * module.exports = { * module: { * rules: [ * { * test: /\.s[ac]ss$/i, * use: [ * 'style-loader', * 'css-loader', * { * loader: 'sass-loader', * options: { * prependData: '$env: ' + process.env.NODE_ENV + ';', * }, * }, * ], * }, * ], * }, * }; * ``` * * #### `Function` * * ```js * module.exports = { * module: { * rules: [ * { * test: /\.s[ac]ss$/i, * use: [ * 'style-loader', * 'css-loader', * { * loader: 'sass-loader', * options: { * prependData: (loaderContext) => { * // More information about available properties https://webpack.js.org/api/loaders/ * const { resourcePath, rootContext } = loaderContext; * const relativePath = path.relative(rootContext, resourcePath); * * if (relativePath === 'styles/foo.scss') { * return '$value: 100px;'; * } * * return '$value: 200px;'; * }, * }, * }, * ], * }, * ], * }, * }; * ``` * * @default * undefined */ additionalData?: string | LoaderOptions.Callback | undefined; /** * Enables/Disables generation of source maps. * * By default generation of source maps depends on the [`devtool`](https://webpack.js.org/configuration/devtool/) * option. All values enable source map generation except `eval` and `false` * value. * * **webpack.config.js** * * ```js * module.exports = { * module: { * rules: [ * { * test: /\.s[ac]ss$/i, * use: [ * 'style-loader', * { * loader: 'css-loader', * options: { * sourceMap: true, * }, * }, * { * loader: 'sass-loader', * options: { * sourceMap: true, * }, * }, * ], * }, * ], * }, * }; * ``` * * > ℹ In some rare cases `node-sass` can output invalid source maps (it is a * `node-sass` bug). In order to avoid this, you can try to update `node-sass` * to latest version or you can try to set within `sassOptions` the * `outputStyle` option to `compressed`. * * @default * Depends on the `compiler.devtool` value. */ sourceMap?: boolean | undefined; /** * Enables/Disables the default Webpack importer. * * This can improve performance in some cases. Use it with caution because * aliases and `@import` at-rules starting with `~` will not work. You can pass * own `importer` to solve this (see [`importer docs`](https://github.com/sass/node-sass#importer--v200---experimental)). * * **webpack.config.js** * * ```js * module.exports = { * module: { * rules: [ * { * test: /\.s[ac]ss$/i, * use: [ * 'style-loader', * 'css-loader', * { * loader: 'sass-loader', * options: { * webpackImporter: false, * }, * }, * ], * }, * ], * }, * }; * ``` * * @default * true */ webpackImporter?: boolean | undefined; /** * Treats the @warn rule as a webpack warning. * * Note: It will be true by default in the next major release. * * **webpack.config.js** * * ```js * module.exports = { * module: { * rules: [ * { * test: /\.s[ac]ss$/i, * use: [ * 'style-loader', * 'css-loader', * { * loader: 'sass-loader', * options: { * warnRuleAsWarning: false, * }, * }, * ], * }, * ], * }, * }; * ``` */ warnRuleAsWarning?: boolean | undefined; } declare namespace LoaderOptions { type Callback = (content: string | Buffer, loaderContext: Webpack.loader.LoaderContext) => T; type SassOptions = Options | Sass.LegacyOptions<"sync">; } declare function loader(content: string): void; declare namespace loader { type Options = LoaderOptions; } export { loader as default };