schnee effeckt und fehler Korektur

This commit is contained in:
2023-08-14 17:52:24 +02:00
parent 4a843d4936
commit 79af4e9907
6813 changed files with 343821 additions and 356128 deletions

1334
node_modules/sass/LICENSE generated vendored

File diff suppressed because it is too large Load Diff

66
node_modules/sass/README.md generated vendored
View File

@@ -25,7 +25,6 @@ executable and a Node.js API.
[Dart Sass]: https://github.com/sass/dart-sass
* [Usage](#usage)
* [API](#api)
* [See Also](#see-also)
* [Behavioral Differences from Ruby Sass](#behavioral-differences-from-ruby-sass)
@@ -39,59 +38,46 @@ library:
[npm]: https://www.npmjs.com/package/sass
```js
var sass = require('sass');
const sass = require('sass');
sass.render({file: scss_filename}, function(err, result) { /* ... */ });
const result = sass.compile(scssFilename);
// OR
var result = sass.renderSync({file: scss_filename});
// Note that `compileAsync()` is substantially slower than `compile()`.
const result = await sass.compileAsync(scssFilename);
```
[See below](#api) for details on Dart Sass's JavaScript API.
See [the Sass website][js api] for full API documentation.
## API
When installed via npm, Dart Sass supports a JavaScript API that's fully
compatible with [Node Sass][] (with a few exceptions listed below), with support
for both the `render()` and `renderSync()` functions. See [the Sass
website][js api] for full API documentation!
[Node Sass]: https://github.com/sass/node-sass
[js api]: https://sass-lang.com/documentation/js-api
Note however that **`renderSync()` is more than twice as fast as `render()`**
due to the overhead of asynchronous callbacks. Both `render()` and
`renderSync()` support the following options:
### Legacy API
* [`data`](https://github.com/sass/node-sass#data)
* [`file`](https://github.com/sass/node-sass#file)
* [`functions`](https://github.com/sass/node-sass#functions--v300---experimental)
* [`importer`](https://github.com/sass/node-sass#importer--v200---experimental)
* [`includePaths`](https://github.com/sass/node-sass#includepaths)
* [`indentType`](https://github.com/sass/node-sass#indenttype)
* [`indentWidth`](https://github.com/sass/node-sass#indentwidth)
* [`indentedSyntax`](https://github.com/sass/node-sass#indentedsyntax)
* [`linefeed`](https://github.com/sass/node-sass#linefeed)
* [`omitSourceMapUrl`](https://github.com/sass/node-sass#omitsourcemapurl)
* [`outFile`](https://github.com/sass/node-sass#outfile)
* [`sourceMapContents`](https://github.com/sass/node-sass#sourcemapcontents)
* [`sourceMapEmbed`](https://github.com/sass/node-sass#sourcemapembed)
* [`sourceMapRoot`](https://github.com/sass/node-sass#sourcemaproot)
* [`sourceMap`](https://github.com/sass/node-sass#sourcemap)
* Only the `"expanded"` and `"compressed"` values of
[`outputStyle`](https://github.com/sass/node-sass#outputstyle) are supported.
* `charset` (`true`, the default, will prefix non-ASCII CSS with `U+FEFF` or
[`@charset "UTF-8";`](https://developer.mozilla.org/en-US/docs/Web/CSS/@charset))
Dart Sass also supports an older JavaScript API that's fully compatible with
[Node Sass] (with a few exceptions listed below), with support for both the
[`render()`] and [`renderSync()`] functions. This API is considered deprecated
and will be removed in Dart Sass 2.0.0, so it should be avoided in new projects.
No support is intended for the following options:
[Node Sass]: https://github.com/sass/node-sass
[`render()`]: https://sass-lang.com/documentation/js-api/functions/render
[`renderSync()`]: https://sass-lang.com/documentation/js-api/functions/renderSync
* [`precision`](https://github.com/sass/node-sass#precision). Dart Sass defaults
to a sufficiently high precision for all existing browsers, and making this
Sass's support for the legacy JavaScript API has the following limitations:
* Only the `"expanded"` and `"compressed"` values of [`outputStyle`] are
supported.
* Dart Sass doesn't support the [`precision`] option. Dart Sass defaults to a
sufficiently high precision for all existing browsers, and making this
customizable would make the code substantially less efficient.
* [`sourceComments`](https://github.com/sass/node-sass#sourcecomments). Source
maps are the recommended way of locating the origin of generated selectors.
* Dart Sass doesn't support the [`sourceComments`] option. Source maps are the
recommended way of locating the origin of generated selectors.
[`outputStyle`]: https://sass-lang.com/documentation/js-api/interfaces/LegacySharedOptions#outputStyle
[`precision`]: https://github.com/sass/node-sass#precision
[`sourceComments`]: https://github.com/sass/node-sass#sourcecomments
## See Also

View File

@@ -1,15 +0,0 @@
The ISC License
Copyright (c) 2019 Elan Shanker, Paul Miller (https://paulmillr.com)
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@@ -1,87 +0,0 @@
anymatch [![Build Status](https://travis-ci.org/micromatch/anymatch.svg?branch=master)](https://travis-ci.org/micromatch/anymatch) [![Coverage Status](https://img.shields.io/coveralls/micromatch/anymatch.svg?branch=master)](https://coveralls.io/r/micromatch/anymatch?branch=master)
======
Javascript module to match a string against a regular expression, glob, string,
or function that takes the string as an argument and returns a truthy or falsy
value. The matcher can also be an array of any or all of these. Useful for
allowing a very flexible user-defined config to define things like file paths.
__Note: This module has Bash-parity, please be aware that Windows-style backslashes are not supported as separators. See https://github.com/micromatch/micromatch#backslashes for more information.__
Usage
-----
```sh
npm install anymatch
```
#### anymatch(matchers, testString, [returnIndex], [options])
* __matchers__: (_Array|String|RegExp|Function_)
String to be directly matched, string with glob patterns, regular expression
test, function that takes the testString as an argument and returns a truthy
value if it should be matched, or an array of any number and mix of these types.
* __testString__: (_String|Array_) The string to test against the matchers. If
passed as an array, the first element of the array will be used as the
`testString` for non-function matchers, while the entire array will be applied
as the arguments for function matchers.
* __options__: (_Object_ [optional]_) Any of the [picomatch](https://github.com/micromatch/picomatch#options) options.
* __returnIndex__: (_Boolean [optional]_) If true, return the array index of
the first matcher that that testString matched, or -1 if no match, instead of a
boolean result.
```js
const anymatch = require('anymatch');
const matchers = [ 'path/to/file.js', 'path/anyjs/**/*.js', /foo.js$/, string => string.includes('bar') && string.length > 10 ] ;
anymatch(matchers, 'path/to/file.js'); // true
anymatch(matchers, 'path/anyjs/baz.js'); // true
anymatch(matchers, 'path/to/foo.js'); // true
anymatch(matchers, 'path/to/bar.js'); // true
anymatch(matchers, 'bar.js'); // false
// returnIndex = true
anymatch(matchers, 'foo.js', {returnIndex: true}); // 2
anymatch(matchers, 'path/anyjs/foo.js', {returnIndex: true}); // 1
// any picomatc
// using globs to match directories and their children
anymatch('node_modules', 'node_modules'); // true
anymatch('node_modules', 'node_modules/somelib/index.js'); // false
anymatch('node_modules/**', 'node_modules/somelib/index.js'); // true
anymatch('node_modules/**', '/absolute/path/to/node_modules/somelib/index.js'); // false
anymatch('**/node_modules/**', '/absolute/path/to/node_modules/somelib/index.js'); // true
const matcher = anymatch(matchers);
['foo.js', 'bar.js'].filter(matcher); // [ 'foo.js' ]
anymatch master*
```
#### anymatch(matchers)
You can also pass in only your matcher(s) to get a curried function that has
already been bound to the provided matching criteria. This can be used as an
`Array#filter` callback.
```js
var matcher = anymatch(matchers);
matcher('path/to/file.js'); // true
matcher('path/anyjs/baz.js', true); // 1
['foo.js', 'bar.js'].filter(matcher); // ['foo.js']
```
Changelog
----------
[See release notes page on GitHub](https://github.com/micromatch/anymatch/releases)
- **v3.0:** Removed `startIndex` and `endIndex` arguments. Node 8.x-only.
- **v2.0:** [micromatch](https://github.com/jonschlinkert/micromatch) moves away from minimatch-parity and inline with Bash. This includes handling backslashes differently (see https://github.com/micromatch/micromatch#backslashes for more information).
- **v1.2:** anymatch uses [micromatch](https://github.com/jonschlinkert/micromatch)
for glob pattern matching. Issues with glob pattern matching should be
reported directly to the [micromatch issue tracker](https://github.com/jonschlinkert/micromatch/issues).
License
-------
[ISC](https://raw.github.com/micromatch/anymatch/master/LICENSE)

View File

@@ -1,19 +0,0 @@
type AnymatchFn = (testString: string) => boolean;
type AnymatchPattern = string|RegExp|AnymatchFn;
type AnymatchMatcher = AnymatchPattern|AnymatchPattern[]
type AnymatchTester = {
(testString: string|any[], returnIndex: true): number;
(testString: string|any[]): boolean;
}
type PicomatchOptions = {dot: boolean};
declare const anymatch: {
(matchers: AnymatchMatcher): AnymatchTester;
(matchers: AnymatchMatcher, testString: string|any[], returnIndex: true | PicomatchOptions): number;
(matchers: AnymatchMatcher, testString: string|any[]): boolean;
}
export {AnymatchMatcher as Matcher}
export {AnymatchTester as Tester}
export default anymatch

View File

@@ -1,104 +0,0 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const picomatch = require('picomatch');
const normalizePath = require('normalize-path');
/**
* @typedef {(testString: string) => boolean} AnymatchFn
* @typedef {string|RegExp|AnymatchFn} AnymatchPattern
* @typedef {AnymatchPattern|AnymatchPattern[]} AnymatchMatcher
*/
const BANG = '!';
const DEFAULT_OPTIONS = {returnIndex: false};
const arrify = (item) => Array.isArray(item) ? item : [item];
/**
* @param {AnymatchPattern} matcher
* @param {object} options
* @returns {AnymatchFn}
*/
const createPattern = (matcher, options) => {
if (typeof matcher === 'function') {
return matcher;
}
if (typeof matcher === 'string') {
const glob = picomatch(matcher, options);
return (string) => matcher === string || glob(string);
}
if (matcher instanceof RegExp) {
return (string) => matcher.test(string);
}
return (string) => false;
};
/**
* @param {Array<Function>} patterns
* @param {Array<Function>} negPatterns
* @param {String|Array} args
* @param {Boolean} returnIndex
* @returns {boolean|number}
*/
const matchPatterns = (patterns, negPatterns, args, returnIndex) => {
const isList = Array.isArray(args);
const _path = isList ? args[0] : args;
if (!isList && typeof _path !== 'string') {
throw new TypeError('anymatch: second argument must be a string: got ' +
Object.prototype.toString.call(_path))
}
const path = normalizePath(_path);
for (let index = 0; index < negPatterns.length; index++) {
const nglob = negPatterns[index];
if (nglob(path)) {
return returnIndex ? -1 : false;
}
}
const applied = isList && [path].concat(args.slice(1));
for (let index = 0; index < patterns.length; index++) {
const pattern = patterns[index];
if (isList ? pattern(...applied) : pattern(path)) {
return returnIndex ? index : true;
}
}
return returnIndex ? -1 : false;
};
/**
* @param {AnymatchMatcher} matchers
* @param {Array|string} testString
* @param {object} options
* @returns {boolean|number|Function}
*/
const anymatch = (matchers, testString, options = DEFAULT_OPTIONS) => {
if (matchers == null) {
throw new TypeError('anymatch: specify first argument');
}
const opts = typeof options === 'boolean' ? {returnIndex: options} : options;
const returnIndex = opts.returnIndex || false;
// Early cache for matchers.
const mtchers = arrify(matchers);
const negatedGlobs = mtchers
.filter(item => typeof item === 'string' && item.charAt(0) === BANG)
.map(item => item.slice(1))
.map(item => picomatch(item, opts));
const patterns = mtchers
.filter(item => typeof item !== 'string' || (typeof item === 'string' && item.charAt(0) !== BANG))
.map(matcher => createPattern(matcher, opts));
if (testString == null) {
return (testString, ri = false) => {
const returnIndex = typeof ri === 'boolean' ? ri : false;
return matchPatterns(patterns, negatedGlobs, testString, returnIndex);
}
}
return matchPatterns(patterns, negatedGlobs, testString, returnIndex);
};
anymatch.default = anymatch;
module.exports = anymatch;

View File

@@ -1,48 +0,0 @@
{
"name": "anymatch",
"version": "3.1.2",
"description": "Matches strings against configurable strings, globs, regular expressions, and/or functions",
"files": [
"index.js",
"index.d.ts"
],
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"author": {
"name": "Elan Shanker",
"url": "https://github.com/es128"
},
"license": "ISC",
"homepage": "https://github.com/micromatch/anymatch",
"repository": {
"type": "git",
"url": "https://github.com/micromatch/anymatch"
},
"keywords": [
"match",
"any",
"string",
"file",
"fs",
"list",
"glob",
"regex",
"regexp",
"regular",
"expression",
"function"
],
"scripts": {
"test": "nyc mocha",
"mocha": "mocha"
},
"devDependencies": {
"mocha": "^6.1.3",
"nyc": "^14.0.0"
},
"engines": {
"node": ">= 8"
}
}

View File

@@ -1,260 +0,0 @@
[
"3dm",
"3ds",
"3g2",
"3gp",
"7z",
"a",
"aac",
"adp",
"ai",
"aif",
"aiff",
"alz",
"ape",
"apk",
"appimage",
"ar",
"arj",
"asf",
"au",
"avi",
"bak",
"baml",
"bh",
"bin",
"bk",
"bmp",
"btif",
"bz2",
"bzip2",
"cab",
"caf",
"cgm",
"class",
"cmx",
"cpio",
"cr2",
"cur",
"dat",
"dcm",
"deb",
"dex",
"djvu",
"dll",
"dmg",
"dng",
"doc",
"docm",
"docx",
"dot",
"dotm",
"dra",
"DS_Store",
"dsk",
"dts",
"dtshd",
"dvb",
"dwg",
"dxf",
"ecelp4800",
"ecelp7470",
"ecelp9600",
"egg",
"eol",
"eot",
"epub",
"exe",
"f4v",
"fbs",
"fh",
"fla",
"flac",
"flatpak",
"fli",
"flv",
"fpx",
"fst",
"fvt",
"g3",
"gh",
"gif",
"graffle",
"gz",
"gzip",
"h261",
"h263",
"h264",
"icns",
"ico",
"ief",
"img",
"ipa",
"iso",
"jar",
"jpeg",
"jpg",
"jpgv",
"jpm",
"jxr",
"key",
"ktx",
"lha",
"lib",
"lvp",
"lz",
"lzh",
"lzma",
"lzo",
"m3u",
"m4a",
"m4v",
"mar",
"mdi",
"mht",
"mid",
"midi",
"mj2",
"mka",
"mkv",
"mmr",
"mng",
"mobi",
"mov",
"movie",
"mp3",
"mp4",
"mp4a",
"mpeg",
"mpg",
"mpga",
"mxu",
"nef",
"npx",
"numbers",
"nupkg",
"o",
"odp",
"ods",
"odt",
"oga",
"ogg",
"ogv",
"otf",
"ott",
"pages",
"pbm",
"pcx",
"pdb",
"pdf",
"pea",
"pgm",
"pic",
"png",
"pnm",
"pot",
"potm",
"potx",
"ppa",
"ppam",
"ppm",
"pps",
"ppsm",
"ppsx",
"ppt",
"pptm",
"pptx",
"psd",
"pya",
"pyc",
"pyo",
"pyv",
"qt",
"rar",
"ras",
"raw",
"resources",
"rgb",
"rip",
"rlc",
"rmf",
"rmvb",
"rpm",
"rtf",
"rz",
"s3m",
"s7z",
"scpt",
"sgi",
"shar",
"snap",
"sil",
"sketch",
"slk",
"smv",
"snk",
"so",
"stl",
"suo",
"sub",
"swf",
"tar",
"tbz",
"tbz2",
"tga",
"tgz",
"thmx",
"tif",
"tiff",
"tlz",
"ttc",
"ttf",
"txz",
"udf",
"uvh",
"uvi",
"uvm",
"uvp",
"uvs",
"uvu",
"viv",
"vob",
"war",
"wav",
"wax",
"wbmp",
"wdp",
"weba",
"webm",
"webp",
"whl",
"wim",
"wm",
"wma",
"wmv",
"wmx",
"woff",
"woff2",
"wrm",
"wvx",
"xbm",
"xif",
"xla",
"xlam",
"xls",
"xlsb",
"xlsm",
"xlsx",
"xlt",
"xltm",
"xltx",
"xm",
"xmind",
"xpi",
"xpm",
"xwd",
"xz",
"z",
"zip",
"zipx"
]

View File

@@ -1,3 +0,0 @@
declare const binaryExtensionsJson: readonly string[];
export = binaryExtensionsJson;

View File

@@ -1,14 +0,0 @@
/**
List of binary file extensions.
@example
```
import binaryExtensions = require('binary-extensions');
console.log(binaryExtensions);
//=> ['3ds', '3g2', …]
```
*/
declare const binaryExtensions: readonly string[];
export = binaryExtensions;

View File

@@ -1 +0,0 @@
module.exports = require('./binary-extensions.json');

View File

@@ -1,9 +0,0 @@
MIT License
Copyright (c) 2019 Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com), Paul Miller (https://paulmillr.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,38 +0,0 @@
{
"name": "binary-extensions",
"version": "2.2.0",
"description": "List of binary file extensions",
"license": "MIT",
"repository": "sindresorhus/binary-extensions",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=8"
},
"scripts": {
"test": "xo && ava && tsd"
},
"files": [
"index.js",
"index.d.ts",
"binary-extensions.json",
"binary-extensions.json.d.ts"
],
"keywords": [
"binary",
"extensions",
"extension",
"file",
"json",
"list",
"array"
],
"devDependencies": {
"ava": "^1.4.1",
"tsd": "^0.7.2",
"xo": "^0.24.0"
}
}

View File

@@ -1,41 +0,0 @@
# binary-extensions
> List of binary file extensions
The list is just a [JSON file](binary-extensions.json) and can be used anywhere.
## Install
```
$ npm install binary-extensions
```
## Usage
```js
const binaryExtensions = require('binary-extensions');
console.log(binaryExtensions);
//=> ['3ds', '3g2', …]
```
## Related
- [is-binary-path](https://github.com/sindresorhus/is-binary-path) - Check if a filepath is a binary file
- [text-extensions](https://github.com/sindresorhus/text-extensions) - List of text file extensions
---
<div align="center">
<b>
<a href="https://tidelift.com/subscription/pkg/npm-binary-extensions?utm_source=npm-binary-extensions&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>

View File

@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2012-2019 Paul Miller (https://paulmillr.com), Elan Shanker
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,308 +0,0 @@
# Chokidar [![Weekly downloads](https://img.shields.io/npm/dw/chokidar.svg)](https://github.com/paulmillr/chokidar) [![Yearly downloads](https://img.shields.io/npm/dy/chokidar.svg)](https://github.com/paulmillr/chokidar)
> Minimal and efficient cross-platform file watching library
[![NPM](https://nodei.co/npm/chokidar.png)](https://www.npmjs.com/package/chokidar)
## Why?
Node.js `fs.watch`:
* Doesn't report filenames on MacOS.
* Doesn't report events at all when using editors like Sublime on MacOS.
* Often reports events twice.
* Emits most changes as `rename`.
* Does not provide an easy way to recursively watch file trees.
* Does not support recursive watching on Linux.
Node.js `fs.watchFile`:
* Almost as bad at event handling.
* Also does not provide any recursive watching.
* Results in high CPU utilization.
Chokidar resolves these problems.
Initially made for **[Brunch](https://brunch.io/)** (an ultra-swift web app build tool), it is now used in
[Microsoft's Visual Studio Code](https://github.com/microsoft/vscode),
[gulp](https://github.com/gulpjs/gulp/),
[karma](https://karma-runner.github.io/),
[PM2](https://github.com/Unitech/PM2),
[browserify](http://browserify.org/),
[webpack](https://webpack.github.io/),
[BrowserSync](https://www.browsersync.io/),
and [many others](https://www.npmjs.com/browse/depended/chokidar).
It has proven itself in production environments.
Version 3 is out! Check out our blog post about it: [Chokidar 3: How to save 32TB of traffic every week](https://paulmillr.com/posts/chokidar-3-save-32tb-of-traffic/)
## How?
Chokidar does still rely on the Node.js core `fs` module, but when using
`fs.watch` and `fs.watchFile` for watching, it normalizes the events it
receives, often checking for truth by getting file stats and/or dir contents.
On MacOS, chokidar by default uses a native extension exposing the Darwin
`FSEvents` API. This provides very efficient recursive watching compared with
implementations like `kqueue` available on most \*nix platforms. Chokidar still
does have to do some work to normalize the events received that way as well.
On most other platforms, the `fs.watch`-based implementation is the default, which
avoids polling and keeps CPU usage down. Be advised that chokidar will initiate
watchers recursively for everything within scope of the paths that have been
specified, so be judicious about not wasting system resources by watching much
more than needed.
## Getting started
Install with npm:
```sh
npm install chokidar
```
Then `require` and use it in your code:
```javascript
const chokidar = require('chokidar');
// One-liner for current directory
chokidar.watch('.').on('all', (event, path) => {
console.log(event, path);
});
```
## API
```javascript
// Example of a more typical implementation structure
// Initialize watcher.
const watcher = chokidar.watch('file, dir, glob, or array', {
ignored: /(^|[\/\\])\../, // ignore dotfiles
persistent: true
});
// Something to use when events are received.
const log = console.log.bind(console);
// Add event listeners.
watcher
.on('add', path => log(`File ${path} has been added`))
.on('change', path => log(`File ${path} has been changed`))
.on('unlink', path => log(`File ${path} has been removed`));
// More possible events.
watcher
.on('addDir', path => log(`Directory ${path} has been added`))
.on('unlinkDir', path => log(`Directory ${path} has been removed`))
.on('error', error => log(`Watcher error: ${error}`))
.on('ready', () => log('Initial scan complete. Ready for changes'))
.on('raw', (event, path, details) => { // internal
log('Raw event info:', event, path, details);
});
// 'add', 'addDir' and 'change' events also receive stat() results as second
// argument when available: https://nodejs.org/api/fs.html#fs_class_fs_stats
watcher.on('change', (path, stats) => {
if (stats) console.log(`File ${path} changed size to ${stats.size}`);
});
// Watch new files.
watcher.add('new-file');
watcher.add(['new-file-2', 'new-file-3', '**/other-file*']);
// Get list of actual paths being watched on the filesystem
var watchedPaths = watcher.getWatched();
// Un-watch some files.
await watcher.unwatch('new-file*');
// Stop watching.
// The method is async!
watcher.close().then(() => console.log('closed'));
// Full list of options. See below for descriptions.
// Do not use this example!
chokidar.watch('file', {
persistent: true,
ignored: '*.txt',
ignoreInitial: false,
followSymlinks: true,
cwd: '.',
disableGlobbing: false,
usePolling: false,
interval: 100,
binaryInterval: 300,
alwaysStat: false,
depth: 99,
awaitWriteFinish: {
stabilityThreshold: 2000,
pollInterval: 100
},
ignorePermissionErrors: false,
atomic: true // or a custom 'atomicity delay', in milliseconds (default 100)
});
```
`chokidar.watch(paths, [options])`
* `paths` (string or array of strings). Paths to files, dirs to be watched
recursively, or glob patterns.
- Note: globs must not contain windows separators (`\`),
because that's how they work by the standard —
you'll need to replace them with forward slashes (`/`).
- Note 2: for additional glob documentation, check out low-level
library: [picomatch](https://github.com/micromatch/picomatch).
* `options` (object) Options object as defined below:
#### Persistence
* `persistent` (default: `true`). Indicates whether the process
should continue to run as long as files are being watched. If set to
`false` when using `fsevents` to watch, no more events will be emitted
after `ready`, even if the process continues to run.
#### Path filtering
* `ignored` ([anymatch](https://github.com/es128/anymatch)-compatible definition)
Defines files/paths to be ignored. The whole relative or absolute path is
tested, not just filename. If a function with two arguments is provided, it
gets called twice per path - once with a single argument (the path), second
time with two arguments (the path and the
[`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats)
object of that path).
* `ignoreInitial` (default: `false`). If set to `false` then `add`/`addDir` events are also emitted for matching paths while
instantiating the watching as chokidar discovers these file paths (before the `ready` event).
* `followSymlinks` (default: `true`). When `false`, only the
symlinks themselves will be watched for changes instead of following
the link references and bubbling events through the link's path.
* `cwd` (no default). The base directory from which watch `paths` are to be
derived. Paths emitted with events will be relative to this.
* `disableGlobbing` (default: `false`). If set to `true` then the strings passed to `.watch()` and `.add()` are treated as
literal path names, even if they look like globs.
#### Performance
* `usePolling` (default: `false`).
Whether to use fs.watchFile (backed by polling), or fs.watch. If polling
leads to high CPU utilization, consider setting this to `false`. It is
typically necessary to **set this to `true` to successfully watch files over
a network**, and it may be necessary to successfully watch files in other
non-standard situations. Setting to `true` explicitly on MacOS overrides the
`useFsEvents` default. You may also set the CHOKIDAR_USEPOLLING env variable
to true (1) or false (0) in order to override this option.
* _Polling-specific settings_ (effective when `usePolling: true`)
* `interval` (default: `100`). Interval of file system polling, in milliseconds. You may also
set the CHOKIDAR_INTERVAL env variable to override this option.
* `binaryInterval` (default: `300`). Interval of file system
polling for binary files.
([see list of binary extensions](https://github.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json))
* `useFsEvents` (default: `true` on MacOS). Whether to use the
`fsevents` watching interface if available. When set to `true` explicitly
and `fsevents` is available this supercedes the `usePolling` setting. When
set to `false` on MacOS, `usePolling: true` becomes the default.
* `alwaysStat` (default: `false`). If relying upon the
[`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats)
object that may get passed with `add`, `addDir`, and `change` events, set
this to `true` to ensure it is provided even in cases where it wasn't
already available from the underlying watch events.
* `depth` (default: `undefined`). If set, limits how many levels of
subdirectories will be traversed.
* `awaitWriteFinish` (default: `false`).
By default, the `add` event will fire when a file first appears on disk, before
the entire file has been written. Furthermore, in some cases some `change`
events will be emitted while the file is being written. In some cases,
especially when watching for large files there will be a need to wait for the
write operation to finish before responding to a file creation or modification.
Setting `awaitWriteFinish` to `true` (or a truthy value) will poll file size,
holding its `add` and `change` events until the size does not change for a
configurable amount of time. The appropriate duration setting is heavily
dependent on the OS and hardware. For accurate detection this parameter should
be relatively high, making file watching much less responsive.
Use with caution.
* *`options.awaitWriteFinish` can be set to an object in order to adjust
timing params:*
* `awaitWriteFinish.stabilityThreshold` (default: 2000). Amount of time in
milliseconds for a file size to remain constant before emitting its event.
* `awaitWriteFinish.pollInterval` (default: 100). File size polling interval, in milliseconds.
#### Errors
* `ignorePermissionErrors` (default: `false`). Indicates whether to watch files
that don't have read permissions if possible. If watching fails due to `EPERM`
or `EACCES` with this set to `true`, the errors will be suppressed silently.
* `atomic` (default: `true` if `useFsEvents` and `usePolling` are `false`).
Automatically filters out artifacts that occur when using editors that use
"atomic writes" instead of writing directly to the source file. If a file is
re-added within 100 ms of being deleted, Chokidar emits a `change` event
rather than `unlink` then `add`. If the default of 100 ms does not work well
for you, you can override it by setting `atomic` to a custom value, in
milliseconds.
### Methods & Events
`chokidar.watch()` produces an instance of `FSWatcher`. Methods of `FSWatcher`:
* `.add(path / paths)`: Add files, directories, or glob patterns for tracking.
Takes an array of strings or just one string.
* `.on(event, callback)`: Listen for an FS event.
Available events: `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `ready`,
`raw`, `error`.
Additionally `all` is available which gets emitted with the underlying event
name and path for every event other than `ready`, `raw`, and `error`. `raw` is internal, use it carefully.
* `.unwatch(path / paths)`: Stop watching files, directories, or glob patterns.
Takes an array of strings or just one string.
* `.close()`: **async** Removes all listeners from watched files. Asynchronous, returns Promise. Use with `await` to ensure bugs don't happen.
* `.getWatched()`: Returns an object representing all the paths on the file
system being watched by this `FSWatcher` instance. The object's keys are all the
directories (using absolute paths unless the `cwd` option was used), and the
values are arrays of the names of the items contained in each directory.
## CLI
If you need a CLI interface for your file watching, check out
[chokidar-cli](https://github.com/kimmobrunfeldt/chokidar-cli), allowing you to
execute a command on each change, or get a stdio stream of change events.
## Install Troubleshooting
* `npm WARN optional dep failed, continuing fsevents@n.n.n`
* This message is normal part of how `npm` handles optional dependencies and is
not indicative of a problem. Even if accompanied by other related error messages,
Chokidar should function properly.
* `TypeError: fsevents is not a constructor`
* Update chokidar by doing `rm -rf node_modules package-lock.json yarn.lock && npm install`, or update your dependency that uses chokidar.
* Chokidar is producing `ENOSP` error on Linux, like this:
* `bash: cannot set terminal process group (-1): Inappropriate ioctl for device bash: no job control in this shell`
`Error: watch /home/ ENOSPC`
* This means Chokidar ran out of file handles and you'll need to increase their count by executing the following command in Terminal:
`echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`
## Changelog
For more detailed changelog, see [`full_changelog.md`](.github/full_changelog.md).
- **v3.5 (Jan 6, 2021):** Support for ARM Macs with Apple Silicon. Fixes for deleted symlinks.
- **v3.4 (Apr 26, 2020):** Support for directory-based symlinks. Fixes for macos file replacement.
- **v3.3 (Nov 2, 2019):** `FSWatcher#close()` method became async. That fixes IO race conditions related to close method.
- **v3.2 (Oct 1, 2019):** Improve Linux RAM usage by 50%. Race condition fixes. Windows glob fixes. Improve stability by using tight range of dependency versions.
- **v3.1 (Sep 16, 2019):** dotfiles are no longer filtered out by default. Use `ignored` option if needed. Improve initial Linux scan time by 50%.
- **v3 (Apr 30, 2019):** massive CPU & RAM consumption improvements; reduces deps / package size by a factor of 17x and bumps Node.js requirement to v8.16 and higher.
- **v2 (Dec 29, 2017):** Globs are now posix-style-only; without windows support. Tons of bugfixes.
- **v1 (Apr 7, 2015):** Glob support, symlink support, tons of bugfixes. Node 0.8+ is supported
- **v0.1 (Apr 20, 2012):** Initial release, extracted from [Brunch](https://github.com/brunch/brunch/blob/9847a065aea300da99bd0753f90354cde9de1261/src/helpers.coffee#L66)
## Also
Why was chokidar named this way? What's the meaning behind it?
>Chowkidar is a transliteration of a Hindi word meaning 'watchman, gatekeeper', चौकीदार. This ultimately comes from Sanskrit _ चतुष्क_ (crossway, quadrangle, consisting-of-four).
## License
MIT (c) Paul Miller (<https://paulmillr.com>), see [LICENSE](LICENSE) file.

View File

@@ -1,973 +0,0 @@
'use strict';
const { EventEmitter } = require('events');
const fs = require('fs');
const sysPath = require('path');
const { promisify } = require('util');
const readdirp = require('readdirp');
const anymatch = require('anymatch').default;
const globParent = require('glob-parent');
const isGlob = require('is-glob');
const braces = require('braces');
const normalizePath = require('normalize-path');
const NodeFsHandler = require('./lib/nodefs-handler');
const FsEventsHandler = require('./lib/fsevents-handler');
const {
EV_ALL,
EV_READY,
EV_ADD,
EV_CHANGE,
EV_UNLINK,
EV_ADD_DIR,
EV_UNLINK_DIR,
EV_RAW,
EV_ERROR,
STR_CLOSE,
STR_END,
BACK_SLASH_RE,
DOUBLE_SLASH_RE,
SLASH_OR_BACK_SLASH_RE,
DOT_RE,
REPLACER_RE,
SLASH,
SLASH_SLASH,
BRACE_START,
BANG,
ONE_DOT,
TWO_DOTS,
GLOBSTAR,
SLASH_GLOBSTAR,
ANYMATCH_OPTS,
STRING_TYPE,
FUNCTION_TYPE,
EMPTY_STR,
EMPTY_FN,
isWindows,
isMacos,
isIBMi
} = require('./lib/constants');
const stat = promisify(fs.stat);
const readdir = promisify(fs.readdir);
/**
* @typedef {String} Path
* @typedef {'all'|'add'|'addDir'|'change'|'unlink'|'unlinkDir'|'raw'|'error'|'ready'} EventName
* @typedef {'readdir'|'watch'|'add'|'remove'|'change'} ThrottleType
*/
/**
*
* @typedef {Object} WatchHelpers
* @property {Boolean} followSymlinks
* @property {'stat'|'lstat'} statMethod
* @property {Path} path
* @property {Path} watchPath
* @property {Function} entryPath
* @property {Boolean} hasGlob
* @property {Object} globFilter
* @property {Function} filterPath
* @property {Function} filterDir
*/
const arrify = (value = []) => Array.isArray(value) ? value : [value];
const flatten = (list, result = []) => {
list.forEach(item => {
if (Array.isArray(item)) {
flatten(item, result);
} else {
result.push(item);
}
});
return result;
};
const unifyPaths = (paths_) => {
/**
* @type {Array<String>}
*/
const paths = flatten(arrify(paths_));
if (!paths.every(p => typeof p === STRING_TYPE)) {
throw new TypeError(`Non-string provided as watch path: ${paths}`);
}
return paths.map(normalizePathToUnix);
};
// If SLASH_SLASH occurs at the beginning of path, it is not replaced
// because "//StoragePC/DrivePool/Movies" is a valid network path
const toUnix = (string) => {
let str = string.replace(BACK_SLASH_RE, SLASH);
let prepend = false;
if (str.startsWith(SLASH_SLASH)) {
prepend = true;
}
while (str.match(DOUBLE_SLASH_RE)) {
str = str.replace(DOUBLE_SLASH_RE, SLASH);
}
if (prepend) {
str = SLASH + str;
}
return str;
};
// Our version of upath.normalize
// TODO: this is not equal to path-normalize module - investigate why
const normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path)));
const normalizeIgnored = (cwd = EMPTY_STR) => (path) => {
if (typeof path !== STRING_TYPE) return path;
return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path));
};
const getAbsolutePath = (path, cwd) => {
if (sysPath.isAbsolute(path)) {
return path;
}
if (path.startsWith(BANG)) {
return BANG + sysPath.join(cwd, path.slice(1));
}
return sysPath.join(cwd, path);
};
const undef = (opts, key) => opts[key] === undefined;
/**
* Directory entry.
* @property {Path} path
* @property {Set<Path>} items
*/
class DirEntry {
/**
* @param {Path} dir
* @param {Function} removeWatcher
*/
constructor(dir, removeWatcher) {
this.path = dir;
this._removeWatcher = removeWatcher;
/** @type {Set<Path>} */
this.items = new Set();
}
add(item) {
const {items} = this;
if (!items) return;
if (item !== ONE_DOT && item !== TWO_DOTS) items.add(item);
}
async remove(item) {
const {items} = this;
if (!items) return;
items.delete(item);
if (items.size > 0) return;
const dir = this.path;
try {
await readdir(dir);
} catch (err) {
if (this._removeWatcher) {
this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir));
}
}
}
has(item) {
const {items} = this;
if (!items) return;
return items.has(item);
}
/**
* @returns {Array<String>}
*/
getChildren() {
const {items} = this;
if (!items) return;
return [...items.values()];
}
dispose() {
this.items.clear();
delete this.path;
delete this._removeWatcher;
delete this.items;
Object.freeze(this);
}
}
const STAT_METHOD_F = 'stat';
const STAT_METHOD_L = 'lstat';
class WatchHelper {
constructor(path, watchPath, follow, fsw) {
this.fsw = fsw;
this.path = path = path.replace(REPLACER_RE, EMPTY_STR);
this.watchPath = watchPath;
this.fullWatchPath = sysPath.resolve(watchPath);
this.hasGlob = watchPath !== path;
/** @type {object|boolean} */
if (path === EMPTY_STR) this.hasGlob = false;
this.globSymlink = this.hasGlob && follow ? undefined : false;
this.globFilter = this.hasGlob ? anymatch(path, undefined, ANYMATCH_OPTS) : false;
this.dirParts = this.getDirParts(path);
this.dirParts.forEach((parts) => {
if (parts.length > 1) parts.pop();
});
this.followSymlinks = follow;
this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
}
checkGlobSymlink(entry) {
// only need to resolve once
// first entry should always have entry.parentDir === EMPTY_STR
if (this.globSymlink === undefined) {
this.globSymlink = entry.fullParentDir === this.fullWatchPath ?
false : {realPath: entry.fullParentDir, linkPath: this.fullWatchPath};
}
if (this.globSymlink) {
return entry.fullPath.replace(this.globSymlink.realPath, this.globSymlink.linkPath);
}
return entry.fullPath;
}
entryPath(entry) {
return sysPath.join(this.watchPath,
sysPath.relative(this.watchPath, this.checkGlobSymlink(entry))
);
}
filterPath(entry) {
const {stats} = entry;
if (stats && stats.isSymbolicLink()) return this.filterDir(entry);
const resolvedPath = this.entryPath(entry);
const matchesGlob = this.hasGlob && typeof this.globFilter === FUNCTION_TYPE ?
this.globFilter(resolvedPath) : true;
return matchesGlob &&
this.fsw._isntIgnored(resolvedPath, stats) &&
this.fsw._hasReadPermissions(stats);
}
getDirParts(path) {
if (!this.hasGlob) return [];
const parts = [];
const expandedPath = path.includes(BRACE_START) ? braces.expand(path) : [path];
expandedPath.forEach((path) => {
parts.push(sysPath.relative(this.watchPath, path).split(SLASH_OR_BACK_SLASH_RE));
});
return parts;
}
filterDir(entry) {
if (this.hasGlob) {
const entryParts = this.getDirParts(this.checkGlobSymlink(entry));
let globstar = false;
this.unmatchedGlob = !this.dirParts.some((parts) => {
return parts.every((part, i) => {
if (part === GLOBSTAR) globstar = true;
return globstar || !entryParts[0][i] || anymatch(part, entryParts[0][i], ANYMATCH_OPTS);
});
});
}
return !this.unmatchedGlob && this.fsw._isntIgnored(this.entryPath(entry), entry.stats);
}
}
/**
* Watches files & directories for changes. Emitted events:
* `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`
*
* new FSWatcher()
* .add(directories)
* .on('add', path => log('File', path, 'was added'))
*/
class FSWatcher extends EventEmitter {
// Not indenting methods for history sake; for now.
constructor(_opts) {
super();
const opts = {};
if (_opts) Object.assign(opts, _opts); // for frozen objects
/** @type {Map<String, DirEntry>} */
this._watched = new Map();
/** @type {Map<String, Array>} */
this._closers = new Map();
/** @type {Set<String>} */
this._ignoredPaths = new Set();
/** @type {Map<ThrottleType, Map>} */
this._throttled = new Map();
/** @type {Map<Path, String|Boolean>} */
this._symlinkPaths = new Map();
this._streams = new Set();
this.closed = false;
// Set up default options.
if (undef(opts, 'persistent')) opts.persistent = true;
if (undef(opts, 'ignoreInitial')) opts.ignoreInitial = false;
if (undef(opts, 'ignorePermissionErrors')) opts.ignorePermissionErrors = false;
if (undef(opts, 'interval')) opts.interval = 100;
if (undef(opts, 'binaryInterval')) opts.binaryInterval = 300;
if (undef(opts, 'disableGlobbing')) opts.disableGlobbing = false;
opts.enableBinaryInterval = opts.binaryInterval !== opts.interval;
// Enable fsevents on OS X when polling isn't explicitly enabled.
if (undef(opts, 'useFsEvents')) opts.useFsEvents = !opts.usePolling;
// If we can't use fsevents, ensure the options reflect it's disabled.
const canUseFsEvents = FsEventsHandler.canUse();
if (!canUseFsEvents) opts.useFsEvents = false;
// Use polling on Mac if not using fsevents.
// Other platforms use non-polling fs_watch.
if (undef(opts, 'usePolling') && !opts.useFsEvents) {
opts.usePolling = isMacos;
}
// Always default to polling on IBM i because fs.watch() is not available on IBM i.
if(isIBMi) {
opts.usePolling = true;
}
// Global override (useful for end-developers that need to force polling for all
// instances of chokidar, regardless of usage/dependency depth)
const envPoll = process.env.CHOKIDAR_USEPOLLING;
if (envPoll !== undefined) {
const envLower = envPoll.toLowerCase();
if (envLower === 'false' || envLower === '0') {
opts.usePolling = false;
} else if (envLower === 'true' || envLower === '1') {
opts.usePolling = true;
} else {
opts.usePolling = !!envLower;
}
}
const envInterval = process.env.CHOKIDAR_INTERVAL;
if (envInterval) {
opts.interval = Number.parseInt(envInterval, 10);
}
// Editor atomic write normalization enabled by default with fs.watch
if (undef(opts, 'atomic')) opts.atomic = !opts.usePolling && !opts.useFsEvents;
if (opts.atomic) this._pendingUnlinks = new Map();
if (undef(opts, 'followSymlinks')) opts.followSymlinks = true;
if (undef(opts, 'awaitWriteFinish')) opts.awaitWriteFinish = false;
if (opts.awaitWriteFinish === true) opts.awaitWriteFinish = {};
const awf = opts.awaitWriteFinish;
if (awf) {
if (!awf.stabilityThreshold) awf.stabilityThreshold = 2000;
if (!awf.pollInterval) awf.pollInterval = 100;
this._pendingWrites = new Map();
}
if (opts.ignored) opts.ignored = arrify(opts.ignored);
let readyCalls = 0;
this._emitReady = () => {
readyCalls++;
if (readyCalls >= this._readyCount) {
this._emitReady = EMPTY_FN;
this._readyEmitted = true;
// use process.nextTick to allow time for listener to be bound
process.nextTick(() => this.emit(EV_READY));
}
};
this._emitRaw = (...args) => this.emit(EV_RAW, ...args);
this._readyEmitted = false;
this.options = opts;
// Initialize with proper watcher.
if (opts.useFsEvents) {
this._fsEventsHandler = new FsEventsHandler(this);
} else {
this._nodeFsHandler = new NodeFsHandler(this);
}
// Youre frozen when your hearts not open.
Object.freeze(opts);
}
// Public methods
/**
* Adds paths to be watched on an existing FSWatcher instance
* @param {Path|Array<Path>} paths_
* @param {String=} _origAdd private; for handling non-existent paths to be watched
* @param {Boolean=} _internal private; indicates a non-user add
* @returns {FSWatcher} for chaining
*/
add(paths_, _origAdd, _internal) {
const {cwd, disableGlobbing} = this.options;
this.closed = false;
let paths = unifyPaths(paths_);
if (cwd) {
paths = paths.map((path) => {
const absPath = getAbsolutePath(path, cwd);
// Check `path` instead of `absPath` because the cwd portion can't be a glob
if (disableGlobbing || !isGlob(path)) {
return absPath;
}
return normalizePath(absPath);
});
}
// set aside negated glob strings
paths = paths.filter((path) => {
if (path.startsWith(BANG)) {
this._ignoredPaths.add(path.slice(1));
return false;
}
// if a path is being added that was previously ignored, stop ignoring it
this._ignoredPaths.delete(path);
this._ignoredPaths.delete(path + SLASH_GLOBSTAR);
// reset the cached userIgnored anymatch fn
// to make ignoredPaths changes effective
this._userIgnored = undefined;
return true;
});
if (this.options.useFsEvents && this._fsEventsHandler) {
if (!this._readyCount) this._readyCount = paths.length;
if (this.options.persistent) this._readyCount *= 2;
paths.forEach((path) => this._fsEventsHandler._addToFsEvents(path));
} else {
if (!this._readyCount) this._readyCount = 0;
this._readyCount += paths.length;
Promise.all(
paths.map(async path => {
const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, 0, 0, _origAdd);
if (res) this._emitReady();
return res;
})
).then(results => {
if (this.closed) return;
results.filter(item => item).forEach(item => {
this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item));
});
});
}
return this;
}
/**
* Close watchers or start ignoring events from specified paths.
* @param {Path|Array<Path>} paths_ - string or array of strings, file/directory paths and/or globs
* @returns {FSWatcher} for chaining
*/
unwatch(paths_) {
if (this.closed) return this;
const paths = unifyPaths(paths_);
const {cwd} = this.options;
paths.forEach((path) => {
// convert to absolute path unless relative path already matches
if (!sysPath.isAbsolute(path) && !this._closers.has(path)) {
if (cwd) path = sysPath.join(cwd, path);
path = sysPath.resolve(path);
}
this._closePath(path);
this._ignoredPaths.add(path);
if (this._watched.has(path)) {
this._ignoredPaths.add(path + SLASH_GLOBSTAR);
}
// reset the cached userIgnored anymatch fn
// to make ignoredPaths changes effective
this._userIgnored = undefined;
});
return this;
}
/**
* Close watchers and remove all listeners from watched paths.
* @returns {Promise<void>}.
*/
close() {
if (this.closed) return this._closePromise;
this.closed = true;
// Memory management.
this.removeAllListeners();
const closers = [];
this._closers.forEach(closerList => closerList.forEach(closer => {
const promise = closer();
if (promise instanceof Promise) closers.push(promise);
}));
this._streams.forEach(stream => stream.destroy());
this._userIgnored = undefined;
this._readyCount = 0;
this._readyEmitted = false;
this._watched.forEach(dirent => dirent.dispose());
['closers', 'watched', 'streams', 'symlinkPaths', 'throttled'].forEach(key => {
this[`_${key}`].clear();
});
this._closePromise = closers.length ? Promise.all(closers).then(() => undefined) : Promise.resolve();
return this._closePromise;
}
/**
* Expose list of watched paths
* @returns {Object} for chaining
*/
getWatched() {
const watchList = {};
this._watched.forEach((entry, dir) => {
const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir;
watchList[key || ONE_DOT] = entry.getChildren().sort();
});
return watchList;
}
emitWithAll(event, args) {
this.emit(...args);
if (event !== EV_ERROR) this.emit(EV_ALL, ...args);
}
// Common helpers
// --------------
/**
* Normalize and emit events.
* Calling _emit DOES NOT MEAN emit() would be called!
* @param {EventName} event Type of event
* @param {Path} path File or directory path
* @param {*=} val1 arguments to be passed with event
* @param {*=} val2
* @param {*=} val3
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
*/
async _emit(event, path, val1, val2, val3) {
if (this.closed) return;
const opts = this.options;
if (isWindows) path = sysPath.normalize(path);
if (opts.cwd) path = sysPath.relative(opts.cwd, path);
/** @type Array<any> */
const args = [event, path];
if (val3 !== undefined) args.push(val1, val2, val3);
else if (val2 !== undefined) args.push(val1, val2);
else if (val1 !== undefined) args.push(val1);
const awf = opts.awaitWriteFinish;
let pw;
if (awf && (pw = this._pendingWrites.get(path))) {
pw.lastChange = new Date();
return this;
}
if (opts.atomic) {
if (event === EV_UNLINK) {
this._pendingUnlinks.set(path, args);
setTimeout(() => {
this._pendingUnlinks.forEach((entry, path) => {
this.emit(...entry);
this.emit(EV_ALL, ...entry);
this._pendingUnlinks.delete(path);
});
}, typeof opts.atomic === 'number' ? opts.atomic : 100);
return this;
}
if (event === EV_ADD && this._pendingUnlinks.has(path)) {
event = args[0] = EV_CHANGE;
this._pendingUnlinks.delete(path);
}
}
if (awf && (event === EV_ADD || event === EV_CHANGE) && this._readyEmitted) {
const awfEmit = (err, stats) => {
if (err) {
event = args[0] = EV_ERROR;
args[1] = err;
this.emitWithAll(event, args);
} else if (stats) {
// if stats doesn't exist the file must have been deleted
if (args.length > 2) {
args[2] = stats;
} else {
args.push(stats);
}
this.emitWithAll(event, args);
}
};
this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);
return this;
}
if (event === EV_CHANGE) {
const isThrottled = !this._throttle(EV_CHANGE, path, 50);
if (isThrottled) return this;
}
if (opts.alwaysStat && val1 === undefined &&
(event === EV_ADD || event === EV_ADD_DIR || event === EV_CHANGE)
) {
const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path;
let stats;
try {
stats = await stat(fullPath);
} catch (err) {}
// Suppress event when fs_stat fails, to avoid sending undefined 'stat'
if (!stats || this.closed) return;
args.push(stats);
}
this.emitWithAll(event, args);
return this;
}
/**
* Common handler for errors
* @param {Error} error
* @returns {Error|Boolean} The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
*/
_handleError(error) {
const code = error && error.code;
if (error && code !== 'ENOENT' && code !== 'ENOTDIR' &&
(!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))
) {
this.emit(EV_ERROR, error);
}
return error || this.closed;
}
/**
* Helper utility for throttling
* @param {ThrottleType} actionType type being throttled
* @param {Path} path being acted upon
* @param {Number} timeout duration of time to suppress duplicate actions
* @returns {Object|false} tracking object or false if action should be suppressed
*/
_throttle(actionType, path, timeout) {
if (!this._throttled.has(actionType)) {
this._throttled.set(actionType, new Map());
}
/** @type {Map<Path, Object>} */
const action = this._throttled.get(actionType);
/** @type {Object} */
const actionPath = action.get(path);
if (actionPath) {
actionPath.count++;
return false;
}
let timeoutObject;
const clear = () => {
const item = action.get(path);
const count = item ? item.count : 0;
action.delete(path);
clearTimeout(timeoutObject);
if (item) clearTimeout(item.timeoutObject);
return count;
};
timeoutObject = setTimeout(clear, timeout);
const thr = {timeoutObject, clear, count: 0};
action.set(path, thr);
return thr;
}
_incrReadyCount() {
return this._readyCount++;
}
/**
* Awaits write operation to finish.
* Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
* @param {Path} path being acted upon
* @param {Number} threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
* @param {EventName} event
* @param {Function} awfEmit Callback to be called when ready for event to be emitted.
*/
_awaitWriteFinish(path, threshold, event, awfEmit) {
let timeoutHandler;
let fullPath = path;
if (this.options.cwd && !sysPath.isAbsolute(path)) {
fullPath = sysPath.join(this.options.cwd, path);
}
const now = new Date();
const awaitWriteFinish = (prevStat) => {
fs.stat(fullPath, (err, curStat) => {
if (err || !this._pendingWrites.has(path)) {
if (err && err.code !== 'ENOENT') awfEmit(err);
return;
}
const now = Number(new Date());
if (prevStat && curStat.size !== prevStat.size) {
this._pendingWrites.get(path).lastChange = now;
}
const pw = this._pendingWrites.get(path);
const df = now - pw.lastChange;
if (df >= threshold) {
this._pendingWrites.delete(path);
awfEmit(undefined, curStat);
} else {
timeoutHandler = setTimeout(
awaitWriteFinish,
this.options.awaitWriteFinish.pollInterval,
curStat
);
}
});
};
if (!this._pendingWrites.has(path)) {
this._pendingWrites.set(path, {
lastChange: now,
cancelWait: () => {
this._pendingWrites.delete(path);
clearTimeout(timeoutHandler);
return event;
}
});
timeoutHandler = setTimeout(
awaitWriteFinish,
this.options.awaitWriteFinish.pollInterval
);
}
}
_getGlobIgnored() {
return [...this._ignoredPaths.values()];
}
/**
* Determines whether user has asked to ignore this path.
* @param {Path} path filepath or dir
* @param {fs.Stats=} stats result of fs.stat
* @returns {Boolean}
*/
_isIgnored(path, stats) {
if (this.options.atomic && DOT_RE.test(path)) return true;
if (!this._userIgnored) {
const {cwd} = this.options;
const ign = this.options.ignored;
const ignored = ign && ign.map(normalizeIgnored(cwd));
const paths = arrify(ignored)
.filter((path) => typeof path === STRING_TYPE && !isGlob(path))
.map((path) => path + SLASH_GLOBSTAR);
const list = this._getGlobIgnored().map(normalizeIgnored(cwd)).concat(ignored, paths);
this._userIgnored = anymatch(list, undefined, ANYMATCH_OPTS);
}
return this._userIgnored([path, stats]);
}
_isntIgnored(path, stat) {
return !this._isIgnored(path, stat);
}
/**
* Provides a set of common helpers and properties relating to symlink and glob handling.
* @param {Path} path file, directory, or glob pattern being watched
* @param {Number=} depth at any depth > 0, this isn't a glob
* @returns {WatchHelper} object containing helpers for this path
*/
_getWatchHelpers(path, depth) {
const watchPath = depth || this.options.disableGlobbing || !isGlob(path) ? path : globParent(path);
const follow = this.options.followSymlinks;
return new WatchHelper(path, watchPath, follow, this);
}
// Directory helpers
// -----------------
/**
* Provides directory tracking objects
* @param {String} directory path of the directory
* @returns {DirEntry} the directory's tracking object
*/
_getWatchedDir(directory) {
if (!this._boundRemove) this._boundRemove = this._remove.bind(this);
const dir = sysPath.resolve(directory);
if (!this._watched.has(dir)) this._watched.set(dir, new DirEntry(dir, this._boundRemove));
return this._watched.get(dir);
}
// File helpers
// ------------
/**
* Check for read permissions.
* Based on this answer on SO: https://stackoverflow.com/a/11781404/1358405
* @param {fs.Stats} stats - object, result of fs_stat
* @returns {Boolean} indicates whether the file can be read
*/
_hasReadPermissions(stats) {
if (this.options.ignorePermissionErrors) return true;
// stats.mode may be bigint
const md = stats && Number.parseInt(stats.mode, 10);
const st = md & 0o777;
const it = Number.parseInt(st.toString(8)[0], 10);
return Boolean(4 & it);
}
/**
* Handles emitting unlink events for
* files and directories, and via recursion, for
* files and directories within directories that are unlinked
* @param {String} directory within which the following item is located
* @param {String} item base path of item/directory
* @returns {void}
*/
_remove(directory, item, isDirectory) {
// if what is being deleted is a directory, get that directory's paths
// for recursive deleting and cleaning of watched object
// if it is not a directory, nestedDirectoryChildren will be empty array
const path = sysPath.join(directory, item);
const fullPath = sysPath.resolve(path);
isDirectory = isDirectory != null
? isDirectory
: this._watched.has(path) || this._watched.has(fullPath);
// prevent duplicate handling in case of arriving here nearly simultaneously
// via multiple paths (such as _handleFile and _handleDir)
if (!this._throttle('remove', path, 100)) return;
// if the only watched file is removed, watch for its return
if (!isDirectory && !this.options.useFsEvents && this._watched.size === 1) {
this.add(directory, item, true);
}
// This will create a new entry in the watched object in either case
// so we got to do the directory check beforehand
const wp = this._getWatchedDir(path);
const nestedDirectoryChildren = wp.getChildren();
// Recursively remove children directories / files.
nestedDirectoryChildren.forEach(nested => this._remove(path, nested));
// Check if item was on the watched list and remove it
const parent = this._getWatchedDir(directory);
const wasTracked = parent.has(item);
parent.remove(item);
// Fixes issue #1042 -> Relative paths were detected and added as symlinks
// (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612),
// but never removed from the map in case the path was deleted.
// This leads to an incorrect state if the path was recreated:
// https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553
if (this._symlinkPaths.has(fullPath)) {
this._symlinkPaths.delete(fullPath);
}
// If we wait for this file to be fully written, cancel the wait.
let relPath = path;
if (this.options.cwd) relPath = sysPath.relative(this.options.cwd, path);
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
const event = this._pendingWrites.get(relPath).cancelWait();
if (event === EV_ADD) return;
}
// The Entry will either be a directory that just got removed
// or a bogus entry to a file, in either case we have to remove it
this._watched.delete(path);
this._watched.delete(fullPath);
const eventName = isDirectory ? EV_UNLINK_DIR : EV_UNLINK;
if (wasTracked && !this._isIgnored(path)) this._emit(eventName, path);
// Avoid conflicts if we later create another file with the same name
if (!this.options.useFsEvents) {
this._closePath(path);
}
}
/**
* Closes all watchers for a path
* @param {Path} path
*/
_closePath(path) {
this._closeFile(path)
const dir = sysPath.dirname(path);
this._getWatchedDir(dir).remove(sysPath.basename(path));
}
/**
* Closes only file-specific watchers
* @param {Path} path
*/
_closeFile(path) {
const closers = this._closers.get(path);
if (!closers) return;
closers.forEach(closer => closer());
this._closers.delete(path);
}
/**
*
* @param {Path} path
* @param {Function} closer
*/
_addPathCloser(path, closer) {
if (!closer) return;
let list = this._closers.get(path);
if (!list) {
list = [];
this._closers.set(path, list);
}
list.push(closer);
}
_readdirp(root, opts) {
if (this.closed) return;
const options = {type: EV_ALL, alwaysStat: true, lstat: true, ...opts};
let stream = readdirp(root, options);
this._streams.add(stream);
stream.once(STR_CLOSE, () => {
stream = undefined;
});
stream.once(STR_END, () => {
if (stream) {
this._streams.delete(stream);
stream = undefined;
}
});
return stream;
}
}
// Export FSWatcher class
exports.FSWatcher = FSWatcher;
/**
* Instantiates watcher with paths to be tracked.
* @param {String|Array<String>} paths file/directory paths and/or globs
* @param {Object=} options chokidar opts
* @returns an instance of FSWatcher for chaining.
*/
const watch = (paths, options) => {
const watcher = new FSWatcher(options);
watcher.add(paths);
return watcher;
};
exports.watch = watch;

View File

@@ -1,65 +0,0 @@
'use strict';
const {sep} = require('path');
const {platform} = process;
const os = require('os');
exports.EV_ALL = 'all';
exports.EV_READY = 'ready';
exports.EV_ADD = 'add';
exports.EV_CHANGE = 'change';
exports.EV_ADD_DIR = 'addDir';
exports.EV_UNLINK = 'unlink';
exports.EV_UNLINK_DIR = 'unlinkDir';
exports.EV_RAW = 'raw';
exports.EV_ERROR = 'error';
exports.STR_DATA = 'data';
exports.STR_END = 'end';
exports.STR_CLOSE = 'close';
exports.FSEVENT_CREATED = 'created';
exports.FSEVENT_MODIFIED = 'modified';
exports.FSEVENT_DELETED = 'deleted';
exports.FSEVENT_MOVED = 'moved';
exports.FSEVENT_CLONED = 'cloned';
exports.FSEVENT_UNKNOWN = 'unknown';
exports.FSEVENT_TYPE_FILE = 'file';
exports.FSEVENT_TYPE_DIRECTORY = 'directory';
exports.FSEVENT_TYPE_SYMLINK = 'symlink';
exports.KEY_LISTENERS = 'listeners';
exports.KEY_ERR = 'errHandlers';
exports.KEY_RAW = 'rawEmitters';
exports.HANDLER_KEYS = [exports.KEY_LISTENERS, exports.KEY_ERR, exports.KEY_RAW];
exports.DOT_SLASH = `.${sep}`;
exports.BACK_SLASH_RE = /\\/g;
exports.DOUBLE_SLASH_RE = /\/\//;
exports.SLASH_OR_BACK_SLASH_RE = /[/\\]/;
exports.DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
exports.REPLACER_RE = /^\.[/\\]/;
exports.SLASH = '/';
exports.SLASH_SLASH = '//';
exports.BRACE_START = '{';
exports.BANG = '!';
exports.ONE_DOT = '.';
exports.TWO_DOTS = '..';
exports.STAR = '*';
exports.GLOBSTAR = '**';
exports.ROOT_GLOBSTAR = '/**/*';
exports.SLASH_GLOBSTAR = '/**';
exports.DIR_SUFFIX = 'Dir';
exports.ANYMATCH_OPTS = {dot: true};
exports.STRING_TYPE = 'string';
exports.FUNCTION_TYPE = 'function';
exports.EMPTY_STR = '';
exports.EMPTY_FN = () => {};
exports.IDENTITY_FN = val => val;
exports.isWindows = platform === 'win32';
exports.isMacos = platform === 'darwin';
exports.isLinux = platform === 'linux';
exports.isIBMi = os.type() === 'OS400';

View File

@@ -1,524 +0,0 @@
'use strict';
const fs = require('fs');
const sysPath = require('path');
const { promisify } = require('util');
let fsevents;
try {
fsevents = require('fsevents');
} catch (error) {
if (process.env.CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR) console.error(error);
}
if (fsevents) {
// TODO: real check
const mtch = process.version.match(/v(\d+)\.(\d+)/);
if (mtch && mtch[1] && mtch[2]) {
const maj = Number.parseInt(mtch[1], 10);
const min = Number.parseInt(mtch[2], 10);
if (maj === 8 && min < 16) {
fsevents = undefined;
}
}
}
const {
EV_ADD,
EV_CHANGE,
EV_ADD_DIR,
EV_UNLINK,
EV_ERROR,
STR_DATA,
STR_END,
FSEVENT_CREATED,
FSEVENT_MODIFIED,
FSEVENT_DELETED,
FSEVENT_MOVED,
// FSEVENT_CLONED,
FSEVENT_UNKNOWN,
FSEVENT_TYPE_FILE,
FSEVENT_TYPE_DIRECTORY,
FSEVENT_TYPE_SYMLINK,
ROOT_GLOBSTAR,
DIR_SUFFIX,
DOT_SLASH,
FUNCTION_TYPE,
EMPTY_FN,
IDENTITY_FN
} = require('./constants');
const Depth = (value) => isNaN(value) ? {} : {depth: value};
const stat = promisify(fs.stat);
const lstat = promisify(fs.lstat);
const realpath = promisify(fs.realpath);
const statMethods = { stat, lstat };
/**
* @typedef {String} Path
*/
/**
* @typedef {Object} FsEventsWatchContainer
* @property {Set<Function>} listeners
* @property {Function} rawEmitter
* @property {{stop: Function}} watcher
*/
// fsevents instance helper functions
/**
* Object to hold per-process fsevents instances (may be shared across chokidar FSWatcher instances)
* @type {Map<Path,FsEventsWatchContainer>}
*/
const FSEventsWatchers = new Map();
// Threshold of duplicate path prefixes at which to start
// consolidating going forward
const consolidateThreshhold = 10;
const wrongEventFlags = new Set([
69888, 70400, 71424, 72704, 73472, 131328, 131840, 262912
]);
/**
* Instantiates the fsevents interface
* @param {Path} path path to be watched
* @param {Function} callback called when fsevents is bound and ready
* @returns {{stop: Function}} new fsevents instance
*/
const createFSEventsInstance = (path, callback) => {
const stop = fsevents.watch(path, callback);
return {stop};
};
/**
* Instantiates the fsevents interface or binds listeners to an existing one covering
* the same file tree.
* @param {Path} path - to be watched
* @param {Path} realPath - real path for symlinks
* @param {Function} listener - called when fsevents emits events
* @param {Function} rawEmitter - passes data to listeners of the 'raw' event
* @returns {Function} closer
*/
function setFSEventsListener(path, realPath, listener, rawEmitter) {
let watchPath = sysPath.extname(realPath) ? sysPath.dirname(realPath) : realPath;
const parentPath = sysPath.dirname(watchPath);
let cont = FSEventsWatchers.get(watchPath);
// If we've accumulated a substantial number of paths that
// could have been consolidated by watching one directory
// above the current one, create a watcher on the parent
// path instead, so that we do consolidate going forward.
if (couldConsolidate(parentPath)) {
watchPath = parentPath;
}
const resolvedPath = sysPath.resolve(path);
const hasSymlink = resolvedPath !== realPath;
const filteredListener = (fullPath, flags, info) => {
if (hasSymlink) fullPath = fullPath.replace(realPath, resolvedPath);
if (
fullPath === resolvedPath ||
!fullPath.indexOf(resolvedPath + sysPath.sep)
) listener(fullPath, flags, info);
};
// check if there is already a watcher on a parent path
// modifies `watchPath` to the parent path when it finds a match
let watchedParent = false;
for (const watchedPath of FSEventsWatchers.keys()) {
if (realPath.indexOf(sysPath.resolve(watchedPath) + sysPath.sep) === 0) {
watchPath = watchedPath;
cont = FSEventsWatchers.get(watchPath);
watchedParent = true;
break;
}
}
if (cont || watchedParent) {
cont.listeners.add(filteredListener);
} else {
cont = {
listeners: new Set([filteredListener]),
rawEmitter,
watcher: createFSEventsInstance(watchPath, (fullPath, flags) => {
if (!cont.listeners.size) return;
const info = fsevents.getInfo(fullPath, flags);
cont.listeners.forEach(list => {
list(fullPath, flags, info);
});
cont.rawEmitter(info.event, fullPath, info);
})
};
FSEventsWatchers.set(watchPath, cont);
}
// removes this instance's listeners and closes the underlying fsevents
// instance if there are no more listeners left
return () => {
const lst = cont.listeners;
lst.delete(filteredListener);
if (!lst.size) {
FSEventsWatchers.delete(watchPath);
if (cont.watcher) return cont.watcher.stop().then(() => {
cont.rawEmitter = cont.watcher = undefined;
Object.freeze(cont);
});
}
};
}
// Decide whether or not we should start a new higher-level
// parent watcher
const couldConsolidate = (path) => {
let count = 0;
for (const watchPath of FSEventsWatchers.keys()) {
if (watchPath.indexOf(path) === 0) {
count++;
if (count >= consolidateThreshhold) {
return true;
}
}
}
return false;
};
// returns boolean indicating whether fsevents can be used
const canUse = () => fsevents && FSEventsWatchers.size < 128;
// determines subdirectory traversal levels from root to path
const calcDepth = (path, root) => {
let i = 0;
while (!path.indexOf(root) && (path = sysPath.dirname(path)) !== root) i++;
return i;
};
// returns boolean indicating whether the fsevents' event info has the same type
// as the one returned by fs.stat
const sameTypes = (info, stats) => (
info.type === FSEVENT_TYPE_DIRECTORY && stats.isDirectory() ||
info.type === FSEVENT_TYPE_SYMLINK && stats.isSymbolicLink() ||
info.type === FSEVENT_TYPE_FILE && stats.isFile()
)
/**
* @mixin
*/
class FsEventsHandler {
/**
* @param {import('../index').FSWatcher} fsw
*/
constructor(fsw) {
this.fsw = fsw;
}
checkIgnored(path, stats) {
const ipaths = this.fsw._ignoredPaths;
if (this.fsw._isIgnored(path, stats)) {
ipaths.add(path);
if (stats && stats.isDirectory()) {
ipaths.add(path + ROOT_GLOBSTAR);
}
return true;
}
ipaths.delete(path);
ipaths.delete(path + ROOT_GLOBSTAR);
}
addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts) {
const event = watchedDir.has(item) ? EV_CHANGE : EV_ADD;
this.handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts);
}
async checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts) {
try {
const stats = await stat(path)
if (this.fsw.closed) return;
if (sameTypes(info, stats)) {
this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
} else {
this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts);
}
} catch (error) {
if (error.code === 'EACCES') {
this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
} else {
this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts);
}
}
}
handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts) {
if (this.fsw.closed || this.checkIgnored(path)) return;
if (event === EV_UNLINK) {
const isDirectory = info.type === FSEVENT_TYPE_DIRECTORY
// suppress unlink events on never before seen files
if (isDirectory || watchedDir.has(item)) {
this.fsw._remove(parent, item, isDirectory);
}
} else {
if (event === EV_ADD) {
// track new directories
if (info.type === FSEVENT_TYPE_DIRECTORY) this.fsw._getWatchedDir(path);
if (info.type === FSEVENT_TYPE_SYMLINK && opts.followSymlinks) {
// push symlinks back to the top of the stack to get handled
const curDepth = opts.depth === undefined ?
undefined : calcDepth(fullPath, realPath) + 1;
return this._addToFsEvents(path, false, true, curDepth);
}
// track new paths
// (other than symlinks being followed, which will be tracked soon)
this.fsw._getWatchedDir(parent).add(item);
}
/**
* @type {'add'|'addDir'|'unlink'|'unlinkDir'}
*/
const eventName = info.type === FSEVENT_TYPE_DIRECTORY ? event + DIR_SUFFIX : event;
this.fsw._emit(eventName, path);
if (eventName === EV_ADD_DIR) this._addToFsEvents(path, false, true);
}
}
/**
* Handle symlinks encountered during directory scan
* @param {String} watchPath - file/dir path to be watched with fsevents
* @param {String} realPath - real path (in case of symlinks)
* @param {Function} transform - path transformer
* @param {Function} globFilter - path filter in case a glob pattern was provided
* @returns {Function} closer for the watcher instance
*/
_watchWithFsEvents(watchPath, realPath, transform, globFilter) {
if (this.fsw.closed || this.fsw._isIgnored(watchPath)) return;
const opts = this.fsw.options;
const watchCallback = async (fullPath, flags, info) => {
if (this.fsw.closed) return;
if (
opts.depth !== undefined &&
calcDepth(fullPath, realPath) > opts.depth
) return;
const path = transform(sysPath.join(
watchPath, sysPath.relative(watchPath, fullPath)
));
if (globFilter && !globFilter(path)) return;
// ensure directories are tracked
const parent = sysPath.dirname(path);
const item = sysPath.basename(path);
const watchedDir = this.fsw._getWatchedDir(
info.type === FSEVENT_TYPE_DIRECTORY ? path : parent
);
// correct for wrong events emitted
if (wrongEventFlags.has(flags) || info.event === FSEVENT_UNKNOWN) {
if (typeof opts.ignored === FUNCTION_TYPE) {
let stats;
try {
stats = await stat(path);
} catch (error) {}
if (this.fsw.closed) return;
if (this.checkIgnored(path, stats)) return;
if (sameTypes(info, stats)) {
this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
} else {
this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts);
}
} else {
this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts);
}
} else {
switch (info.event) {
case FSEVENT_CREATED:
case FSEVENT_MODIFIED:
return this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
case FSEVENT_DELETED:
case FSEVENT_MOVED:
return this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts);
}
}
};
const closer = setFSEventsListener(
watchPath,
realPath,
watchCallback,
this.fsw._emitRaw
);
this.fsw._emitReady();
return closer;
}
/**
* Handle symlinks encountered during directory scan
* @param {String} linkPath path to symlink
* @param {String} fullPath absolute path to the symlink
* @param {Function} transform pre-existing path transformer
* @param {Number} curDepth level of subdirectories traversed to where symlink is
* @returns {Promise<void>}
*/
async _handleFsEventsSymlink(linkPath, fullPath, transform, curDepth) {
// don't follow the same symlink more than once
if (this.fsw.closed || this.fsw._symlinkPaths.has(fullPath)) return;
this.fsw._symlinkPaths.set(fullPath, true);
this.fsw._incrReadyCount();
try {
const linkTarget = await realpath(linkPath);
if (this.fsw.closed) return;
if (this.fsw._isIgnored(linkTarget)) {
return this.fsw._emitReady();
}
this.fsw._incrReadyCount();
// add the linkTarget for watching with a wrapper for transform
// that causes emitted paths to incorporate the link's path
this._addToFsEvents(linkTarget || linkPath, (path) => {
let aliasedPath = linkPath;
if (linkTarget && linkTarget !== DOT_SLASH) {
aliasedPath = path.replace(linkTarget, linkPath);
} else if (path !== DOT_SLASH) {
aliasedPath = sysPath.join(linkPath, path);
}
return transform(aliasedPath);
}, false, curDepth);
} catch(error) {
if (this.fsw._handleError(error)) {
return this.fsw._emitReady();
}
}
}
/**
*
* @param {Path} newPath
* @param {fs.Stats} stats
*/
emitAdd(newPath, stats, processPath, opts, forceAdd) {
const pp = processPath(newPath);
const isDir = stats.isDirectory();
const dirObj = this.fsw._getWatchedDir(sysPath.dirname(pp));
const base = sysPath.basename(pp);
// ensure empty dirs get tracked
if (isDir) this.fsw._getWatchedDir(pp);
if (dirObj.has(base)) return;
dirObj.add(base);
if (!opts.ignoreInitial || forceAdd === true) {
this.fsw._emit(isDir ? EV_ADD_DIR : EV_ADD, pp, stats);
}
}
initWatch(realPath, path, wh, processPath) {
if (this.fsw.closed) return;
const closer = this._watchWithFsEvents(
wh.watchPath,
sysPath.resolve(realPath || wh.watchPath),
processPath,
wh.globFilter
);
this.fsw._addPathCloser(path, closer);
}
/**
* Handle added path with fsevents
* @param {String} path file/dir path or glob pattern
* @param {Function|Boolean=} transform converts working path to what the user expects
* @param {Boolean=} forceAdd ensure add is emitted
* @param {Number=} priorDepth Level of subdirectories already traversed.
* @returns {Promise<void>}
*/
async _addToFsEvents(path, transform, forceAdd, priorDepth) {
if (this.fsw.closed) {
return;
}
const opts = this.fsw.options;
const processPath = typeof transform === FUNCTION_TYPE ? transform : IDENTITY_FN;
const wh = this.fsw._getWatchHelpers(path);
// evaluate what is at the path we're being asked to watch
try {
const stats = await statMethods[wh.statMethod](wh.watchPath);
if (this.fsw.closed) return;
if (this.fsw._isIgnored(wh.watchPath, stats)) {
throw null;
}
if (stats.isDirectory()) {
// emit addDir unless this is a glob parent
if (!wh.globFilter) this.emitAdd(processPath(path), stats, processPath, opts, forceAdd);
// don't recurse further if it would exceed depth setting
if (priorDepth && priorDepth > opts.depth) return;
// scan the contents of the dir
this.fsw._readdirp(wh.watchPath, {
fileFilter: entry => wh.filterPath(entry),
directoryFilter: entry => wh.filterDir(entry),
...Depth(opts.depth - (priorDepth || 0))
}).on(STR_DATA, (entry) => {
// need to check filterPath on dirs b/c filterDir is less restrictive
if (this.fsw.closed) {
return;
}
if (entry.stats.isDirectory() && !wh.filterPath(entry)) return;
const joinedPath = sysPath.join(wh.watchPath, entry.path);
const {fullPath} = entry;
if (wh.followSymlinks && entry.stats.isSymbolicLink()) {
// preserve the current depth here since it can't be derived from
// real paths past the symlink
const curDepth = opts.depth === undefined ?
undefined : calcDepth(joinedPath, sysPath.resolve(wh.watchPath)) + 1;
this._handleFsEventsSymlink(joinedPath, fullPath, processPath, curDepth);
} else {
this.emitAdd(joinedPath, entry.stats, processPath, opts, forceAdd);
}
}).on(EV_ERROR, EMPTY_FN).on(STR_END, () => {
this.fsw._emitReady();
});
} else {
this.emitAdd(wh.watchPath, stats, processPath, opts, forceAdd);
this.fsw._emitReady();
}
} catch (error) {
if (!error || this.fsw._handleError(error)) {
// TODO: Strange thing: "should not choke on an ignored watch path" will be failed without 2 ready calls -__-
this.fsw._emitReady();
this.fsw._emitReady();
}
}
if (opts.persistent && forceAdd !== true) {
if (typeof transform === FUNCTION_TYPE) {
// realpath has already been resolved
this.initWatch(undefined, path, wh, processPath);
} else {
let realPath;
try {
realPath = await realpath(wh.watchPath);
} catch (e) {}
this.initWatch(realPath, path, wh, processPath);
}
}
}
}
module.exports = FsEventsHandler;
module.exports.canUse = canUse;

View File

@@ -1,646 +0,0 @@
'use strict';
const fs = require('fs');
const sysPath = require('path');
const { promisify } = require('util');
const isBinaryPath = require('is-binary-path');
const {
isWindows,
isLinux,
EMPTY_FN,
EMPTY_STR,
KEY_LISTENERS,
KEY_ERR,
KEY_RAW,
HANDLER_KEYS,
EV_CHANGE,
EV_ADD,
EV_ADD_DIR,
EV_ERROR,
STR_DATA,
STR_END,
BRACE_START,
STAR
} = require('./constants');
const THROTTLE_MODE_WATCH = 'watch';
const open = promisify(fs.open);
const stat = promisify(fs.stat);
const lstat = promisify(fs.lstat);
const close = promisify(fs.close);
const fsrealpath = promisify(fs.realpath);
const statMethods = { lstat, stat };
// TODO: emit errors properly. Example: EMFILE on Macos.
const foreach = (val, fn) => {
if (val instanceof Set) {
val.forEach(fn);
} else {
fn(val);
}
};
const addAndConvert = (main, prop, item) => {
let container = main[prop];
if (!(container instanceof Set)) {
main[prop] = container = new Set([container]);
}
container.add(item);
};
const clearItem = cont => key => {
const set = cont[key];
if (set instanceof Set) {
set.clear();
} else {
delete cont[key];
}
};
const delFromSet = (main, prop, item) => {
const container = main[prop];
if (container instanceof Set) {
container.delete(item);
} else if (container === item) {
delete main[prop];
}
};
const isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
/**
* @typedef {String} Path
*/
// fs_watch helpers
// object to hold per-process fs_watch instances
// (may be shared across chokidar FSWatcher instances)
/**
* @typedef {Object} FsWatchContainer
* @property {Set} listeners
* @property {Set} errHandlers
* @property {Set} rawEmitters
* @property {fs.FSWatcher=} watcher
* @property {Boolean=} watcherUnusable
*/
/**
* @type {Map<String,FsWatchContainer>}
*/
const FsWatchInstances = new Map();
/**
* Instantiates the fs_watch interface
* @param {String} path to be watched
* @param {Object} options to be passed to fs_watch
* @param {Function} listener main event handler
* @param {Function} errHandler emits info about errors
* @param {Function} emitRaw emits raw event data
* @returns {fs.FSWatcher} new fsevents instance
*/
function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
const handleEvent = (rawEvent, evPath) => {
listener(path);
emitRaw(rawEvent, evPath, {watchedPath: path});
// emit based on events occurring for files from a directory's watcher in
// case the file's watcher misses it (and rely on throttling to de-dupe)
if (evPath && path !== evPath) {
fsWatchBroadcast(
sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath)
);
}
};
try {
return fs.watch(path, options, handleEvent);
} catch (error) {
errHandler(error);
}
}
/**
* Helper for passing fs_watch event data to a collection of listeners
* @param {Path} fullPath absolute path bound to fs_watch instance
* @param {String} type listener type
* @param {*=} val1 arguments to be passed to listeners
* @param {*=} val2
* @param {*=} val3
*/
const fsWatchBroadcast = (fullPath, type, val1, val2, val3) => {
const cont = FsWatchInstances.get(fullPath);
if (!cont) return;
foreach(cont[type], (listener) => {
listener(val1, val2, val3);
});
};
/**
* Instantiates the fs_watch interface or binds listeners
* to an existing one covering the same file system entry
* @param {String} path
* @param {String} fullPath absolute path
* @param {Object} options to be passed to fs_watch
* @param {Object} handlers container for event listener functions
*/
const setFsWatchListener = (path, fullPath, options, handlers) => {
const {listener, errHandler, rawEmitter} = handlers;
let cont = FsWatchInstances.get(fullPath);
/** @type {fs.FSWatcher=} */
let watcher;
if (!options.persistent) {
watcher = createFsWatchInstance(
path, options, listener, errHandler, rawEmitter
);
return watcher.close.bind(watcher);
}
if (cont) {
addAndConvert(cont, KEY_LISTENERS, listener);
addAndConvert(cont, KEY_ERR, errHandler);
addAndConvert(cont, KEY_RAW, rawEmitter);
} else {
watcher = createFsWatchInstance(
path,
options,
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
errHandler, // no need to use broadcast here
fsWatchBroadcast.bind(null, fullPath, KEY_RAW)
);
if (!watcher) return;
watcher.on(EV_ERROR, async (error) => {
const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);
cont.watcherUnusable = true; // documented since Node 10.4.1
// Workaround for https://github.com/joyent/node/issues/4337
if (isWindows && error.code === 'EPERM') {
try {
const fd = await open(path, 'r');
await close(fd);
broadcastErr(error);
} catch (err) {}
} else {
broadcastErr(error);
}
});
cont = {
listeners: listener,
errHandlers: errHandler,
rawEmitters: rawEmitter,
watcher
};
FsWatchInstances.set(fullPath, cont);
}
// const index = cont.listeners.indexOf(listener);
// removes this instance's listeners and closes the underlying fs_watch
// instance if there are no more listeners left
return () => {
delFromSet(cont, KEY_LISTENERS, listener);
delFromSet(cont, KEY_ERR, errHandler);
delFromSet(cont, KEY_RAW, rawEmitter);
if (isEmptySet(cont.listeners)) {
// Check to protect against issue gh-730.
// if (cont.watcherUnusable) {
cont.watcher.close();
// }
FsWatchInstances.delete(fullPath);
HANDLER_KEYS.forEach(clearItem(cont));
cont.watcher = undefined;
Object.freeze(cont);
}
};
};
// fs_watchFile helpers
// object to hold per-process fs_watchFile instances
// (may be shared across chokidar FSWatcher instances)
const FsWatchFileInstances = new Map();
/**
* Instantiates the fs_watchFile interface or binds listeners
* to an existing one covering the same file system entry
* @param {String} path to be watched
* @param {String} fullPath absolute path
* @param {Object} options options to be passed to fs_watchFile
* @param {Object} handlers container for event listener functions
* @returns {Function} closer
*/
const setFsWatchFileListener = (path, fullPath, options, handlers) => {
const {listener, rawEmitter} = handlers;
let cont = FsWatchFileInstances.get(fullPath);
/* eslint-disable no-unused-vars, prefer-destructuring */
let listeners = new Set();
let rawEmitters = new Set();
const copts = cont && cont.options;
if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
// "Upgrade" the watcher to persistence or a quicker interval.
// This creates some unlikely edge case issues if the user mixes
// settings in a very weird way, but solving for those cases
// doesn't seem worthwhile for the added complexity.
listeners = cont.listeners;
rawEmitters = cont.rawEmitters;
fs.unwatchFile(fullPath);
cont = undefined;
}
/* eslint-enable no-unused-vars, prefer-destructuring */
if (cont) {
addAndConvert(cont, KEY_LISTENERS, listener);
addAndConvert(cont, KEY_RAW, rawEmitter);
} else {
// TODO
// listeners.add(listener);
// rawEmitters.add(rawEmitter);
cont = {
listeners: listener,
rawEmitters: rawEmitter,
options,
watcher: fs.watchFile(fullPath, options, (curr, prev) => {
foreach(cont.rawEmitters, (rawEmitter) => {
rawEmitter(EV_CHANGE, fullPath, {curr, prev});
});
const currmtime = curr.mtimeMs;
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
foreach(cont.listeners, (listener) => listener(path, curr));
}
})
};
FsWatchFileInstances.set(fullPath, cont);
}
// const index = cont.listeners.indexOf(listener);
// Removes this instance's listeners and closes the underlying fs_watchFile
// instance if there are no more listeners left.
return () => {
delFromSet(cont, KEY_LISTENERS, listener);
delFromSet(cont, KEY_RAW, rawEmitter);
if (isEmptySet(cont.listeners)) {
FsWatchFileInstances.delete(fullPath);
fs.unwatchFile(fullPath);
cont.options = cont.watcher = undefined;
Object.freeze(cont);
}
};
};
/**
* @mixin
*/
class NodeFsHandler {
/**
* @param {import("../index").FSWatcher} fsW
*/
constructor(fsW) {
this.fsw = fsW;
this._boundHandleError = (error) => fsW._handleError(error);
}
/**
* Watch file for changes with fs_watchFile or fs_watch.
* @param {String} path to file or dir
* @param {Function} listener on fs change
* @returns {Function} closer for the watcher instance
*/
_watchWithNodeFs(path, listener) {
const opts = this.fsw.options;
const directory = sysPath.dirname(path);
const basename = sysPath.basename(path);
const parent = this.fsw._getWatchedDir(directory);
parent.add(basename);
const absolutePath = sysPath.resolve(path);
const options = {persistent: opts.persistent};
if (!listener) listener = EMPTY_FN;
let closer;
if (opts.usePolling) {
options.interval = opts.enableBinaryInterval && isBinaryPath(basename) ?
opts.binaryInterval : opts.interval;
closer = setFsWatchFileListener(path, absolutePath, options, {
listener,
rawEmitter: this.fsw._emitRaw
});
} else {
closer = setFsWatchListener(path, absolutePath, options, {
listener,
errHandler: this._boundHandleError,
rawEmitter: this.fsw._emitRaw
});
}
return closer;
}
/**
* Watch a file and emit add event if warranted.
* @param {Path} file Path
* @param {fs.Stats} stats result of fs_stat
* @param {Boolean} initialAdd was the file added at watch instantiation?
* @returns {Function} closer for the watcher instance
*/
_handleFile(file, stats, initialAdd) {
if (this.fsw.closed) {
return;
}
const dirname = sysPath.dirname(file);
const basename = sysPath.basename(file);
const parent = this.fsw._getWatchedDir(dirname);
// stats is always present
let prevStats = stats;
// if the file is already being watched, do nothing
if (parent.has(basename)) return;
const listener = async (path, newStats) => {
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5)) return;
if (!newStats || newStats.mtimeMs === 0) {
try {
const newStats = await stat(file);
if (this.fsw.closed) return;
// Check that change event was not fired because of changed only accessTime.
const at = newStats.atimeMs;
const mt = newStats.mtimeMs;
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
this.fsw._emit(EV_CHANGE, file, newStats);
}
if (isLinux && prevStats.ino !== newStats.ino) {
this.fsw._closeFile(path)
prevStats = newStats;
this.fsw._addPathCloser(path, this._watchWithNodeFs(file, listener));
} else {
prevStats = newStats;
}
} catch (error) {
// Fix issues where mtime is null but file is still present
this.fsw._remove(dirname, basename);
}
// add is about to be emitted if file not already tracked in parent
} else if (parent.has(basename)) {
// Check that change event was not fired because of changed only accessTime.
const at = newStats.atimeMs;
const mt = newStats.mtimeMs;
if (!at || at <= mt || mt !== prevStats.mtimeMs) {
this.fsw._emit(EV_CHANGE, file, newStats);
}
prevStats = newStats;
}
}
// kick off the watcher
const closer = this._watchWithNodeFs(file, listener);
// emit an add event if we're supposed to
if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {
if (!this.fsw._throttle(EV_ADD, file, 0)) return;
this.fsw._emit(EV_ADD, file, stats);
}
return closer;
}
/**
* Handle symlinks encountered while reading a dir.
* @param {Object} entry returned by readdirp
* @param {String} directory path of dir being read
* @param {String} path of this item
* @param {String} item basename of this item
* @returns {Promise<Boolean>} true if no more processing is needed for this entry.
*/
async _handleSymlink(entry, directory, path, item) {
if (this.fsw.closed) {
return;
}
const full = entry.fullPath;
const dir = this.fsw._getWatchedDir(directory);
if (!this.fsw.options.followSymlinks) {
// watch symlink directly (don't follow) and detect changes
this.fsw._incrReadyCount();
const linkPath = await fsrealpath(path);
if (this.fsw.closed) return;
if (dir.has(item)) {
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
this.fsw._symlinkPaths.set(full, linkPath);
this.fsw._emit(EV_CHANGE, path, entry.stats);
}
} else {
dir.add(item);
this.fsw._symlinkPaths.set(full, linkPath);
this.fsw._emit(EV_ADD, path, entry.stats);
}
this.fsw._emitReady();
return true;
}
// don't follow the same symlink more than once
if (this.fsw._symlinkPaths.has(full)) {
return true;
}
this.fsw._symlinkPaths.set(full, true);
}
_handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
// Normalize the directory name on Windows
directory = sysPath.join(directory, EMPTY_STR);
if (!wh.hasGlob) {
throttler = this.fsw._throttle('readdir', directory, 1000);
if (!throttler) return;
}
const previous = this.fsw._getWatchedDir(wh.path);
const current = new Set();
let stream = this.fsw._readdirp(directory, {
fileFilter: entry => wh.filterPath(entry),
directoryFilter: entry => wh.filterDir(entry),
depth: 0
}).on(STR_DATA, async (entry) => {
if (this.fsw.closed) {
stream = undefined;
return;
}
const item = entry.path;
let path = sysPath.join(directory, item);
current.add(item);
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path, item)) {
return;
}
if (this.fsw.closed) {
stream = undefined;
return;
}
// Files that present in current directory snapshot
// but absent in previous are added to watch list and
// emit `add` event.
if (item === target || !target && !previous.has(item)) {
this.fsw._incrReadyCount();
// ensure relativeness of path is preserved in case of watcher reuse
path = sysPath.join(dir, sysPath.relative(dir, path));
this._addToNodeFs(path, initialAdd, wh, depth + 1);
}
}).on(EV_ERROR, this._boundHandleError);
return new Promise(resolve =>
stream.once(STR_END, () => {
if (this.fsw.closed) {
stream = undefined;
return;
}
const wasThrottled = throttler ? throttler.clear() : false;
resolve();
// Files that absent in current directory snapshot
// but present in previous emit `remove` event
// and are removed from @watched[directory].
previous.getChildren().filter((item) => {
return item !== directory &&
!current.has(item) &&
// in case of intersecting globs;
// a path may have been filtered out of this readdir, but
// shouldn't be removed because it matches a different glob
(!wh.hasGlob || wh.filterPath({
fullPath: sysPath.resolve(directory, item)
}));
}).forEach((item) => {
this.fsw._remove(directory, item);
});
stream = undefined;
// one more time for any missed in case changes came in extremely quickly
if (wasThrottled) this._handleRead(directory, false, wh, target, dir, depth, throttler);
})
);
}
/**
* Read directory to add / remove files from `@watched` list and re-read it on change.
* @param {String} dir fs path
* @param {fs.Stats} stats
* @param {Boolean} initialAdd
* @param {Number} depth relative to user-supplied path
* @param {String} target child path targeted for watch
* @param {Object} wh Common watch helpers for this path
* @param {String} realpath
* @returns {Promise<Function>} closer for the watcher instance.
*/
async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {
const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
const tracked = parentDir.has(sysPath.basename(dir));
if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
if (!wh.hasGlob || wh.globFilter(dir)) this.fsw._emit(EV_ADD_DIR, dir, stats);
}
// ensure dir is tracked (harmless if redundant)
parentDir.add(sysPath.basename(dir));
this.fsw._getWatchedDir(dir);
let throttler;
let closer;
const oDepth = this.fsw.options.depth;
if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {
if (!target) {
await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);
if (this.fsw.closed) return;
}
closer = this._watchWithNodeFs(dir, (dirPath, stats) => {
// if current directory is removed, do nothing
if (stats && stats.mtimeMs === 0) return;
this._handleRead(dirPath, false, wh, target, dir, depth, throttler);
});
}
return closer;
}
/**
* Handle added file, directory, or glob pattern.
* Delegates call to _handleFile / _handleDir after checks.
* @param {String} path to file or ir
* @param {Boolean} initialAdd was the file added at watch instantiation?
* @param {Object} priorWh depth relative to user-supplied path
* @param {Number} depth Child path actually targeted for watch
* @param {String=} target Child path actually targeted for watch
* @returns {Promise}
*/
async _addToNodeFs(path, initialAdd, priorWh, depth, target) {
const ready = this.fsw._emitReady;
if (this.fsw._isIgnored(path) || this.fsw.closed) {
ready();
return false;
}
const wh = this.fsw._getWatchHelpers(path, depth);
if (!wh.hasGlob && priorWh) {
wh.hasGlob = priorWh.hasGlob;
wh.globFilter = priorWh.globFilter;
wh.filterPath = entry => priorWh.filterPath(entry);
wh.filterDir = entry => priorWh.filterDir(entry);
}
// evaluate what is at the path we're being asked to watch
try {
const stats = await statMethods[wh.statMethod](wh.watchPath);
if (this.fsw.closed) return;
if (this.fsw._isIgnored(wh.watchPath, stats)) {
ready();
return false;
}
const follow = this.fsw.options.followSymlinks && !path.includes(STAR) && !path.includes(BRACE_START);
let closer;
if (stats.isDirectory()) {
const absPath = sysPath.resolve(path);
const targetPath = follow ? await fsrealpath(path) : path;
if (this.fsw.closed) return;
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
if (this.fsw.closed) return;
// preserve this symlink's target path
if (absPath !== targetPath && targetPath !== undefined) {
this.fsw._symlinkPaths.set(absPath, targetPath);
}
} else if (stats.isSymbolicLink()) {
const targetPath = follow ? await fsrealpath(path) : path;
if (this.fsw.closed) return;
const parent = sysPath.dirname(wh.watchPath);
this.fsw._getWatchedDir(parent).add(wh.watchPath);
this.fsw._emit(EV_ADD, wh.watchPath, stats);
closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
if (this.fsw.closed) return;
// preserve this symlink's target path
if (targetPath !== undefined) {
this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);
}
} else {
closer = this._handleFile(wh.watchPath, stats, initialAdd);
}
ready();
this.fsw._addPathCloser(path, closer);
return false;
} catch (error) {
if (this.fsw._handleError(error)) {
ready();
return path;
}
}
}
}
module.exports = NodeFsHandler;

View File

@@ -1,78 +0,0 @@
{
"name": "chokidar",
"description": "Minimal and efficient cross-platform file watching library",
"version": "3.5.2",
"homepage": "https://github.com/paulmillr/chokidar",
"author": "Paul Miller (https://paulmillr.com)",
"contributors": [
"Paul Miller (https://paulmillr.com)",
"Elan Shanker"
],
"engines": {
"node": ">= 8.10.0"
},
"main": "index.js",
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
},
"devDependencies": {
"@types/node": "^14",
"chai": "^4.3",
"dtslint": "^3.3.0",
"eslint": "^7.0.0",
"mocha": "^7.0.0",
"nyc": "^15.0.0",
"rimraf": "^3.0.0",
"sinon": "^9.0.1",
"sinon-chai": "^3.3.0",
"upath": "^1.2.0"
},
"files": [
"index.js",
"lib/*.js",
"types/index.d.ts"
],
"repository": {
"type": "git",
"url": "git+https://github.com/paulmillr/chokidar.git"
},
"bugs": {
"url": "https://github.com/paulmillr/chokidar/issues"
},
"license": "MIT",
"scripts": {
"dtslint": "dtslint types",
"lint": "eslint --report-unused-disable-directives --ignore-path .gitignore .",
"mocha": "mocha --exit --timeout 90000",
"test": "npm run lint && npm run mocha"
},
"keywords": [
"fs",
"watch",
"watchFile",
"watcher",
"watching",
"file",
"fsevents"
],
"types": "./types/index.d.ts",
"nyc": {
"include": [
"index.js",
"lib/*.js"
],
"reporter": [
"html",
"text"
]
}
}

View File

@@ -1,187 +0,0 @@
// TypeScript Version: 3.0
/// <reference types="node" />
import * as fs from "fs";
import { EventEmitter } from "events";
export class FSWatcher extends EventEmitter implements fs.FSWatcher {
options: WatchOptions;
/**
* Constructs a new FSWatcher instance with optional WatchOptions parameter.
*/
constructor(options?: WatchOptions);
/**
* Add files, directories, or glob patterns for tracking. Takes an array of strings or just one
* string.
*/
add(paths: string | ReadonlyArray<string>): void;
/**
* Stop watching files, directories, or glob patterns. Takes an array of strings or just one
* string.
*/
unwatch(paths: string | ReadonlyArray<string>): void;
/**
* Returns an object representing all the paths on the file system being watched by this
* `FSWatcher` instance. The object's keys are all the directories (using absolute paths unless
* the `cwd` option was used), and the values are arrays of the names of the items contained in
* each directory.
*/
getWatched(): {
[directory: string]: string[];
};
/**
* Removes all listeners from watched files.
*/
close(): Promise<void>;
on(event: 'add'|'addDir'|'change', listener: (path: string, stats?: fs.Stats) => void): this;
on(event: 'all', listener: (eventName: 'add'|'addDir'|'change'|'unlink'|'unlinkDir', path: string, stats?: fs.Stats) => void): this;
/**
* Error occurred
*/
on(event: 'error', listener: (error: Error) => void): this;
/**
* Exposes the native Node `fs.FSWatcher events`
*/
on(event: 'raw', listener: (eventName: string, path: string, details: any) => void): this;
/**
* Fires when the initial scan is complete
*/
on(event: 'ready', listener: () => void): this;
on(event: 'unlink'|'unlinkDir', listener: (path: string) => void): this;
on(event: string, listener: (...args: any[]) => void): this;
}
export interface WatchOptions {
/**
* Indicates whether the process should continue to run as long as files are being watched. If
* set to `false` when using `fsevents` to watch, no more events will be emitted after `ready`,
* even if the process continues to run.
*/
persistent?: boolean;
/**
* ([anymatch](https://github.com/micromatch/anymatch)-compatible definition) Defines files/paths to
* be ignored. The whole relative or absolute path is tested, not just filename. If a function
* with two arguments is provided, it gets called twice per path - once with a single argument
* (the path), second time with two arguments (the path and the
* [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object of that path).
*/
ignored?: any;
/**
* If set to `false` then `add`/`addDir` events are also emitted for matching paths while
* instantiating the watching as chokidar discovers these file paths (before the `ready` event).
*/
ignoreInitial?: boolean;
/**
* When `false`, only the symlinks themselves will be watched for changes instead of following
* the link references and bubbling events through the link's path.
*/
followSymlinks?: boolean;
/**
* The base directory from which watch `paths` are to be derived. Paths emitted with events will
* be relative to this.
*/
cwd?: string;
/**
* If set to true then the strings passed to .watch() and .add() are treated as literal path
* names, even if they look like globs. Default: false.
*/
disableGlobbing?: boolean;
/**
* Whether to use fs.watchFile (backed by polling), or fs.watch. If polling leads to high CPU
* utilization, consider setting this to `false`. It is typically necessary to **set this to
* `true` to successfully watch files over a network**, and it may be necessary to successfully
* watch files in other non-standard situations. Setting to `true` explicitly on OS X overrides
* the `useFsEvents` default.
*/
usePolling?: boolean;
/**
* Whether to use the `fsevents` watching interface if available. When set to `true` explicitly
* and `fsevents` is available this supercedes the `usePolling` setting. When set to `false` on
* OS X, `usePolling: true` becomes the default.
*/
useFsEvents?: boolean;
/**
* If relying upon the [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object that
* may get passed with `add`, `addDir`, and `change` events, set this to `true` to ensure it is
* provided even in cases where it wasn't already available from the underlying watch events.
*/
alwaysStat?: boolean;
/**
* If set, limits how many levels of subdirectories will be traversed.
*/
depth?: number;
/**
* Interval of file system polling.
*/
interval?: number;
/**
* Interval of file system polling for binary files. ([see list of binary extensions](https://gi
* thub.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json))
*/
binaryInterval?: number;
/**
* Indicates whether to watch files that don't have read permissions if possible. If watching
* fails due to `EPERM` or `EACCES` with this set to `true`, the errors will be suppressed
* silently.
*/
ignorePermissionErrors?: boolean;
/**
* `true` if `useFsEvents` and `usePolling` are `false`). Automatically filters out artifacts
* that occur when using editors that use "atomic writes" instead of writing directly to the
* source file. If a file is re-added within 100 ms of being deleted, Chokidar emits a `change`
* event rather than `unlink` then `add`. If the default of 100 ms does not work well for you,
* you can override it by setting `atomic` to a custom value, in milliseconds.
*/
atomic?: boolean | number;
/**
* can be set to an object in order to adjust timing params:
*/
awaitWriteFinish?: AwaitWriteFinishOptions | boolean;
}
export interface AwaitWriteFinishOptions {
/**
* Amount of time in milliseconds for a file size to remain constant before emitting its event.
*/
stabilityThreshold?: number;
/**
* File size polling interval.
*/
pollInterval?: number;
}
/**
* produces an instance of `FSWatcher`.
*/
export function watch(
paths: string | ReadonlyArray<string>,
options?: WatchOptions
): FSWatcher;

View File

@@ -1,17 +0,0 @@
/**
Check if a file path is a binary file.
@example
```
import isBinaryPath = require('is-binary-path');
isBinaryPath('source/unicorn.png');
//=> true
isBinaryPath('source/unicorn.txt');
//=> false
```
*/
declare function isBinaryPath(filePath: string): boolean;
export = isBinaryPath;

View File

@@ -1,7 +0,0 @@
'use strict';
const path = require('path');
const binaryExtensions = require('binary-extensions');
const extensions = new Set(binaryExtensions);
module.exports = filePath => extensions.has(path.extname(filePath).slice(1).toLowerCase());

View File

@@ -1,9 +0,0 @@
MIT License
Copyright (c) 2019 Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com), Paul Miller (https://paulmillr.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,40 +0,0 @@
{
"name": "is-binary-path",
"version": "2.1.0",
"description": "Check if a file path is a binary file",
"license": "MIT",
"repository": "sindresorhus/is-binary-path",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=8"
},
"scripts": {
"test": "xo && ava && tsd"
},
"files": [
"index.js",
"index.d.ts"
],
"keywords": [
"binary",
"extensions",
"extension",
"file",
"path",
"check",
"detect",
"is"
],
"dependencies": {
"binary-extensions": "^2.0.0"
},
"devDependencies": {
"ava": "^1.4.1",
"tsd": "^0.7.2",
"xo": "^0.24.0"
}
}

View File

@@ -1,34 +0,0 @@
# is-binary-path [![Build Status](https://travis-ci.org/sindresorhus/is-binary-path.svg?branch=master)](https://travis-ci.org/sindresorhus/is-binary-path)
> Check if a file path is a binary file
## Install
```
$ npm install is-binary-path
```
## Usage
```js
const isBinaryPath = require('is-binary-path');
isBinaryPath('source/unicorn.png');
//=> true
isBinaryPath('source/unicorn.txt');
//=> false
```
## Related
- [binary-extensions](https://github.com/sindresorhus/binary-extensions) - List of binary file extensions
- [is-text-path](https://github.com/sindresorhus/is-text-path) - Check if a filepath is a text file
## License
MIT © [Sindre Sorhus](https://sindresorhus.com), [Paul Miller](https://paulmillr.com)

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2012-2019 Thorsten Lorenz, Paul Miller (https://paulmillr.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,122 +0,0 @@
# readdirp [![Weekly downloads](https://img.shields.io/npm/dw/readdirp.svg)](https://github.com/paulmillr/readdirp)
Recursive version of [fs.readdir](https://nodejs.org/api/fs.html#fs_fs_readdir_path_options_callback). Exposes a **stream API** and a **promise API**.
```sh
npm install readdirp
```
```javascript
const readdirp = require('readdirp');
// Use streams to achieve small RAM & CPU footprint.
// 1) Streams example with for-await.
for await (const entry of readdirp('.')) {
const {path} = entry;
console.log(`${JSON.stringify({path})}`);
}
// 2) Streams example, non for-await.
// Print out all JS files along with their size within the current folder & subfolders.
readdirp('.', {fileFilter: '*.js', alwaysStat: true})
.on('data', (entry) => {
const {path, stats: {size}} = entry;
console.log(`${JSON.stringify({path, size})}`);
})
// Optionally call stream.destroy() in `warn()` in order to abort and cause 'close' to be emitted
.on('warn', error => console.error('non-fatal error', error))
.on('error', error => console.error('fatal error', error))
.on('end', () => console.log('done'));
// 3) Promise example. More RAM and CPU than streams / for-await.
const files = await readdirp.promise('.');
console.log(files.map(file => file.path));
// Other options.
readdirp('test', {
fileFilter: '*.js',
directoryFilter: ['!.git', '!*modules']
// directoryFilter: (di) => di.basename.length === 9
type: 'files_directories',
depth: 1
});
```
For more examples, check out `examples` directory.
## API
`const stream = readdirp(root[, options])`**Stream API**
- Reads given root recursively and returns a `stream` of [entry infos](#entryinfo)
- Optionally can be used like `for await (const entry of stream)` with node.js 10+ (`asyncIterator`).
- `on('data', (entry) => {})` [entry info](#entryinfo) for every file / dir.
- `on('warn', (error) => {})` non-fatal `Error` that prevents a file / dir from being processed. Example: inaccessible to the user.
- `on('error', (error) => {})` fatal `Error` which also ends the stream. Example: illegal options where passed.
- `on('end')` — we are done. Called when all entries were found and no more will be emitted.
- `on('close')` — stream is destroyed via `stream.destroy()`.
Could be useful if you want to manually abort even on a non fatal error.
At that point the stream is no longer `readable` and no more entries, warning or errors are emitted
- To learn more about streams, consult the very detailed [nodejs streams documentation](https://nodejs.org/api/stream.html)
or the [stream-handbook](https://github.com/substack/stream-handbook)
`const entries = await readdirp.promise(root[, options])`**Promise API**. Returns a list of [entry infos](#entryinfo).
First argument is awalys `root`, path in which to start reading and recursing into subdirectories.
### options
- `fileFilter: ["*.js"]`: filter to include or exclude files. A `Function`, Glob string or Array of glob strings.
- **Function**: a function that takes an entry info as a parameter and returns true to include or false to exclude the entry
- **Glob string**: a string (e.g., `*.js`) which is matched using [picomatch](https://github.com/micromatch/picomatch), so go there for more
information. Globstars (`**`) are not supported since specifying a recursive pattern for an already recursive function doesn't make sense. Negated globs (as explained in the minimatch documentation) are allowed, e.g., `!*.txt` matches everything but text files.
- **Array of glob strings**: either need to be all inclusive or all exclusive (negated) patterns otherwise an error is thrown.
`['*.json', '*.js']` includes all JavaScript and Json files.
`['!.git', '!node_modules']` includes all directories except the '.git' and 'node_modules'.
- Directories that do not pass a filter will not be recursed into.
- `directoryFilter: ['!.git']`: filter to include/exclude directories found and to recurse into. Directories that do not pass a filter will not be recursed into.
- `depth: 5`: depth at which to stop recursing even if more subdirectories are found
- `type: 'files'`: determines if data events on the stream should be emitted for `'files'` (default), `'directories'`, `'files_directories'`, or `'all'`. Setting to `'all'` will also include entries for other types of file descriptors like character devices, unix sockets and named pipes.
- `alwaysStat: false`: always return `stats` property for every file. Default is `false`, readdirp will return `Dirent` entries. Setting it to `true` can double readdir execution time - use it only when you need file `size`, `mtime` etc. Cannot be enabled on node <10.10.0.
- `lstat: false`: include symlink entries in the stream along with files. When `true`, `fs.lstat` would be used instead of `fs.stat`
### `EntryInfo`
Has the following properties:
- `path: 'assets/javascripts/react.js'`: path to the file/directory (relative to given root)
- `fullPath: '/Users/dev/projects/app/assets/javascripts/react.js'`: full path to the file/directory found
- `basename: 'react.js'`: name of the file/directory
- `dirent: fs.Dirent`: built-in [dir entry object](https://nodejs.org/api/fs.html#fs_class_fs_dirent) - only with `alwaysStat: false`
- `stats: fs.Stats`: built in [stat object](https://nodejs.org/api/fs.html#fs_class_fs_stats) - only with `alwaysStat: true`
## Changelog
- 3.5 (Oct 13, 2020) disallows recursive directory-based symlinks.
Before, it could have entered infinite loop.
- 3.4 (Mar 19, 2020) adds support for directory-based symlinks.
- 3.3 (Dec 6, 2019) stabilizes RAM consumption and enables perf management with `highWaterMark` option. Fixes race conditions related to `for-await` looping.
- 3.2 (Oct 14, 2019) improves performance by 250% and makes streams implementation more idiomatic.
- 3.1 (Jul 7, 2019) brings `bigint` support to `stat` output on Windows. This is backwards-incompatible for some cases. Be careful. It you use it incorrectly, you'll see "TypeError: Cannot mix BigInt and other types, use explicit conversions".
- 3.0 brings huge performance improvements and stream backpressure support.
- Upgrading 2.x to 3.x:
- Signature changed from `readdirp(options)` to `readdirp(root, options)`
- Replaced callback API with promise API.
- Renamed `entryType` option to `type`
- Renamed `entryType: 'both'` to `'files_directories'`
- `EntryInfo`
- Renamed `stat` to `stats`
- Emitted only when `alwaysStat: true`
- `dirent` is emitted instead of `stats` by default with `alwaysStat: false`
- Renamed `name` to `basename`
- Removed `parentDir` and `fullParentDir` properties
- Supported node.js versions:
- 3.x: node 8+
- 2.x: node 0.6+
## License
Copyright (c) 2012-2019 Thorsten Lorenz, Paul Miller (<https://paulmillr.com>)
MIT License, see [LICENSE](LICENSE) file.

View File

@@ -1,43 +0,0 @@
// TypeScript Version: 3.2
/// <reference types="node" lib="esnext" />
import * as fs from 'fs';
import { Readable } from 'stream';
declare namespace readdir {
interface EntryInfo {
path: string;
fullPath: string;
basename: string;
stats?: fs.Stats;
dirent?: fs.Dirent;
}
interface ReaddirpOptions {
root?: string;
fileFilter?: string | string[] | ((entry: EntryInfo) => boolean);
directoryFilter?: string | string[] | ((entry: EntryInfo) => boolean);
type?: 'files' | 'directories' | 'files_directories' | 'all';
lstat?: boolean;
depth?: number;
alwaysStat?: boolean;
}
interface ReaddirpStream extends Readable, AsyncIterable<EntryInfo> {
read(): EntryInfo;
[Symbol.asyncIterator](): AsyncIterableIterator<EntryInfo>;
}
function promise(
root: string,
options?: ReaddirpOptions
): Promise<EntryInfo[]>;
}
declare function readdir(
root: string,
options?: readdir.ReaddirpOptions
): readdir.ReaddirpStream;
export = readdir;

View File

@@ -1,287 +0,0 @@
'use strict';
const fs = require('fs');
const { Readable } = require('stream');
const sysPath = require('path');
const { promisify } = require('util');
const picomatch = require('picomatch');
const readdir = promisify(fs.readdir);
const stat = promisify(fs.stat);
const lstat = promisify(fs.lstat);
const realpath = promisify(fs.realpath);
/**
* @typedef {Object} EntryInfo
* @property {String} path
* @property {String} fullPath
* @property {fs.Stats=} stats
* @property {fs.Dirent=} dirent
* @property {String} basename
*/
const BANG = '!';
const RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR';
const NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]);
const FILE_TYPE = 'files';
const DIR_TYPE = 'directories';
const FILE_DIR_TYPE = 'files_directories';
const EVERYTHING_TYPE = 'all';
const ALL_TYPES = [FILE_TYPE, DIR_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE];
const isNormalFlowError = error => NORMAL_FLOW_ERRORS.has(error.code);
const [maj, min] = process.versions.node.split('.').slice(0, 2).map(n => Number.parseInt(n, 10));
const wantBigintFsStats = process.platform === 'win32' && (maj > 10 || (maj === 10 && min >= 5));
const normalizeFilter = filter => {
if (filter === undefined) return;
if (typeof filter === 'function') return filter;
if (typeof filter === 'string') {
const glob = picomatch(filter.trim());
return entry => glob(entry.basename);
}
if (Array.isArray(filter)) {
const positive = [];
const negative = [];
for (const item of filter) {
const trimmed = item.trim();
if (trimmed.charAt(0) === BANG) {
negative.push(picomatch(trimmed.slice(1)));
} else {
positive.push(picomatch(trimmed));
}
}
if (negative.length > 0) {
if (positive.length > 0) {
return entry =>
positive.some(f => f(entry.basename)) && !negative.some(f => f(entry.basename));
}
return entry => !negative.some(f => f(entry.basename));
}
return entry => positive.some(f => f(entry.basename));
}
};
class ReaddirpStream extends Readable {
static get defaultOptions() {
return {
root: '.',
/* eslint-disable no-unused-vars */
fileFilter: (path) => true,
directoryFilter: (path) => true,
/* eslint-enable no-unused-vars */
type: FILE_TYPE,
lstat: false,
depth: 2147483648,
alwaysStat: false
};
}
constructor(options = {}) {
super({
objectMode: true,
autoDestroy: true,
highWaterMark: options.highWaterMark || 4096
});
const opts = { ...ReaddirpStream.defaultOptions, ...options };
const { root, type } = opts;
this._fileFilter = normalizeFilter(opts.fileFilter);
this._directoryFilter = normalizeFilter(opts.directoryFilter);
const statMethod = opts.lstat ? lstat : stat;
// Use bigint stats if it's windows and stat() supports options (node 10+).
if (wantBigintFsStats) {
this._stat = path => statMethod(path, { bigint: true });
} else {
this._stat = statMethod;
}
this._maxDepth = opts.depth;
this._wantsDir = [DIR_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type);
this._wantsFile = [FILE_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type);
this._wantsEverything = type === EVERYTHING_TYPE;
this._root = sysPath.resolve(root);
this._isDirent = ('Dirent' in fs) && !opts.alwaysStat;
this._statsProp = this._isDirent ? 'dirent' : 'stats';
this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };
// Launch stream with one parent, the root dir.
this.parents = [this._exploreDir(root, 1)];
this.reading = false;
this.parent = undefined;
}
async _read(batch) {
if (this.reading) return;
this.reading = true;
try {
while (!this.destroyed && batch > 0) {
const { path, depth, files = [] } = this.parent || {};
if (files.length > 0) {
const slice = files.splice(0, batch).map(dirent => this._formatEntry(dirent, path));
for (const entry of await Promise.all(slice)) {
if (this.destroyed) return;
const entryType = await this._getEntryType(entry);
if (entryType === 'directory' && this._directoryFilter(entry)) {
if (depth <= this._maxDepth) {
this.parents.push(this._exploreDir(entry.fullPath, depth + 1));
}
if (this._wantsDir) {
this.push(entry);
batch--;
}
} else if ((entryType === 'file' || this._includeAsFile(entry)) && this._fileFilter(entry)) {
if (this._wantsFile) {
this.push(entry);
batch--;
}
}
}
} else {
const parent = this.parents.pop();
if (!parent) {
this.push(null);
break;
}
this.parent = await parent;
if (this.destroyed) return;
}
}
} catch (error) {
this.destroy(error);
} finally {
this.reading = false;
}
}
async _exploreDir(path, depth) {
let files;
try {
files = await readdir(path, this._rdOptions);
} catch (error) {
this._onError(error);
}
return { files, depth, path };
}
async _formatEntry(dirent, path) {
let entry;
try {
const basename = this._isDirent ? dirent.name : dirent;
const fullPath = sysPath.resolve(sysPath.join(path, basename));
entry = { path: sysPath.relative(this._root, fullPath), fullPath, basename };
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
} catch (err) {
this._onError(err);
}
return entry;
}
_onError(err) {
if (isNormalFlowError(err) && !this.destroyed) {
this.emit('warn', err);
} else {
this.destroy(err);
}
}
async _getEntryType(entry) {
// entry may be undefined, because a warning or an error were emitted
// and the statsProp is undefined
const stats = entry && entry[this._statsProp];
if (!stats) {
return;
}
if (stats.isFile()) {
return 'file';
}
if (stats.isDirectory()) {
return 'directory';
}
if (stats && stats.isSymbolicLink()) {
const full = entry.fullPath;
try {
const entryRealPath = await realpath(full);
const entryRealPathStats = await lstat(entryRealPath);
if (entryRealPathStats.isFile()) {
return 'file';
}
if (entryRealPathStats.isDirectory()) {
const len = entryRealPath.length;
if (full.startsWith(entryRealPath) && full.substr(len, 1) === sysPath.sep) {
const recursiveError = new Error(
`Circular symlink detected: "${full}" points to "${entryRealPath}"`
);
recursiveError.code = RECURSIVE_ERROR_CODE;
return this._onError(recursiveError);
}
return 'directory';
}
} catch (error) {
this._onError(error);
}
}
}
_includeAsFile(entry) {
const stats = entry && entry[this._statsProp];
return stats && this._wantsEverything && !stats.isDirectory();
}
}
/**
* @typedef {Object} ReaddirpArguments
* @property {Function=} fileFilter
* @property {Function=} directoryFilter
* @property {String=} type
* @property {Number=} depth
* @property {String=} root
* @property {Boolean=} lstat
* @property {Boolean=} bigint
*/
/**
* Main function which ends up calling readdirRec and reads all files and directories in given root recursively.
* @param {String} root Root directory
* @param {ReaddirpArguments=} options Options to specify root (start directory), filters and recursion depth
*/
const readdirp = (root, options = {}) => {
let type = options.entryType || options.type;
if (type === 'both') type = FILE_DIR_TYPE; // backwards-compatibility
if (type) options.type = type;
if (!root) {
throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');
} else if (typeof root !== 'string') {
throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');
} else if (type && !ALL_TYPES.includes(type)) {
throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);
}
options.root = root;
return new ReaddirpStream(options);
};
const readdirpPromise = (root, options = {}) => {
return new Promise((resolve, reject) => {
const files = [];
readdirp(root, options)
.on('data', entry => files.push(entry))
.on('end', () => resolve(files))
.on('error', error => reject(error));
});
};
readdirp.promise = readdirpPromise;
readdirp.ReaddirpStream = ReaddirpStream;
readdirp.default = readdirp;
module.exports = readdirp;

View File

@@ -1,122 +0,0 @@
{
"name": "readdirp",
"description": "Recursive version of fs.readdir with streaming API.",
"version": "3.6.0",
"homepage": "https://github.com/paulmillr/readdirp",
"repository": {
"type": "git",
"url": "git://github.com/paulmillr/readdirp.git"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/paulmillr/readdirp/issues"
},
"author": "Thorsten Lorenz <thlorenz@gmx.de> (thlorenz.com)",
"contributors": [
"Thorsten Lorenz <thlorenz@gmx.de> (thlorenz.com)",
"Paul Miller (https://paulmillr.com)"
],
"main": "index.js",
"engines": {
"node": ">=8.10.0"
},
"files": [
"index.js",
"index.d.ts"
],
"keywords": [
"recursive",
"fs",
"stream",
"streams",
"readdir",
"filesystem",
"find",
"filter"
],
"scripts": {
"dtslint": "dtslint",
"nyc": "nyc",
"mocha": "mocha --exit",
"lint": "eslint --report-unused-disable-directives --ignore-path .gitignore .",
"test": "npm run lint && nyc npm run mocha"
},
"dependencies": {
"picomatch": "^2.2.1"
},
"devDependencies": {
"@types/node": "^14",
"chai": "^4.2",
"chai-subset": "^1.6",
"dtslint": "^3.3.0",
"eslint": "^7.0.0",
"mocha": "^7.1.1",
"nyc": "^15.0.0",
"rimraf": "^3.0.0",
"typescript": "^4.0.3"
},
"nyc": {
"reporter": [
"html",
"text"
]
},
"eslintConfig": {
"root": true,
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 9,
"sourceType": "script"
},
"env": {
"node": true,
"es6": true
},
"rules": {
"array-callback-return": "error",
"no-empty": [
"error",
{
"allowEmptyCatch": true
}
],
"no-else-return": [
"error",
{
"allowElseIf": false
}
],
"no-lonely-if": "error",
"no-var": "error",
"object-shorthand": "error",
"prefer-arrow-callback": [
"error",
{
"allowNamedFunctions": true
}
],
"prefer-const": [
"error",
{
"ignoreReadBeforeAssign": true
}
],
"prefer-destructuring": [
"error",
{
"object": true,
"array": false
}
],
"prefer-spread": "error",
"prefer-template": "error",
"radix": "error",
"semi": "error",
"strict": "error",
"quotes": [
"error",
"single"
]
}
}
}

2
node_modules/sass/package.json generated vendored
View File

@@ -1 +1 @@
{"name":"sass","description":"A pure JavaScript implementation of Sass.","license":"MIT","bugs":"https://github.com/sass/dart-sass/issues","homepage":"https://github.com/sass/dart-sass","repository":{"type":"git","url":"https://github.com/sass/dart-sass"},"author":{"name":"Natalie Weizenbaum","email":"nweiz@google.com","url":"https://github.com/nex3"},"engines":{"node":">=8.9.0"},"dependencies":{"chokidar":">=3.0.0 <4.0.0"},"keywords":["style","scss","sass","preprocessor","css"],"version":"1.43.4","bin":{"sass":"sass.js"},"main":"sass.default.dart.js","exports":{"default":"./sass.default.dart.js"}}
{"name":"sass","description":"A pure JavaScript implementation of Sass.","license":"MIT","bugs":"https://github.com/sass/dart-sass/issues","homepage":"https://github.com/sass/dart-sass","repository":{"type":"git","url":"https://github.com/sass/dart-sass"},"author":{"name":"Natalie Weizenbaum","email":"nweiz@google.com","url":"https://github.com/nex3"},"engines":{"node":">=14.0.0"},"dependencies":{"chokidar":">=3.0.0 <4.0.0","immutable":"^4.0.0","source-map-js":">=0.6.2 <2.0.0"},"keywords":["style","scss","sass","preprocessor","css"],"types":"types/index.d.ts","exports":{"types":"./types/index.d.ts","node":{"require":"./sass.node.js","default":"./sass.node.mjs"},"default":{"require":"./sass.default.cjs","default":"./sass.default.js"}},"version":"1.64.2","bin":{"sass":"sass.js"},"main":"sass.node.js"}

86254
node_modules/sass/sass.dart.js generated vendored

File diff suppressed because one or more lines are too long

8
node_modules/sass/sass.default.cjs generated vendored Normal file
View File

@@ -0,0 +1,8 @@
require('./sass.dart.js');
const library = globalThis._cliPkgExports.pop();
if (globalThis._cliPkgExports.length === 0) delete globalThis._cliPkgExports;
library.load({
immutable: require("immutable"),
});
module.exports = library;

View File

@@ -1,4 +0,0 @@
var library = require('./sass.dart.js');
library.load({});
module.exports = library;

39
node_modules/sass/sass.default.js generated vendored Normal file
View File

@@ -0,0 +1,39 @@
import * as immutable from "immutable"
import "./sass.dart.js";
const _cliPkgLibrary = globalThis._cliPkgExports.pop();
if (globalThis._cliPkgExports.length === 0) delete globalThis._cliPkgExports;
const _cliPkgExports = {};
_cliPkgLibrary.load({immutable}, _cliPkgExports);
export const compile = _cliPkgExports.compile;
export const compileAsync = _cliPkgExports.compileAsync;
export const compileString = _cliPkgExports.compileString;
export const compileStringAsync = _cliPkgExports.compileStringAsync;
export const Logger = _cliPkgExports.Logger;
export const SassArgumentList = _cliPkgExports.SassArgumentList;
export const SassBoolean = _cliPkgExports.SassBoolean;
export const SassCalculation = _cliPkgExports.SassCalculation;
export const CalculationOperation = _cliPkgExports.CalculationOperation;
export const CalculationInterpolation = _cliPkgExports.CalculationInterpolation;
export const SassColor = _cliPkgExports.SassColor;
export const SassFunction = _cliPkgExports.SassFunction;
export const SassList = _cliPkgExports.SassList;
export const SassMap = _cliPkgExports.SassMap;
export const SassNumber = _cliPkgExports.SassNumber;
export const SassString = _cliPkgExports.SassString;
export const Value = _cliPkgExports.Value;
export const CustomFunction = _cliPkgExports.CustomFunction;
export const ListSeparator = _cliPkgExports.ListSeparator;
export const sassFalse = _cliPkgExports.sassFalse;
export const sassNull = _cliPkgExports.sassNull;
export const sassTrue = _cliPkgExports.sassTrue;
export const Exception = _cliPkgExports.Exception;
export const PromiseOr = _cliPkgExports.PromiseOr;
export const info = _cliPkgExports.info;
export const render = _cliPkgExports.render;
export const renderSync = _cliPkgExports.renderSync;
export const TRUE = _cliPkgExports.TRUE;
export const FALSE = _cliPkgExports.FALSE;
export const NULL = _cliPkgExports.NULL;
export const types = _cliPkgExports.types;

9
node_modules/sass/sass.js generated vendored
View File

@@ -1,9 +1,16 @@
#!/usr/bin/env node
var library = require('./sass.dart.js');
require('./sass.dart.js');
var library = globalThis._cliPkgExports.pop();
if (globalThis._cliPkgExports.length === 0) delete globalThis._cliPkgExports;
library.load({
readline: require("readline"),
chokidar: require("chokidar"),
util: require("util"),
stream: require("stream"),
fs: require("fs"),
immutable: require("immutable"),
});
library.cli_pkg_main_0_(process.argv.slice(2));

11
node_modules/sass/sass.node.js generated vendored Normal file
View File

@@ -0,0 +1,11 @@
require('./sass.dart.js');
const library = globalThis._cliPkgExports.pop();
if (globalThis._cliPkgExports.length === 0) delete globalThis._cliPkgExports;
library.load({
util: require("util"),
stream: require("stream"),
fs: require("fs"),
immutable: require("immutable"),
});
module.exports = library;

169
node_modules/sass/sass.node.mjs generated vendored Normal file
View File

@@ -0,0 +1,169 @@
import cjs from "./sass.node.js";
export const compile = cjs.compile;
export const compileAsync = cjs.compileAsync;
export const compileString = cjs.compileString;
export const compileStringAsync = cjs.compileStringAsync;
export const Logger = cjs.Logger;
export const SassArgumentList = cjs.SassArgumentList;
export const SassBoolean = cjs.SassBoolean;
export const SassCalculation = cjs.SassCalculation;
export const CalculationOperation = cjs.CalculationOperation;
export const CalculationInterpolation = cjs.CalculationInterpolation;
export const SassColor = cjs.SassColor;
export const SassFunction = cjs.SassFunction;
export const SassList = cjs.SassList;
export const SassMap = cjs.SassMap;
export const SassNumber = cjs.SassNumber;
export const SassString = cjs.SassString;
export const Value = cjs.Value;
export const CustomFunction = cjs.CustomFunction;
export const ListSeparator = cjs.ListSeparator;
export const sassFalse = cjs.sassFalse;
export const sassNull = cjs.sassNull;
export const sassTrue = cjs.sassTrue;
export const Exception = cjs.Exception;
export const PromiseOr = cjs.PromiseOr;
export const info = cjs.info;
export const render = cjs.render;
export const renderSync = cjs.renderSync;
export const TRUE = cjs.TRUE;
export const FALSE = cjs.FALSE;
export const NULL = cjs.NULL;
export const types = cjs.types;
let printedDefaultExportDeprecation = false;
function defaultExportDeprecation() {
if (printedDefaultExportDeprecation) return;
printedDefaultExportDeprecation = true;
console.error(
"`import sass from 'sass'` is deprecated.\n" +
"Please use `import * as sass from 'sass'` instead.");
}
export default {
get compile() {
defaultExportDeprecation();
return cjs.compile;
},
get compileAsync() {
defaultExportDeprecation();
return cjs.compileAsync;
},
get compileString() {
defaultExportDeprecation();
return cjs.compileString;
},
get compileStringAsync() {
defaultExportDeprecation();
return cjs.compileStringAsync;
},
get Logger() {
defaultExportDeprecation();
return cjs.Logger;
},
get SassArgumentList() {
defaultExportDeprecation();
return cjs.SassArgumentList;
},
get SassBoolean() {
defaultExportDeprecation();
return cjs.SassBoolean;
},
get SassCalculation() {
defaultExportDeprecation();
return cjs.SassCalculation;
},
get CalculationOperation() {
defaultExportDeprecation();
return cjs.CalculationOperation;
},
get CalculationInterpolation() {
defaultExportDeprecation();
return cjs.CalculationInterpolation;
},
get SassColor() {
defaultExportDeprecation();
return cjs.SassColor;
},
get SassFunction() {
defaultExportDeprecation();
return cjs.SassFunction;
},
get SassList() {
defaultExportDeprecation();
return cjs.SassList;
},
get SassMap() {
defaultExportDeprecation();
return cjs.SassMap;
},
get SassNumber() {
defaultExportDeprecation();
return cjs.SassNumber;
},
get SassString() {
defaultExportDeprecation();
return cjs.SassString;
},
get Value() {
defaultExportDeprecation();
return cjs.Value;
},
get CustomFunction() {
defaultExportDeprecation();
return cjs.CustomFunction;
},
get ListSeparator() {
defaultExportDeprecation();
return cjs.ListSeparator;
},
get sassFalse() {
defaultExportDeprecation();
return cjs.sassFalse;
},
get sassNull() {
defaultExportDeprecation();
return cjs.sassNull;
},
get sassTrue() {
defaultExportDeprecation();
return cjs.sassTrue;
},
get Exception() {
defaultExportDeprecation();
return cjs.Exception;
},
get PromiseOr() {
defaultExportDeprecation();
return cjs.PromiseOr;
},
get info() {
defaultExportDeprecation();
return cjs.info;
},
get render() {
defaultExportDeprecation();
return cjs.render;
},
get renderSync() {
defaultExportDeprecation();
return cjs.renderSync;
},
get TRUE() {
defaultExportDeprecation();
return cjs.TRUE;
},
get FALSE() {
defaultExportDeprecation();
return cjs.FALSE;
},
get NULL() {
defaultExportDeprecation();
return cjs.NULL;
},
get types() {
defaultExportDeprecation();
return cjs.types;
},
};

153
node_modules/sass/types/compile.d.ts generated vendored Normal file
View File

@@ -0,0 +1,153 @@
import {RawSourceMap} from 'source-map-js';
import {Options, StringOptions} from './options';
/**
* The result of compiling Sass to CSS. Returned by {@link compile}, {@link
* compileAsync}, {@link compileString}, and {@link 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 {@link Importer} return {@link
* ImporterResult.sourceMapUrl}.
*
* This is set if and only if {@link Options.sourceMap} is `true`.
*/
sourceMap?: RawSourceMap;
}
/**
* Synchronously compiles the Sass file at `path` to CSS. If it succeeds it
* returns a {@link CompileResult}, and if it fails it throws an {@link
* Exception}.
*
* This only allows synchronous {@link Importer}s and {@link 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;
/**
* Asynchronously compiles the Sass file at `path` to CSS. Returns a promise
* that resolves with a {@link CompileResult} if it succeeds and rejects with an
* {@link Exception} if it fails.
*
* This only allows synchronous or asynchronous {@link Importer}s and
* {@link CustomFunction}s.
*
* **Heads up!** When using Dart Sass, **{@link compile} is almost twice as fast
* as {@link 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<CompileResult>;
/**
* Synchronously compiles a stylesheet whose contents is `source` to CSS. If it
* succeeds it returns a {@link CompileResult}, and if it fails it throws an
* {@link Exception}.
*
* This only allows synchronous {@link Importer}s and {@link 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;
/**
* Asynchronously compiles a stylesheet whose contents is `source` to CSS.
* Returns a promise that resolves with a {@link CompileResult} if it succeeds
* and rejects with an {@link Exception} if it fails.
*
* This only allows synchronous or asynchronous {@link Importer}s and {@link
* CustomFunction}s.
*
* **Heads up!** When using Dart Sass, **{@link compile} is almost twice as fast
* as {@link 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'>
): Promise<CompileResult>;

41
node_modules/sass/types/exception.d.ts generated vendored Normal file
View File

@@ -0,0 +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 {@link sassMessage})
* but also an indication of where in the Sass stylesheet the error occurred
* (the {@link span}) and the Sass stack trace at the point of error (the
* {@link sassStack}).
*/
message: string;
/**
* A textual description of what went wrong.
*
* Unlike {@link message}, this does *not* include representations of {@link
* span} or {@link sassStack}.
*/
readonly sassMessage: string;
/**
* A human-friendly representation of the Sass stack trace at the point of
* error.
*/
readonly sassStack: string;
/** The location the error occurred in the Sass file that triggered it. */
readonly span: SourceSpan;
/** Returns the same string as {@link message}. */
toString(): string;
}

298
node_modules/sass/types/importer.d.ts generated vendored Normal file
View File

@@ -0,0 +1,298 @@
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 {@link 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 {@link Options.importers} or {@link StringOptionsWithImporter.importer}.
*
* @typeParam sync - A `FileImporter<'sync'>`'s {@link findFileUrl} must return
* synchronously, but in return it can be passed to {@link compile} and {@link
* compileString} in addition to {@link compileAsync} and {@link
* compileStringAsync}.
*
* A `FileImporter<'async'>`'s {@link findFileUrl} may either return
* synchronously or asynchronously, but it can only be used with {@link
* compileAsync} and {@link compileStringAsync}.
*
* @example
*
* ```js
* const {pathToFileURL} = 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 {@link Importer}, the compiler will automatically handle relative
* loads for a {@link FileImporter}. See {@link 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 {@link 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 {@link compileAsync} and {@link compileStringAsync}, not {@link
* compile} or {@link 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<URL | null, sync>;
/** @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 {@link Options.importers} or {@link StringOptionsWithImporter.importer}.
*
* Importers that simply redirect to files on disk are encouraged to use the
* {@link FileImporter} interface instead.
*
* ### 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 {@link canonicalize} with `"db:foo/bar/baz"`.
* - {@link 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 {@link load} with `new
* URL("db:foo/bar/baz/_index.scss")`.
* - {@link load} returns an {@link ImporterResult} that the compiler uses as
* the contents of the module.
*
* See {@link Options.importers} for more details on the way loads are resolved
* using multiple importers and load paths.
*
* @typeParam sync - An `Importer<'sync'>`'s {@link canonicalize} and {@link
* load} must return synchronously, but in return it can be passed to {@link
* compile} and {@link compileString} in addition to {@link compileAsync} and
* {@link compileStringAsync}.
*
* An `Importer<'async'>`'s {@link canonicalize} and {@link load} may either
* return synchronously or asynchronously, but it can only be used with {@link
* compileAsync} and {@link compileStringAsync}.
*
* @example
*
* ```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<sync extends 'sync' | 'async' = 'sync' | 'async'> {
/**
* 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 {@link canonicalize} multiple times with the same URL must return
* the same result. Calling {@link canonicalize} with a URL returned by a
* previous call to {@link 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 {@link
* 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 {@link canonicalize} with `"db:foo/bar/baz/mixins"`.
* - {@link canonicalize} returns `new URL("db:foo/bar/baz/_mixins.scss")`.
*
* Because of this, {@link canonicalize} must return a meaningful result when
* called with a URL relative to one returned by an earlier call to {@link
* canonicalize}.
*
* @param url - The loaded URL. Since this might be relative, it's represented
* as a string rather than a {@link 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 {@link compileAsync} and {@link compileStringAsync}, not {@link
* compile} or {@link 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<URL | null, sync>;
/**
* 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 {@link canonicalize}, although not every
* call to {@link canonicalize} will result in a call to {@link 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 {@link compileAsync} and {@link compileStringAsync}, not {@link
* compile} or {@link 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<ImporterResult | null, sync>;
/** @hidden */
findFileUrl?: never;
}
/**
* The result of successfully loading a stylesheet with an {@link Importer}.
*
* @category Importer
*/
export interface ImporterResult {
/** The contents of the stylesheet. */
contents: string;
/** The syntax with which to parse {@link 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;
}

85
node_modules/sass/types/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,85 @@
// This is a mirror of the JS API definitions in `spec/js-api`, but with comments
// written to provide user-facing documentation rather than to specify behavior for
// implementations.
export {
CompileResult,
compile,
compileAsync,
compileString,
compileStringAsync,
} from './compile';
export {Exception} from './exception';
export {FileImporter, Importer, ImporterResult} from './importer';
export {Logger, SourceSpan, SourceLocation} from './logger';
export {
CustomFunction,
Options,
OutputStyle,
StringOptions,
StringOptionsWithImporter,
StringOptionsWithoutImporter,
Syntax,
} from './options';
export {PromiseOr} from './util/promise_or';
export {
CalculationInterpolation,
CalculationOperation,
CalculationOperator,
CalculationValue,
ListSeparator,
SassArgumentList,
SassBoolean,
SassCalculation,
SassColor,
SassFunction,
SassList,
SassMap,
SassNumber,
SassString,
Value,
sassFalse,
sassNull,
sassTrue,
} from './value';
// Legacy APIs
export {LegacyException} from './legacy/exception';
export {
FALSE,
LegacyAsyncFunction,
LegacyAsyncFunctionDone,
LegacyFunction,
LegacySyncFunction,
LegacyValue,
NULL,
TRUE,
types,
} from './legacy/function';
export {
LegacyAsyncImporter,
LegacyImporter,
LegacyImporterResult,
LegacyImporterThis,
LegacySyncImporter,
} from './legacy/importer';
export {
LegacySharedOptions,
LegacyFileOptions,
LegacyStringOptions,
LegacyOptions,
} from './legacy/options';
export {LegacyPluginThis} from './legacy/plugin_this';
export {LegacyResult, render, renderSync} from './legacy/render';
/**
* Information about the Sass implementation. This always begins with a unique
* identifier for the Sass implementation, followed by U+0009 TAB, followed by
* its npm package version. Some implementations include additional information
* as well, but not in any standardized format.
*
* * For Dart Sass, the implementation name is `dart-sass`.
* * For Node Sass, the implementation name is `node-sass`.
* * For the embedded host, the implementation name is `sass-embedded`.
*/
export const info: string;

55
node_modules/sass/types/legacy/exception.d.ts generated vendored Normal file
View File

@@ -0,0 +1,55 @@
/**
* The exception type thrown by {@link renderSync} and passed as the error to
* {@link render}'s callback.
*
* @category Legacy
* @deprecated This is only thrown by the legacy {@link render} and {@link
* renderSync} APIs. Use {@link compile}, {@link compileString}, {@link
* compileAsync}, and {@link compileStringAsync} instead.
*/
export interface LegacyException extends Error {
/**
* The error message. For Dart Sass, when possible this includes a highlighted
* indication of where in the source file the error occurred as well as the
* Sass stack trace.
*/
message: string;
/**
* The error message. For Dart Sass, this is the same as the result of calling
* {@link toString}, which is itself the same as {@link message} but with the
* prefix "Error:".
*/
formatted: string;
/**
* The (1-based) line number on which the error occurred, if this exception is
* associated with a specific Sass file location.
*/
line?: number;
/**
* The (1-based) column number within {@link line} at which the error
* occurred, if this exception is associated with a specific Sass file
* location.
*/
column?: number;
/**
* Analogous to the exit code for an executable. `1` for an error caused by a
* Sass file, `3` for any other type of error.
*/
status: number;
/**
* If this exception was caused by an error in a Sass file, this will
* represent the Sass file's location. It can be in one of three formats:
*
* * If the Sass file was loaded from disk, this is the path to that file.
* * If the Sass file was generated by an importer, this is its canonical URL.
* * If the Sass file was passed as {@link LegacyStringOptions.data} without a
* corresponding {@link LegacyStringOptions.file}, this is the special
* string `"stdin"`.
*/
file?: string;
}

757
node_modules/sass/types/legacy/function.d.ts generated vendored Normal file
View File

@@ -0,0 +1,757 @@
import {LegacyPluginThis} from './plugin_this';
/**
* A synchronous callback that implements a custom Sass function. This can be
* passed to {@link LegacySharedOptions.functions} for either {@link render} or
* {@link renderSync}.
*
* If this throws an error, Sass will treat that as the function failing with
* that error message.
*
* ```js
* const result = sass.renderSync({
* file: 'style.scss',
* functions: {
* "sum($arg1, $arg2)": (arg1, arg2) => {
* if (!(arg1 instanceof sass.types.Number)) {
* throw new Error("$arg1: Expected a number");
* } else if (!(arg2 instanceof sass.types.Number)) {
* throw new Error("$arg2: Expected a number");
* }
* return new sass.types.Number(arg1.getValue() + arg2.getValue());
* }
* }
* });
* ```
*
* @param args - One argument for each argument that's declared in the signature
* that's passed to {@link 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 {@link render} and {@link
* renderSync} APIs. Use {@link CustomFunction} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export type LegacySyncFunction = (
this: LegacyPluginThis,
...args: LegacyValue[]
) => LegacyValue;
/**
* An asynchronous callback that implements a custom Sass function. This can be
* passed to {@link LegacySharedOptions.functions}, but only for {@link render}.
*
* An asynchronous function must return `undefined`. Its final argument will
* always be a callback, which it should call with the result of the function
* once it's done running.
*
* If this throws an error, Sass will treat that as the function failing with
* that error message.
*
* ```js
* sass.render({
* file: 'style.scss',
* functions: {
* "sum($arg1, $arg2)": (arg1, arg2, done) => {
* if (!(arg1 instanceof sass.types.Number)) {
* throw new Error("$arg1: Expected a number");
* } else if (!(arg2 instanceof sass.types.Number)) {
* throw new Error("$arg2: Expected a number");
* }
* done(new sass.types.Number(arg1.getValue() + arg2.getValue()));
* }
* }
* }, (result, error) => {
* // ...
* });
* ```
*
* This is passed one argument for each argument that's declared in the
* signature that's passed to {@link 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 before the
* callback.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link CustomFunction} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export type LegacyAsyncFunction =
| ((this: LegacyPluginThis, done: (result: LegacyValue) => void) => void)
| ((
this: LegacyPluginThis,
arg1: LegacyValue,
done: LegacyAsyncFunctionDone
) => void)
| ((
this: LegacyPluginThis,
arg1: LegacyValue,
arg2: LegacyValue,
done: LegacyAsyncFunctionDone
) => void)
| ((
this: LegacyPluginThis,
arg1: LegacyValue,
arg2: LegacyValue,
arg3: LegacyValue,
done: LegacyAsyncFunctionDone
) => void)
| ((
this: LegacyPluginThis,
arg1: LegacyValue,
arg2: LegacyValue,
arg3: LegacyValue,
arg4: LegacyValue,
done: LegacyAsyncFunctionDone
) => void)
| ((
this: LegacyPluginThis,
arg1: LegacyValue,
arg2: LegacyValue,
arg3: LegacyValue,
arg4: LegacyValue,
arg5: LegacyValue,
done: LegacyAsyncFunctionDone
) => void)
| ((
this: LegacyPluginThis,
arg1: LegacyValue,
arg2: LegacyValue,
arg3: LegacyValue,
arg4: LegacyValue,
arg5: LegacyValue,
arg6: LegacyValue,
done: LegacyAsyncFunctionDone
) => void)
| ((
this: LegacyPluginThis,
...args: [...LegacyValue[], LegacyAsyncFunctionDone]
) => void);
/**
* The function called by a {@link LegacyAsyncFunction} to indicate that it's
* finished.
*
* @param result - If this is a {@link LegacyValue}, that indicates that the
* function call completed successfully. If it's a {@link types.Error}, that
* indicates that the function call failed.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link CustomFunction} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export type LegacyAsyncFunctionDone = (
result: LegacyValue | types.Error
) => void;
/**
* A callback that implements a custom Sass function. For {@link renderSync},
* this must be a {@link LegacySyncFunction} which returns its result directly;
* for {@link render}, it may be either a {@link LegacySyncFunction} or a {@link
* LegacyAsyncFunction} which calls a callback with its result.
*
* See {@link LegacySharedOptions.functions} for more details.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link CustomFunction} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export type LegacyFunction<sync extends 'sync' | 'async'> = sync extends 'async'
? LegacySyncFunction | LegacyAsyncFunction
: LegacySyncFunction;
/**
* A type representing all the possible values that may be passed to or returned
* from a {@link LegacyFunction}.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link Value} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export type LegacyValue =
| types.Null
| types.Number
| types.String
| types.Boolean
| types.Color
| types.List
| types.Map;
/**
* A shorthand for `sass.types.Boolean.TRUE`.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link sassTrue} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export const TRUE: types.Boolean<true>;
/**
* A shorthand for `sass.types.Boolean.FALSE`.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link sassFalse} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export const FALSE: types.Boolean<false>;
/**
* A shorthand for `sass.types.Null.NULL`.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link sassNull} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export const NULL: types.Null;
/**
* The namespace for value types used in the legacy function API.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link Value} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export namespace types {
/**
* The class for Sass's singleton [`null`
* value](https://sass-lang.com/documentation/values/null). The value itself
* can be accessed through the {@link NULL} field.
*/
export class Null {
/** Sass's singleton `null` value. */
static readonly NULL: Null;
}
/**
* Sass's [number type](https://sass-lang.com/documentation/values/numbers).
*/
export class Number {
/**
* @param value - The numeric value of the number.
*
* @param unit - If passed, the number's unit.
*
* Complex units can be represented as
* `<unit>*<unit>*.../<unit>*<unit>*...`, with numerator units on the
* left-hand side of the `/` and denominator units on the right. A number
* with only numerator units may omit the `/` and the units after it, and a
* number with only denominator units may be represented
* with no units before the `/`.
*
* @example
*
* ```scss
* new sass.types.Number(0.5); // == 0.5
* new sass.types.Number(10, "px"); // == 10px
* new sass.types.Number(10, "px*px"); // == 10px * 1px
* new sass.types.Number(10, "px/s"); // == math.div(10px, 1s)
* new sass.types.Number(10, "px*px/s*s"); // == 10px * math.div(math.div(1px, 1s), 1s)
* ```
*/
constructor(value: number, unit?: string);
/**
* Returns the value of the number, ignoring units.
*
* **Heads up!** This means that `96px` and `1in` will return different
* values, even though they represent the same length.
*
* @example
*
* ```js
* const number = new sass.types.Number(10, "px");
* number.getValue(); // 10
* ```
*/
getValue(): number;
/**
* Destructively modifies this number by setting its numeric value to
* `value`, independent of its units.
*
* @deprecated Use {@link constructor} instead.
*/
setValue(value: number): void;
/**
* Returns a string representation of this number's units. Complex units are
* returned in the same format that {@link constructor} accepts them.
*
* @example
*
* ```js
* // number is `10px`.
* number.getUnit(); // "px"
*
* // number is `math.div(10px, 1s)`.
* number.getUnit(); // "px/s"
* ```
*/
getUnit(): string;
/**
* Destructively modifies this number by setting its units to `unit`,
* independent of its numeric value. Complex units are specified in the same
* format as {@link constructor}.
*
* @deprecated Use {@link constructor} instead.
*/
setUnit(unit: string): void;
}
/**
* Sass's [string type](https://sass-lang.com/documentation/values/strings).
*
* **Heads up!** This API currently provides no way of distinguishing between
* a [quoted](https://sass-lang.com/documentation/values/strings#quoted) and
* [unquoted](https://sass-lang.com/documentation/values/strings#unquoted)
* string.
*/
export class String {
/**
* Creates an unquoted string with the given contents.
*
* **Heads up!** This API currently provides no way of creating a
* [quoted](https://sass-lang.com/documentation/values/strings#quoted)
* string.
*/
constructor(value: string);
/**
* Returns the contents of the string. If the string contains escapes,
* those escapes are included literally if its
* [unquoted](https://sass-lang.com/documentation/values/strings#unquoted),
* while the values of the escapes are included if its
* [quoted](https://sass-lang.com/documentation/values/strings#quoted).
*
* @example
*
* ```
* // string is `Arial`.
* string.getValue(); // "Arial"
*
* // string is `"Helvetica Neue"`.
* string.getValue(); // "Helvetica Neue"
*
* // string is `\1F46D`.
* string.getValue(); // "\\1F46D"
*
* // string is `"\1F46D"`.
* string.getValue(); // "👭"
* ```
*/
getValue(): string;
/**
* Destructively modifies this string by setting its numeric value to
* `value`.
*
* **Heads up!** Even if the string was originally quoted, this will cause
* it to become unquoted.
*
* @deprecated Use {@link constructor} instead.
*/
setValue(value: string): void;
}
/**
* Sass's [boolean type](https://sass-lang.com/documentation/values/booleans).
*
* Custom functions should respect Sasss notion of
* [truthiness](https://sass-lang.com/documentation/at-rules/control/if#truthiness-and-falsiness)
* by treating `false` and `null` as falsey and everything else as truthy.
*
* **Heads up!** Boolean values can't be constructed, they can only be
* accessed through the {@link TRUE} and {@link FALSE} constants.
*/
export class Boolean<T extends boolean = boolean> {
/**
* Returns `true` if this is Sass's `true` value and `false` if this is
* Sass's `false` value.
*
* @example
*
* ```js
* // boolean is `true`.
* boolean.getValue(); // true
* boolean === sass.types.Boolean.TRUE; // true
*
* // boolean is `false`.
* boolean.getValue(); // false
* boolean === sass.types.Boolean.FALSE; // true
* ```
*/
getValue(): T;
/** Sass's `true` value. */
static readonly TRUE: Boolean<true>;
/** Sass's `false` value. */
static readonly FALSE: Boolean<false>;
}
/**
* Sass's [color type](https://sass-lang.com/documentation/values/colors).
*/
export class Color {
/**
* Creates a new Sass color with the given red, green, blue, and alpha
* channels. The red, green, and blue channels must be integers between 0
* and 255 (inclusive), and alpha must be between 0 and 1 (inclusive).
*
* @example
*
* ```js
* new sass.types.Color(107, 113, 127); // #6b717f
* new sass.types.Color(0, 0, 0, 0); // rgba(0, 0, 0, 0)
* ```
*/
constructor(r: number, g: number, b: number, a?: number);
/**
* Creates a new Sass color with alpha, red, green, and blue channels taken
* from respective two-byte chunks of a hexidecimal number.
*
* @example
*
* ```js
* new sass.types.Color(0xff6b717f); // #6b717f
* new sass.types.Color(0x00000000); // rgba(0, 0, 0, 0)
* ```
*/
constructor(argb: number);
/**
* Returns the red channel of the color as an integer from 0 to 255.
*
* @example
*
* ```js
* // color is `#6b717f`.
* color.getR(); // 107
*
* // color is `#b37399`.
* color.getR(); // 179
* ```
*/
getR(): number;
/**
* Sets the red channel of the color. The value must be an integer between 0
* and 255 (inclusive).
*
* @deprecated Use {@link constructor} instead.
*/
setR(value: number): void;
/**
* Returns the green channel of the color as an integer from 0 to 255.
*
* @example
*
* ```js
* // color is `#6b717f`.
* color.getG(); // 113
*
* // color is `#b37399`.
* color.getG(); // 115
* ```
*/
getG(): number;
/**
* Sets the green channel of the color. The value must be an integer between
* 0 and 255 (inclusive).
*
* @deprecated Use {@link constructor} instead.
*/
setG(value: number): void;
/**
* Returns the blue channel of the color as an integer from 0 to 255.
*
* @example
*
* ```js
* // color is `#6b717f`.
* color.getB(); // 127
*
* // color is `#b37399`.
* color.getB(); // 153
* ```
*/
getB(): number;
/**
* Sets the blue channel of the color. The value must be an integer between
* 0 and 255 (inclusive).
*
* @deprecated Use {@link constructor} instead.
*/
setB(value: number): void;
/**
* Returns the alpha channel of the color as a number from 0 to 1.
*
* @example
*
* ```js
* // color is `#6b717f`.
* color.getA(); // 1
*
* // color is `transparent`.
* color.getA(); // 0
* ```
*/
getA(): number;
/**
* Sets the alpha channel of the color. The value must be between 0 and 1
* (inclusive).
*
* @deprecated Use {@link constructor} instead.
*/
setA(value: number): void;
}
/**
* Sass's [list type](https://sass-lang.com/documentation/values/lists).
*
* **Heads up!** This list types methods use 0-based indexing, even though
* within Sass lists use 1-based indexing. These methods also dont support
* using negative numbers to index backwards from the end of the list.
*/
export class List {
/**
* Creates a new Sass list.
*
* **Heads up!** The initial values of the list elements are undefined.
* These elements must be set using {@link setValue} before accessing them
* or passing the list back to Sass.
*
* @example
*
* ```js
* const list = new sass.types.List(3);
* list.setValue(0, new sass.types.Number(10, "px"));
* list.setValue(1, new sass.types.Number(15, "px"));
* list.setValue(2, new sass.types.Number(32, "px"));
* list; // 10px, 15px, 32px
* ```
*
* @param length - The number of (initially undefined) elements in the list.
* @param commaSeparator - If `true`, the list is comma-separated; otherwise,
* it's space-separated. Defaults to `true`.
*/
constructor(length: number, commaSeparator?: boolean);
/**
* Returns the element at `index`, or `undefined` if that value hasn't yet
* been set.
*
* @example
*
* ```js
* // list is `10px, 15px, 32px`
* list.getValue(0); // 10px
* list.getValue(2); // 32px
* ```
*
* @param index - A (0-based) index into this list.
* @throws `Error` if `index` is less than 0 or greater than or equal to the
* number of elements in this list.
*/
getValue(index: number): LegacyValue | undefined;
/**
* Sets the element at `index` to `value`.
*
* @example
*
* ```js
* // list is `10px, 15px, 32px`
* list.setValue(1, new sass.types.Number(18, "px"));
* list; // 10px, 18px, 32px
* ```
*
* @param index - A (0-based) index into this list.
* @throws `Error` if `index` is less than 0 or greater than or equal to the
* number of elements in this list.
*/
setValue(index: number, value: LegacyValue): void;
/**
* Returns `true` if this list is comma-separated and `false` otherwise.
*
* @example
*
* ```js
* // list is `10px, 15px, 32px`
* list.getSeparator(); // true
*
* // list is `1px solid`
* list.getSeparator(); // false
* ```
*/
getSeparator(): boolean;
/**
* Sets whether the list is comma-separated.
*
* @param isComma - `true` to make the list comma-separated, `false` otherwise.
*/
setSeparator(isComma: boolean): void;
/**
* Returns the number of elements in the list.
*
* @example
*
* ```js
* // list is `10px, 15px, 32px`
* list.getLength(); // 3
*
* // list is `1px solid`
* list.getLength(); // 2
* ```
*/
getLength(): number;
}
/**
* Sass's [map type](https://sass-lang.com/documentation/values/maps).
*
* **Heads up!** This map type is represented as a list of key-value pairs
* rather than a mapping from keys to values. The only way to find the value
* associated with a given key is to iterate through the map checking for that
* key. Maps created through this API are still forbidden from having duplicate
* keys.
*/
export class Map {
/**
* Creates a new Sass map.
*
* **Heads up!** The initial keys and values of the map are undefined. They
* must be set using {@link setKey} and {@link setValue} before accessing
* them or passing the map back to Sass.
*
* @example
*
* ```js
* const map = new sass.types.Map(2);
* map.setKey(0, new sass.types.String("width"));
* map.setValue(0, new sass.types.Number(300, "px"));
* map.setKey(1, new sass.types.String("height"));
* map.setValue(1, new sass.types.Number(100, "px"));
* map; // (width: 300px, height: 100px)
* ```
*
* @param length - The number of (initially undefined) key/value pairs in the map.
*/
constructor(length: number);
/**
* Returns the value in the key/value pair at `index`.
*
* @example
*
* ```js
* // map is `(width: 300px, height: 100px)`
* map.getValue(0); // 300px
* map.getValue(1); // 100px
* ```
*
* @param index - A (0-based) index of a key/value pair in this map.
* @throws `Error` if `index` is less than 0 or greater than or equal to the
* number of pairs in this map.
*/
getValue(index: number): LegacyValue;
/**
* Sets the value in the key/value pair at `index` to `value`.
*
* @example
*
* ```js
* // map is `("light": 200, "medium": 400, "bold": 600)`
* map.setValue(1, new sass.types.Number(300));
* map; // ("light": 200, "medium": 300, "bold": 600)
* ```
*
* @param index - A (0-based) index of a key/value pair in this map.
* @throws `Error` if `index` is less than 0 or greater than or equal to the
* number of pairs in this map.
*/
setValue(index: number, value: LegacyValue): void;
/**
* Returns the key in the key/value pair at `index`.
*
* @example
*
* ```js
* // map is `(width: 300px, height: 100px)`
* map.getKey(0); // width
* map.getKey(1); // height
* ```
*
* @param index - A (0-based) index of a key/value pair in this map.
* @throws `Error` if `index` is less than 0 or greater than or equal to the
* number of pairs in this map.
*/
getKey(index: number): LegacyValue;
/**
* Sets the value in the key/value pair at `index` to `value`.
*
* @example
*
* ```js
* // map is `("light": 200, "medium": 400, "bold": 600)`
* map.setValue(1, new sass.types.String("lighter"));
* map; // ("lighter": 200, "medium": 300, "bold": 600)
* ```
*
* @param index - A (0-based) index of a key/value pair in this map.
* @throws `Error` if `index` is less than 0 or greater than or equal to the
* number of pairs in this map.
*/
setKey(index: number, key: LegacyValue): void;
/**
* Returns the number of key/value pairs in this map.
*
* @example
*
* ```js
* // map is `("light": 200, "medium": 400, "bold": 600)`
* map.getLength(); // 3
*
* // map is `(width: 300px, height: 100px)`
* map.getLength(); // 2
* ```
*/
getLength(): number;
}
/**
* An error that can be returned from a Sass function to signal that it
* encountered an error. This is the only way to signal an error
* asynchronously from a {@link LegacyAsyncFunction}.
*/
export class Error {
constructor(message: string);
}
}

169
node_modules/sass/types/legacy/importer.d.ts generated vendored Normal file
View File

@@ -0,0 +1,169 @@
import {LegacyPluginThis} from './plugin_this';
/**
* The value of `this` in the context of a {@link LegacyImporter} function.
*
* @category Legacy
* @deprecated This is only used by the legacy {@link render} and {@link
* renderSync} APIs. Use {@link Importer} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
interface LegacyImporterThis extends LegacyPluginThis {
/**
* Whether the importer 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).
*
* @compatibility dart: "1.33.0", node: false
*/
fromImport: boolean;
}
/**
* The result of running a {@link LegacyImporter}. It must be one of the
* following types:
*
* * An object with the key `contents` whose value is the contents of a stylesheet
* (in SCSS syntax). This causes Sass to load that stylesheets contents.
*
* * An object with the key `file` whose value is a path on disk. This causes Sass
* to load that file as though it had been imported directly.
*
* * `null`, which indicates that it doesnt recognize the URL and another
* importer should be tried instead.
*
* * 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 {@link render} and {@link
* renderSync} APIs. Use {@link ImporterResult} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export type LegacyImporterResult =
| {file: string}
| {contents: string}
| Error
| null;
/**
* A synchronous callback that implements custom Sass loading logic for
* [`@import` rules](https://sass-lang.com/documentation/at-rules/import) and
* [`@use` rules](https://sass-lang.com/documentation/at-rules/use). This can be
* passed to {@link LegacySharedOptions.importer} for either {@link render} or
* {@link renderSync}.
*
* See {@link LegacySharedOptions.importer} for more detailed documentation.
*
* ```js
* sass.renderSync({
* file: "style.scss",
* importer: [
* function(url, prev) {
* if (url != "big-headers") return null;
*
* return {
* contents: 'h1 { font-size: 40px; }'
* };
* }
* ]
* });
* ```
*
* @param url - The `@use` or `@import` rules URL as a string, exactly as it
* appears in the stylesheet.
*
* @param prev - A string identifying the stylesheet that contained the `@use`
* or `@import`. This strings format depends on how that stylesheet was loaded:
*
* * If the stylesheet was loaded from the filesystem, its the absolute path of
* its file.
* * If the stylesheet was loaded from an importer that returned its contents,
* its the URL of the `@use` or `@import` rule that loaded it.
* * If the stylesheet came from the data option, its the string "stdin".
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link Importer} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
type LegacySyncImporter = (
this: LegacyImporterThis,
url: string,
prev: string
) => LegacyImporterResult;
/**
* An asynchronous callback that implements custom Sass loading logic for
* [`@import` rules](https://sass-lang.com/documentation/at-rules/import) and
* [`@use` rules](https://sass-lang.com/documentation/at-rules/use). This can be
* passed to {@link LegacySharedOptions.importer} for either {@link render} or
* {@link renderSync}.
*
* An asynchronous importer must return `undefined`, and then call `done` with
* the result of its {@link LegacyImporterResult} once it's done running.
*
* See {@link LegacySharedOptions.importer} for more detailed documentation.
*
* ```js
* sass.render({
* file: "style.scss",
* importer: [
* function(url, prev, done) {
* if (url != "big-headers") done(null);
*
* done({
* contents: 'h1 { font-size: 40px; }'
* });
* }
* ]
* });
* ```
*
* @param url - The `@use` or `@import` rules URL as a string, exactly as it
* appears in the stylesheet.
*
* @param prev - A string identifying the stylesheet that contained the `@use`
* or `@import`. This strings format depends on how that stylesheet was loaded:
*
* * If the stylesheet was loaded from the filesystem, its the absolute path of
* its file.
* * If the stylesheet was loaded from an importer that returned its contents,
* its the URL of the `@use` or `@import` rule that loaded it.
* * If the stylesheet came from the data option, its the string "stdin".
*
* @param done - The callback to call once the importer has finished running.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link Importer} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
type LegacyAsyncImporter = (
this: LegacyImporterThis,
url: string,
prev: string,
done: (result: LegacyImporterResult) => void
) => void;
/**
* A callback that implements custom Sass loading logic for [`@import`
* rules](https://sass-lang.com/documentation/at-rules/import) and [`@use`
* rules](https://sass-lang.com/documentation/at-rules/use). For {@link
* renderSync}, this must be a {@link LegacySyncImporter} which returns its
* result directly; for {@link render}, it may be either a {@link
* LegacySyncImporter} or a {@link LegacyAsyncImporter} which calls a callback
* with its result.
*
* See {@link LegacySharedOptions.importer} for more details.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link Importer} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export type LegacyImporter<sync = 'sync' | 'async'> = sync extends 'async'
? LegacySyncImporter | LegacyAsyncImporter
: LegacySyncImporter;

641
node_modules/sass/types/legacy/options.d.ts generated vendored Normal file
View File

@@ -0,0 +1,641 @@
import {Logger} from '../logger';
import {LegacyImporter} from './importer';
import {LegacyFunction} from './function';
/**
* Options for {@link render} and {@link renderSync} that are shared between
* {@link LegacyFileOptions} and {@link LegacyStringOptions}.
*
* @typeParam sync - This lets the TypeScript checker verify that {@link
* LegacyAsyncImporter}s and {@link LegacyAsyncFunction}s aren't passed to
* {@link renderSync}.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link Options} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export interface LegacySharedOptions<sync extends 'sync' | 'async'> {
/**
* This array of strings option provides [load
* paths](https://sass-lang.com/documentation/at-rules/import#load-paths) for
* Sass to look for stylesheets. Earlier load paths will take precedence over
* later ones.
*
* ```js
* sass.renderSync({
* file: "style.scss",
* includePaths: ["node_modules/bootstrap/dist/css"]
* });
* ```
*
* Load paths are also loaded from the `SASS_PATH` environment variable, if
* its set. This variable should be a list of paths separated by `;` (on
* Windows) or `:` (on other operating systems). Load paths from the
* `includePaths` option take precedence over load paths from `SASS_PATH`.
*
* ```sh
* $ SASS_PATH=node_modules/bootstrap/dist/css sass style.scss style.css
* ```
*
* @category Input
* @compatibility feature: "SASS_PATH", dart: "1.15.0", node: "3.9.0"
*
* Earlier versions of Dart Sass and Node Sass didnt support the `SASS_PATH`
* environment variable.
*/
includePaths?: string[];
/**
* Whether the generated CSS should use spaces or tabs for indentation.
*
* ```js
* const result = sass.renderSync({
* file: "style.scss",
* indentType: "tab",
* indentWidth: 1
* });
*
* result.css.toString();
* // "h1 {\n\tfont-size: 40px;\n}\n"
* ```
*
* @defaultValue `'space'`
* @category Output
* @compatibility dart: true, node: "3.0.0"
*/
indentType?: 'space' | 'tab';
/**
* How many spaces or tabs (depending on {@link indentType}) should be used
* per indentation level in the generated CSS. It must be between 0 and 10
* (inclusive).
*
* @defaultValue `2`
* @category Output
* @compatibility dart: true, node: "3.0.0"
*/
indentWidth?: number;
/**
* Which character sequence to use at the end of each line in the generated
* CSS. It can have the following values:
*
* * `'lf'` uses U+000A LINE FEED.
* * `'lfcr'` uses U+000A LINE FEED followed by U+000D CARRIAGE RETURN.
* * `'cr'` uses U+000D CARRIAGE RETURN.
* * `'crlf'` uses U+000D CARRIAGE RETURN followed by U+000A LINE FEED.
*
* @defaultValue `'lf'`
* @category Output
* @compatibility dart: true, node: "3.0.0"
*/
linefeed?: 'cr' | 'crlf' | 'lf' | 'lfcr';
/**
* If `true`, Sass won't add a link from the generated CSS to the source map.
*
* ```js
* const result = sass.renderSync({
* file: "style.scss",
* sourceMap: "out.map",
* omitSourceMapUrl: true
* })
* console.log(result.css.toString());
* // h1 {
* // font-size: 40px;
* // }
* ```
*
* @defaultValue `false`
* @category Source Maps
*/
omitSourceMapUrl?: boolean;
/**
* The location that Sass expects the generated CSS to be saved to. Its used
* to determine the URL used to link from the generated CSS to the source map,
* and from the source map to the Sass source files.
*
* **Heads up!** Despite the name, Sass does *not* write the CSS output to
* this file. The caller must do that themselves.
*
* ```js
* result = sass.renderSync({
* file: "style.scss",
* sourceMap: true,
* outFile: "out.css"
* })
* console.log(result.css.toString());
* // h1 {
* // font-size: 40px;
* // }
* // /*# sourceMappingURL=out.css.map * /
* ```
*
* @category Source Maps
*/
outFile?: string;
/**
* The output style of the compiled CSS. There are four possible output styles:
*
* * `"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.
*
* * `"nested"` (the default for Node Sass, not supported by Dart Sass)
* indents CSS rules to match the nesting of the Sass source.
*
* * `"compact"` (not supported by Dart Sass) puts each CSS rule on its own single line.
*
* @example
*
* ```js
* const source = `
* h1 {
* font-size: 40px;
* code {
* font-face: Roboto Mono;
* }
* }`;
*
* let result = sass.renderSync({
* data: source,
* outputStyle: "expanded"
* });
* console.log(result.css.toString());
* // h1 {
* // font-size: 40px;
* // }
* // h1 code {
* // font-face: Roboto Mono;
* // }
*
* result = sass.renderSync({
* data: source,
* outputStyle: "compressed"
* });
* console.log(result.css.toString());
* // h1{font-size:40px}h1 code{font-face:Roboto Mono}
*
* result = sass.renderSync({
* data: source,
* outputStyle: "nested"
* });
* console.log(result.css.toString());
* // h1 {
* // font-size: 40px; }
* // h1 code {
* // font-face: Roboto Mono; }
*
* result = sass.renderSync({
* data: source,
* outputStyle: "compact"
* });
* console.log(result.css.toString());
* // h1 { font-size: 40px; }
* // h1 code { font-face: Roboto Mono; }
* ```
*
* @category Output
*/
outputStyle?: 'compressed' | 'expanded' | 'nested' | 'compact';
/**
* Whether or not Sass should generate a source map. If it does, the source
* map will be available as {@link LegacyResult.map} (unless {@link
* sourceMapEmbed} is `true`).
*
* If this option is a string, its the path that the source map is expected
* to be written to, which is used to link to the source map from the
* generated CSS and to link *from* the source map to the Sass source files.
* Note that if `sourceMap` is a string and {@link outFile} isnt passed, Sass
* assumes that the CSS will be written to the same directory as the file
* option if its passed.
*
* If this option is `true`, the path is assumed to be {@link outFile} with
* `.map` added to the end. If its `true` and {@link outFile} isnt passed,
* it has no effect.
*
* @example
*
* ```js
* let result = sass.renderSync({
* file: "style.scss",
* sourceMap: "out.map"
* })
* console.log(result.css.toString());
* // h1 {
* // font-size: 40px;
* // }
* // /*# sourceMappingURL=out.map * /
*
* result = sass.renderSync({
* file: "style.scss",
* sourceMap: true,
* outFile: "out.css"
* })
* console.log(result.css.toString());
* // h1 {
* // font-size: 40px;
* // }
* // /*# sourceMappingURL=out.css.map * /
* ```
*
* @defaultValue `false`
* @category Source Maps
*/
sourceMap?: boolean | string;
/**
* Whether to embed the entire contents of the Sass files that contributed to
* the generated CSS in the source map. This may produce very large source
* maps, but it guarantees that the source will be available on any computer
* no matter how the CSS is served.
*
* @example
*
* ```js
* sass.renderSync({
* file: "style.scss",
* sourceMap: "out.map",
* sourceMapContents: true
* })
* ```
*
* @defaultValue `false`
* @category Source Maps
*/
sourceMapContents?: boolean;
/**
* Whether to embed the contents of the source map file in the generated CSS,
* rather than creating a separate file and linking to it from the CSS.
*
* @example
*
* ```js
* sass.renderSync({
* file: "style.scss",
* sourceMap: "out.map",
* sourceMapEmbed: true
* });
* ```
*
* @defaultValue `false`
* @category Source Maps
*/
sourceMapEmbed?: boolean;
/**
* If this is passed, it's prepended to all the links from the source map to
* the Sass source files.
*
* @category Source Maps
*/
sourceMapRoot?: string;
/**
* Additional handler(s) for loading files when a [`@use`
* rule](https://sass-lang.com/documentation/at-rules/use) or an [`@import`
* rule](https://sass-lang.com/documentation/at-rules/import) is encountered.
* It can either be a single {@link LegacyImporter} function, or an array of
* {@link LegacyImporter}s.
*
* Importers take the URL of the `@import` or `@use` rule and return a {@link
* LegacyImporterResult} indicating how to handle that rule. For more details,
* see {@link LegacySyncImporter} and {@link LegacyAsyncImporter}.
*
* Loads are resolved by trying, in order:
*
* * Loading a file from disk relative to the file in which the `@use` or
* `@import` appeared.
*
* * Each custom importer.
*
* * Loading a file relative to the current working directory.
*
* * Each load path in {@link includePaths}.
*
* * Each load path specified in the `SASS_PATH` environment variable, which
* should be semicolon-separated on Windows and colon-separated elsewhere.
*
* @example
*
* ```js
* sass.render({
* file: "style.scss",
* importer: [
* // This importer uses the synchronous API, and can be passed to either
* // renderSync() or render().
* function(url, prev) {
* // This generates a stylesheet from scratch for `@use "big-headers"`.
* if (url != "big-headers") return null;
*
* return {
* contents: `
* h1 {
* font-size: 40px;
* }`
* };
* },
*
* // This importer uses the asynchronous API, and can only be passed to
* // render().
* function(url, prev, done) {
* // Convert `@use "foo/bar"` to "node_modules/foo/sass/bar".
* const components = url.split('/');
* const innerPath = components.slice(1).join('/');
* done({
* file: `node_modules/${components.first}/sass/${innerPath}`
* });
* }
* ]
* }, function(err, result) {
* // ...
* });
* ```
*
* @category Plugins
* @compatibility dart: true, node: "3.0.0"
*
* Versions of Node Sass before 3.0.0 dont support arrays of importers, nor
* do they support importers that return `Error` objects.
*
* Versions of Node Sass before 2.0.0 dont support the `importer` option at
* all.
*
* @compatibility feature: "Import order", dart: "1.20.2", node: false
*
* Versions of Dart Sass before 1.20.2 preferred resolving imports using
* {@link includePaths} before resolving them using custom importers.
*
* All versions of Node Sass currently pass imports to importers before
* loading them relative to the file in which the `@import` appears. This
* behavior is considered incorrect and should not be relied on because it
* violates the principle of *locality*, which says that it should be possible
* to reason about a stylesheet without knowing everything about how the
* entire system is set up. If a user tries to import a stylesheet relative to
* another stylesheet, that import should *always* work. It shouldnt be
* possible for some configuration somewhere else to break it.
*/
importer?: LegacyImporter<sync> | LegacyImporter<sync>[];
/**
* Additional built-in Sass functions that are available in all stylesheets.
* This option takes an object whose keys are Sass function signatures and
* whose values are {@link LegacyFunction}s. Each function should take the
* same arguments as its signature.
*
* Functions are passed subclasses of {@link LegacyValue}, and must return the
* same.
*
* **Heads up!** When writing custom functions, its important to ensure that
* all the arguments are the types you expect. Otherwise, users stylesheets
* could crash in hard-to-debug ways or, worse, compile to meaningless CSS.
*
* @example
*
* ```js
* sass.render({
* data: `
* h1 {
* font-size: pow(2, 5) * 1px;
* }`,
* functions: {
* // This function uses the synchronous API, and can be passed to either
* // renderSync() or render().
* 'pow($base, $exponent)': function(base, exponent) {
* if (!(base instanceof sass.types.Number)) {
* throw "$base: Expected a number.";
* } else if (base.getUnit()) {
* throw "$base: Expected a unitless number.";
* }
*
* if (!(exponent instanceof sass.types.Number)) {
* throw "$exponent: Expected a number.";
* } else if (exponent.getUnit()) {
* throw "$exponent: Expected a unitless number.";
* }
*
* return new sass.types.Number(
* Math.pow(base.getValue(), exponent.getValue()));
* },
*
* // This function uses the asynchronous API, and can only be passed to
* // render().
* 'sqrt($number)': function(number, done) {
* if (!(number instanceof sass.types.Number)) {
* throw "$number: Expected a number.";
* } else if (number.getUnit()) {
* throw "$number: Expected a unitless number.";
* }
*
* done(new sass.types.Number(Math.sqrt(number.getValue())));
* }
* }
* }, function(err, result) {
* console.log(result.css.toString());
* // h1 {
* // font-size: 32px;
* // }
* });
* ```
*
* @category Plugins
*/
functions?: {[key: string]: LegacyFunction<sync>};
/**
* By default, if the CSS document contains non-ASCII characters, Sass adds a
* `@charset` declaration (in expanded output mode) or a byte-order mark (in
* compressed mode) to indicate its encoding to browsers or other consumers.
* If `charset` is `false`, these annotations are omitted.
*
* @category Output
* @compatibility dart: "1.39.0", node: false
*/
charset?: boolean;
/**
* If this option is set to `true`, Sass wont print warnings that are caused
* by dependencies. A “dependency” is defined as any file thats loaded
* through {@link includePaths} or {@link importer}. Stylesheets that are
* imported relative to the entrypoint are not considered dependencies.
*
* This is useful for silencing deprecation warnings that you cant fix on
* your own. However, please <em>also</em> notify your dependencies of the deprecations
* so that they can get fixed as soon as possible!
*
* **Heads up!** If {@link render} or {@link renderSync} is called without
* {@link LegacyFileOptions.file} or {@link LegacyStringOptions.file},
* <em>all</em> stylesheets it loads will be considered dependencies. Since it
* doesnt have a path of its own, everything it loads is coming from a load
* path rather than a relative import.
*
* @defaultValue `false`
* @category Messages
* @compatibility dart: "1.35.0", node: false
*/
quietDeps?: boolean;
/**
* 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
* @compatibility dart: "1.35.0", node: false
*/
verbose?: boolean;
/**
* 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 {@link Logger.warn} or {@link Logger.debug} is set, this will invoke
* them instead.
*
* The special value {@link Logger.silent} can be used to easily silence all
* messages.
*
* @category Messages
* @compatibility dart: "1.43.0", node: false
*/
logger?: Logger;
}
/**
* If {@link file} is passed without {@link data}, Sass will load the stylesheet
* at {@link file} and compile it to CSS.
*
* @typeParam sync - This lets the TypeScript checker verify that {@link
* LegacyAsyncImporter}s and {@link LegacyAsyncFunction}s aren't passed to
* {@link renderSync}.
*/
export interface LegacyFileOptions<sync extends 'sync' | 'async'>
extends LegacySharedOptions<sync> {
/**
* The path to the file for Sass to load and compile. If the files extension
* is `.scss`, it will be parsed as SCSS; if its `.sass`, it will be parsed
* as the indented syntax; and if its `.css`, it will be parsed as plain CSS.
* If it has no extension, it will be parsed as SCSS.
*
* @example
*
* ```js
* sass.renderSync({file: "style.scss"});
* ```
*
* @category Input
* @compatibility feature: "Plain CSS files", dart: "1.11.0", node: "partial"
*
* Node Sass and older versions of Dart Sass support loading files with the
* extension `.css`, but contrary to the specification theyre treated as SCSS
* files rather than being parsed as CSS. This behavior has been deprecated
* and should not be relied on. Any files that use Sass features should use
* the `.scss` extension.
*
* All versions of Node Sass and Dart Sass otherwise support the file option
* as described below.
*/
file: string;
/**
* See {@link LegacyStringOptions.file} for documentation of passing {@link
* file} along with {@link data}.
*
* @category Input
*/
data?: never;
}
/**
* If {@link data} is passed, Sass will use it as the contents of the stylesheet
* to compile.
*
* @typeParam sync - This lets the TypeScript checker verify that {@link
* LegacyAsyncImporter}s and {@link LegacyAsyncFunction}s aren't passed to
* {@link renderSync}.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link StringOptions} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export interface LegacyStringOptions<sync extends 'sync' | 'async'>
extends LegacySharedOptions<sync> {
/**
* The contents of the stylesheet to compile. Unless {@link file} is passed as
* well, the stylesheets URL is set to `"stdin"`.
*
* By default, this stylesheet is parsed as SCSS. This can be controlled using
* {@link indentedSyntax}.
*
* @example
*
* ```js
* sass.renderSync({
* data: `
* h1 {
* font-size: 40px;
* }`
* });
* ```
*
* @category Input
*/
data: string;
/**
* If `file` and {@link data} are both passed, `file` is used as the path of
* the stylesheet for error reporting, but {@link data} is used as the
* contents of the stylesheet. In this case, `file`s extension is not used to
* determine the syntax of the stylesheet.
*
* @category Input
*/
file?: string;
/**
* This flag controls whether {@link data} is parsed as the indented syntax or
* not.
*
* @example
*
* ```js
* sass.renderSync({
* data: `
* h1
* font-size: 40px`,
* indentedSyntax: true
* });
* ```
*
* @defaultValue `false`
* @category Input
*/
indentedSyntax?: boolean;
}
/**
* Options for {@link render} and {@link renderSync}. This can either be {@link
* LegacyFileOptions} to load a file from disk, or {@link LegacyStringOptions}
* to compile a string of Sass code.
*
* See {@link LegacySharedOptions} for options that are shared across both file
* and string inputs.
*
* @category Legacy
* @deprecated This only works with the legacy {@link render} and {@link
* renderSync} APIs. Use {@link Options} with {@link compile}, {@link
* compileString}, {@link compileAsync}, and {@link compileStringAsync} instead.
*/
export type LegacyOptions<sync extends 'sync' | 'async'> =
| LegacyFileOptions<sync>
| LegacyStringOptions<sync>;

74
node_modules/sass/types/legacy/plugin_this.d.ts generated vendored Normal file
View File

@@ -0,0 +1,74 @@
/**
* The value of `this` in the context of a {@link LegacyImporter} or {@link
* LegacyFunction} callback.
*
* @category Legacy
* @deprecated This is only used by the legacy {@link render} and {@link
* renderSync} APIs. Use {@link compile}, {@link compileString}, {@link
* compileAsync}, and {@link compileStringAsync} instead.
*/
export interface LegacyPluginThis {
/**
* A partial representation of the options passed to {@link render} or {@link
* renderSync}.
*/
options: {
/** The same {@link LegacyPluginThis} instance that contains this object. */
context: LegacyPluginThis;
/**
* The value passed to {@link LegacyFileOptions.file} or {@link
* LegacyStringOptions.file}.
*/
file?: string;
/** The value passed to {@link LegacyStringOptions.data}. */
data?: string;
/**
* The value passed to {@link LegacySharedOptions.includePaths} separated by
* `";"` on Windows or `":"` on other operating systems. This always
* includes the current working directory as the first entry.
*/
includePaths: string;
/** Always the number 10. */
precision: 10;
/** Always the number 1. */
style: 1;
/** 1 if {@link LegacySharedOptions.indentType} was `"tab"`, 0 otherwise. */
indentType: 1 | 0;
/**
* The value passed to {@link LegacySharedOptions.indentWidth}, or `2`
* otherwise.
*/
indentWidth: number;
/**
* The value passed to {@link LegacySharedOptions.linefeed}, or `"\n"`
* otherwise.
*/
linefeed: '\r' | '\r\n' | '\n' | '\n\r';
/** A partially-constructed {@link LegacyResult} object. */
result: {
/** Partial information about the compilation in progress. */
stats: {
/**
* The number of milliseconds between 1 January 1970 at 00:00:00 UTC and
* the time at which Sass compilation began.
*/
start: number;
/**
* {@link LegacyFileOptions.file} if it was passed, otherwise the string
* `"data"`.
*/
entry: string;
};
};
};
}

139
node_modules/sass/types/legacy/render.d.ts generated vendored Normal file
View File

@@ -0,0 +1,139 @@
import {LegacyException} from './exception';
import {LegacyOptions} from './options';
/**
* The object returned by {@link render} and {@link renderSync} after a
* successful compilation.
*
* @category Legacy
* @deprecated This is only used by the legacy {@link render} and {@link
* renderSync} APIs. Use {@link compile}, {@link compileString}, {@link
* compileAsync}, and {@link compileStringAsync} instead.
*/
export interface LegacyResult {
/**
* The compiled CSS. This can be converted to a string by calling
* [Buffer.toString](https://nodejs.org/api/buffer.html#buffer_buf_tostring_encoding_start_end).
*
* @example
*
* ```js
* const result = sass.renderSync({file: "style.scss"});
*
* console.log(result.css.toString());
* ```
*/
css: Buffer;
/**
* The source map that maps the compiled CSS to the source files from which it
* was generated. This can be converted to a string by calling
* [Buffer.toString](https://nodejs.org/api/buffer.html#buffer_buf_tostring_encoding_start_end).
*
* This is `undefined` unless either
*
* * {@link LegacySharedOptions.sourceMap} is a string; or
* * {@link LegacySharedOptions.sourceMap} is `true` and
* {@link LegacySharedOptions.outFile} is set.
*
* The source map uses absolute [`file:`
* URLs](https://en.wikipedia.org/wiki/File_URI_scheme) to link to the Sass
* source files, except if the source file comes from {@link
* LegacyStringOptions.data} in which case it lists its URL as `"stdin"`.
*
* @example
*
* ```js
* const result = sass.renderSync({
* file: "style.scss",
* sourceMap: true,
* outFile: "style.css"
* })
*
* console.log(result.map.toString());
* ```
*/
map?: Buffer;
/** Additional information about the compilation. */
stats: {
/**
* The absolute path of {@link LegacyFileOptions.file} or {@link
* LegacyStringOptions.file}, or `"data"` if {@link
* LegacyStringOptions.file} wasn't set.
*/
entry: string;
/**
* The number of milliseconds between 1 January 1970 at 00:00:00 UTC and the
* time at which Sass compilation began.
*/
start: number;
/**
* The number of milliseconds between 1 January 1970 at 00:00:00 UTC and the
* time at which Sass compilation ended.
*/
end: number;
/**
* The number of milliseconds it took to compile the Sass file. This is
* always equal to `start` minus `end`.
*/
duration: number;
/**
* An array of the absolute paths of all Sass files loaded during
* compilation. If a stylesheet was loaded from a {@link LegacyImporter}
* that returned the stylesheets contents, the raw string of the `@use` or
* `@import` that loaded that stylesheet included in this array.
*/
includedFiles: string[];
};
}
/**
* This function synchronously compiles a Sass file to CSS. If it succeeds, it
* returns the result, and if it fails it throws an error.
*
* @example
*
* ```js
* const sass = require('sass'); // or require('node-sass');
*
* const result = sass.renderSync({file: "style.scss"});
* // ...
* ```
*
* @category Legacy
* @deprecated Use {@link compile} or {@link compileString} instead.
*/
export function renderSync(options: LegacyOptions<'sync'>): LegacyResult;
/**
* This function asynchronously compiles a Sass file to CSS, and calls
* `callback` with a {@link LegacyResult} if compilation succeeds or {@link
* LegacyException} if it fails.
*
* **Heads up!** When using Dart Sass, **{@link renderSync} is almost twice as
* fast as {@link render}** by default, due to the overhead of making the entire
* evaluation process asynchronous.
*
* ```js
* const sass = require('sass'); // or require('node-sass');
*
* sass.render({
* file: "style.scss"
* }, function(err, result) {
* // ...
* });
* ```
*
* @category Legacy
* @deprecated Use {@link compileAsync} or {@link compileStringAsync} instead.
*/
export function render(
options: LegacyOptions<'async'>,
callback: (exception?: LegacyException, result?: LegacyResult) => void
): void;

94
node_modules/sass/types/logger/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,94 @@
import {SourceSpan} from './source_span';
export {SourceLocation} from './source_location';
export {SourceSpan} from './source_span';
/**
* An object that can be passed to {@link LegacySharedOptions.logger} to control
* how Sass emits warnings and debug messages.
*
* @example
*
* ```js
* const fs = require('fs');
* const sass = require('sass');
*
* let log = "";
* sass.renderSync({
* file: 'input.scss',
* logger: {
* warn(message, options) {
* if (options.span) {
* log += `${span.url}:${span.start.line}:${span.start.column}: ` +
* `${message}\n`;
* } else {
* log += `::: ${message}\n`;
* }
* }
* }
* });
*
* fs.writeFileSync('log.txt', log);
* ```
*
* @category Logger
*/
export interface Logger {
/**
* This method is called when Sass emits a warning, whether due to a [`@warn`
* rule](https://sass-lang.com/documentation/at-rules/warn) or a warning
* generated by the Sass compiler.
*
* If this is `undefined`, Sass will print warnings to standard error.
*
* @param message - The warning message.
* @param options.deprecation - Whether this is a deprecation warning.
* @param options.span - The location in the Sass source code that generated this
* warning.
* @param options.stack - The Sass stack trace at the point the warning was issued.
*/
warn?(
message: string,
options: {
deprecation: boolean;
span?: SourceSpan;
stack?: string;
}
): void;
/**
* This method is called when Sass emits a debug message due to a [`@debug`
* rule](https://sass-lang.com/documentation/at-rules/debug).
*
* If this is `undefined`, Sass will print debug messages to standard error.
*
* @param message - The debug message.
* @param options.span - The location in the Sass source code that generated this
* debug message.
*/
debug?(message: string, options: {span: SourceSpan}): void;
}
/**
* A namespace for built-in {@link Logger}s.
*
* @category Logger
* @compatibility dart: "1.43.0", node: false
*/
export namespace Logger {
/**
* A {@link Logger} that silently ignores all warnings and debug messages.
*
* @example
*
* ```js
* const sass = require('sass');
*
* const result = sass.renderSync({
* file: 'input.scss',
* logger: sass.Logger.silent,
* });
* ```
*/
export const silent: Logger;
}

21
node_modules/sass/types/logger/source_location.d.ts generated vendored Normal file
View File

@@ -0,0 +1,21 @@
/**
* A specific location within a source file.
*
* This is always associated with a {@link 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;
}

34
node_modules/sass/types/logger/source_span.d.ts generated vendored Normal file
View File

@@ -0,0 +1,34 @@
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 {@link start} and {@link end} refer to the same location, the span has
* zero length and refers to the point immediately after {@link 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;
}

439
node_modules/sass/types/options.d.ts generated vendored Normal file
View File

@@ -0,0 +1,439 @@
import {FileImporter, Importer} from './importer';
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
* {@link Options.functions}.
*
* ```js
* const result = sass.compile('style.scss', {
* functions: {
* "sum($arg1, $arg2)": (args) => {
* const arg1 = args[0].assertNumber('arg1');
* const value1 = 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 {@link compile} and {@link compileString} in
* addition to {@link compileAsync} and {@link compileStringAsync}.
*
* A `CustomFunction<'async'>` may either return synchronously or
* asynchronously, but it can only be used with {@link compileAsync} and {@link
* 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 {@link 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 {@link compileAsync} and {@link
* compileStringAsync}, not {@link compile} or {@link 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<sync extends 'sync' | 'async'> = (
args: Value[]
) => PromiseOr<Value, sync>;
/**
* Options that can be passed to {@link compile}, {@link compileAsync}, {@link
* compileString}, or {@link compileStringAsync}.
*
* @typeParam sync - This lets the TypeScript checker verify that asynchronous
* {@link Importer}s, {@link FileImporter}s, and {@link CustomFunction}s aren't
* passed to {@link compile} or {@link compileString}.
*
* @category Options
*/
export interface Options<sync extends 'sync' | 'async'> {
/**
* 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;
/**
* If `true`, the compiler may prepend `@charset "UTF-8";` or U+FEFF
* (byte-order marker) if it outputs non-ASCII CSS.
*
* If `false`, the compiler never emits these byte sequences. This is ideal
* when concatenating or embedding in HTML `<style>` tags. (The output will
* still be UTF-8.)
*
* @defaultValue `true`
* @category Output
* @compatibility dart: "1.54.0", node: false
*/
charset?: 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 {@link CustomFunction}s.
*
* Functions are passed subclasses of {@link Value}, and must return the same.
* If the return value includes {@link SassCalculation}s they will be
* simplified before being returned.
*
* 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 {@link 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 {@link
* SassNumber.assertInt}, which should be used when possible.
*
* * In Sass, every value counts as a list. Rather than trying to detect the
* {@link SassList} type, you should use {@link 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. {@link Value.sassIndexToListIndex} and {@link
* 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. {@link SassString.sassIndexToStringIndex} can be used to do
* this automatically, and the {@link 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<string, CustomFunction<sync>>;
/**
* 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 {@link Importer} or {@link FileImporter} in {@link importers}, in
* order.
*
* - Each load path in {@link loadPaths}, in order.
*
* If none of these return a Sass file, the load fails and Sass throws an
* error.
*
* @category Plugins
*/
importers?: (Importer<sync> | FileImporter<sync>)[];
/**
* 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 {@link 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 {@link Logger.warn} or {@link Logger.debug} is set, this will invoke
* them instead.
*
* The special value {@link Logger.silent} can be used to easily silence all
* messages.
*
* @category Messages
*/
logger?: Logger;
/**
* If this option is set to `true`, Sass wont print warnings that are caused
* by dependencies. A “dependency” is defined as any file thats loaded
* through {@link loadPaths} or {@link importers}. Stylesheets that are
* imported relative to the entrypoint are not considered dependencies.
*
* This is useful for silencing deprecation warnings that you cant fix on
* your own. However, please <em>also</em> notify your dependencies of the deprecations
* so that they can get fixed as soon as possible!
*
* **Heads up!** If {@link compileString} or {@link compileStringAsync} is
* called without {@link StringOptionsWithoutImporter.url}, <em>all</em>
* stylesheets it loads will be considered dependencies. Since it doesnt 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 {@link 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;
/**
* Whether Sass should include the sources in the generated source map.
*
* This option has no effect if {@link sourceMap} is `false`.
*
* @defaultValue `false`
* @category Output
*/
sourceMapIncludeSources?: boolean;
/**
* The {@link 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;
}
/**
* Options that can be passed to {@link compileString} or {@link
* compileStringAsync}.
*
* If the {@link StringOptionsWithImporter.importer} field isn't passed, the
* entrypoint file can load files relative to itself if a `file://` URL is
* passed to the {@link url} field.
*
* @typeParam sync - This lets the TypeScript checker verify that asynchronous
* {@link Importer}s, {@link FileImporter}s, and {@link CustomFunction}s aren't
* passed to {@link compile} or {@link compileString}.
*
* @category Options
*/
export interface StringOptionsWithoutImporter<sync extends 'sync' | 'async'>
extends Options<sync> {
/**
* The {@link Syntax} to use to parse the entrypoint stylesheet.
*
* @default `'scss'`
*
* @category Input
*/
syntax?: Syntax;
/**
* The canonical URL of the entrypoint stylesheet.
*
* A relative load's URL is first resolved relative to {@link url}, then
* resolved to a file on disk if it's a `file://` URL. If it can't be resolved
* to a file on disk, it's then passed to {@link importers} and {@link
* loadPaths}.
*
* @category Input
*/
url?: URL;
}
/**
* Options that can be passed to {@link compileString} or {@link
* compileStringAsync}.
*
* If the {@link StringOptionsWithImporter.importer} field is passed, the
* entrypoint file uses it to load files relative to itself and the {@link url}
* field is mandatory.
*
* @typeParam sync - This lets the TypeScript checker verify that asynchronous
* {@link Importer}s, {@link FileImporter}s, and {@link CustomFunction}s aren't
* passed to {@link compile} or {@link compileString}.
*
* @category Options
*/
export interface StringOptionsWithImporter<sync extends 'sync' | 'async'>
extends StringOptionsWithoutImporter<sync> {
/**
* The importer to use to handle loads that are relative to the entrypoint
* stylesheet.
*
* A relative load's URL is first resolved relative to {@link url}, then
* passed to {@link importer}. If the importer doesn't recognize it, it's then
* passed to {@link importers} and {@link loadPaths}.
*
* @category Input
*/
importer: Importer<sync> | FileImporter<sync>;
/**
* The canonical URL of the entrypoint stylesheet. If this is passed along
* with {@link importer}, it's used to resolve relative loads in the
* entrypoint stylesheet.
*
* @category Input
*/
url: URL;
}
/**
* Options that can be passed to {@link compileString} or {@link
* compileStringAsync}.
*
* This is a {@link StringOptionsWithImporter} if it has a {@link
* StringOptionsWithImporter.importer} field, and a {@link
* StringOptionsWithoutImporter} otherwise.
*
* @typeParam sync - This lets the TypeScript checker verify that asynchronous
* {@link Importer}s, {@link FileImporter}s, and {@link CustomFunction}s aren't
* passed to {@link compile} or {@link compileString}.
*
* @category Options
*/
export type StringOptions<sync extends 'sync' | 'async'> =
| StringOptionsWithImporter<sync>
| StringOptionsWithoutImporter<sync>;

17
node_modules/sass/types/util/promise_or.d.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/**
* A utility type for choosing between synchronous and asynchronous return
* values.
*
* This is used as the return value for plugins like {@link CustomFunction},
* {@link Importer}, and {@link FileImporter} so that TypeScript enforces that
* asynchronous plugins are only passed to {@link compileAsync} and {@link
* compileStringAsync}, not {@link compile} or {@link 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<T>`.
*
* @category Other
*/
export type PromiseOr<T, sync extends 'sync' | 'async'> = sync extends 'async'
? T | Promise<T>
: T;

47
node_modules/sass/types/value/argument_list.d.ts generated vendored Normal file
View File

@@ -0,0 +1,47 @@
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
* {@link 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 {@link 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 {@link OrderedMap}
* from the [`immutable` package](https://immutable-js.com/)
*
* @param separator - The separator for this list. Defaults to `','`.
*/
constructor(
contents: Value[] | List<Value>,
keywords: Record<string, Value> | OrderedMap<string, Value>,
separator?: ListSeparator
);
/**
* The keyword arguments attached to this argument list.
*
* The argument names don't include `$`.
*
* @returns An immutable {@link OrderedMap} from the [`immutable`
* package](https://immutable-js.com/).
*/
get keywords(): OrderedMap<string, Value>;
}

29
node_modules/sass/types/value/boolean.d.ts generated vendored Normal file
View File

@@ -0,0 +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;
/**
* 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;
}

137
node_modules/sass/types/value/calculation.d.ts generated vendored Normal file
View File

@@ -0,0 +1,137 @@
import {List, ValueObject} from 'immutable';
import {Value, SassNumber, SassString} from './index';
/**
* The type of values that can be arguments to a {@link SassCalculation}.
* @category Custom Function
* */
export type CalculationValue =
| SassNumber
| SassCalculation
| SassString
| CalculationOperation
| CalculationInterpolation;
/**
* Sass's [calculation
* type](https://sass-lang.com/documentation/values/calculations).
*
* Note: in the JS API calculations are not simplified eagerly. This also means
* that unsimplified calculations are not equal to the numbers they would be
* simplified to.
*
* @category Custom Function
*/
export class SassCalculation extends Value {
/**
* Creates a value that represents `calc(argument)`.
*
* @throws `Error` if `argument` is a quoted {@link SassString}
* @returns A calculation with the name `calc` and `argument` as its single
* argument.
*/
static calc(argument: CalculationValue): SassCalculation;
/**
* Creates a value that represents `min(arguments...)`.
*
* @throws `Error` if `arguments` contains a quoted {@link SassString}
* @returns A calculation with the name `min` and `arguments` as its
* arguments.
*/
static min(
arguments: CalculationValue[] | List<CalculationValue>
): SassCalculation;
/**
* Creates a value that represents `max(arguments...)`.
*
* @throws `Error` if `arguments` contains a quoted {@link SassString}
* @returns A calculation with the name `max` and `arguments` as its
* arguments.
*/
static max(
arguments: CalculationValue[] | List<CalculationValue>
): SassCalculation;
/**
* Creates a value that represents `clamp(value, min, max)`.
*
* @throws `Error` if any of `value`, `min`, or `max` are a quoted
* {@link SassString}.
* @throws `Error` if `value` is undefined and `max` is not undefined.
* @throws `Error` if either `value` or `max` is undefined and neither `min`
nor `value` is a {@link SassString} or {@link CalculationInterpolation}.
@returns A calculation with the name `clamp` and `min`, `value`, and `max`
as it's arguments, excluding any arguments that are undefined.
*/
static clamp(
min: CalculationValue,
value?: CalculationValue,
max?: CalculationValue
): SassCalculation;
/** Returns the calculation's `name` field. */
get name(): string;
/** Returns a list of the calculation's `arguments` */
get arguments(): List<CalculationValue>;
}
/**
* The set of possible operators in a Sass calculation.
* @category Custom Function
*/
export type CalculationOperator = '+' | '-' | '*' | '/';
/**
* A binary operation that can appear in a {@link SassCalculation}.
* @category Custom Function
*/
export class CalculationOperation implements ValueObject {
/**
* Creates a Sass CalculationOperation with the given `operator`, `left`, and
* `right` values.
* @throws `Error` if `left` or `right` are quoted {@link SassString}s.
*/
constructor(
operator: CalculationOperator,
left: CalculationValue,
right: CalculationValue
);
/** Returns the operation's `operator` field. */
get operator(): CalculationOperator;
/** Returns the operation's `left` field. */
get left(): CalculationValue;
/** Returns the operation's `right` field. */
get right(): CalculationValue;
equals(other: unknown): boolean;
hashCode(): number;
}
/**
* A string injected into a {@link SassCalculation} using interpolation. Unlike
* unquoted strings, interpolations are always surrounded in parentheses when
* they appear in {@link CalculationOperation}s.
* @category Custom Function
*/
export class CalculationInterpolation implements ValueObject {
/**
* Creates a Sass CalculationInterpolation with the given `value`.
*/
constructor(value: string);
/**
* Returns the interpolation's `value` field.
*/
get value(): string;
equals(other: unknown): boolean;
hashCode(): number;
}

107
node_modules/sass/types/value/color.d.ts generated vendored Normal file
View File

@@ -0,0 +1,107 @@
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;
blue: number;
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;
lightness: number;
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;
blackness: number;
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;
blue?: number;
alpha?: number;
}): SassColor;
/**
* Changes one or more of this color's HSL channels and returns the result.
*/
change(options: {
hue?: number;
saturation?: number;
lightness?: number;
alpha?: number;
}): SassColor;
/**
* Changes one or more of this color's HWB channels and returns the result.
*/
change(options: {
hue?: number;
whiteness?: number;
blackness?: number;
alpha?: number;
}): SassColor;
}

22
node_modules/sass/types/value/function.d.ts generated vendored Normal file
View File

@@ -0,0 +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 {@link CustomFunction}.
*/
constructor(signature: string, callback: (args: Value[]) => Value);
}

189
node_modules/sass/types/value/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,189 @@
import {List, ValueObject} from 'immutable';
import {SassBoolean} from './boolean';
import {SassCalculation} from './calculation';
import {SassColor} from './color';
import {SassFunction} from './function';
import {ListSeparator} from './list';
import {SassMap} from './map';
import {SassNumber} from './number';
import {SassString} from './string';
export {SassArgumentList} from './argument_list';
export {SassBoolean, sassTrue, sassFalse} from './boolean';
export {
SassCalculation,
CalculationValue,
CalculationOperator,
CalculationOperation,
CalculationInterpolation,
} from './calculation';
export {SassColor} from './color';
export {SassFunction} from './function';
export {SassList, ListSeparator} from './list';
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 {@link CustomFunction}s, which are passed
* into the Sass implementation using {@link 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 {@link List} from the [`immutable`
* package](https://immutable-js.com/).
*/
get asList(): List<Value>;
/**
* 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 {@link 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 {@link 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 {@link 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 {@link SassBoolean}.
*
* **Heads up!** Functions should generally use {@link 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 {@link SassCalculation}.
*
* @param name - The name of the function argument `this` came from (without
* the `$`) if it came from an argument. Used for error reporting.
*/
assertCalculation(name?: string): SassCalculation;
/**
* Throws if `this` isn't a {@link 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 {@link 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 {@link 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 {@link 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 {@link 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;
}

54
node_modules/sass/types/value/list.d.ts generated vendored Normal file
View File

@@ -0,0 +1,54 @@
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 {@link 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<Value>,
options?: {
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;
}

41
node_modules/sass/types/value/map.d.ts generated vendored Normal file
View File

@@ -0,0 +1,41 @@
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<Value, Value>);
/**
* Returns the contents of this map as an immutable {@link OrderedMap} from the
* [`immutable` package](https://immutable-js.com/).
*/
get contents(): OrderedMap<Value, Value>;
/**
* 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 {@link Value.get}. */
get(index: number): SassList | undefined;
/** @hidden */
tryMap(): SassMap;
}

305
node_modules/sass/types/value/number.d.ts generated vendored Normal file
View File

@@ -0,0 +1,305 @@
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 {@link 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 {@link List} from the [`immutable`
* package](https://immutable-js.com/).
*/
constructor(
value: number,
unit?:
| string
| {
numeratorUnits?: string[] | List<string>;
denominatorUnits?: string[] | List<string>;
}
);
/** This number's numeric value. */
get value(): number;
/** Whether {@link value} is an integer according to Sass's equality logic. */
get isInt(): boolean;
/**
* If {@link value} is an integer according to {@link isInt}, returns {@link
* 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 {@link List} from the
* [`immutable` package](https://immutable-js.com/).
*/
get numeratorUnits(): List<string>;
/**
* This number's denominator units as an immutable {@link List} from the
* [`immutable` package](https://immutable-js.com/).
*/
get denominatorUnits(): List<string>;
/** Whether this number has any numerator or denominator units. */
get hasUnits(): boolean;
/**
* If {@link value} is an integer according to {@link 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 {@link value} if it's within `min` and `max`. If {@link 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 {@link 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 {@link 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<string>,
newDenominators: string[] | List<string>,
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 {@link 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 {@link value} to.
* This may be either a plain JavaScript array or an immutable {@link List}
* from the [`immutable` package](https://immutable-js.com/).
*
* @param newDenominators - The denominator units to convert {@link value} to.
* This may be either a plain JavaScript array or an immutable {@link 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<string>,
newDenominators: string[] | List<string>,
name?: string
): number;
/**
* Returns {@link 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 {@link 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 {@link 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 {@link 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<string>,
newDenominators: string[] | List<string>,
name?: string
): SassNumber;
/**
* Returns a copy of this number, converted to the units represented by
* `newNumerators` and `newDenominators`.
*
* Unlike {@link 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 {@link value}, converted to the units represented by
* `newNumerators` and `newDenominators`.
*
* Unlike {@link 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 {@link value} to.
* This may be either a plain JavaScript array or an immutable {@link List}
* from the [`immutable` package](https://immutable-js.com/).
*
* @param newDenominators - The denominator units to convert {@link value} to.
* This may be either a plain JavaScript array or an immutable {@link 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<string>,
newDenominators: string[] | List<string>,
name?: string
): number;
/**
* Returns {@link value}, converted to the units represented by
* `newNumerators` and `newDenominators`.
*
* Unlike {@link 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,
otherName?: string
): number;
}

84
node_modules/sass/types/value/string.d.ts generated vendored Normal file
View File

@@ -0,0 +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?: {
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 {@link 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;
}