From b192519b5543499e9ac64d5f3f7d839010308553 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 30 Nov 2021 15:32:04 -0800 Subject: [PATCH] Document the new JS API (#3183) --- js-api-doc/README.md | 91 ++++-- js-api-doc/compile.d.ts | 130 ++++++++- js-api-doc/exception.d.ts | 34 ++- js-api-doc/importer.d.ts | 262 +++++++++++++++++ js-api-doc/index.d.ts | 8 +- js-api-doc/legacy/exception.d.ts | 5 + js-api-doc/legacy/function.d.ts | 29 +- js-api-doc/legacy/importer.d.ts | 29 +- js-api-doc/legacy/options.d.ts | 19 +- js-api-doc/legacy/plugin_this.d.ts | 5 + js-api-doc/legacy/render.d.ts | 11 + js-api-doc/logger/index.d.ts | 3 + js-api-doc/logger/source_location.d.ts | 14 + js-api-doc/logger/source_span.d.ts | 21 ++ js-api-doc/options.d.ts | 382 ++++++++++++++++++++++++- js-api-doc/util/promise_or.d.ts | 16 +- js-api-doc/value/argument_list.d.ts | 34 ++- js-api-doc/value/boolean.d.ts | 22 +- js-api-doc/value/color.d.ts | 44 +++ js-api-doc/value/function.d.ts | 17 ++ js-api-doc/value/index.d.ts | 115 ++++++++ js-api-doc/value/list.d.ts | 36 ++- js-api-doc/value/map.d.ts | 25 ++ js-api-doc/value/number.d.ts | 218 ++++++++++++++ js-api-doc/value/string.d.ts | 65 ++++- spec/js-api/compile.d.ts | 2 + spec/js-api/exception.d.ts | 8 +- spec/js-api/index.d.ts | 2 + spec/js-api/options.d.ts | 33 ++- spec/js-api/util/promise_or.d.ts | 6 +- spec/js-api/value/boolean.d.ts | 4 +- typedoc.json | 18 +- 32 files changed, 1628 insertions(+), 80 deletions(-) diff --git a/js-api-doc/README.md b/js-api-doc/README.md index 98213fdc..9a1b1e98 100644 --- a/js-api-doc/README.md +++ b/js-api-doc/README.md @@ -1,15 +1,75 @@ -Both [Dart Sass] and [LibSass] support the same JavaScript API. Dart Sass is -distributed as the pure-Javascript [`sass` package], and LibSass is distributed -as a native extension in the [`node-sass` package]. +The [`sass` package] on npm is a pure-JavaScript package built from the [Dart +Sass] implementation. In addition to Dart Sass's [command-line interface], it +provides a JavaScript API that can be used to drive Sass compilations from +JavaScript. It even allows an application to control {@link Options.importers | +how stylesheets are loaded} and {@link Options.functions | define custom +functions}. -[Dart Sass]: https://sass-lang.com/dart-sass -[LibSass]: https://sass-lang.com/libsass [`sass` package]: https://www.npmjs.com/package/sass -[`node-sass` package]: https://www.npmjs.com/package/node-sass +[Dart Sass]: https://sass-lang.com/dart-sass +[command-line interface]: https://sass-lang.com/documentation/cli/dart-sass ## Usage -The JavaScript API has two entrypoints for compiling Sass to CSS. Each one can +The JavaScript API provides two entrypoints for compiling Sass to CSS, each of +which has a synchronous variant that returns a plain [[CompileResult]] and an +asynchronous variant that returns a `Promise`. **The asynchronous variants are +much slower,** but they allow custom importers and functions to run +asynchronously. + +* [[compile]] and [[compileAsync]] take a path to a Sass file and return the + result of compiling that file to CSS. + + ```js + const sass = require('sass'); + + const result = sass.compile("style.scss"); + console.log(result.css); + ``` + +* [[compileString]] and [[compileStringAsync]] take a string that represents the + contents of a Sass file and return the result of compiling that file to CSS. + + ```js + const sass = require('sass'); + + const result = sass.compileString(` + h1 { + font-size: 40px; + code { + font-face: Roboto Mono; + } + }`); + console.log(result.css); + ``` + +## Integrations + +Most popular Node.js build systems have integrations available for the JS API: + +* Webpack uses the [`sass-loader` package]. +* Gulp uses the [`gulp-sass` package]. +* Broccoli uses the [`broccoli-sass-source-maps` package]. +* Ember uses the [`ember-cli-sass` package]. +* Grunt uses the [`grunt-sass` package]. + +[`sass-loader` package]: https://www.npmjs.com/package/sass-loader +[`gulp-sass` package]: https://www.npmjs.com/package/gulp-sass +[`broccoli-sass-source-maps` package]: https://www.npmjs.com/package/broccoli-sass-source-maps +[`ember-cli-sass` package]: https://www.npmjs.com/package/ember-cli-sass +[`grunt-sass` package]: https://www.npmjs.com/package/grunt-sass + +## Legacy API + +The `sass` package also supports an older API. Although this API is deprecated, +it will continue to be supported until the release of version 2.0.0 of the +`sass` package. The legacy API is also supported by the [`node-sass` package], +which is a native extension wrapper for the deprecated [LibSass] implementation. + +[`node-sass` package]: https://www.npmjs.com/package/node-sass +[LibSass]: https://sass-lang.com/libsass + +The legacy API has two entrypoints for compiling Sass to CSS. Each one can compile either a Sass file by passing in [[LegacyFileOptions]] or a string of Sass code by passing in a [[LegacyStringOptions]]. @@ -41,20 +101,3 @@ Sass code by passing in a [[LegacyStringOptions]]. } }); ``` - -## Integrations - -Most popular Node.js build systems have integrations available for the JS API: - -* Webpack uses the [`sass-loader` package]. -* Gulp uses the [`gulp-sass` package]. -* Broccoli uses the [`broccoli-sass-source-maps` package]. -* Ember uses the [`ember-cli-sass` package]. -* Grunt uses the [`grunt-sass` package]. - -[`sass-loader` package]: https://www.npmjs.com/package/sass-loader -[`gulp-sass` package]: https://www.npmjs.com/package/gulp-sass -[`broccoli-sass-source-maps` package]: https://www.npmjs.com/package/broccoli-sass-source-maps -[`ember-cli-sass` package]: https://www.npmjs.com/package/ember-cli-sass -[`grunt-sass` package]: https://www.npmjs.com/package/grunt-sass - diff --git a/js-api-doc/compile.d.ts b/js-api-doc/compile.d.ts index d14da527..032774ba 100644 --- a/js-api-doc/compile.d.ts +++ b/js-api-doc/compile.d.ts @@ -3,28 +3,150 @@ import {RawSourceMap} from 'source-map-js'; import {Options, StringOptions} from './options'; +/** + * The result of compiling Sass to CSS. Returned by [[compile]], + * [[compileAsync]], [[compileString]], and [[compileStringAsync]]. + * + * @category Compile + */ export interface CompileResult { + /** + * The generated CSS. + * + * Note that this *never* includes a `sourceMapUrl` comment—it's up to the + * caller to determine where to save the source map and how to link to it from + * the stylesheet. + */ css: string; + + /** + * The canonical URLs of all the stylesheets that were loaded during the + * Sass compilation. The order of these URLs is not guaranteed. + */ loadedUrls: URL[]; + + /** + * The object representation of the source map that maps locations in the + * generated CSS back to locations in the Sass source code. + * + * This typically uses absolute `file:` URLs to refer to Sass files, although + * this can be controlled by having a custom [[Importer]] return + * [[ImporterResult.sourceMapUrl]]. + * + * This is set if and only if [[Options.sourceMap]] is `true`. + */ sourceMap?: RawSourceMap; } -/** @hidden */ +/** + * Synchronously compiles the Sass file at `path` to CSS. If it succeeds it + * returns a [[CompileResult]], and if it fails it throws an [[Exception]]. + * + * This only allows synchronous [[Importer]]s and [[CustomFunction]]s. + * + * @example + * + * ```js + * const sass = require('sass'); + * + * const result = sass.compile("style.scss"); + * console.log(result.css); + * ``` + * + * @category Compile + * @compatibility dart: "1.45.0", node: false + */ export function compile(path: string, options?: Options<'sync'>): CompileResult; -/** @hidden */ +/** + * Asynchronously compiles the Sass file at `path` to CSS. Returns a promise + * that resolves with a [[CompileResult]] if it succeeds and rejects with an + * [[Exception]] if it fails. + * + * This only allows synchronous or asynchronous [[Importer]]s and + * [[CustomFunction]]s. + * + * **Heads up!** When using Dart Sass, **[[compile]] is almost twice as fast as + * [[compileAsync]]**, due to the overhead of making the entire evaluation + * process asynchronous. + * + * @example + * + * ```js + * const sass = require('sass'); + * + * const result = await sass.compileAsync("style.scss"); + * console.log(result.css); + * ``` + * + * @category Compile + * @compatibility dart: "1.45.0", node: false + */ export function compileAsync( path: string, options?: Options<'async'> ): Promise; -/** @hidden */ +/** + * Synchronously compiles a stylesheet whose contents is `source` to CSS. If it + * succeeds it returns a [[CompileResult]], and if it fails it throws an + * [[Exception]]. + * + * This only allows synchronous [[Importer]]s and [[CustomFunction]]s. + * + * @example + * + * ```js + * const sass = require('sass'); + * + * const result = sass.compileString(` + * h1 { + * font-size: 40px; + * code { + * font-face: Roboto Mono; + * } + * }`); + * console.log(result.css); + * ``` + * + * @category Compile + * @compatibility dart: "1.45.0", node: false + */ export function compileString( source: string, options?: StringOptions<'sync'> ): CompileResult; -/** @hidden */ +/** + * Asynchronously compiles a stylesheet whose contents is `source` to CSS. + * Returns a promise that resolves with a [[CompileResult]] if it succeeds and + * rejects with an [[Exception]] if it fails. + * + * This only allows synchronous or asynchronous [[Importer]]s and + * [[CustomFunction]]s. + * + * **Heads up!** When using Dart Sass, **[[compile]] is almost twice as fast as + * [[compileAsync]]**, due to the overhead of making the entire evaluation + * process asynchronous. + * + * @example + * + * ```js + * const sass = require('sass'); + * + * const result = await sass.compileStringAsync(` + * h1 { + * font-size: 40px; + * code { + * font-face: Roboto Mono; + * } + * }`); + * console.log(result.css); + * ``` + * + * @category Compile + * @compatibility dart: "1.45.0", node: false + */ export function compileStringAsync( source: string, options?: StringOptions<'async'> diff --git a/js-api-doc/exception.d.ts b/js-api-doc/exception.d.ts index a503d89d..07a62706 100644 --- a/js-api-doc/exception.d.ts +++ b/js-api-doc/exception.d.ts @@ -1,13 +1,41 @@ import {SourceSpan} from './logger'; +/** + * An exception thrown because a Sass compilation failed. + * + * @category Other + */ export class Exception extends Error { + private constructor(); + + /** + * A human-friendly representation of the exception. + * + * Because many tools simply print `Error.message` directly, this includes not + * only the textual description of what went wrong (the [[sassMessage]]) but + * also an indication of where in the Sass stylesheet the error occurred (the + * [[span]]) and the Sass stack trace at the point of error (the + * [[sassStack]]). + */ message: string; - sassMessage: string; + /** + * A textual description of what went wrong. + * + * Unlike [[message]], this does *not* include representations of [[span]] or + * [[sassStack]]. + */ + readonly sassMessage: string; - sassStack: string; + /** + * A human-friendly representation of the Sass stack trace at the point of + * error. + */ + readonly sassStack: string; - span: SourceSpan; + /** The location the error occurred in the Sass file that triggered it. */ + readonly span: SourceSpan; + /** Returns the same string as [[message]]. */ toString(): string; } diff --git a/js-api-doc/importer.d.ts b/js-api-doc/importer.d.ts index f307df17..1a74d6a6 100644 --- a/js-api-doc/importer.d.ts +++ b/js-api-doc/importer.d.ts @@ -3,32 +3,294 @@ import {URL} from 'url'; import {Syntax} from './options'; import {PromiseOr} from './util/promise_or'; +/** + * A special type of importer that redirects all loads to existing files on + * disk. Although this is less powerful than a full [[Importer]], it + * automatically takes care of Sass features like resolving partials and file + * extensions and of loading the file from disk. + * + * Like all importers, this implements custom Sass loading logic for [`@use` + * rules](https://sass-lang.com/documentation/at-rules/use) and [`@import` + * rules](https://sass-lang.com/documentation/at-rules/import). It can be passed + * to [[Options.importers]] or [[StringOptionsWithImporter.importer]]. + * + * @typeParam sync - A `FileImporter<'sync'>`'s [[findFileUrl]] must return + * synchronously, but in return it can be passed to [[compile]] and + * [[compileString]] in addition to [[compileAsync]] and [[compileStringAsync]]. + * + * A `FileImporter<'async'>`'s [[findFileUrl]] may either return synchronously + * or asynchronously, but it can only be used with [[compileAsync]] and + * [[compileStringAsync]]. + * + * @example + * + * ```js + * const {fileURLToPath} = require('url'); + * + * sass.compile('style.scss', { + * importers: [{ + * // An importer that redirects relative URLs starting with "~" to + * // `node_modules`. + * findFileUrl(url) { + * if (!url.startsWith('~')) return null; + * return new URL(url.substring(1), pathToFileURL('node_modules')); + * } + * }] + * }); + * ``` + * + * @category Importer + */ export interface FileImporter< sync extends 'sync' | 'async' = 'sync' | 'async' > { + /** + * A callback that's called to partially resolve a load (such as + * [`@use`](https://sass-lang.com/documentation/at-rules/use) or + * [`@import`](https://sass-lang.com/documentation/at-rules/import)) to a file + * on disk. + * + * Unlike an [[Importer]], the compiler will automatically handle relative + * loads for a [[FileImporter]]. See [[Options.importers]] for more details on + * the way loads are resolved. + * + * @param url - The loaded URL. Since this might be relative, it's represented + * as a string rather than a [[URL]] object. + * + * @param options.fromImport - Whether this is being invoked because of a Sass + * `@import` rule, as opposed to a `@use` or `@forward` rule. + * + * This should *only* be used for determining whether or not to load + * [import-only files](https://sass-lang.com/documentation/at-rules/import#import-only-files). + * + * @returns An absolute `file:` URL if this importer recognizes the `url`. + * This may be only partially resolved: the compiler will automatically look + * for [partials](https://sass-lang.com/documentation/at-rules/use#partials), + * [index files](https://sass-lang.com/documentation/at-rules/use#index-files), + * and file extensions based on the returned URL. An importer may also return + * a fully resolved URL if it so chooses. + * + * If this importer doesn't recognize the URL, it should return `null` instead + * to allow other importers or {@link Options.loadPaths | load paths} to + * handle it. + * + * This may also return a `Promise`, but if it does the importer may only be + * passed to [[compileAsync]] and [[compileStringAsync]], not [[compile]] or + * [[compileString]]. + * + * @throws any - If this importer recognizes `url` but determines that it's + * invalid, it may throw an exception that will be wrapped by Sass. If the + * exception object has a `message` property, it will be used as the wrapped + * exception's message; otherwise, the exception object's `toString()` will be + * used. This means it's safe for importers to throw plain strings. + */ findFileUrl( url: string, options: {fromImport: boolean} ): PromiseOr; + /** @hidden */ canonicalize?: never; } +/** + * An object that implements custom Sass loading logic for [`@use` + * rules](https://sass-lang.com/documentation/at-rules/use) and [`@import` + * rules](https://sass-lang.com/documentation/at-rules/import). It can be passed + * to [[Options.importers]] or [[StringOptionsWithImporter.importer]]. + * + * Importers that simply redirect to files on disk are encouraged to use the + * [[FileImporter]] interface instead. + * + * See [[Options.importers]] for more details on the way loads are resolved. + * + * @typeParam sync - An `Importer<'sync'>`'s [[canonicalize]] and [[load]] must + * return synchronously, but in return it can be passed to [[compile]] and + * [[compileString]] in addition to [[compileAsync]] and [[compileStringAsync]]. + * + * An `Importer<'async'>`'s [[canonicalize]] and [[load]] may either return + * synchronously or asynchronously, but it can only be used with + * [[compileAsync]] and [[compileStringAsync]]. + * + * @example Resolving a Load + * + * This is the process of resolving a load using a custom importer: + * + * - The compiler encounters `@use "db:foo/bar/baz"`. + * - It calls [[canonicalize]] with `"db:foo/bar/baz"`. + * - [[canonicalize]] returns `new URL("db:foo/bar/baz/_index.scss")`. + * - If the compiler has already loaded a stylesheet with this canonical URL, it + * re-uses the existing module. + * - Otherwise, it calls [[load]] with `new URL("db:foo/bar/baz/_index.scss")`. + * - [[load]] returns an [[ImporterResult]] that the compiler uses as the + * contents of the module. + * + * @example Code Sample + * + * ```js + * sass.compile('style.scss', { + * // An importer for URLs like `bgcolor:orange` that generates a + * // stylesheet with the given background color. + * importers: [{ + * canonicalize(url) { + * if (!url.startsWith('bgcolor:')) return null; + * return new URL(url); + * }, + * load(canonicalUrl) { + * return { + * contents: `body {background-color: ${canonicalUrl.pathname}}`, + * syntax: 'scss' + * }; + * } + * }] + * }); + * ``` + * + * @category Importer + */ export interface Importer { + /** + * If `url` is recognized by this importer, returns its canonical format. + * + * If Sass has already loaded a stylesheet with the returned canonical URL, it + * re-uses the existing parse tree (and the loaded module for `@use`). This + * means that importers **must ensure** that the same canonical URL always + * refers to the same stylesheet, *even across different importers*. As such, + * importers are encouraged to use unique URL schemes to disambiguate between + * one another. + * + * As much as possible, custom importers should canonicalize URLs the same way + * as the built-in filesystem importer: + * + * - The importer should look for stylesheets by adding the prefix `_` to the + * URL's basename, and by adding the extensions `.sass` and `.scss` if the + * URL doesn't already have one of those extensions. For example, if the + * URL was `foo/bar/baz`, the importer would look for: + * - `foo/bar/baz.sass` + * - `foo/bar/baz.scss` + * - `foo/bar/_baz.sass` + * - `foo/bar/_baz.scss` + * + * If the URL was `foo/bar/baz.scss`, the importer would just look for: + * - `foo/bar/baz.scss` + * - `foo/bar/_baz.scss` + * + * If the importer finds a stylesheet at more than one of these URLs, it + * should throw an exception indicating that the URL is ambiguous. Note that + * if the extension is explicitly specified, a stylesheet with the opposite + * extension is allowed to exist. + * + * - If none of the possible paths is valid, the importer should perform the + * same resolution on the URL followed by `/index`. In the example above, + * it would look for: + * - `foo/bar/baz/index.sass` + * - `foo/bar/baz/index.scss` + * - `foo/bar/baz/_index.sass` + * - `foo/bar/baz/_index.scss` + * + * As above, if the importer finds a stylesheet at more than one of these + * URLs, it should throw an exception indicating that the import is + * ambiguous. + * + * If no stylesheets are found, the importer should return `null`. + * + * Calling [[canonicalize]] multiple times with the same URL must return the + * same result. Calling [[canonicalize]] with a URL returned by a previous + * call to [[canonicalize]] must return that URL. + * + * Relative loads in stylesheets loaded from an importer are handled by + * resolving the loaded URL relative to the canonical URL of the stylesheet + * that contains it, and passing that URL back to the importer's + * [[canonicalize]] method. For example, suppose the "Resolving a Load" + * example {@link Importer | above} returned a stylesheet that contained + * `@use "mixins"`: + * + * - The compiler resolves the URL `mixins` relative to the current + * stylesheet's canonical URL `db:foo/bar/baz/_index.scss` to get + * `db:foo/bar/baz/mixins`. + * - It calls [[canonicalize]] with `"db:foo/bar/baz/mixins"`. + * - [[canonicalize]] returns `new URL("db:foo/bar/baz/_mixins.scss")`. + * + * Because of this, [[canonicalize]] must return a meaningful result when + * called with a URL relative to one returned by an earlier call to + * [[canonicalize]]. + * + * @param url - The loaded URL. Since this might be relative, it's represented + * as a string rather than a [[URL]] object. + * + * @param options.fromImport - Whether this is being invoked because of a Sass + * `@import` rule, as opposed to a `@use` or `@forward` rule. + * + * This should *only* be used for determining whether or not to load + * [import-only files](https://sass-lang.com/documentation/at-rules/import#import-only-files). + * + * @returns An absolute URL if this importer recognizes the `url`, or `null` + * if it doesn't. If this returns `null`, other importers or {@link + * Options.loadPaths | load paths} may handle the load. + * + * This may also return a `Promise`, but if it does the importer may only be + * passed to [[compileAsync]] and [[compileStringAsync]], not [[compile]] or + * [[compileString]]. + * + * @throws any - If this importer recognizes `url` but determines that it's + * invalid, it may throw an exception that will be wrapped by Sass. If the + * exception object has a `message` property, it will be used as the wrapped + * exception's message; otherwise, the exception object's `toString()` will be + * used. This means it's safe for importers to throw plain strings. + */ canonicalize( url: string, options: {fromImport: boolean} ): PromiseOr; + /** + * Loads the Sass text for the given `canonicalUrl`, or returns `null` if this + * importer can't find the stylesheet it refers to. + * + * @param canonicalUrl - The canonical URL of the stylesheet to load. This is + * guaranteed to come from a call to [[canonicalize]], although not every call + * to [[canonicalize]] will result in a call to [[load]]. + * + * @returns The contents of the stylesheet at `canonicalUrl` if it can be + * loaded, or `null` if it can't. + * + * This may also return a `Promise`, but if it does the importer may only be + * passed to [[compileAsync]] and [[compileStringAsync]], not [[compile]] or + * [[compileString]]. + * + * @throws any - If this importer finds a stylesheet at `url` but it fails to + * load for some reason, or if `url` is uniquely associated with this importer + * but doesn't refer to a real stylesheet, the importer may throw an exception + * that will be wrapped by Sass. If the exception object has a `message` + * property, it will be used as the wrapped exception's message; otherwise, + * the exception object's `toString()` will be used. This means it's safe for + * importers to throw plain strings. + */ load(canonicalUrl: URL): PromiseOr; + /** @hidden */ findFileUrl?: never; } +/** + * The result of successfully loading a stylesheet with an [[Importer]]. + * + * @category Importer + */ export interface ImporterResult { + /** The contents of the stylesheet. */ contents: string; + /** The syntax with which to parse [[contents]]. */ syntax: Syntax; + /** + * The URL to use to link to the loaded stylesheet's source code in source + * maps. A `file:` URL is ideal because it's accessible to both browsers and + * other build tools, but an `http:` URL is also acceptable. + * + * If this isn't set, it defaults to a `data:` URL that contains the contents + * of the loaded stylesheet. + */ sourceMapUrl?: URL; } diff --git a/js-api-doc/index.d.ts b/js-api-doc/index.d.ts index 4afcdd52..a86cce45 100644 --- a/js-api-doc/index.d.ts +++ b/js-api-doc/index.d.ts @@ -2,7 +2,6 @@ // written to provide user-facing documentation rather than to specify behavior for // implementations. -/** @hidden */ export { CompileResult, compile, @@ -10,22 +9,19 @@ export { compileString, compileStringAsync, } from './compile'; -/** @hidden */ export {Exception} from './exception'; -/** @hidden */ export {FileImporter, Importer, ImporterResult} from './importer'; export {Logger, SourceSpan, SourceLocation} from './logger'; -/** @hidden */ export { CustomFunction, Options, OutputStyle, StringOptions, + StringOptionsWithImporter, + StringOptionsWithoutImporter, Syntax, } from './options'; -/** @hidden */ export {PromiseOr} from './util/promise_or'; -/** @hidden */ export { ListSeparator, SassArgumentList, diff --git a/js-api-doc/legacy/exception.d.ts b/js-api-doc/legacy/exception.d.ts index 927d1c9f..30b54d5a 100644 --- a/js-api-doc/legacy/exception.d.ts +++ b/js-api-doc/legacy/exception.d.ts @@ -1,6 +1,11 @@ /** * The exception type thrown by [[renderSync]] and passed as the error to * [[render]]'s callback. + * + * @category Legacy + * @deprecated This is only thrown by the legacy [[render]] and [[renderSync]] + * APIs. Use [[compile]], [[compileString]], [[compileAsync]], and + * [[compileStringAsync]] instead. */ export interface LegacyException extends Error { /** diff --git a/js-api-doc/legacy/function.d.ts b/js-api-doc/legacy/function.d.ts index aeb74fc2..57ed85e2 100644 --- a/js-api-doc/legacy/function.d.ts +++ b/js-api-doc/legacy/function.d.ts @@ -28,6 +28,11 @@ import {LegacyPluginThis} from './plugin_this'; * that's passed to [[LegacySharedOptions.functions]]. If the signature [takes * arbitrary arguments](https://sass-lang.com/documentation/at-rules/function#taking-arbitrary-arguments), * they're passed as a single argument list in the last argument. + * + * @category Legacy + * @deprecated This only works with the legacy [[render]] and [[renderSync]] + * APIs. Use [[CustomFunction]] with [[compile]], [[compileString]], + * [[compileAsync]], and [[compileStringAsync]] instead. */ export type LegacySyncFunction = ( this: LegacyPluginThis, @@ -68,6 +73,11 @@ export type LegacySyncFunction = ( * arbitrary arguments](https://sass-lang.com/documentation/at-rules/function#taking-arbitrary-arguments), * they're passed as a single argument list in the last argument before the * callback. + * + * @category Legacy + * @deprecated This only works with the legacy [[render]] and [[renderSync]] + * APIs. Use [[CustomFunction]] with [[compile]], [[compileString]], + * [[compileAsync]], and [[compileStringAsync]] instead. */ export type LegacyAsyncFunction = ( this: LegacyPluginThis, @@ -81,6 +91,11 @@ export type LegacyAsyncFunction = ( * [[LegacyAsyncFunction]] which calls a callback with its result. * * See [[LegacySharedOptions.functions]] for more details. + * + * @category Legacy + * @deprecated This only works with the legacy [[render]] and [[renderSync]] + * APIs. Use [[CustomFunction]] with [[compile]], [[compileString]], + * [[compileAsync]], and [[compileStringAsync]] instead. */ export type LegacyFunction = sync extends 'async' ? LegacySyncFunction | LegacyAsyncFunction @@ -89,6 +104,11 @@ export type LegacyFunction = sync extends 'async' /** * A type representing all the possible values that may be passed to or returned * from a [[LegacyFunction]]. + * + * @category Legacy + * @deprecated This only works with the legacy [[render]] and [[renderSync]] + * APIs. Use [[Value]] with [[compile]], [[compileString]], [[compileAsync]], + * and [[compileStringAsync]] instead. */ export type LegacyValue = | types.Null @@ -99,7 +119,14 @@ export type LegacyValue = | types.List | types.Map; -/** The namespace for value types used in the legacy function API. */ +/** + * The namespace for value types used in the legacy function API. + * + * @category Legacy + * @deprecated This only works with the legacy [[render]] and [[renderSync]] + * APIs. Use [[Value]] with [[compile]], [[compileString]], [[compileAsync]], + * and [[compileStringAsync]] instead. + */ export namespace types { /** * The class for Sass's singleton [`null` diff --git a/js-api-doc/legacy/importer.d.ts b/js-api-doc/legacy/importer.d.ts index 60167e00..70ef843b 100644 --- a/js-api-doc/legacy/importer.d.ts +++ b/js-api-doc/legacy/importer.d.ts @@ -1,6 +1,13 @@ import {LegacyPluginThis} from './plugin_this'; -/** The value of `this` in the context of a [[LegacyImporter]] function. */ +/** + * The value of `this` in the context of a [[LegacyImporter]] function. + * + * @category Legacy + * @deprecated This is only used by the legacy [[render]] and [[renderSync]] + * APIs. Use [[Importer]] with [[compile]], [[compileString]], [[compileAsync]], + * and [[compileStringAsync]] instead. + */ interface LegacyImporterThis extends LegacyPluginThis { /** * Whether the importer is being invoked because of a Sass `@import` rule, as @@ -29,6 +36,11 @@ interface LegacyImporterThis extends LegacyPluginThis { * * * An [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) * object, indicating that importing failed. + * + * @category Legacy + * @deprecated This only works with the legacy [[render]] and [[renderSync]] + * APIs. Use [[ImporterResult]] with [[compile]], [[compileString]], + * [[compileAsync]], and [[compileStringAsync]] instead. */ export type LegacyImporterResult = | {file: string} @@ -71,6 +83,11 @@ export type LegacyImporterResult = * * If the stylesheet was loaded from an importer that returned its contents, * it’s the URL of the `@use` or `@import` rule that loaded it. * * If the stylesheet came from the data option, it’s the string "stdin". + * + * @category Legacy + * @deprecated This only works with the legacy [[render]] and [[renderSync]] + * APIs. Use [[Importer]] with [[compile]], [[compileString]], [[compileAsync]], + * and [[compileStringAsync]] instead. */ type LegacySyncImporter = ( this: LegacyImporterThis, @@ -118,6 +135,11 @@ type LegacySyncImporter = ( * * If the stylesheet came from the data option, it’s the string "stdin". * * @param done - The callback to call once the importer has finished running. + * + * @category Legacy + * @deprecated This only works with the legacy [[render]] and [[renderSync]] + * APIs. Use [[Importer]] with [[compile]], [[compileString]], [[compileAsync]], + * and [[compileStringAsync]] instead. */ type LegacyAsyncImporter = ( this: LegacyImporterThis, @@ -135,6 +157,11 @@ type LegacyAsyncImporter = ( * [[LegacyAsyncImporter]] which calls a callback with its result. * * See [[LegacySharedOptions.importer]] for more details. + * + * @category Legacy + * @deprecated This only works with the legacy [[render]] and [[renderSync]] + * APIs. Use [[Importer]] with [[compile]], [[compileString]], [[compileAsync]], + * and [[compileStringAsync]] instead. */ export type LegacyImporter = sync extends 'async' ? LegacySyncImporter | LegacyAsyncImporter diff --git a/js-api-doc/legacy/options.d.ts b/js-api-doc/legacy/options.d.ts index 0427cd94..e70ef9a0 100644 --- a/js-api-doc/legacy/options.d.ts +++ b/js-api-doc/legacy/options.d.ts @@ -9,6 +9,11 @@ import {LegacyFunction} from './function'; * @typeParam sync - This lets the TypeScript checker verify that * [[LegacyAsyncImporter]]s and [[LegacyAsyncFunction]]s aren't passed to * [[renderSync]]. + * + * @category Legacy + * @deprecated This only works with the legacy [[render]] and [[renderSync]] + * APIs. Use [[Options]] with [[compile]], [[compileString]], [[compileAsync]], + * and [[compileStringAsync]] instead. */ export interface LegacySharedOptions { /** @@ -157,7 +162,7 @@ export interface LegacySharedOptions { * } * }`; * - * const result = sass.renderSync({ + * let result = sass.renderSync({ * data: source, * outputStyle: "expanded" * }); @@ -218,7 +223,7 @@ export interface LegacySharedOptions { * @example * * ```js - * const result = sass.renderSync({ + * let result = sass.renderSync({ * file: "style.scss", * sourceMap: "out.map" * }) @@ -558,6 +563,11 @@ export interface LegacyFileOptions * @typeParam sync - This lets the TypeScript checker verify that * [[LegacyAsyncImporter]]s and [[LegacyAsyncFunction]]s aren't passed to * [[renderSync]]. + * + * @category Legacy + * @deprecated This only works with the legacy [[render]] and [[renderSync]] + * APIs. Use [[StringOptions]] with [[compile]], [[compileString]], + * [[compileAsync]], and [[compileStringAsync]] instead. */ export interface LegacyStringOptions extends LegacySharedOptions { @@ -621,6 +631,11 @@ export interface LegacyStringOptions * * See [[LegacySharedOptions]] for options that are shared across both file and * string inputs. + * + * @category Legacy + * @deprecated This only works with the legacy [[render]] and [[renderSync]] + * APIs. Use [[Options]] with [[compile]], [[compileString]], [[compileAsync]], + * and [[compileStringAsync]] instead. */ export type LegacyOptions = | LegacyFileOptions diff --git a/js-api-doc/legacy/plugin_this.d.ts b/js-api-doc/legacy/plugin_this.d.ts index 05be969d..d6c5e1db 100644 --- a/js-api-doc/legacy/plugin_this.d.ts +++ b/js-api-doc/legacy/plugin_this.d.ts @@ -1,6 +1,11 @@ /** * The value of `this` in the context of a [[LegacyImporter]] or * [[LegacyFunction]] callback. + * + * @category Legacy + * @deprecated This is only used by the legacy [[render]] and [[renderSync]] + * APIs. Use [[compile]], [[compileString]], [[compileAsync]], and + * [[compileStringAsync]] instead. */ export interface LegacyPluginThis { /** diff --git a/js-api-doc/legacy/render.d.ts b/js-api-doc/legacy/render.d.ts index fa3b7190..80028db1 100644 --- a/js-api-doc/legacy/render.d.ts +++ b/js-api-doc/legacy/render.d.ts @@ -4,6 +4,11 @@ import {LegacyOptions} from './options'; /** * The object returned by [[render]] and [[renderSync]] after a successful * compilation. + * + * @category Legacy + * @deprecated This is only used by the legacy [[render]] and [[renderSync]] + * APIs. Use [[compile]], [[compileString]], [[compileAsync]], and + * [[compileStringAsync]] instead. */ export interface LegacyResult { /** @@ -99,6 +104,9 @@ export interface LegacyResult { * const result = sass.renderSync({file: "style.scss"}); * // ... * ``` + * + * @category Legacy + * @deprecated Use [[compile]] or [[compileString]] instead. */ export function renderSync(options: LegacyOptions<'sync'>): LegacyResult; @@ -121,6 +129,9 @@ export function renderSync(options: LegacyOptions<'sync'>): LegacyResult; * // ... * }); * ``` + * + * @category Legacy + * @deprecated Use [[compileAsync]] or [[compileStringAsync]] instead. */ export function render( options: LegacyOptions<'async'>, diff --git a/js-api-doc/logger/index.d.ts b/js-api-doc/logger/index.d.ts index 5e233e62..aa9bcd09 100644 --- a/js-api-doc/logger/index.d.ts +++ b/js-api-doc/logger/index.d.ts @@ -30,6 +30,8 @@ export {SourceSpan} from './source_span'; * * fs.writeFileSync('log.txt', log); * ``` + * + * @category Logger */ export interface Logger { /** @@ -70,6 +72,7 @@ export interface Logger { /** * A namespace for built-in [[Logger]]s. * + * @category Logger * @compatibility dart: "1.43.0", node: false */ export namespace Logger { diff --git a/js-api-doc/logger/source_location.d.ts b/js-api-doc/logger/source_location.d.ts index 30de7922..1cf538b6 100644 --- a/js-api-doc/logger/source_location.d.ts +++ b/js-api-doc/logger/source_location.d.ts @@ -1,7 +1,21 @@ +/** + * A specific location within a source file. + * + * This is always associated with a [[SourceSpan]] which indicates *which* file + * it refers to. + * + * @category Logger + */ export interface SourceLocation { + /** + * The 0-based index of this location within its source file, in terms of + * UTF-16 code units. + */ offset: number; + /** The 0-based line number of this location. */ line: number; + /** The 0-based column number of this location. */ column: number; } diff --git a/js-api-doc/logger/source_span.d.ts b/js-api-doc/logger/source_span.d.ts index f7dfd59b..89d28932 100644 --- a/js-api-doc/logger/source_span.d.ts +++ b/js-api-doc/logger/source_span.d.ts @@ -2,14 +2,35 @@ import {URL} from 'url'; import {SourceLocation} from './source_location'; +/** + * A span of text within a source file. + * + * @category Logger + */ export interface SourceSpan { + /** The beginning of this span, inclusive. */ start: SourceLocation; + /** + * The end of this span, exclusive. + * + * If [[start]] and [[end]] refer to the same location, the span has zero + * length and refers to the point immediately after [[start]] and before the + * next character. + */ end: SourceLocation; + /** The canonical URL of the file this span refers to. */ url?: URL; + /** The text covered by the span. */ text: string; + /** + * Text surrounding the span. + * + * If this is set, it must include only whole lines, and it must include at + * least all line(s) which are partially covered by this span. + */ context?: string; } diff --git a/js-api-doc/options.d.ts b/js-api-doc/options.d.ts index 35df9605..a601356d 100644 --- a/js-api-doc/options.d.ts +++ b/js-api-doc/options.d.ts @@ -5,44 +5,406 @@ import {Logger} from './logger'; import {Value} from './value'; import {PromiseOr} from './util/promise_or'; +/** + * Syntaxes supported by Sass: + * + * - `'scss'` is the [SCSS + * syntax](https://sass-lang.com/documentation/syntax#scss). + * - `'indented'` is the [indented + * syntax](https://sass-lang.com/documentation/syntax#the-indented-syntax) + * - `'css'` is plain CSS, which is parsed like SCSS but forbids the use of any + * special Sass features. + * + * @category Options + */ export type Syntax = 'scss' | 'indented' | 'css'; +/** + * Possible output styles for the compiled CSS: + * + * - `"expanded"` (the default for Dart Sass) writes each selector and + * declaration on its own line. + * + * - `"compressed"` removes as many extra characters as possible, and writes + * the entire stylesheet on a single line. + * + * @category Options + */ export type OutputStyle = 'expanded' | 'compressed'; +/** + * A callback that implements a custom Sass function. This can be passed to + * [[Options.functions]]. + * + * ```js + * const result = sass.compile('style.scss', { + * functions: { + * "sum($arg1, $arg2)": (args) => { + * const value1 = args[0].assertNumber('arg1').value; + * const value2 = args[1].assertNumber('arg2') + * .convertValueToMatch(arg1, 'arg2', 'arg1'); + * return new sass.SassNumber(value1 + value2).coerceToMatch(arg1); + * } + * } + * }); + * ``` + * + * @typeParam sync - A `CustomFunction<'sync'>` must return synchronously, but + * in return it can be passed to [[compile]] and [[compileString]] in addition + * to [[compileAsync]] and [[compileStringAsync]]. + * + * A `CustomFunction<'async'>` may either return synchronously or + * asynchronously, but it can only be used with [[compileAsync]] and + * [[compileStringAsync]]. + * + * @param args - An array of arguments passed by the function's caller. If the + * function takes [arbitrary + * arguments](https://sass-lang.com/documentation/at-rules/function#taking-arbitrary-arguments), + * the last element will be a [[SassArgumentList]]. + * + * @returns The function's result. This may be in the form of a `Promise`, but + * if it is the function may only be passed to [[compileAsync]] and + * [[compileStringAsync]], not [[compile]] or [[compileString]]. + * + * @throws any - This function may throw an error, which the Sass compiler will + * treat as the function call failing. If the exception object has a `message` + * property, it will be used as the wrapped exception's message; otherwise, the + * exception object's `toString()` will be used. This means it's safe for custom + * functions to throw plain strings. + * + * @category Custom Function + */ export type CustomFunction = ( args: Value[] ) => PromiseOr; +/** + * Options that can be passed to [[compile]], [[compileAsync]], + * [[compileString]], or [[compileStringAsync]]. + * + * @typeParam sync - This lets the TypeScript checker verify that asynchronous + * [[Importer]]s, [[FileImporter]]s, and [[CustomFunction]]s aren't passed to + * [[compile]] or [[compileString]]. + * + * @category Options + */ export interface Options { + /** + * If this is `true`, the compiler will exclusively use ASCII characters in + * its error and warning messages. Otherwise, it may use non-ASCII Unicode + * characters as well. + * + * @defaultValue `false` + * @category Messages + */ alertAscii?: boolean; + /** + * If this is `true`, the compiler will use ANSI color escape codes in its + * error and warning messages. If it's `false`, it won't use these. If it's + * undefined, the compiler will determine whether or not to use colors + * depending on whether the user is using an interactive terminal. + * + * @category Messages + */ alertColor?: boolean; + /** + * Additional built-in Sass functions that are available in all stylesheets. + * This option takes an object whose keys are Sass function signatures like + * you'd write for the [`@function + * rule`](https://sass-lang.com/documentation/at-rules/function) and whose + * values are [[CustomFunction]]s. + * + * Functions are passed JavaScript representations of [Sass value + * types](https://sass-lang.com/documentation/js-api#value-types), and must + * return the same. + * + * When writing custom functions, it's important to make them as user-friendly + * and as close to the standards set by Sass's core functions as possible. Some + * good guidelines to follow include: + * + * * Use `Value.assert*` methods, like [[Value.assertString]], to cast untyped + * `Value` objects to more specific types. For values that were passed + * directly as arguments, pass in the argument name as well. This ensures + * that the user gets good error messages when they pass in the wrong type + * to your function. + * + * * Individual classes may have more specific `assert*` methods, like + * [[SassNumber.assertInt]], which should be used when possible. + * + * * In Sass, every value counts as a list. Rather than trying to detect the + * [[SassList]] type, you should use [[Value.asList]] to treat all values as + * lists. + * + * * When manipulating values like lists, strings, and numbers that have + * metadata (comma versus space separated, bracketed versus unbracketed, + * quoted versus unquoted, units), the output metadata should match the + * input metadata. + * + * * When in doubt, lists should default to comma-separated, strings should + * default to quoted, and numbers should default to unitless. + * + * * In Sass, lists and strings use one-based indexing and use negative + * indices to index from the end of value. Functions should follow these + * conventions. [[Value.sassIndexToListIndex]] and + * [[SassString.sassIndexToStringIndex]] can be used to do this + * automatically. + * + * * String indexes in Sass refer to Unicode code points while JavaScript + * string indices refer to UTF-16 code units. For example, the character + * U+1F60A SMILING FACE WITH SMILING EYES is a single Unicode code point but + * is represented in UTF-16 as two code units (`0xD83D` and `0xDE0A`). So in + * JavaScript, `"a😊b".charCodeAt(1)` returns `0xD83D`, whereas in Sass + * `str-slice("a😊b", 1, 1)` returns `"😊"`. Functions should follow Sass's + * convention. [[SassString.sassIndexToStringIndex]] can be used to do this + * automatically, and the [[SassString.sassLength]] getter can be used to + * access a string's length in code points. + * + * @example + * + * ```js + * sass.compileString(` + * h1 { + * font-size: pow(2, 5) * 1px; + * }`, { + * functions: { + * // Note: in real code, you should use `math.pow()` from the built-in + * // `sass:math` module. + * 'pow($base, $exponent)': function(args) { + * const base = args[0].assertNumber('base').assertNoUnits('base'); + * const exponent = + * args[1].assertNumber('exponent').assertNoUnits('exponent'); + * + * return new sass.SassNumber(Math.pow(base.value, exponent.value)); + * } + * } + * }); + * ``` + * + * @category Plugins + */ functions?: Record>; + /** + * Custom importers that control how Sass resolves loads from rules like + * [`@use`](https://sass-lang.com/documentation/at-rules/use) and + * [`@import`](https://sass-lang.com/documentation/at-rules/import). + * + * Loads are resolved by trying, in order: + * + * - The importer that was used to load the current stylesheet, with the + * loaded URL resolved relative to the current stylesheet's canonical URL. + * + * - Each [[Importer]] or [[FileImporter]] in [[importers]], in order. + * + * - Each load path in [[loadPaths]], in order. + * + * If none of these return a Sass file, the load fails and Sass throws an + * error. + * + * @category Plugins + */ importers?: (Importer | FileImporter)[]; + /** + * Paths in which to look for stylesheets loaded by rules like + * [`@use`](https://sass-lang.com/documentation/at-rules/use) and + * [`@import`](https://sass-lang.com/documentation/at-rules/import). + * + * A load path `loadPath` is equivalent to the following [[FileImporter]]: + * + * ```js + * { + * findFileUrl(url) { + * // Load paths only support relative URLs. + * if (/^[a-z]+:/i.test(url)) return null; + * return new URL(url, pathToFileURL(loadPath)); + * } + * } + * ``` + * + * @category Input + */ loadPaths?: string[]; + /** + * An object to use to handle warnings and/or debug messages from Sass. + * + * By default, Sass emits warnings and debug messages to standard error, but + * if [[Logger.warn]] or [[Logger.debug]] is set, this will invoke them + * instead. + * + * The special value [[Logger.silent]] can be used to easily silence all + * messages. + * + * @category Messages + */ logger?: Logger; + /** + * If this option is set to `true`, Sass won’t print warnings that are caused + * by dependencies. A “dependency” is defined as any file that’s loaded + * through [[loadPaths]] or [[importer]]. Stylesheets that are imported + * relative to the entrypoint are not considered dependencies. + * + * This is useful for silencing deprecation warnings that you can’t fix on + * your own. However, please also notify your dependencies of the deprecations + * so that they can get fixed as soon as possible! + * + * **Heads up!** If [[compileString]] or [[compileStringAsync]] is called + * without [[StringWithoutImporter.url]], all stylesheets it loads + * will be considered dependencies. Since it doesn’t have a path of its own, + * everything it loads is coming from a load path rather than a relative + * import. + * + * @defaultValue `false` + * @category Messages + */ quietDeps?: boolean; + /** + * Whether or not Sass should generate a source map. If it does, the source + * map will be available as [[CompileResult.sourceMap]]. + * + * **Heads up!** Sass doesn't automatically add a `sourceMappingURL` comment + * to the generated CSS. It's up to callers to do that, since callers have + * full knowledge of where the CSS and the source map will exist in relation + * to one another and how they'll be served to the browser. + * + * @defaultValue `false` + * @category Output + */ sourceMap?: boolean; + /** + * The [[OutputStyle]] of the compiled CSS. + * + * @example + * + * ```js + * const source = ` + * h1 { + * font-size: 40px; + * code { + * font-face: Roboto Mono; + * } + * }`; + * + * let result = sass.compileString(source, {style: "expanded"}); + * console.log(result.css.toString()); + * // h1 { + * // font-size: 40px; + * // } + * // h1 code { + * // font-face: Roboto Mono; + * // } + * + * result = sass.compileString(source, {style: "compressed"}) + * console.log(result.css.toString()); + * // h1{font-size:40px}h1 code{font-face:Roboto Mono} + * ``` + * + * @category Output + */ style?: OutputStyle; + /** + * By default, Dart Sass will print only five instances of the same + * deprecation warning per compilation to avoid deluging users in console + * noise. If you set `verbose` to `true`, it will instead print every + * deprecation warning it encounters. + * + * @defaultValue `false` + * @category Messages + */ verbose?: boolean; } -export type StringOptions = Options & { +/** + * Options that can be passed to [[compileString]] or [[compileStringAsync]]. + * + * If the [[StringOptionsWithImporter.importer]] field isn't passed, the + * entrypoint file can't load files relative to itself and the [[url]] field is + * optional. + * + * @typeParam sync - This lets the TypeScript checker verify that asynchronous + * [[Importer]]s, [[FileImporter]]s, and [[CustomFunction]]s aren't passed to + * [[compile]] or [[compileString]]. + * + * @category Options + */ +export interface StringOptionsWithoutImporter + extends Options { + /** + * The [[Syntax]] to use to parse the entrypoint stylesheet. + * + * @default `'scss'` + * + * @category Input + */ syntax?: Syntax; -} & ( - | { - url?: URL; - } - | { - importer: Importer | FileImporter; - url: URL; - } - ); + + /** + * The canonical URL of the entrypoint stylesheet. If this isn't passed along + * with [[StringOptionsWithoutImporter.importer]], it's optional and only used + * for error reporting. + * + * @category Input + */ + url?: URL; +} + +/** + * Options that can be passed to [[compileString]] or [[compileStringAsync]]. + * + * If the [[StringOptionsWithImporter.importer]] field is passed, the entrypoint + * file uses it to load files relative to itself and the [[url]] field is + * mandatory. + * + * @typeParam sync - This lets the TypeScript checker verify that asynchronous + * [[Importer]]s, [[FileImporter]]s, and [[CustomFunction]]s aren't passed to + * [[compile]] or [[compileString]]. + * + * @category Options + */ +export interface StringOptionsWithImporter + extends StringOptionsWithoutImporter { + /** + * The importer to use to handle loads that are relative to the entrypoint + * stylesheet. + * + * A relative load's URL is first resolved relative to [[url]], then passed to + * [[importer]]. If the importer doesn't recognize it, it's then passed to + * [[importers]] and [[loadPaths]]. + * + * @category Input + */ + importer: Importer | FileImporter; + + /** + * The canonical URL of the entrypoint stylesheet. If this is passed along + * with [[importer]], it's used to resolve relative loads in the entrypoint + * stylesheet. + * + * @category Input + */ + url: URL; +} + +/** + * Options that can be passed to [[compileString]] or [[compileStringAsync]]. + * + * This is a [[StringOptionsWithImporter]] if it has a + * [[StringOptionsWithImporter.importer]] field, and a + * [[StringOptionsWithoutImporter]] otherwise. + * + * @typeParam sync - This lets the TypeScript checker verify that asynchronous + * [[Importer]]s, [[FileImporter]]s, and [[CustomFunction]]s aren't passed to + * [[compile]] or [[compileString]]. + * + * @category Options + */ +export type StringOptions = + | StringOptionsWithImporter + | StringOptionsWithoutImporter; diff --git a/js-api-doc/util/promise_or.d.ts b/js-api-doc/util/promise_or.d.ts index 1c473f54..d597a6a5 100644 --- a/js-api-doc/util/promise_or.d.ts +++ b/js-api-doc/util/promise_or.d.ts @@ -1,7 +1,17 @@ /** * A utility type for choosing between synchronous and asynchronous return * values. + * + * This is used as the return value for plugins like [[CustomFunction]], + * [[Importer]], and [[FileImporter]] so that TypeScript enforces that + * asynchronous plugins are only passed to [[compileAsync]] and + * [[compileStringAsync]], not [[compile]] or [[compileString]]. + * + * @typeParam sync - If this is `'sync'`, this can only be a `T`. If it's + * `'async'`, this can be either a `T` or a `Promise`. + * + * @category Other */ -export type PromiseOr = sync extends 'sync' - ? T - : T | Promise; +export type PromiseOr = sync extends 'async' + ? T | Promise + : T; diff --git a/js-api-doc/value/argument_list.d.ts b/js-api-doc/value/argument_list.d.ts index c05424f9..98576fe8 100644 --- a/js-api-doc/value/argument_list.d.ts +++ b/js-api-doc/value/argument_list.d.ts @@ -3,13 +3,45 @@ import {List, OrderedMap} from 'immutable'; import {Value} from './index'; import {SassList, ListSeparator} from './list'; +/** + * Sass's [argument list + * type](https://sass-lang.com/documentation/values/lists#argument-lists). + * + * An argument list comes from a rest argument. It's distinct from a normal + * [[SassList]] in that it may contain a keyword map as well as the positional + * arguments. + * + * @category Custom Function + */ export class SassArgumentList extends SassList { + /** + * Creates a new argument list. + * + * @param contents - The positional arguments that make up the primary + * contents of the list. This may be either a plain JavaScript array or an + * immutable [[List]] from the [`immutable` + * package](https://immutable-js.com/). + * + * @param keywords - The keyword arguments attached to this argument list, + * whose names should exclude `$`. This can be either a plain JavaScript + * object with argument names as fields, or an immutable [[OrderedMap]] from + * the [`immutable` package](https://immutable-js.com/) + * + * @param separator - The separator for this list. Defaults to `','`. + */ constructor( contents: Value[] | List, keywords: Record | OrderedMap, - /** @default ',' */ separator?: ListSeparator ); + /** + * The keyword arguments attached to this argument list. + * + * The argument names don't include `$`. + * + * @returns An immutable [[OrderedMap]] from the [`immutable` + * package](https://immutable-js.com/). + */ get keywords(): OrderedMap; } diff --git a/js-api-doc/value/boolean.d.ts b/js-api-doc/value/boolean.d.ts index a1b38921..b3f3af72 100644 --- a/js-api-doc/value/boolean.d.ts +++ b/js-api-doc/value/boolean.d.ts @@ -1,9 +1,29 @@ import {Value} from './index'; +/** + * Sass's [`true` value](https://sass-lang.com/documentation/values/booleans). + * + * @category Custom Function + */ export const sassTrue: SassBoolean; +/** + * Sass's [`false` value](https://sass-lang.com/documentation/values/booleans). + * + * @category Custom Function + */ export const sassFalse: SassBoolean; -export interface SassBoolean extends Value { +/** + * Sass's [boolean type](https://sass-lang.com/documentation/values/booleans). + * + * @category Custom Function + */ +export class SassBoolean extends Value { + private constructor(); + + /** + * Whether this value is `true` or `false`. + */ get value(): boolean; } diff --git a/js-api-doc/value/color.d.ts b/js-api-doc/value/color.d.ts index 341928c6..383f4649 100644 --- a/js-api-doc/value/color.d.ts +++ b/js-api-doc/value/color.d.ts @@ -1,6 +1,20 @@ import {Value} from './index'; +/** + * Sass's [color type](https://sass-lang.com/documentation/values/colors). + * + * No matter what representation was originally used to create this color, all + * of its channels are accessible. + * + * @category Custom Function + */ export class SassColor extends Value { + /** + * Creates an RGB color. + * + * @throws `Error` if `red`, `green`, and `blue` aren't between `0` and + * `255`, or if `alpha` isn't between `0` and `1`. + */ constructor(options: { red: number; green: number; @@ -8,6 +22,12 @@ export class SassColor extends Value { alpha?: number; }); + /** + * Creates an HSL color. + * + * @throws `Error` if `saturation` or `lightness` aren't between `0` and + * `100`, or if `alpha` isn't between `0` and `1`. + */ constructor(options: { hue: number; saturation: number; @@ -15,6 +35,12 @@ export class SassColor extends Value { alpha?: number; }); + /** + * Creates an HWB color. + * + * @throws `Error` if `whiteness` or `blackness` aren't between `0` and `100`, + * or if `alpha` isn't between `0` and `1`. + */ constructor(options: { hue: number; whiteness: number; @@ -22,24 +48,36 @@ export class SassColor extends Value { alpha?: number; }); + /** This color's red channel, between `0` and `255`. */ get red(): number; + /** This color's green channel, between `0` and `255`. */ get green(): number; + /** This color's blue channel, between `0` and `255`. */ get blue(): number; + /** This color's hue, between `0` and `360`. */ get hue(): number; + /** This color's saturation, between `0` and `100`. */ get saturation(): number; + /** This color's lightness, between `0` and `100`. */ get lightness(): number; + /** This color's whiteness, between `0` and `100`. */ get whiteness(): number; + /** This color's blackness, between `0` and `100`. */ get blackness(): number; + /** This color's alpha channel, between `0` and `1`. */ get alpha(): number; + /** + * Changes one or more of this color's RGB channels and returns the result. + */ change(options: { red?: number; green?: number; @@ -47,6 +85,9 @@ export class SassColor extends Value { alpha?: number; }): SassColor; + /** + * Changes one or more of this color's HSL channels and returns the result. + */ change(options: { hue?: number; saturation?: number; @@ -54,6 +95,9 @@ export class SassColor extends Value { alpha?: number; }): SassColor; + /** + * Changes one or more of this color's HWB channels and returns the result. + */ change(options: { hue?: number; whiteness?: number; diff --git a/js-api-doc/value/function.d.ts b/js-api-doc/value/function.d.ts index 22aa5dbb..1751c7a9 100644 --- a/js-api-doc/value/function.d.ts +++ b/js-api-doc/value/function.d.ts @@ -1,5 +1,22 @@ import {Value} from './index'; +/** + * Sass's [function type](https://sass-lang.com/documentation/values/functions). + * + * **Heads up!** Although first-class Sass functions can be processed by custom + * functions, there's no way to invoke them outside of a Sass stylesheet. + * + * @category Custom Function + */ export class SassFunction extends Value { + /** + * Creates a new first-class function that can be invoked using + * [`meta.call()`](https://sass-lang.com/documentation/modules/meta#call). + * + * @param signature - The function signature, like you'd write for the + * [`@function rule`](https://sass-lang.com/documentation/at-rules/function). + * @param callback - The callback that's invoked when this function is called, + * just like for a [[CustomFunction]]. + */ constructor(signature: string, callback: (args: Value[]) => Value); } diff --git a/js-api-doc/value/index.d.ts b/js-api-doc/value/index.d.ts index a06f62c7..8d532f12 100644 --- a/js-api-doc/value/index.d.ts +++ b/js-api-doc/value/index.d.ts @@ -17,42 +17,157 @@ export {SassMap} from './map'; export {SassNumber} from './number'; export {SassString} from './string'; +/** + * Sass's [`null` value](https://sass-lang.com/documentation/values/null). + * + * @category Custom Function + */ export const sassNull: Value; +/** + * The abstract base class of Sass's value types. + * + * This is passed to and returned by [[CustomFunction]]s, which are passed into + * the Sass implementation using [[Options.functions]]. + * + * @category Custom Function + */ export abstract class Value implements ValueObject { protected constructor(); + /** + * This value as a list. + * + * All SassScript values can be used as lists. Maps count as lists of pairs, + * and all other values count as single-value lists. + * + * @returns An immutable [[List]] from the [`immutable` + * package](https://immutable-js.com/). + */ get asList(): List; + /** + * Whether this value as a list has brackets. + * + * All SassScript values can be used as lists. Maps count as lists of pairs, + * and all other values count as single-value lists. + */ get hasBrackets(): boolean; + /** + * Whether the value counts as `true` in an `@if` statement and other + * contexts. + */ get isTruthy(): boolean; + /** + * Returns JavaScript's `null` value if this is [[sassNull]], and returns + * `this` otherwise. + */ get realNull(): null | Value; + /** + * The separator for this value as a list. + * + * All SassScript values can be used as lists. Maps count as lists of pairs, + * and all other values count as single-value lists. + */ get separator(): ListSeparator; + /** + * Converts `sassIndex` into a JavaScript-style index into the list returned + * by [[asList]]. + * + * Sass indexes are one-based, while JavaScript indexes are zero-based. Sass + * indexes may also be negative in order to index from the end of the list. + * + * @param sassIndex - The Sass-style index into this as a list. + * @param name - The name of the function argument `sassIndex` came from + * (without the `$`) if it came from an argument. Used for error reporting. + * @throws `Error` If `sassIndex` isn't a number, if that number isn't an + * integer, or if that integer isn't a valid index for [[asList]]. + */ sassIndexToListIndex(sassIndex: Value, name?: string): number; + /** + * Returns the value at index `index` in this value as a list, or `undefined` + * if `index` isn't valid for this list. + * + * All SassScript values can be used as lists. Maps count as lists of pairs, + * and all other values count as single-value lists. + * + * This is a shorthand for `this.asList.get(index)`, although it may be more + * efficient in some cases. + * + * **Heads up!** This method uses the same indexing conventions as the + * `immutable` package: unlike Sass the index of the first element is 0, but + * like Sass negative numbers index from the end of the list. + */ get(index: number): Value | undefined; + /** + * Throws if `this` isn't a [[SassBoolean]]. + * + * **Heads up!** Functions should generally use [[isTruthy]] rather than + * requiring a literal boolean. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ assertBoolean(name?: string): SassBoolean; + /** + * Throws if `this` isn't a [[SassColor]]. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ assertColor(name?: string): SassColor; + /** + * Throws if `this` isn't a [[SassFunction]]. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ assertFunction(name?: string): SassFunction; + /** + * Throws if `this` isn't a [[SassMap]]. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ assertMap(name?: string): SassMap; + /** + * Throws if `this` isn't a [[SassNumber]]. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ assertNumber(name?: string): SassNumber; + /** + * Throws if `this` isn't a [[SassString]]. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ assertString(name?: string): SassString; + /** + * Returns `this` as a map if it counts as one (empty lists count as empty + * maps) or `null` if it doesn't. + */ tryMap(): SassMap | null; + /** Returns whether `this` represents the same value as `other`. */ equals(other: Value): boolean; + /** Returns a hash code that can be used to store `this` in a hash map. */ hashCode(): number; + /** @hidden */ toString(): string; } diff --git a/js-api-doc/value/list.d.ts b/js-api-doc/value/list.d.ts index 190c846e..bf36d3ae 100644 --- a/js-api-doc/value/list.d.ts +++ b/js-api-doc/value/list.d.ts @@ -2,19 +2,53 @@ import {List} from 'immutable'; import {Value} from './index'; +/** + * Possible separators used by Sass lists. The special separator `null` is only + * used for lists with fewer than two elements, and indicates that the separator + * has not yet been decided for this list. + * + * @category Custom Function + */ export type ListSeparator = ',' | '/' | ' ' | null; +/** + * Sass's [list type](https://sass-lang.com/documentation/values/lists). + * + * @category Custom Function + */ export class SassList extends Value { + /** + * Creates a new list. + * + * @param contents - The contents of the list. This may be either a plain + * JavaScript array or an immutable [[List]] from the [`immutable` + * package](https://immutable-js.com/). + * + * @param options.separator - The separator to use between elements of this + * list. Defaults to `','`. + * + * @param options.brackets - Whether the list has square brackets. Defaults to + * `false`. + */ constructor( contents: Value[] | List, options?: { - /** @default ',' */ separator?: ListSeparator; brackets?: boolean; } ); + /** + * Creates an empty list. + * + * @param options.separator - The separator to use between elements of this + * list. Defaults to `','`. + * + * @param options.brackets - Whether the list has square brackets. Defaults to + * `false`. + */ constructor(options?: {separator?: ListSeparator; brackets?: boolean}); + /** @hidden */ get separator(): ListSeparator; } diff --git a/js-api-doc/value/map.d.ts b/js-api-doc/value/map.d.ts index 8dccc1e5..2aebebd3 100644 --- a/js-api-doc/value/map.d.ts +++ b/js-api-doc/value/map.d.ts @@ -3,14 +3,39 @@ import {OrderedMap} from 'immutable'; import {SassList} from './list'; import {Value} from './index'; +/** + * Sass's [map type](https://sass-lang.com/documentation/values/maps). + * + * @category Custom Function + */ export class SassMap extends Value { + /** + * Creates a new map. + * + * @param contents - The contents of the map. This is an immutable + * [[OrderedMap]] from the [`immutable` package](https://immutable-js.com/). + * Defaults to an empty map. + */ constructor(contents?: OrderedMap); + /** + * Returns the contents of this map as an immutable [[OrderedMap]] from the + * [`immutable` package](https://immutable-js.com/). + */ get contents(): OrderedMap; + /** + * Returns the value associated with `key` in this map, or `undefined` if + * `key` isn't in the map. + * + * This is a shorthand for `this.contents.get(key)`, although it may be more + * efficient in some cases. + */ get(key: Value): Value | undefined; + /** Inherited from [[Value.get]]. */ get(index: number): SassList | undefined; + /** @hidden */ tryMap(): SassMap; } diff --git a/js-api-doc/value/number.d.ts b/js-api-doc/value/number.d.ts index a9555537..ced9887a 100644 --- a/js-api-doc/value/number.d.ts +++ b/js-api-doc/value/number.d.ts @@ -2,7 +2,33 @@ import {List} from 'immutable'; import {Value} from './index'; +/** + * Sass's [number type](https://sass-lang.com/documentation/values/numbers). + * + * @category Custom Function + */ export class SassNumber extends Value { + /** + * Creates a new number with more complex units than just a single numerator. + * + * Upon construction, any compatible numerator and denominator units are + * simplified away according to the conversion factor between them. + * + * @param value - The number's numeric value. + * + * @param unit - If this is a string, it's used as the single numerator unit + * for the number. + * + * @param unit.numeratorUnits - If passed, these are the numerator units to + * use for the number. This may be either a plain JavaScript array or an + * immutable [[List]] from the [`immutable` + * package](https://immutable-js.com/). + * + * @param unit.denominatorUnits - If passed, these are the denominator units + * to use for the number. This may be either a plain JavaScript array or an + * immutable [[List]] from the [`immutable` + * package](https://immutable-js.com/). + */ constructor( value: number, unit?: @@ -13,72 +39,264 @@ export class SassNumber extends Value { } ); + /** This number's numeric value. */ get value(): number; + /** Whether [[value]] is an integer according to Sass's equality logic. */ get isInt(): boolean; + /** + * If [[value]] is an integer according to [[isInt]], returns [[value]] + * rounded to that integer. If it's not an integer, returns `null`. + */ get asInt(): number | null; + /** + * This number's numerator units as an immutable [[List]] from the + * [`immutable` package](https://immutable-js.com/). + */ get numeratorUnits(): List; + /** + * This number's denominator units as an immutable [[List]] from the + * [`immutable` package](https://immutable-js.com/). + */ get denominatorUnits(): List; + /** Whether this number has any numerator or denominator units. */ get hasUnits(): boolean; + /** + * If [[value]] is an integer according to [[isInt]], returns it rounded to + * that integer. Otherwise, throws an error. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ assertInt(name?: string): number; + /** + * Returns [[value]] if it's within `min` and `max`. If [[value]] is equal to + * `min` or `max` according to Sass's equality, returns `min` or `max` + * respectively. Otherwise, throws an error. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ assertInRange(min: number, max: number, name?: string): number; + /** + * If this number has no units, returns it. Otherwise, throws an error. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ assertNoUnits(name?: string): SassNumber; + /** + * If this number has `unit` as its only unit (and as a numerator), returns + * this number. Otherwise, throws an error. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ assertUnit(unit: string, name?: string): SassNumber; + /** Whether this number has `unit` as its only unit (and as a numerator). */ hasUnit(unit: string): boolean; + /** + * Whether this has exactly one numerator unit, and that unit is compatible + * with `unit`. + */ compatibleWithUnit(unit: string): boolean; + /** + * Returns a copy of this number, converted to the units represented by + * `newNumerators` and `newDenominators`. + * + * @throws `Error` if this number's units are incompatible with + * `newNumerators` and `newDenominators`; or if this number is unitless and + * either `newNumerators` or `newDenominators` are not empty, or vice-versa. + * + * @param newNumerators - The numerator units to convert this number to. This + * may be either a plain JavaScript array or an immutable [[List]] from the + * [`immutable` package](https://immutable-js.com/). + * + * @param newDenominators - The denominator units to convert this number to. + * This may be either a plain JavaScript array or an immutable [[List]] from + * the [`immutable` package](https://immutable-js.com/). + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ convert( newNumerators: string[] | List, newDenominators: string[] | List, name?: string ): SassNumber; + /** + * Returns a copy of this number, converted to the same units as `other`. + * + * @throws `Error` if this number's units are incompatible with `other`'s + * units, or if either number is unitless but the other is not. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + * + * @param otherName - The name of the function argument `other` came from + * (without the `$`) if it came from an argument. Used for error reporting. + */ convertToMatch( other: SassNumber, name?: string, otherName?: string ): SassNumber; + /** + * Returns [[value]], converted to the units represented by `newNumerators` + * and `newDenominators`. + * + * @throws `Error` if this number's units are incompatible with + * `newNumerators` and `newDenominators`; or if this number is unitless and + * either `newNumerators` or `newDenominators` are not empty, or vice-versa. + * + * @param newNumerators - The numerator units to convert [[value]] to. This + * may be either a plain JavaScript array or an immutable [[List]] from the + * [`immutable` package](https://immutable-js.com/). + * + * @param newDenominators - The denominator units to convert [[value]] to. + * This may be either a plain JavaScript array or an immutable [[List]] from + * the [`immutable` package](https://immutable-js.com/). + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ convertValue( newNumerators: string[] | List, newDenominators: string[] | List, name?: string ): number; + /** + * Returns [[value]], converted to the same units as `other`. + * + * @throws `Error` if this number's units are incompatible with `other`'s + * units, or if either number is unitless but the other is not. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + * + * @param otherName - The name of the function argument `other` came from + * (without the `$`) if it came from an argument. Used for error reporting. + */ convertValueToMatch( other: SassNumber, name?: string, otherName?: string ): number; + /** + * Returns a copy of this number, converted to the units represented by + * `newNumerators` and `newDenominators`. + * + * Unlike [[convert]] this does *not* throw an error if this number is + * unitless and either `newNumerators` or `newDenominators` are not empty, or + * vice-versa. Instead, it treats all unitless numbers as convertible to and + * from all units without changing the value. + * + * @throws `Error` if this number's units are incompatible with + * `newNumerators` and `newDenominators`. + * + * @param newNumerators - The numerator units to convert this number to. This + * may be either a plain JavaScript array or an immutable [[List]] from the + * [`immutable` package](https://immutable-js.com/). + * + * @param newDenominators - The denominator units to convert this number to. + * This may be either a plain JavaScript array or an immutable [[List]] from + * the [`immutable` package](https://immutable-js.com/). + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ coerce( newNumerators: string[] | List, newDenominators: string[] | List, name?: string ): SassNumber; + /** + * Returns a copy of this number, converted to the units represented by + * `newNumerators` and `newDenominators`. + * + * Unlike [[convertToMatch]] this does *not* throw an error if this number is + * unitless and either `newNumerators` or `newDenominators` are not empty, or + * vice-versa. Instead, it treats all unitless numbers as convertible to and + * from all units without changing the value. + * + * @throws `Error` if this number's units are incompatible with `other`'s + * units. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + * + * @param otherName - The name of the function argument `other` came from + * (without the `$`) if it came from an argument. Used for error reporting. + */ coerceToMatch( other: SassNumber, name?: string, otherName?: string ): SassNumber; + /** + * Returns [[value]], converted to the units represented by `newNumerators` and + * `newDenominators`. + * + * Unlike [[convertValue]] this does *not* throw an error if this number is + * unitless and either `newNumerators` or `newDenominators` are not empty, or + * vice-versa. Instead, it treats all unitless numbers as convertible to and + * from all units without changing the value. + * + * @throws `Error` if this number's units are incompatible with + * `newNumerators` and `newDenominators`. + * + * @param newNumerators - The numerator units to convert [[value]] to. This + * may be either a plain JavaScript array or an immutable [[List]] from the + * [`immutable` package](https://immutable-js.com/). + * + * @param newDenominators - The denominator units to convert [[value]] to. + * This may be either a plain JavaScript array or an immutable [[List]] from + * the [`immutable` package](https://immutable-js.com/). + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + */ coerceValue( newNumerators: string[] | List, newDenominators: string[] | List, name?: string ): number; + /** + * Returns [[value]], converted to the units represented by `newNumerators` + * and `newDenominators`. + * + * Unlike [[convertValueToMatch]] this does *not* throw an error if this + * number is unitless and either `newNumerators` or `newDenominators` are not + * empty, or vice-versa. Instead, it treats all unitless numbers as + * convertible to and from all units without changing the value. + * + * @throws `Error` if this number's units are incompatible with `other`'s + * units. + * + * @param name - The name of the function argument `this` came from (without + * the `$`) if it came from an argument. Used for error reporting. + * + * @param otherName - The name of the function argument `other` came from + * (without the `$`) if it came from an argument. Used for error reporting. + */ coerceValueToMatch( other: SassNumber, name?: string, diff --git a/js-api-doc/value/string.d.ts b/js-api-doc/value/string.d.ts index 1843bbd9..592e098c 100644 --- a/js-api-doc/value/string.d.ts +++ b/js-api-doc/value/string.d.ts @@ -1,21 +1,84 @@ import {Value} from './index'; +/** + * Sass's [string type](https://sass-lang.com/documentation/values/strings). + * + * @category Custom Function + */ export class SassString extends Value { + /** + * Creates a new string. + * + * @param text - The contents of the string. For quoted strings, this is the + * semantic content—any escape sequences that were been written in the source + * text are resolved to their Unicode values. For unquoted strings, though, + * escape sequences are preserved as literal backslashes. + * + * @param options.quotes - Whether the string is quoted. Defaults to `true`. + */ constructor( text: string, options?: { - /** @default true */ quotes?: boolean; } ); + /** + * Creates an empty string. + * + * @param options.quotes - Whether the string is quoted. Defaults to `true`. + */ constructor(options?: {quotes?: boolean}); + /** + * The contents of the string. + * + * For quoted strings, this is the semantic content—any escape sequences that + * were been written in the source text are resolved to their Unicode values. + * For unquoted strings, though, escape sequences are preserved as literal + * backslashes. + * + * This difference allows us to distinguish between identifiers with escapes, + * such as `url\u28 http://example.com\u29`, and unquoted strings that contain + * characters that aren't valid in identifiers, such as + * `url(http://example.com)`. Unfortunately, it also means that we don't + * consider `foo` and `f\6F\6F` the same string. + */ get text(): string; + /** Whether this string has quotes. */ get hasQuotes(): boolean; + /** + * Sass's notion of this string's length. + * + * Sass treats strings as a series of Unicode code points while JavaScript + * treats them as a series of UTF-16 code units. For example, the character + * U+1F60A SMILING FACE WITH SMILING EYES is a single Unicode code point but + * is represented in UTF-16 as two code units (`0xD83D` and `0xDE0A`). So in + * JavaScript, `"n😊b".length` returns `4`, whereas in Sass + * `string.length("n😊b")` returns `3`. + */ get sassLength(): number; + /** + * Converts `sassIndex` to a JavaScript index into [[text]]. + * + * Sass indices are one-based, while JavaScript indices are zero-based. Sass + * indices may also be negative in order to index from the end of the string. + * + * In addition, Sass indices refer to Unicode code points while JavaScript + * string indices refer to UTF-16 code units. For example, the character + * U+1F60A SMILING FACE WITH SMILING EYES is a single Unicode code point but + * is represented in UTF-16 as two code units (`0xD83D` and `0xDE0A`). So in + * JavaScript, `"n😊b".charCodeAt(1)` returns `0xD83D`, whereas in Sass + * `string.slice("n😊b", 1, 1)` returns `"😊"`. + * + * This function converts Sass's code point indices to JavaScript's code unit + * indices. This means it's O(n) in the length of `text`. + * + * @throws `Error` - If `sassIndex` isn't a number, if that number isn't an + * integer, or if that integer isn't a valid index for this string. + */ sassIndexToStringIndex(sassIndex: Value, name?: string): number; } diff --git a/spec/js-api/compile.d.ts b/spec/js-api/compile.d.ts index efd302b2..f6e535bc 100644 --- a/spec/js-api/compile.d.ts +++ b/spec/js-api/compile.d.ts @@ -6,7 +6,9 @@ import {Options, StringOptions} from './options'; /** The object returned by the compiler when a Sass compilation succeeds. */ export interface CompileResult { css: string; + loadedUrls: URL[]; + sourceMap?: RawSourceMap; } diff --git a/spec/js-api/exception.d.ts b/spec/js-api/exception.d.ts index 5e9cc712..98c70d02 100644 --- a/spec/js-api/exception.d.ts +++ b/spec/js-api/exception.d.ts @@ -6,6 +6,8 @@ import {SourceSpan} from './logger'; * argument verification errors. */ export class Exception extends Error { + private constructor(); + /** * The compiler supplies this error message to the JS runtime. This should * contain the description of the Sass exception as well as human-friendly @@ -23,7 +25,7 @@ export class Exception extends Error { * * > The format can vary from implementation to implementation. */ - sassMessage: string; + readonly sassMessage: string; /** * A human-friendly representation of the loads, function calls, and mixin @@ -31,7 +33,7 @@ export class Exception extends Error { * * > The format can vary from implementation to implementation. */ - sassStack: string; + readonly sassStack: string; /** * A span whose `url` is the canonical URL of the stylesheet being parsed or @@ -43,7 +45,7 @@ export class Exception extends Error { * > that this covers a span of text that clearly indicates the location of * > the error. */ - span: SourceSpan; + readonly span: SourceSpan; /** * Provides a formatted string with useful information about the error. diff --git a/spec/js-api/index.d.ts b/spec/js-api/index.d.ts index 63c8da1b..64d280ee 100644 --- a/spec/js-api/index.d.ts +++ b/spec/js-api/index.d.ts @@ -45,6 +45,8 @@ export { Options, OutputStyle, StringOptions, + StringOptionsWithImporter, + StringOptionsWithoutImporter, Syntax, } from './options'; export {PromiseOr} from './util/promise_or'; diff --git a/spec/js-api/options.d.ts b/spec/js-api/options.d.ts index f9a4887f..ce3fc977 100644 --- a/spec/js-api/options.d.ts +++ b/spec/js-api/options.d.ts @@ -121,23 +121,28 @@ export interface Options { verbose?: boolean; } -/** Additional options specific to compiling from a string. */ -export type StringOptions = Options & { +export interface StringOptionsWithoutImporter + extends Options { /** * The compiler must parse `source` using this syntax. * * @default 'scss' */ syntax?: Syntax; -} & ( - | { - /** The canonical URL of the entrypoint. */ - url?: URL; - } - | { - /** The importer to use to resolve relative imports in the entrypoint. */ - importer: Importer | FileImporter; - /** The canonical URL of the entrypoint. */ - url: URL; - } - ); + + /** When `importer` isn't passed, this is purely advisory. */ + url?: URL; +} + +export interface StringOptionsWithImporter + extends StringOptionsWithoutImporter { + /** The importer to use to resolve relative imports in the entrypoint. */ + importer: Importer | FileImporter; + + /** The canonical URL of the entrypoint. */ + url: URL; +} + +export type StringOptions = + | StringOptionsWithImporter + | StringOptionsWithoutImporter; diff --git a/spec/js-api/util/promise_or.d.ts b/spec/js-api/util/promise_or.d.ts index 1c473f54..5d20bbe4 100644 --- a/spec/js-api/util/promise_or.d.ts +++ b/spec/js-api/util/promise_or.d.ts @@ -2,6 +2,6 @@ * A utility type for choosing between synchronous and asynchronous return * values. */ -export type PromiseOr = sync extends 'sync' - ? T - : T | Promise; +export type PromiseOr = sync extends 'async' + ? T | Promise + : T; diff --git a/spec/js-api/value/boolean.d.ts b/spec/js-api/value/boolean.d.ts index 349ff92e..0b795fdb 100644 --- a/spec/js-api/value/boolean.d.ts +++ b/spec/js-api/value/boolean.d.ts @@ -7,6 +7,8 @@ export const sassTrue: SassBoolean; export const sassFalse: SassBoolean; /** The JS API representation of a Sass boolean. */ -export interface SassBoolean extends Value { +export class SassBoolean extends Value { + private constructor(); + get value(): boolean; } diff --git a/typedoc.json b/typedoc.json index 82bae5b8..471db74d 100644 --- a/typedoc.json +++ b/typedoc.json @@ -1,4 +1,20 @@ { "excludePrivate": true, - "excludeProtected": true + "excludeProtected": true, + "categorizeByGroup": false, + "categoryOrder": [ + "Compile", + "Options", + "Logger", + "Importer", + "Custom Function", + "Other", + "Legacy", + + "Input", + "Output", + "Plugins", + "Messages", + "Source Maps" + ] }