Initial commit

This commit is contained in:
jiapengyu
2026-07-27 13:37:48 +08:00
commit ecba71e2a5
39123 changed files with 5989154 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021-present Johnson Chu
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.
@@ -0,0 +1,2 @@
tidelift: "npm/brace-expansion"
patreon: juliangruber
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2013 Julian Gruber <julian@juliangruber.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.
+135
View File
@@ -0,0 +1,135 @@
# brace-expansion
[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html),
as known from sh/bash, in JavaScript.
[![build status](https://secure.travis-ci.org/juliangruber/brace-expansion.svg)](http://travis-ci.org/juliangruber/brace-expansion)
[![downloads](https://img.shields.io/npm/dm/brace-expansion.svg)](https://www.npmjs.org/package/brace-expansion)
[![Greenkeeper badge](https://badges.greenkeeper.io/juliangruber/brace-expansion.svg)](https://greenkeeper.io/)
[![testling badge](https://ci.testling.com/juliangruber/brace-expansion.png)](https://ci.testling.com/juliangruber/brace-expansion)
## Example
```js
var expand = require('brace-expansion');
expand('file-{a,b,c}.jpg')
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
expand('-v{,,}')
// => ['-v', '-v', '-v']
expand('file{0..2}.jpg')
// => ['file0.jpg', 'file1.jpg', 'file2.jpg']
expand('file-{a..c}.jpg')
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
expand('file{2..0}.jpg')
// => ['file2.jpg', 'file1.jpg', 'file0.jpg']
expand('file{0..4..2}.jpg')
// => ['file0.jpg', 'file2.jpg', 'file4.jpg']
expand('file-{a..e..2}.jpg')
// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg']
expand('file{00..10..5}.jpg')
// => ['file00.jpg', 'file05.jpg', 'file10.jpg']
expand('{{A..C},{a..c}}')
// => ['A', 'B', 'C', 'a', 'b', 'c']
expand('ppp{,config,oe{,conf}}')
// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']
```
## API
```js
var expand = require('brace-expansion');
```
### var expanded = expand(str)
Return an array of all possible and valid expansions of `str`. If none are
found, `[str]` is returned.
Valid expansions are:
```js
/^(.*,)+(.+)?$/
// {a,b,...}
```
A comma separated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`.
```js
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
// {x..y[..incr]}
```
A numeric sequence from `x` to `y` inclusive, with optional increment.
If `x` or `y` start with a leading `0`, all the numbers will be padded
to have equal length. Negative numbers and backwards iteration work too.
```js
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
// {x..y[..incr]}
```
An alphabetic sequence from `x` to `y` inclusive, with optional increment.
`x` and `y` must be exactly one character, and if given, `incr` must be a
number.
For compatibility reasons, the string `${` is not eligible for brace expansion.
## Installation
With [npm](https://npmjs.org) do:
```bash
npm install brace-expansion
```
## Contributors
- [Julian Gruber](https://github.com/juliangruber)
- [Isaac Z. Schlueter](https://github.com/isaacs)
## Sponsors
This module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)!
Do you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)!
## Security contact information
To report a security vulnerability, please use the
[Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
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.
+205
View File
@@ -0,0 +1,205 @@
var balanced = require('balanced-match');
module.exports = expandTop;
var escSlash = '\0SLASH'+Math.random()+'\0';
var escOpen = '\0OPEN'+Math.random()+'\0';
var escClose = '\0CLOSE'+Math.random()+'\0';
var escComma = '\0COMMA'+Math.random()+'\0';
var escPeriod = '\0PERIOD'+Math.random()+'\0';
function numeric(str) {
return parseInt(str, 10) == str
? parseInt(str, 10)
: str.charCodeAt(0);
}
function escapeBraces(str) {
return str.split('\\\\').join(escSlash)
.split('\\{').join(escOpen)
.split('\\}').join(escClose)
.split('\\,').join(escComma)
.split('\\.').join(escPeriod);
}
function unescapeBraces(str) {
return str.split(escSlash).join('\\')
.split(escOpen).join('{')
.split(escClose).join('}')
.split(escComma).join(',')
.split(escPeriod).join('.');
}
// Basically just str.split(","), but handling cases
// where we have nested braced sections, which should be
// treated as individual members, like {a,{b,c},d}
function parseCommaParts(str) {
if (!str)
return [''];
var parts = [];
var m = balanced('{', '}', str);
if (!m)
return str.split(',');
var pre = m.pre;
var body = m.body;
var post = m.post;
var p = pre.split(',');
p[p.length-1] += '{' + body + '}';
var postParts = parseCommaParts(post);
if (post.length) {
p[p.length-1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
function expandTop(str, options) {
if (!str)
return [];
options = options || {};
var max = options.max == null ? Infinity : options.max;
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
// but a{},b}c will be expanded to [a}c,abc].
// One could argue that this is a bug in Bash, but since the goal of
// this module is to match Bash's rules, we escape a leading {}
if (str.substr(0, 2) === '{}') {
str = '\\{\\}' + str.substr(2);
}
return expand(escapeBraces(str), max, true).map(unescapeBraces);
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
function expand(str, max, isTop) {
var expansions = [];
var m = balanced('{', '}', str);
if (!m) return [str];
// no need to expand pre, since it is guaranteed to be free of brace-sets
var pre = m.pre;
var post = m.post.length
? expand(m.post, max, false)
: [''];
if (/\$$/.test(m.pre)) {
for (var k = 0; k < post.length && k < max; k++) {
var expansion = pre+ '{' + m.body + '}' + post[k];
expansions.push(expansion);
}
} else {
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
var isSequence = isNumericSequence || isAlphaSequence;
var isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,(?!,).*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
return expand(str, max, true);
}
return [str];
}
var n;
if (isSequence) {
n = m.body.split(/\.\./);
} else {
n = parseCommaParts(m.body);
if (n.length === 1) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand(n[0], max, false).map(embrace);
if (n.length === 1) {
return post.map(function(p) {
return m.pre + n[0] + p;
});
}
}
}
// at this point, n is the parts, and we know it's not a comma set
// with a single entry.
var N;
if (isSequence) {
var x = numeric(n[0]);
var y = numeric(n[1]);
var width = Math.max(n[0].length, n[1].length)
var incr = n.length == 3
? Math.max(Math.abs(numeric(n[2])), 1)
: 1;
var test = lte;
var reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
var pad = n.some(isPadded);
N = [];
for (var i = x; test(i, y); i += incr) {
var c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\')
c = '';
} else {
c = String(i);
if (pad) {
var need = width - c.length;
if (need > 0) {
var z = new Array(need + 1).join('0');
if (i < 0)
c = '-' + z + c.slice(1);
else
c = z + c;
}
}
}
N.push(c);
}
} else {
N = [];
for (var j = 0; j < n.length; j++) {
N.push.apply(N, expand(n[j], max, false));
}
}
for (var j = 0; j < N.length; j++) {
for (var k = 0; k < post.length && expansions.length < max; k++) {
var expansion = pre + N[j] + post[k];
if (!isTop || isSequence || expansion)
expansions.push(expansion);
}
}
}
return expansions;
}
@@ -0,0 +1,49 @@
{
"name": "brace-expansion",
"description": "Brace expansion as known from sh/bash",
"version": "2.1.0",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/brace-expansion.git"
},
"homepage": "https://github.com/juliangruber/brace-expansion",
"main": "index.js",
"scripts": {
"test": "tape test/*.js",
"gentest": "bash test/generate.sh",
"bench": "matcha test/perf/bench.js"
},
"dependencies": {
"balanced-match": "^1.0.0"
},
"devDependencies": {
"@c4312/matcha": "^1.3.1",
"tape": "^4.6.0"
},
"keywords": [],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT",
"testling": {
"files": "test/*.js",
"browsers": [
"ie/8..latest",
"firefox/20..latest",
"firefox/nightly",
"chrome/25..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
},
"publishConfig": {
"tag": "2.x"
}
}
+15
View File
@@ -0,0 +1,15 @@
The ISC License
Copyright (c) 2011-2023 Isaac Z. Schlueter and Contributors
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.
+491
View File
@@ -0,0 +1,491 @@
# minimatch
A minimal matching utility.
This is the matching library used internally by npm.
It works by converting glob expressions into JavaScript `RegExp`
objects.
## Important Security Consideration!
> [!WARNING]
> This library uses JavaScript regular expressions. Please read
> the following warning carefully, and be thoughtful about what
> you provide to this library in production systems.
_Any_ library in JavaScript that deals with matching string
patterns using regular expressions will be subject to
[ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)
if the pattern is generated using untrusted input.
Efforts have been made to mitigate risk as much as is feasible in
such a library, providing maximum recursion depths and so forth,
but these measures can only ultimately protect against accidents,
not malice. A dedicated attacker can _always_ find patterns that
cannot be defended against by a bash-compatible glob pattern
matching system that uses JavaScript regular expressions.
To be extremely clear:
> [!WARNING]
> **If you create a system where you take user input, and use
> that input as the source of a Regular Expression pattern, in
> this or any extant glob matcher in JavaScript, you will be
> pwned.**
A future version of this library _may_ use a different matching
algorithm which does not exhibit backtracking problems. If and
when that happens, it will likely be a sweeping change, and those
improvements will **not** be backported to legacy versions.
In the near term, it is not reasonable to continue to play
whack-a-mole with security advisories, and so any future ReDoS
reports will be considered "working as intended", and resolved
entirely by this warning.
## Usage
```js
// hybrid module, load with require() or import
import { minimatch } from 'minimatch'
// or:
const { minimatch } = require('minimatch')
minimatch('bar.foo', '*.foo') // true!
minimatch('bar.foo', '*.bar') // false!
minimatch('bar.foo', '*.+(bar|foo)', { debug: true }) // true, and noisy!
```
## Features
Supports these glob features:
- Brace Expansion
- Extended glob matching
- "Globstar" `**` matching
- [Posix character
classes](https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html),
like `[[:alpha:]]`, supporting the full range of Unicode
characters. For example, `[[:alpha:]]` will match against
`'é'`, though `[a-zA-Z]` will not. Collating symbol and set
matching is not supported, so `[[=e=]]` will _not_ match `'é'`
and `[[.ch.]]` will not match `'ch'` in locales where `ch` is
considered a single character.
See:
- `man sh`
- `man bash` [Pattern
Matching](https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html)
- `man 3 fnmatch`
- `man 5 gitignore`
## Windows
**Please only use forward-slashes in glob expressions.**
Though windows uses either `/` or `\` as its path separator, only `/`
characters are used by this glob implementation. You must use
forward-slashes **only** in glob expressions. Back-slashes in patterns
will always be interpreted as escape characters, not path separators.
Note that `\` or `/` _will_ be interpreted as path separators in paths on
Windows, and will match against `/` in glob expressions.
So just always use `/` in patterns.
### UNC Paths
On Windows, UNC paths like `//?/c:/...` or
`//ComputerName/Share/...` are handled specially.
- Patterns starting with a double-slash followed by some
non-slash characters will preserve their double-slash. As a
result, a pattern like `//*` will match `//x`, but not `/x`.
- Patterns staring with `//?/<drive letter>:` will _not_ treat
the `?` as a wildcard character. Instead, it will be treated
as a normal string.
- Patterns starting with `//?/<drive letter>:/...` will match
file paths starting with `<drive letter>:/...`, and vice versa,
as if the `//?/` was not present. This behavior only is
present when the drive letters are a case-insensitive match to
one another. The remaining portions of the path/pattern are
compared case sensitively, unless `nocase:true` is set.
Note that specifying a UNC path using `\` characters as path
separators is always allowed in the file path argument, but only
allowed in the pattern argument when `windowsPathsNoEscape: true`
is set in the options.
## Minimatch Class
Create a minimatch object by instantiating the `minimatch.Minimatch` class.
```javascript
var Minimatch = require('minimatch').Minimatch
var mm = new Minimatch(pattern, options)
```
### Properties
- `pattern` The original pattern the minimatch object represents.
- `options` The options supplied to the constructor.
- `set` A 2-dimensional array of regexp or string expressions.
Each row in the
array corresponds to a brace-expanded pattern. Each item in the row
corresponds to a single path-part. For example, the pattern
`{a,b/c}/d` would expand to a set of patterns like:
[ [ a, d ]
, [ b, c, d ] ]
If a portion of the pattern doesn't have any "magic" in it
(that is, it's something like `"foo"` rather than `fo*o?`), then it
will be left as a string rather than converted to a regular
expression.
- `regexp` Created by the `makeRe` method. A single regular expression
expressing the entire pattern. This is useful in cases where you wish
to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.
- `negate` True if the pattern is negated.
- `comment` True if the pattern is a comment.
- `empty` True if the pattern is `""`.
### Methods
- `makeRe()` Generate the `regexp` member if necessary, and return it.
Will return `false` if the pattern is invalid.
- `match(fname)` Return true if the filename matches the pattern, or
false otherwise.
- `matchOne(fileArray, patternArray, partial)` Take a `/`-split
filename, and match it against a single row in the `regExpSet`. This
method is mainly for internal use, but is exposed so that it can be
used by a glob-walker that needs to avoid excessive filesystem calls.
- `hasMagic()` Returns true if the parsed pattern contains any
magic characters. Returns false if all comparator parts are
string literals. If the `magicalBraces` option is set on the
constructor, then it will consider brace expansions which are
not otherwise magical to be magic. If not set, then a pattern
like `a{b,c}d` will return `false`, because neither `abd` nor
`acd` contain any special glob characters.
This does **not** mean that the pattern string can be used as a
literal filename, as it may contain magic glob characters that
are escaped. For example, the pattern `\\*` or `[*]` would not
be considered to have magic, as the matching portion parses to
the literal string `'*'` and would match a path named `'*'`,
not `'\\*'` or `'[*]'`. The `minimatch.unescape()` method may
be used to remove escape characters.
All other methods are internal, and will be called as necessary.
### minimatch(path, pattern, options)
Main export. Tests a path against the pattern using the options.
```javascript
var isJS = minimatch(file, '*.js', { matchBase: true })
```
### minimatch.filter(pattern, options)
Returns a function that tests its
supplied argument, suitable for use with `Array.filter`. Example:
```javascript
var javascripts = fileList.filter(minimatch.filter('*.js', { matchBase: true }))
```
### minimatch.escape(pattern, options = {})
Escape all magic characters in a glob pattern, so that it will
only ever match literal strings
If the `windowsPathsNoEscape` option is used, then characters are
escaped by wrapping in `[]`, because a magic character wrapped in
a character class can only be satisfied by that exact character.
Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot
be escaped or unescaped.
### minimatch.unescape(pattern, options = {})
Un-escape a glob string that may contain some escaped characters.
If the `windowsPathsNoEscape` option is used, then square-brace
escapes are removed, but not backslash escapes. For example, it
will turn the string `'[*]'` into `*`, but it will not turn
`'\\*'` into `'*'`, because `\` is a path separator in
`windowsPathsNoEscape` mode.
When `windowsPathsNoEscape` is not set, then both brace escapes
and backslash escapes are removed.
Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot
be escaped or unescaped.
### minimatch.match(list, pattern, options)
Match against the list of
files, in the style of fnmatch or glob. If nothing is matched, and
options.nonull is set, then return a list containing the pattern itself.
```javascript
var javascripts = minimatch.match(fileList, '*.js', { matchBase: true })
```
### minimatch.makeRe(pattern, options)
Make a regular expression object from the pattern.
## Options
All options are `false` by default.
### debug
Dump a ton of stuff to stderr.
### nobrace
Do not expand `{a,b}` and `{1..3}` brace sets.
### noglobstar
Disable `**` matching against multiple folder names.
### dot
Allow patterns to match filenames starting with a period, even if
the pattern does not explicitly have a period in that spot.
Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`
is set.
### noext
Disable "extglob" style patterns like `+(a|b)`.
### nocase
Perform a case-insensitive match.
### nocaseMagicOnly
When used with `{nocase: true}`, create regular expressions that
are case-insensitive, but leave string match portions untouched.
Has no effect when used without `{nocase: true}`
Useful when some other form of case-insensitive matching is used,
or if the original string representation is useful in some other
way.
### nonull
When a match is not found by `minimatch.match`, return a list containing
the pattern itself if this option is set. When not set, an empty list
is returned if there are no matches.
### magicalBraces
This only affects the results of the `Minimatch.hasMagic` method.
If the pattern contains brace expansions, such as `a{b,c}d`, but
no other magic characters, then the `Minimatch.hasMagic()` method
will return `false` by default. When this option set, it will
return `true` for brace expansion as well as other magic glob
characters.
### matchBase
If set, then patterns without slashes will be matched
against the basename of the path if it contains slashes. For example,
`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.
### nocomment
Suppress the behavior of treating `#` at the start of a pattern as a
comment.
### nonegate
Suppress the behavior of treating a leading `!` character as negation.
### flipNegate
Returns from negate expressions the same as if they were not negated.
(Ie, true on a hit, false on a miss.)
### partial
Compare a partial path to a pattern. As long as the parts of the path that
are present are not contradicted by the pattern, it will be treated as a
match. This is useful in applications where you're walking through a
folder structure, and don't yet have the full path, but want to ensure that
you do not walk down paths that can never be a match.
For example,
```js
minimatch('/a/b', '/a/*/c/d', { partial: true }) // true, might be /a/b/c/d
minimatch('/a/b', '/**/d', { partial: true }) // true, might be /a/b/.../d
minimatch('/x/y/z', '/a/**/z', { partial: true }) // false, because x !== a
```
### windowsPathsNoEscape
Use `\\` as a path separator _only_, and _never_ as an escape
character. If set, all `\\` characters are replaced with `/` in
the pattern. Note that this makes it **impossible** to match
against paths containing literal glob pattern characters, but
allows matching with patterns constructed using `path.join()` and
`path.resolve()` on Windows platforms, mimicking the (buggy!)
behavior of earlier versions on Windows. Please use with
caution, and be mindful of [the caveat about Windows
paths](#windows).
For legacy reasons, this is also set if
`options.allowWindowsEscape` is set to the exact value `false`.
### windowsNoMagicRoot
When a pattern starts with a UNC path or drive letter, and in
`nocase:true` mode, do not convert the root portions of the
pattern into a case-insensitive regular expression, and instead
leave them as strings.
This is the default when the platform is `win32` and
`nocase:true` is set.
### preserveMultipleSlashes
By default, multiple `/` characters (other than the leading `//`
in a UNC path, see "UNC Paths" above) are treated as a single
`/`.
That is, a pattern like `a///b` will match the file path `a/b`.
Set `preserveMultipleSlashes: true` to suppress this behavior.
### optimizationLevel
A number indicating the level of optimization that should be done
to the pattern prior to parsing and using it for matches.
Globstar parts `**` are always converted to `*` when `noglobstar`
is set, and multiple adjacent `**` parts are converted into a
single `**` (ie, `a/**/**/b` will be treated as `a/**/b`, as this
is equivalent in all cases).
- `0` - Make no further changes. In this mode, `.` and `..` are
maintained in the pattern, meaning that they must also appear
in the same position in the test path string. Eg, a pattern
like `a/*/../c` will match the string `a/b/../c` but not the
string `a/c`.
- `1` - (default) Remove cases where a double-dot `..` follows a
pattern portion that is not `**`, `.`, `..`, or empty `''`. For
example, the pattern `./a/b/../*` is converted to `./a/*`, and
so it will match the path string `./a/c`, but not the path
string `./a/b/../c`. Dots and empty path portions in the
pattern are preserved.
- `2` (or higher) - Much more aggressive optimizations, suitable
for use with file-walking cases:
- Remove cases where a double-dot `..` follows a pattern
portion that is not `**`, `.`, or empty `''`. Remove empty
and `.` portions of the pattern, where safe to do so (ie,
anywhere other than the last position, the first position, or
the second position in a pattern starting with `/`, as this
may indicate a UNC path on Windows).
- Convert patterns containing `<pre>/**/../<p>/<rest>` into the
equivalent `<pre>/{..,**}/<p>/<rest>`, where `<p>` is a
a pattern portion other than `.`, `..`, `**`, or empty
`''`.
- Dedupe patterns where a `**` portion is present in one and
omitted in another, and it is not the final path portion, and
they are otherwise equivalent. So `{a/**/b,a/b}` becomes
`a/**/b`, because `**` matches against an empty path portion.
- Dedupe patterns where a `*` portion is present in one, and a
non-dot pattern other than `**`, `.`, `..`, or `''` is in the
same position in the other. So `a/{*,x}/b` becomes `a/*/b`,
because `*` can match against `x`.
While these optimizations improve the performance of
file-walking use cases such as [glob](http://npm.im/glob) (ie,
the reason this module exists), there are cases where it will
fail to match a literal string that would have been matched in
optimization level 1 or 0.
Specifically, while the `Minimatch.match()` method will
optimize the file path string in the same ways, resulting in
the same matches, it will fail when tested with the regular
expression provided by `Minimatch.makeRe()`, unless the path
string is first processed with
`minimatch.levelTwoFileOptimize()` or similar.
### platform
When set to `win32`, this will trigger all windows-specific
behaviors (special handling for UNC paths, and treating `\` as
separators in file paths for comparison.)
Defaults to the value of `process.platform`.
## Comparisons to other fnmatch/glob implementations
While strict compliance with the existing standards is a
worthwhile goal, some discrepancies exist between minimatch and
other implementations. Some are intentional, and some are
unavoidable.
If the pattern starts with a `!` character, then it is negated. Set the
`nonegate` flag to suppress this behavior, and treat leading `!`
characters normally. This is perhaps relevant if you wish to start the
pattern with a negative extglob pattern like `!(a|B)`. Multiple `!`
characters at the start of a pattern will negate the pattern multiple
times.
If a pattern starts with `#`, then it is treated as a comment, and
will not match anything. Use `\#` to match a literal `#` at the
start of a line, or set the `nocomment` flag to suppress this behavior.
The double-star character `**` is supported by default, unless the
`noglobstar` flag is set. This is supported in the manner of bsdglob
and bash 4.1, where `**` only has special significance if it is the only
thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but
`a/**b` will not.
If an escaped pattern has no matches, and the `nonull` flag is set,
then minimatch.match returns the pattern as-provided, rather than
interpreting the character escapes. For example,
`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
`"*a?"`. This is akin to setting the `nullglob` option in bash, except
that it does not resolve escaped pattern characters.
If brace expansion is not disabled, then it is performed before any
other interpretation of the glob pattern. Thus, a pattern like
`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
checked for validity. Since those two are valid, matching proceeds.
Negated extglob patterns are handled as closely as possible to
Bash semantics, but there are some cases with negative extglobs
which are exceedingly difficult to express in a JavaScript
regular expression. In particular the negated pattern
`<start>!(<pattern>*|)*` will in bash match anything that does
not start with `<start><pattern>`. However,
`<start>!(<pattern>*)*` _will_ match paths starting with
`<start><pattern>`, because the empty string can match against
the negated portion. In this library, `<start>!(<pattern>*|)*`
will _not_ match any pattern starting with `<start>`, due to a
difference in precisely which patterns are considered "greedy" in
Regular Expressions vs bash path expansion. This may be fixable,
but not without incurring some complexity and performance costs,
and the trade-off seems to not be worth pursuing.
Note that `fnmatch(3)` in libc is an extremely naive string comparison
matcher, which does not do anything special for slashes. This library is
designed to be used in glob searching and file walkers, and so it does do
special things with `/`. Thus, `foo*` will not match `foo/bar` in this
library, even though it would in `fnmatch(3)`.
@@ -0,0 +1,2 @@
export declare const assertValidPattern: (pattern: any) => void;
//# sourceMappingURL=assert-valid-pattern.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"assert-valid-pattern.d.ts","sourceRoot":"","sources":["../../src/assert-valid-pattern.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,kBAAkB,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAUlD,CAAA"}
@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.assertValidPattern = void 0;
const MAX_PATTERN_LENGTH = 1024 * 64;
const assertValidPattern = (pattern) => {
if (typeof pattern !== 'string') {
throw new TypeError('invalid pattern');
}
if (pattern.length > MAX_PATTERN_LENGTH) {
throw new TypeError('pattern is too long');
}
};
exports.assertValidPattern = assertValidPattern;
//# sourceMappingURL=assert-valid-pattern.js.map
@@ -0,0 +1 @@
{"version":3,"file":"assert-valid-pattern.js","sourceRoot":"","sources":["../../src/assert-valid-pattern.ts"],"names":[],"mappings":";;;AAAA,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAE,CAAA;AAC7B,MAAM,kBAAkB,GAA2B,CACxD,OAAY,EACe,EAAE;IAC7B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,SAAS,CAAC,iBAAiB,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;QACxC,MAAM,IAAI,SAAS,CAAC,qBAAqB,CAAC,CAAA;IAC5C,CAAC;AACH,CAAC,CAAA;AAVY,QAAA,kBAAkB,sBAU9B","sourcesContent":["const MAX_PATTERN_LENGTH = 1024 * 64\nexport const assertValidPattern: (pattern: any) => void = (\n pattern: any\n): asserts pattern is string => {\n if (typeof pattern !== 'string') {\n throw new TypeError('invalid pattern')\n }\n\n if (pattern.length > MAX_PATTERN_LENGTH) {\n throw new TypeError('pattern is too long')\n }\n}\n"]}
@@ -0,0 +1,20 @@
import { MinimatchOptions, MMRegExp } from './index.js';
export type ExtglobType = '!' | '?' | '+' | '*' | '@';
export declare class AST {
#private;
type: ExtglobType | null;
constructor(type: ExtglobType | null, parent?: AST, options?: MinimatchOptions);
get hasMagic(): boolean | undefined;
toString(): string;
push(...parts: (string | AST)[]): void;
toJSON(): any[];
isStart(): boolean;
isEnd(): boolean;
copyIn(part: AST | string): void;
clone(parent: AST): AST;
static fromGlob(pattern: string, options?: MinimatchOptions): AST;
toMMPattern(): MMRegExp | string;
get options(): MinimatchOptions;
toRegExpSource(allowDot?: boolean): [re: string, body: string, hasMagic: boolean, uflag: boolean];
}
//# sourceMappingURL=ast.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/ast.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAwCvD,MAAM,MAAM,WAAW,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AAiErD,qBAAa,GAAG;;IACd,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;gBAiBtB,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,MAAM,CAAC,EAAE,GAAG,EACZ,OAAO,GAAE,gBAAqB;IAahC,IAAI,QAAQ,IAAI,OAAO,GAAG,SAAS,CAUlC;IAGD,QAAQ,IAAI,MAAM;IA+ClB,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,MAAM,GAAG,GAAG,CAAC,EAAE;IAY/B,MAAM;IAgBN,OAAO,IAAI,OAAO;IAgBlB,KAAK,IAAI,OAAO;IAYhB,MAAM,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM;IAKzB,KAAK,CAAC,MAAM,EAAE,GAAG;IA0RjB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;IAQ/D,WAAW,IAAI,QAAQ,GAAG,MAAM;IA2BhC,IAAI,OAAO,qBAEV;IAuED,cAAc,CACZ,QAAQ,CAAC,EAAE,OAAO,GACjB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC;CA4MjE"}
@@ -0,0 +1,747 @@
"use strict";
// parse a single path portion
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AST = void 0;
const brace_expressions_js_1 = require("./brace-expressions.js");
const unescape_js_1 = require("./unescape.js");
const types = new Set(['!', '?', '+', '*', '@']);
const isExtglobType = (c) => types.has(c);
const isExtglobAST = (c) => isExtglobType(c.type);
const adoptionMap = new Map([
['!', ['@']],
['?', ['?', '@']],
['@', ['@']],
['*', ['*', '+', '?', '@']],
['+', ['+', '@']],
]);
const adoptionWithSpaceMap = new Map([
['!', ['?']],
['@', ['?']],
['+', ['?', '*']],
]);
const adoptionAnyMap = new Map([
['!', ['?', '@']],
['?', ['?', '@']],
['@', ['?', '@']],
['*', ['*', '+', '?', '@']],
['+', ['+', '@', '?', '*']],
]);
const usurpMap = new Map([
['!', new Map([['!', '@']])],
['?', new Map([['*', '*'], ['+', '*']])],
['@', new Map([['!', '!'], ['?', '?'], ['@', '@'], ['*', '*'], ['+', '+']])],
['+', new Map([['?', '*'], ['*', '*']])],
]);
// Patterns that get prepended to bind to the start of either the
// entire string, or just a single path portion, to prevent dots
// and/or traversal patterns, when needed.
// Exts don't need the ^ or / bit, because the root binds that already.
const startNoTraversal = '(?!(?:^|/)\\.\\.?(?:$|/))';
const startNoDot = '(?!\\.)';
// characters that indicate a start of pattern needs the "no dots" bit,
// because a dot *might* be matched. ( is not in the list, because in
// the case of a child extglob, it will handle the prevention itself.
const addPatternStart = new Set(['[', '.']);
// cases where traversal is A-OK, no dot prevention needed
const justDots = new Set(['..', '.']);
const reSpecials = new Set('().*{}+?[]^$\\!');
const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
// any single thing other than /
const qmark = '[^/]';
// * => any number of characters
const star = qmark + '*?';
// use + when we need to ensure that *something* matches, because the * is
// the only thing in the path portion.
const starNoEmpty = qmark + '+?';
// remove the \ chars that we added if we end up doing a nonmagic compare
// const deslash = (s: string) => s.replace(/\\(.)/g, '$1')
class AST {
type;
#root;
#hasMagic;
#uflag = false;
#parts = [];
#parent;
#parentIndex;
#negs;
#filledNegs = false;
#options;
#toString;
// set to true if it's an extglob with no children
// (which really means one child of '')
#emptyExt = false;
constructor(type, parent, options = {}) {
this.type = type;
// extglobs are inherently magical
if (type)
this.#hasMagic = true;
this.#parent = parent;
this.#root = this.#parent ? this.#parent.#root : this;
this.#options = this.#root === this ? options : this.#root.#options;
this.#negs = this.#root === this ? [] : this.#root.#negs;
if (type === '!' && !this.#root.#filledNegs)
this.#negs.push(this);
this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0;
}
get hasMagic() {
/* c8 ignore start */
if (this.#hasMagic !== undefined)
return this.#hasMagic;
/* c8 ignore stop */
for (const p of this.#parts) {
if (typeof p === 'string')
continue;
if (p.type || p.hasMagic)
return (this.#hasMagic = true);
}
// note: will be undefined until we generate the regexp src and find out
return this.#hasMagic;
}
// reconstructs the pattern
toString() {
if (this.#toString !== undefined)
return this.#toString;
if (!this.type) {
return (this.#toString = this.#parts.map(p => String(p)).join(''));
}
else {
return (this.#toString =
this.type + '(' + this.#parts.map(p => String(p)).join('|') + ')');
}
}
#fillNegs() {
/* c8 ignore start */
if (this !== this.#root)
throw new Error('should only call on root');
if (this.#filledNegs)
return this;
/* c8 ignore stop */
// call toString() once to fill this out
this.toString();
this.#filledNegs = true;
let n;
while ((n = this.#negs.pop())) {
if (n.type !== '!')
continue;
// walk up the tree, appending everthing that comes AFTER parentIndex
let p = n;
let pp = p.#parent;
while (pp) {
for (let i = p.#parentIndex + 1; !pp.type && i < pp.#parts.length; i++) {
for (const part of n.#parts) {
/* c8 ignore start */
if (typeof part === 'string') {
throw new Error('string part in extglob AST??');
}
/* c8 ignore stop */
part.copyIn(pp.#parts[i]);
}
}
p = pp;
pp = p.#parent;
}
}
return this;
}
push(...parts) {
for (const p of parts) {
if (p === '')
continue;
/* c8 ignore start */
if (typeof p !== 'string' && !(p instanceof _a && p.#parent === this)) {
throw new Error('invalid part: ' + p);
}
/* c8 ignore stop */
this.#parts.push(p);
}
}
toJSON() {
const ret = this.type === null
? this.#parts.slice().map(p => (typeof p === 'string' ? p : p.toJSON()))
: [this.type, ...this.#parts.map(p => p.toJSON())];
if (this.isStart() && !this.type)
ret.unshift([]);
if (this.isEnd() &&
(this === this.#root ||
(this.#root.#filledNegs && this.#parent?.type === '!'))) {
ret.push({});
}
return ret;
}
isStart() {
if (this.#root === this)
return true;
// if (this.type) return !!this.#parent?.isStart()
if (!this.#parent?.isStart())
return false;
if (this.#parentIndex === 0)
return true;
// if everything AHEAD of this is a negation, then it's still the "start"
const p = this.#parent;
for (let i = 0; i < this.#parentIndex; i++) {
const pp = p.#parts[i];
if (!(pp instanceof _a && pp.type === '!')) {
return false;
}
}
return true;
}
isEnd() {
if (this.#root === this)
return true;
if (this.#parent?.type === '!')
return true;
if (!this.#parent?.isEnd())
return false;
if (!this.type)
return this.#parent?.isEnd();
// if not root, it'll always have a parent
/* c8 ignore start */
const pl = this.#parent ? this.#parent.#parts.length : 0;
/* c8 ignore stop */
return this.#parentIndex === pl - 1;
}
copyIn(part) {
if (typeof part === 'string')
this.push(part);
else
this.push(part.clone(this));
}
clone(parent) {
const c = new _a(this.type, parent);
for (const p of this.#parts) {
c.copyIn(p);
}
return c;
}
static #parseAST(str, ast, pos, opt, extDepth) {
const maxDepth = opt.maxExtglobRecursion ?? 2;
let escaping = false;
let inBrace = false;
let braceStart = -1;
let braceNeg = false;
if (ast.type === null) {
// outside of a extglob, append until we find a start
let i = pos;
let acc = '';
while (i < str.length) {
const c = str.charAt(i++);
// still accumulate escapes at this point, but we do ignore
// starts that are escaped
if (escaping || c === '\\') {
escaping = !escaping;
acc += c;
continue;
}
if (inBrace) {
if (i === braceStart + 1) {
if (c === '^' || c === '!') {
braceNeg = true;
}
}
else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {
inBrace = false;
}
acc += c;
continue;
}
else if (c === '[') {
inBrace = true;
braceStart = i;
braceNeg = false;
acc += c;
continue;
}
const doRecurse = !opt.noext &&
isExtglobType(c) &&
str.charAt(i) === '(' &&
extDepth <= maxDepth;
if (doRecurse) {
ast.push(acc);
acc = '';
const ext = new _a(c, ast);
i = _a.#parseAST(str, ext, i, opt, extDepth + 1);
ast.push(ext);
continue;
}
acc += c;
}
ast.push(acc);
return i;
}
// some kind of extglob, pos is at the (
// find the next | or )
let i = pos + 1;
let part = new _a(null, ast);
const parts = [];
let acc = '';
while (i < str.length) {
const c = str.charAt(i++);
// still accumulate escapes at this point, but we do ignore
// starts that are escaped
if (escaping || c === '\\') {
escaping = !escaping;
acc += c;
continue;
}
if (inBrace) {
if (i === braceStart + 1) {
if (c === '^' || c === '!') {
braceNeg = true;
}
}
else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {
inBrace = false;
}
acc += c;
continue;
}
else if (c === '[') {
inBrace = true;
braceStart = i;
braceNeg = false;
acc += c;
continue;
}
const doRecurse = isExtglobType(c) &&
str.charAt(i) === '(' &&
/* c8 ignore start - the maxDepth is sufficient here */
(extDepth <= maxDepth || (ast && ast.#canAdoptType(c)));
/* c8 ignore stop */
if (doRecurse) {
const depthAdd = ast && ast.#canAdoptType(c) ? 0 : 1;
part.push(acc);
acc = '';
const ext = new _a(c, part);
part.push(ext);
i = _a.#parseAST(str, ext, i, opt, extDepth + depthAdd);
continue;
}
if (c === '|') {
part.push(acc);
acc = '';
parts.push(part);
part = new _a(null, ast);
continue;
}
if (c === ')') {
if (acc === '' && ast.#parts.length === 0) {
ast.#emptyExt = true;
}
part.push(acc);
acc = '';
ast.push(...parts, part);
return i;
}
acc += c;
}
// unfinished extglob
// if we got here, it was a malformed extglob! not an extglob, but
// maybe something else in there.
ast.type = null;
ast.#hasMagic = undefined;
ast.#parts = [str.substring(pos - 1)];
return i;
}
#canAdoptWithSpace(child) {
return this.#canAdopt(child, adoptionWithSpaceMap);
}
#canAdopt(child, map = adoptionMap) {
if (!child ||
typeof child !== 'object' ||
child.type !== null ||
child.#parts.length !== 1 ||
this.type === null) {
return false;
}
const gc = child.#parts[0];
if (!gc || typeof gc !== 'object' || gc.type === null) {
return false;
}
return this.#canAdoptType(gc.type, map);
}
#canAdoptType(c, map = adoptionAnyMap) {
return !!map.get(this.type)?.includes(c);
}
#adoptWithSpace(child, index) {
const gc = child.#parts[0];
const blank = new _a(null, gc, this.options);
blank.#parts.push('');
gc.push(blank);
this.#adopt(child, index);
}
#adopt(child, index) {
const gc = child.#parts[0];
this.#parts.splice(index, 1, ...gc.#parts);
for (const p of gc.#parts) {
if (typeof p === 'object')
p.#parent = this;
}
this.#toString = undefined;
}
#canUsurpType(c) {
const m = usurpMap.get(this.type);
return !!(m?.has(c));
}
#canUsurp(child) {
if (!child ||
typeof child !== 'object' ||
child.type !== null ||
child.#parts.length !== 1 ||
this.type === null ||
this.#parts.length !== 1) {
return false;
}
const gc = child.#parts[0];
if (!gc || typeof gc !== 'object' || gc.type === null) {
return false;
}
return this.#canUsurpType(gc.type);
}
#usurp(child) {
const m = usurpMap.get(this.type);
const gc = child.#parts[0];
const nt = m?.get(gc.type);
/* c8 ignore start - impossible */
if (!nt)
return false;
/* c8 ignore stop */
this.#parts = gc.#parts;
for (const p of this.#parts) {
if (typeof p === 'object')
p.#parent = this;
}
this.type = nt;
this.#toString = undefined;
this.#emptyExt = false;
}
#flatten() {
if (!isExtglobAST(this)) {
for (const p of this.#parts) {
if (typeof p === 'object')
p.#flatten();
}
}
else {
let iterations = 0;
let done = false;
do {
done = true;
for (let i = 0; i < this.#parts.length; i++) {
const c = this.#parts[i];
if (typeof c === 'object') {
c.#flatten();
if (this.#canAdopt(c)) {
done = false;
this.#adopt(c, i);
}
else if (this.#canAdoptWithSpace(c)) {
done = false;
this.#adoptWithSpace(c, i);
}
else if (this.#canUsurp(c)) {
done = false;
this.#usurp(c);
}
}
}
} while (!done && ++iterations < 10);
}
this.#toString = undefined;
}
static fromGlob(pattern, options = {}) {
const ast = new _a(null, undefined, options);
_a.#parseAST(pattern, ast, 0, options, 0);
return ast;
}
// returns the regular expression if there's magic, or the unescaped
// string if not.
toMMPattern() {
// should only be called on root
/* c8 ignore start */
if (this !== this.#root)
return this.#root.toMMPattern();
/* c8 ignore stop */
const glob = this.toString();
const [re, body, hasMagic, uflag] = this.toRegExpSource();
// if we're in nocase mode, and not nocaseMagicOnly, then we do
// still need a regular expression if we have to case-insensitively
// match capital/lowercase characters.
const anyMagic = hasMagic ||
this.#hasMagic ||
(this.#options.nocase &&
!this.#options.nocaseMagicOnly &&
glob.toUpperCase() !== glob.toLowerCase());
if (!anyMagic) {
return body;
}
const flags = (this.#options.nocase ? 'i' : '') + (uflag ? 'u' : '');
return Object.assign(new RegExp(`^${re}$`, flags), {
_src: re,
_glob: glob,
});
}
get options() {
return this.#options;
}
// returns the string match, the regexp source, whether there's magic
// in the regexp (so a regular expression is required) and whether or
// not the uflag is needed for the regular expression (for posix classes)
// TODO: instead of injecting the start/end at this point, just return
// the BODY of the regexp, along with the start/end portions suitable
// for binding the start/end in either a joined full-path makeRe context
// (where we bind to (^|/), or a standalone matchPart context (where
// we bind to ^, and not /). Otherwise slashes get duped!
//
// In part-matching mode, the start is:
// - if not isStart: nothing
// - if traversal possible, but not allowed: ^(?!\.\.?$)
// - if dots allowed or not possible: ^
// - if dots possible and not allowed: ^(?!\.)
// end is:
// - if not isEnd(): nothing
// - else: $
//
// In full-path matching mode, we put the slash at the START of the
// pattern, so start is:
// - if first pattern: same as part-matching mode
// - if not isStart(): nothing
// - if traversal possible, but not allowed: /(?!\.\.?(?:$|/))
// - if dots allowed or not possible: /
// - if dots possible and not allowed: /(?!\.)
// end is:
// - if last pattern, same as part-matching mode
// - else nothing
//
// Always put the (?:$|/) on negated tails, though, because that has to be
// there to bind the end of the negated pattern portion, and it's easier to
// just stick it in now rather than try to inject it later in the middle of
// the pattern.
//
// We can just always return the same end, and leave it up to the caller
// to know whether it's going to be used joined or in parts.
// And, if the start is adjusted slightly, can do the same there:
// - if not isStart: nothing
// - if traversal possible, but not allowed: (?:/|^)(?!\.\.?$)
// - if dots allowed or not possible: (?:/|^)
// - if dots possible and not allowed: (?:/|^)(?!\.)
//
// But it's better to have a simpler binding without a conditional, for
// performance, so probably better to return both start options.
//
// Then the caller just ignores the end if it's not the first pattern,
// and the start always gets applied.
//
// But that's always going to be $ if it's the ending pattern, or nothing,
// so the caller can just attach $ at the end of the pattern when building.
//
// So the todo is:
// - better detect what kind of start is needed
// - return both flavors of starting pattern
// - attach $ at the end of the pattern when creating the actual RegExp
//
// Ah, but wait, no, that all only applies to the root when the first pattern
// is not an extglob. If the first pattern IS an extglob, then we need all
// that dot prevention biz to live in the extglob portions, because eg
// +(*|.x*) can match .xy but not .yx.
//
// So, return the two flavors if it's #root and the first child is not an
// AST, otherwise leave it to the child AST to handle it, and there,
// use the (?:^|/) style of start binding.
//
// Even simplified further:
// - Since the start for a join is eg /(?!\.) and the start for a part
// is ^(?!\.), we can just prepend (?!\.) to the pattern (either root
// or start or whatever) and prepend ^ or / at the Regexp construction.
toRegExpSource(allowDot) {
const dot = allowDot ?? !!this.#options.dot;
if (this.#root === this) {
this.#flatten();
this.#fillNegs();
}
if (!isExtglobAST(this)) {
const noEmpty = this.isStart() && this.isEnd();
const src = this.#parts
.map(p => {
const [re, _, hasMagic, uflag] = typeof p === 'string'
? _a.#parseGlob(p, this.#hasMagic, noEmpty)
: p.toRegExpSource(allowDot);
this.#hasMagic = this.#hasMagic || hasMagic;
this.#uflag = this.#uflag || uflag;
return re;
})
.join('');
let start = '';
if (this.isStart()) {
if (typeof this.#parts[0] === 'string') {
// this is the string that will match the start of the pattern,
// so we need to protect against dots and such.
// '.' and '..' cannot match unless the pattern is that exactly,
// even if it starts with . or dot:true is set.
const dotTravAllowed = this.#parts.length === 1 && justDots.has(this.#parts[0]);
if (!dotTravAllowed) {
const aps = addPatternStart;
// check if we have a possibility of matching . or ..,
// and prevent that.
const needNoTrav =
// dots are allowed, and the pattern starts with [ or .
(dot && aps.has(src.charAt(0))) ||
// the pattern starts with \., and then [ or .
(src.startsWith('\\.') && aps.has(src.charAt(2))) ||
// the pattern starts with \.\., and then [ or .
(src.startsWith('\\.\\.') && aps.has(src.charAt(4)));
// no need to prevent dots if it can't match a dot, or if a
// sub-pattern will be preventing it anyway.
const needNoDot = !dot && !allowDot && aps.has(src.charAt(0));
start = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : '';
}
}
}
// append the "end of path portion" pattern to negation tails
let end = '';
if (this.isEnd() &&
this.#root.#filledNegs &&
this.#parent?.type === '!') {
end = '(?:$|\\/)';
}
const final = start + src + end;
return [
final,
(0, unescape_js_1.unescape)(src),
(this.#hasMagic = !!this.#hasMagic),
this.#uflag,
];
}
// We need to calculate the body *twice* if it's a repeat pattern
// at the start, once in nodot mode, then again in dot mode, so a
// pattern like *(?) can match 'x.y'
const repeated = this.type === '*' || this.type === '+';
// some kind of extglob
const start = this.type === '!' ? '(?:(?!(?:' : '(?:';
let body = this.#partsToRegExp(dot);
if (this.isStart() && this.isEnd() && !body && this.type !== '!') {
// invalid extglob, has to at least be *something* present, if it's
// the entire path portion.
const s = this.toString();
const me = this;
me.#parts = [s];
me.type = null;
me.#hasMagic = undefined;
return [s, (0, unescape_js_1.unescape)(this.toString()), false, false];
}
// XXX abstract out this map method
let bodyDotAllowed = !repeated || allowDot || dot || !startNoDot
? ''
: this.#partsToRegExp(true);
if (bodyDotAllowed === body) {
bodyDotAllowed = '';
}
if (bodyDotAllowed) {
body = `(?:${body})(?:${bodyDotAllowed})*?`;
}
// an empty !() is exactly equivalent to a starNoEmpty
let final = '';
if (this.type === '!' && this.#emptyExt) {
final = (this.isStart() && !dot ? startNoDot : '') + starNoEmpty;
}
else {
const close = this.type === '!'
? // !() must match something,but !(x) can match ''
'))' +
(this.isStart() && !dot && !allowDot ? startNoDot : '') +
star +
')'
: this.type === '@'
? ')'
: this.type === '?'
? ')?'
: this.type === '+' && bodyDotAllowed
? ')'
: this.type === '*' && bodyDotAllowed
? `)?`
: `)${this.type}`;
final = start + body + close;
}
return [
final,
(0, unescape_js_1.unescape)(body),
(this.#hasMagic = !!this.#hasMagic),
this.#uflag,
];
}
#partsToRegExp(dot) {
return this.#parts
.map(p => {
// extglob ASTs should only contain parent ASTs
/* c8 ignore start */
if (typeof p === 'string') {
throw new Error('string type in extglob ast??');
}
/* c8 ignore stop */
// can ignore hasMagic, because extglobs are already always magic
const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot);
this.#uflag = this.#uflag || uflag;
return re;
})
.filter(p => !(this.isStart() && this.isEnd()) || !!p)
.join('|');
}
static #parseGlob(glob, hasMagic, noEmpty = false) {
let escaping = false;
let re = '';
let uflag = false;
// multiple stars that aren't globstars coalesce into one *
let inStar = false;
for (let i = 0; i < glob.length; i++) {
const c = glob.charAt(i);
if (escaping) {
escaping = false;
re += (reSpecials.has(c) ? '\\' : '') + c;
inStar = false;
continue;
}
if (c === '\\') {
if (i === glob.length - 1) {
re += '\\\\';
}
else {
escaping = true;
}
continue;
}
if (c === '[') {
const [src, needUflag, consumed, magic] = (0, brace_expressions_js_1.parseClass)(glob, i);
if (consumed) {
re += src;
uflag = uflag || needUflag;
i += consumed - 1;
hasMagic = hasMagic || magic;
inStar = false;
continue;
}
}
if (c === '*') {
if (inStar)
continue;
inStar = true;
re += noEmpty && /^[*]+$/.test(glob) ? starNoEmpty : star;
hasMagic = true;
continue;
}
else {
inStar = false;
}
if (c === '?') {
re += qmark;
hasMagic = true;
continue;
}
re += regExpEscape(c);
}
return [re, (0, unescape_js_1.unescape)(glob), !!hasMagic, uflag];
}
}
exports.AST = AST;
_a = AST;
//# sourceMappingURL=ast.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
export type ParseClassResult = [
src: string,
uFlag: boolean,
consumed: number,
hasMagic: boolean
];
export declare const parseClass: (glob: string, position: number) => ParseClassResult;
//# sourceMappingURL=brace-expressions.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"brace-expressions.d.ts","sourceRoot":"","sources":["../../src/brace-expressions.ts"],"names":[],"mappings":"AA+BA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM;IACX,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,OAAO;CAClB,CAAA;AAQD,eAAO,MAAM,UAAU,GACrB,MAAM,MAAM,EACZ,UAAU,MAAM,KACf,gBA6HF,CAAA"}
@@ -0,0 +1,152 @@
"use strict";
// translate the various posix character classes into unicode properties
// this works across all unicode locales
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseClass = void 0;
// { <posix class>: [<translation>, /u flag required, negated]
const posixClasses = {
'[:alnum:]': ['\\p{L}\\p{Nl}\\p{Nd}', true],
'[:alpha:]': ['\\p{L}\\p{Nl}', true],
'[:ascii:]': ['\\x' + '00-\\x' + '7f', false],
'[:blank:]': ['\\p{Zs}\\t', true],
'[:cntrl:]': ['\\p{Cc}', true],
'[:digit:]': ['\\p{Nd}', true],
'[:graph:]': ['\\p{Z}\\p{C}', true, true],
'[:lower:]': ['\\p{Ll}', true],
'[:print:]': ['\\p{C}', true],
'[:punct:]': ['\\p{P}', true],
'[:space:]': ['\\p{Z}\\t\\r\\n\\v\\f', true],
'[:upper:]': ['\\p{Lu}', true],
'[:word:]': ['\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}', true],
'[:xdigit:]': ['A-Fa-f0-9', false],
};
// only need to escape a few things inside of brace expressions
// escapes: [ \ ] -
const braceEscape = (s) => s.replace(/[[\]\\-]/g, '\\$&');
// escape all regexp magic characters
const regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
// everything has already been escaped, we just have to join
const rangesToString = (ranges) => ranges.join('');
// takes a glob string at a posix brace expression, and returns
// an equivalent regular expression source, and boolean indicating
// whether the /u flag needs to be applied, and the number of chars
// consumed to parse the character class.
// This also removes out of order ranges, and returns ($.) if the
// entire class just no good.
const parseClass = (glob, position) => {
const pos = position;
/* c8 ignore start */
if (glob.charAt(pos) !== '[') {
throw new Error('not in a brace expression');
}
/* c8 ignore stop */
const ranges = [];
const negs = [];
let i = pos + 1;
let sawStart = false;
let uflag = false;
let escaping = false;
let negate = false;
let endPos = pos;
let rangeStart = '';
WHILE: while (i < glob.length) {
const c = glob.charAt(i);
if ((c === '!' || c === '^') && i === pos + 1) {
negate = true;
i++;
continue;
}
if (c === ']' && sawStart && !escaping) {
endPos = i + 1;
break;
}
sawStart = true;
if (c === '\\') {
if (!escaping) {
escaping = true;
i++;
continue;
}
// escaped \ char, fall through and treat like normal char
}
if (c === '[' && !escaping) {
// either a posix class, a collation equivalent, or just a [
for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {
if (glob.startsWith(cls, i)) {
// invalid, [a-[] is fine, but not [a-[:alpha]]
if (rangeStart) {
return ['$.', false, glob.length - pos, true];
}
i += cls.length;
if (neg)
negs.push(unip);
else
ranges.push(unip);
uflag = uflag || u;
continue WHILE;
}
}
}
// now it's just a normal character, effectively
escaping = false;
if (rangeStart) {
// throw this range away if it's not valid, but others
// can still match.
if (c > rangeStart) {
ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c));
}
else if (c === rangeStart) {
ranges.push(braceEscape(c));
}
rangeStart = '';
i++;
continue;
}
// now might be the start of a range.
// can be either c-d or c-] or c<more...>] or c] at this point
if (glob.startsWith('-]', i + 1)) {
ranges.push(braceEscape(c + '-'));
i += 2;
continue;
}
if (glob.startsWith('-', i + 1)) {
rangeStart = c;
i += 2;
continue;
}
// not the start of a range, just a single character
ranges.push(braceEscape(c));
i++;
}
if (endPos < i) {
// didn't see the end of the class, not a valid class,
// but might still be valid as a literal match.
return ['', false, 0, false];
}
// if we got no ranges and no negates, then we have a range that
// cannot possibly match anything, and that poisons the whole glob
if (!ranges.length && !negs.length) {
return ['$.', false, glob.length - pos, true];
}
// if we got one positive range, and it's a single character, then that's
// not actually a magic pattern, it's just that one literal character.
// we should not treat that as "magic", we should just return the literal
// character. [_] is a perfectly valid way to escape glob magic chars.
if (negs.length === 0 &&
ranges.length === 1 &&
/^\\?.$/.test(ranges[0]) &&
!negate) {
const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0];
return [regexpEscape(r), false, endPos - pos, false];
}
const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']';
const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']';
const comb = ranges.length && negs.length
? '(' + sranges + '|' + snegs + ')'
: ranges.length
? sranges
: snegs;
return [comb, uflag, endPos - pos, true];
};
exports.parseClass = parseClass;
//# sourceMappingURL=brace-expressions.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,12 @@
import { MinimatchOptions } from './index.js';
/**
* Escape all magic characters in a glob pattern.
*
* If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape}
* option is used, then characters are escaped by wrapping in `[]`, because
* a magic character wrapped in a character class can only be satisfied by
* that exact character. In this mode, `\` is _not_ escaped, because it is
* not interpreted as a magic character, but instead as a path separator.
*/
export declare const escape: (s: string, { windowsPathsNoEscape, }?: Pick<MinimatchOptions, "windowsPathsNoEscape">) => string;
//# sourceMappingURL=escape.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"escape.d.ts","sourceRoot":"","sources":["../../src/escape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM,GACjB,GAAG,MAAM,EACT,4BAEG,IAAI,CAAC,gBAAgB,EAAE,sBAAsB,CAAM,WAQvD,CAAA"}
@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.escape = void 0;
/**
* Escape all magic characters in a glob pattern.
*
* If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape}
* option is used, then characters are escaped by wrapping in `[]`, because
* a magic character wrapped in a character class can only be satisfied by
* that exact character. In this mode, `\` is _not_ escaped, because it is
* not interpreted as a magic character, but instead as a path separator.
*/
const escape = (s, { windowsPathsNoEscape = false, } = {}) => {
// don't need to escape +@! because we escape the parens
// that make those magic, and escaping ! as [!] isn't valid,
// because [!]] is a valid glob class meaning not ']'.
return windowsPathsNoEscape
? s.replace(/[?*()[\]]/g, '[$&]')
: s.replace(/[?*()[\]\\]/g, '\\$&');
};
exports.escape = escape;
//# sourceMappingURL=escape.js.map
@@ -0,0 +1 @@
{"version":3,"file":"escape.js","sourceRoot":"","sources":["../../src/escape.ts"],"names":[],"mappings":";;;AACA;;;;;;;;GAQG;AACI,MAAM,MAAM,GAAG,CACpB,CAAS,EACT,EACE,oBAAoB,GAAG,KAAK,MACsB,EAAE,EACtD,EAAE;IACF,wDAAwD;IACxD,4DAA4D;IAC5D,sDAAsD;IACtD,OAAO,oBAAoB;QACzB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC;QACjC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;AACvC,CAAC,CAAA;AAZY,QAAA,MAAM,UAYlB","sourcesContent":["import { MinimatchOptions } from './index.js'\n/**\n * Escape all magic characters in a glob pattern.\n *\n * If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape}\n * option is used, then characters are escaped by wrapping in `[]`, because\n * a magic character wrapped in a character class can only be satisfied by\n * that exact character. In this mode, `\\` is _not_ escaped, because it is\n * not interpreted as a magic character, but instead as a path separator.\n */\nexport const escape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape'> = {}\n) => {\n // don't need to escape +@! because we escape the parens\n // that make those magic, and escaping ! as [!] isn't valid,\n // because [!]] is a valid glob class meaning not ']'.\n return windowsPathsNoEscape\n ? s.replace(/[?*()[\\]]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\]/g, '\\\\$&')\n}\n"]}
@@ -0,0 +1,98 @@
import { AST } from './ast.js';
type Platform = 'aix' | 'android' | 'darwin' | 'freebsd' | 'haiku' | 'linux' | 'openbsd' | 'sunos' | 'win32' | 'cygwin' | 'netbsd';
export interface MinimatchOptions {
nobrace?: boolean;
nocomment?: boolean;
nonegate?: boolean;
debug?: boolean;
noglobstar?: boolean;
noext?: boolean;
nonull?: boolean;
windowsPathsNoEscape?: boolean;
allowWindowsEscape?: boolean;
partial?: boolean;
dot?: boolean;
nocase?: boolean;
nocaseMagicOnly?: boolean;
magicalBraces?: boolean;
matchBase?: boolean;
flipNegate?: boolean;
preserveMultipleSlashes?: boolean;
optimizationLevel?: number;
platform?: Platform;
windowsNoMagicRoot?: boolean;
maxGlobstarRecursion?: number;
maxExtglobRecursion?: number;
}
export declare const minimatch: {
(p: string, pattern: string, options?: MinimatchOptions): boolean;
sep: Sep;
GLOBSTAR: typeof GLOBSTAR;
filter: (pattern: string, options?: MinimatchOptions) => (p: string) => boolean;
defaults: (def: MinimatchOptions) => typeof minimatch;
braceExpand: (pattern: string, options?: MinimatchOptions) => string[];
makeRe: (pattern: string, options?: MinimatchOptions) => false | MMRegExp;
match: (list: string[], pattern: string, options?: MinimatchOptions) => string[];
AST: typeof AST;
Minimatch: typeof Minimatch;
escape: (s: string, { windowsPathsNoEscape, }?: Pick<MinimatchOptions, "windowsPathsNoEscape">) => string;
unescape: (s: string, { windowsPathsNoEscape, }?: Pick<MinimatchOptions, "windowsPathsNoEscape">) => string;
};
type Sep = '\\' | '/';
export declare const sep: Sep;
export declare const GLOBSTAR: unique symbol;
export declare const filter: (pattern: string, options?: MinimatchOptions) => (p: string) => boolean;
export declare const defaults: (def: MinimatchOptions) => typeof minimatch;
export declare const braceExpand: (pattern: string, options?: MinimatchOptions) => string[];
export declare const makeRe: (pattern: string, options?: MinimatchOptions) => false | MMRegExp;
export declare const match: (list: string[], pattern: string, options?: MinimatchOptions) => string[];
export type MMRegExp = RegExp & {
_src?: string;
_glob?: string;
};
export type ParseReturnFiltered = string | MMRegExp | typeof GLOBSTAR;
export type ParseReturn = ParseReturnFiltered | false;
export declare class Minimatch {
#private;
options: MinimatchOptions;
set: ParseReturnFiltered[][];
pattern: string;
windowsPathsNoEscape: boolean;
nonegate: boolean;
negate: boolean;
comment: boolean;
empty: boolean;
preserveMultipleSlashes: boolean;
partial: boolean;
globSet: string[];
globParts: string[][];
nocase: boolean;
isWindows: boolean;
platform: Platform;
windowsNoMagicRoot: boolean;
maxGlobstarRecursion: number;
regexp: false | null | MMRegExp;
constructor(pattern: string, options?: MinimatchOptions);
hasMagic(): boolean;
debug(..._: any[]): void;
make(): void;
preprocess(globParts: string[][]): string[][];
adjascentGlobstarOptimize(globParts: string[][]): string[][];
levelOneOptimize(globParts: string[][]): string[][];
levelTwoFileOptimize(parts: string | string[]): string[];
firstPhasePreProcess(globParts: string[][]): string[][];
secondPhasePreProcess(globParts: string[][]): string[][];
partsMatch(a: string[], b: string[], emptyGSMatch?: boolean): false | string[];
parseNegate(): void;
matchOne(file: string[], pattern: ParseReturn[], partial?: boolean): boolean;
braceExpand(): string[];
parse(pattern: string): ParseReturn;
makeRe(): false | MMRegExp;
slashSplit(p: string): string[];
match(f: string, partial?: boolean): boolean;
static defaults(def: MinimatchOptions): typeof Minimatch;
}
export { AST } from './ast.js';
export { escape } from './escape.js';
export { unescape } from './unescape.js';
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAe,MAAM,UAAU,CAAA;AAI3C,KAAK,QAAQ,GACT,KAAK,GACL,SAAS,GACT,QAAQ,GACR,SAAS,GACT,OAAO,GACP,OAAO,GACP,SAAS,GACT,OAAO,GACP,OAAO,GACP,QAAQ,GACR,QAAQ,CAAA;AAEZ,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,eAAO,MAAM,SAAS;QACjB,MAAM,WACA,MAAM,YACN,gBAAgB;;;sBAuGf,MAAM,YAAW,gBAAgB,MAC1C,GAAG,MAAM;oBAOkB,gBAAgB,KAAG,OAAO,SAAS;2BA6EtD,MAAM,YACN,gBAAgB;sBA2BK,MAAM,YAAW,gBAAgB;kBAKzD,MAAM,EAAE,WACL,MAAM,YACN,gBAAgB;;;;;CArN1B,CAAA;AA+DD,KAAK,GAAG,GAAG,IAAI,GAAG,GAAG,CAAA;AAOrB,eAAO,MAAM,GAAG,KAAgE,CAAA;AAGhF,eAAO,MAAM,QAAQ,eAAwB,CAAA;AAmB7C,eAAO,MAAM,MAAM,GAChB,SAAS,MAAM,EAAE,UAAS,gBAAqB,MAC/C,GAAG,MAAM,YACsB,CAAA;AAMlC,eAAO,MAAM,QAAQ,GAAI,KAAK,gBAAgB,KAAG,OAAO,SA+DvD,CAAA;AAaD,eAAO,MAAM,WAAW,GACtB,SAAS,MAAM,EACf,UAAS,gBAAqB,aAY/B,CAAA;AAeD,eAAO,MAAM,MAAM,GAAI,SAAS,MAAM,EAAE,UAAS,gBAAqB,qBAC5B,CAAA;AAG1C,eAAO,MAAM,KAAK,GAChB,MAAM,MAAM,EAAE,EACd,SAAS,MAAM,EACf,UAAS,gBAAqB,aAQ/B,CAAA;AAQD,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,QAAQ,CAAA;AACrE,MAAM,MAAM,WAAW,GAAG,mBAAmB,GAAG,KAAK,CAAA;AAErD,qBAAa,SAAS;;IACpB,OAAO,EAAE,gBAAgB,CAAA;IACzB,GAAG,EAAE,mBAAmB,EAAE,EAAE,CAAA;IAC5B,OAAO,EAAE,MAAM,CAAA;IAEf,oBAAoB,EAAE,OAAO,CAAA;IAC7B,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,uBAAuB,EAAE,OAAO,CAAA;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,MAAM,EAAE,EAAE,CAAA;IACrB,MAAM,EAAE,OAAO,CAAA;IAEf,SAAS,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,QAAQ,CAAA;IAClB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,oBAAoB,EAAE,MAAM,CAAA;IAE5B,MAAM,EAAE,KAAK,GAAG,IAAI,GAAG,QAAQ,CAAA;gBACnB,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;IAmC3D,QAAQ,IAAI,OAAO;IAYnB,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE;IAEjB,IAAI;IA0FJ,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE;IA8BhC,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE;IAiB/C,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE;IAoBtC,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IA6D7C,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE;IA0F1C,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE;IAkBxD,UAAU,CACR,CAAC,EAAE,MAAM,EAAE,EACX,CAAC,EAAE,MAAM,EAAE,EACX,YAAY,GAAE,OAAe,GAC5B,KAAK,GAAG,MAAM,EAAE;IA+CnB,WAAW;IAqBX,QAAQ,CACN,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,WAAW,EAAE,EACtB,OAAO,GAAE,OAAe;IAuP1B,WAAW,IAAI,MAAM,EAAE;IAIvB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW;IAiDnC,MAAM;IAsFN,UAAU,CAAC,CAAC,EAAE,MAAM;IAepB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,UAAe;IAiEvC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,gBAAgB;CAGtC;AAED,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA"}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
{
"type": "commonjs"
}
@@ -0,0 +1,17 @@
import { MinimatchOptions } from './index.js';
/**
* Un-escape a string that has been escaped with {@link escape}.
*
* If the {@link windowsPathsNoEscape} option is used, then square-brace
* escapes are removed, but not backslash escapes. For example, it will turn
* the string `'[*]'` into `*`, but it will not turn `'\\*'` into `'*'`,
* becuase `\` is a path separator in `windowsPathsNoEscape` mode.
*
* When `windowsPathsNoEscape` is not set, then both brace escapes and
* backslash escapes are removed.
*
* Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped
* or unescaped.
*/
export declare const unescape: (s: string, { windowsPathsNoEscape, }?: Pick<MinimatchOptions, "windowsPathsNoEscape">) => string;
//# sourceMappingURL=unescape.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"unescape.d.ts","sourceRoot":"","sources":["../../src/unescape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,QAAQ,GACnB,GAAG,MAAM,EACT,4BAEG,IAAI,CAAC,gBAAgB,EAAE,sBAAsB,CAAM,WAKvD,CAAA"}
@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.unescape = void 0;
/**
* Un-escape a string that has been escaped with {@link escape}.
*
* If the {@link windowsPathsNoEscape} option is used, then square-brace
* escapes are removed, but not backslash escapes. For example, it will turn
* the string `'[*]'` into `*`, but it will not turn `'\\*'` into `'*'`,
* becuase `\` is a path separator in `windowsPathsNoEscape` mode.
*
* When `windowsPathsNoEscape` is not set, then both brace escapes and
* backslash escapes are removed.
*
* Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped
* or unescaped.
*/
const unescape = (s, { windowsPathsNoEscape = false, } = {}) => {
return windowsPathsNoEscape
? s.replace(/\[([^\/\\])\]/g, '$1')
: s.replace(/((?!\\).|^)\[([^\/\\])\]/g, '$1$2').replace(/\\([^\/])/g, '$1');
};
exports.unescape = unescape;
//# sourceMappingURL=unescape.js.map
@@ -0,0 +1 @@
{"version":3,"file":"unescape.js","sourceRoot":"","sources":["../../src/unescape.ts"],"names":[],"mappings":";;;AACA;;;;;;;;;;;;;GAaG;AACI,MAAM,QAAQ,GAAG,CACtB,CAAS,EACT,EACE,oBAAoB,GAAG,KAAK,MACsB,EAAE,EACtD,EAAE;IACF,OAAO,oBAAoB;QACzB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC;QACnC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,2BAA2B,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;AAChF,CAAC,CAAA;AATY,QAAA,QAAQ,YASpB","sourcesContent":["import { MinimatchOptions } from './index.js'\n/**\n * Un-escape a string that has been escaped with {@link escape}.\n *\n * If the {@link windowsPathsNoEscape} option is used, then square-brace\n * escapes are removed, but not backslash escapes. For example, it will turn\n * the string `'[*]'` into `*`, but it will not turn `'\\\\*'` into `'*'`,\n * becuase `\\` is a path separator in `windowsPathsNoEscape` mode.\n *\n * When `windowsPathsNoEscape` is not set, then both brace escapes and\n * backslash escapes are removed.\n *\n * Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped\n * or unescaped.\n */\nexport const unescape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape'> = {}\n) => {\n return windowsPathsNoEscape\n ? s.replace(/\\[([^\\/\\\\])\\]/g, '$1')\n : s.replace(/((?!\\\\).|^)\\[([^\\/\\\\])\\]/g, '$1$2').replace(/\\\\([^\\/])/g, '$1')\n}\n"]}
@@ -0,0 +1,2 @@
export declare const assertValidPattern: (pattern: any) => void;
//# sourceMappingURL=assert-valid-pattern.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"assert-valid-pattern.d.ts","sourceRoot":"","sources":["../../src/assert-valid-pattern.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,kBAAkB,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAUlD,CAAA"}
@@ -0,0 +1,10 @@
const MAX_PATTERN_LENGTH = 1024 * 64;
export const assertValidPattern = (pattern) => {
if (typeof pattern !== 'string') {
throw new TypeError('invalid pattern');
}
if (pattern.length > MAX_PATTERN_LENGTH) {
throw new TypeError('pattern is too long');
}
};
//# sourceMappingURL=assert-valid-pattern.js.map
@@ -0,0 +1 @@
{"version":3,"file":"assert-valid-pattern.js","sourceRoot":"","sources":["../../src/assert-valid-pattern.ts"],"names":[],"mappings":"AAAA,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAE,CAAA;AACpC,MAAM,CAAC,MAAM,kBAAkB,GAA2B,CACxD,OAAY,EACe,EAAE;IAC7B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,SAAS,CAAC,iBAAiB,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;QACxC,MAAM,IAAI,SAAS,CAAC,qBAAqB,CAAC,CAAA;IAC5C,CAAC;AACH,CAAC,CAAA","sourcesContent":["const MAX_PATTERN_LENGTH = 1024 * 64\nexport const assertValidPattern: (pattern: any) => void = (\n pattern: any\n): asserts pattern is string => {\n if (typeof pattern !== 'string') {\n throw new TypeError('invalid pattern')\n }\n\n if (pattern.length > MAX_PATTERN_LENGTH) {\n throw new TypeError('pattern is too long')\n }\n}\n"]}
@@ -0,0 +1,20 @@
import { MinimatchOptions, MMRegExp } from './index.js';
export type ExtglobType = '!' | '?' | '+' | '*' | '@';
export declare class AST {
#private;
type: ExtglobType | null;
constructor(type: ExtglobType | null, parent?: AST, options?: MinimatchOptions);
get hasMagic(): boolean | undefined;
toString(): string;
push(...parts: (string | AST)[]): void;
toJSON(): any[];
isStart(): boolean;
isEnd(): boolean;
copyIn(part: AST | string): void;
clone(parent: AST): AST;
static fromGlob(pattern: string, options?: MinimatchOptions): AST;
toMMPattern(): MMRegExp | string;
get options(): MinimatchOptions;
toRegExpSource(allowDot?: boolean): [re: string, body: string, hasMagic: boolean, uflag: boolean];
}
//# sourceMappingURL=ast.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/ast.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAwCvD,MAAM,MAAM,WAAW,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AAiErD,qBAAa,GAAG;;IACd,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;gBAiBtB,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,MAAM,CAAC,EAAE,GAAG,EACZ,OAAO,GAAE,gBAAqB;IAahC,IAAI,QAAQ,IAAI,OAAO,GAAG,SAAS,CAUlC;IAGD,QAAQ,IAAI,MAAM;IA+ClB,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,MAAM,GAAG,GAAG,CAAC,EAAE;IAY/B,MAAM;IAgBN,OAAO,IAAI,OAAO;IAgBlB,KAAK,IAAI,OAAO;IAYhB,MAAM,CAAC,IAAI,EAAE,GAAG,GAAG,MAAM;IAKzB,KAAK,CAAC,MAAM,EAAE,GAAG;IA0RjB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;IAQ/D,WAAW,IAAI,QAAQ,GAAG,MAAM;IA2BhC,IAAI,OAAO,qBAEV;IAuED,cAAc,CACZ,QAAQ,CAAC,EAAE,OAAO,GACjB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC;CA4MjE"}
+743
View File
@@ -0,0 +1,743 @@
// parse a single path portion
var _a;
import { parseClass } from './brace-expressions.js';
import { unescape } from './unescape.js';
const types = new Set(['!', '?', '+', '*', '@']);
const isExtglobType = (c) => types.has(c);
const isExtglobAST = (c) => isExtglobType(c.type);
const adoptionMap = new Map([
['!', ['@']],
['?', ['?', '@']],
['@', ['@']],
['*', ['*', '+', '?', '@']],
['+', ['+', '@']],
]);
const adoptionWithSpaceMap = new Map([
['!', ['?']],
['@', ['?']],
['+', ['?', '*']],
]);
const adoptionAnyMap = new Map([
['!', ['?', '@']],
['?', ['?', '@']],
['@', ['?', '@']],
['*', ['*', '+', '?', '@']],
['+', ['+', '@', '?', '*']],
]);
const usurpMap = new Map([
['!', new Map([['!', '@']])],
['?', new Map([['*', '*'], ['+', '*']])],
['@', new Map([['!', '!'], ['?', '?'], ['@', '@'], ['*', '*'], ['+', '+']])],
['+', new Map([['?', '*'], ['*', '*']])],
]);
// Patterns that get prepended to bind to the start of either the
// entire string, or just a single path portion, to prevent dots
// and/or traversal patterns, when needed.
// Exts don't need the ^ or / bit, because the root binds that already.
const startNoTraversal = '(?!(?:^|/)\\.\\.?(?:$|/))';
const startNoDot = '(?!\\.)';
// characters that indicate a start of pattern needs the "no dots" bit,
// because a dot *might* be matched. ( is not in the list, because in
// the case of a child extglob, it will handle the prevention itself.
const addPatternStart = new Set(['[', '.']);
// cases where traversal is A-OK, no dot prevention needed
const justDots = new Set(['..', '.']);
const reSpecials = new Set('().*{}+?[]^$\\!');
const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
// any single thing other than /
const qmark = '[^/]';
// * => any number of characters
const star = qmark + '*?';
// use + when we need to ensure that *something* matches, because the * is
// the only thing in the path portion.
const starNoEmpty = qmark + '+?';
// remove the \ chars that we added if we end up doing a nonmagic compare
// const deslash = (s: string) => s.replace(/\\(.)/g, '$1')
export class AST {
type;
#root;
#hasMagic;
#uflag = false;
#parts = [];
#parent;
#parentIndex;
#negs;
#filledNegs = false;
#options;
#toString;
// set to true if it's an extglob with no children
// (which really means one child of '')
#emptyExt = false;
constructor(type, parent, options = {}) {
this.type = type;
// extglobs are inherently magical
if (type)
this.#hasMagic = true;
this.#parent = parent;
this.#root = this.#parent ? this.#parent.#root : this;
this.#options = this.#root === this ? options : this.#root.#options;
this.#negs = this.#root === this ? [] : this.#root.#negs;
if (type === '!' && !this.#root.#filledNegs)
this.#negs.push(this);
this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0;
}
get hasMagic() {
/* c8 ignore start */
if (this.#hasMagic !== undefined)
return this.#hasMagic;
/* c8 ignore stop */
for (const p of this.#parts) {
if (typeof p === 'string')
continue;
if (p.type || p.hasMagic)
return (this.#hasMagic = true);
}
// note: will be undefined until we generate the regexp src and find out
return this.#hasMagic;
}
// reconstructs the pattern
toString() {
if (this.#toString !== undefined)
return this.#toString;
if (!this.type) {
return (this.#toString = this.#parts.map(p => String(p)).join(''));
}
else {
return (this.#toString =
this.type + '(' + this.#parts.map(p => String(p)).join('|') + ')');
}
}
#fillNegs() {
/* c8 ignore start */
if (this !== this.#root)
throw new Error('should only call on root');
if (this.#filledNegs)
return this;
/* c8 ignore stop */
// call toString() once to fill this out
this.toString();
this.#filledNegs = true;
let n;
while ((n = this.#negs.pop())) {
if (n.type !== '!')
continue;
// walk up the tree, appending everthing that comes AFTER parentIndex
let p = n;
let pp = p.#parent;
while (pp) {
for (let i = p.#parentIndex + 1; !pp.type && i < pp.#parts.length; i++) {
for (const part of n.#parts) {
/* c8 ignore start */
if (typeof part === 'string') {
throw new Error('string part in extglob AST??');
}
/* c8 ignore stop */
part.copyIn(pp.#parts[i]);
}
}
p = pp;
pp = p.#parent;
}
}
return this;
}
push(...parts) {
for (const p of parts) {
if (p === '')
continue;
/* c8 ignore start */
if (typeof p !== 'string' && !(p instanceof _a && p.#parent === this)) {
throw new Error('invalid part: ' + p);
}
/* c8 ignore stop */
this.#parts.push(p);
}
}
toJSON() {
const ret = this.type === null
? this.#parts.slice().map(p => (typeof p === 'string' ? p : p.toJSON()))
: [this.type, ...this.#parts.map(p => p.toJSON())];
if (this.isStart() && !this.type)
ret.unshift([]);
if (this.isEnd() &&
(this === this.#root ||
(this.#root.#filledNegs && this.#parent?.type === '!'))) {
ret.push({});
}
return ret;
}
isStart() {
if (this.#root === this)
return true;
// if (this.type) return !!this.#parent?.isStart()
if (!this.#parent?.isStart())
return false;
if (this.#parentIndex === 0)
return true;
// if everything AHEAD of this is a negation, then it's still the "start"
const p = this.#parent;
for (let i = 0; i < this.#parentIndex; i++) {
const pp = p.#parts[i];
if (!(pp instanceof _a && pp.type === '!')) {
return false;
}
}
return true;
}
isEnd() {
if (this.#root === this)
return true;
if (this.#parent?.type === '!')
return true;
if (!this.#parent?.isEnd())
return false;
if (!this.type)
return this.#parent?.isEnd();
// if not root, it'll always have a parent
/* c8 ignore start */
const pl = this.#parent ? this.#parent.#parts.length : 0;
/* c8 ignore stop */
return this.#parentIndex === pl - 1;
}
copyIn(part) {
if (typeof part === 'string')
this.push(part);
else
this.push(part.clone(this));
}
clone(parent) {
const c = new _a(this.type, parent);
for (const p of this.#parts) {
c.copyIn(p);
}
return c;
}
static #parseAST(str, ast, pos, opt, extDepth) {
const maxDepth = opt.maxExtglobRecursion ?? 2;
let escaping = false;
let inBrace = false;
let braceStart = -1;
let braceNeg = false;
if (ast.type === null) {
// outside of a extglob, append until we find a start
let i = pos;
let acc = '';
while (i < str.length) {
const c = str.charAt(i++);
// still accumulate escapes at this point, but we do ignore
// starts that are escaped
if (escaping || c === '\\') {
escaping = !escaping;
acc += c;
continue;
}
if (inBrace) {
if (i === braceStart + 1) {
if (c === '^' || c === '!') {
braceNeg = true;
}
}
else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {
inBrace = false;
}
acc += c;
continue;
}
else if (c === '[') {
inBrace = true;
braceStart = i;
braceNeg = false;
acc += c;
continue;
}
const doRecurse = !opt.noext &&
isExtglobType(c) &&
str.charAt(i) === '(' &&
extDepth <= maxDepth;
if (doRecurse) {
ast.push(acc);
acc = '';
const ext = new _a(c, ast);
i = _a.#parseAST(str, ext, i, opt, extDepth + 1);
ast.push(ext);
continue;
}
acc += c;
}
ast.push(acc);
return i;
}
// some kind of extglob, pos is at the (
// find the next | or )
let i = pos + 1;
let part = new _a(null, ast);
const parts = [];
let acc = '';
while (i < str.length) {
const c = str.charAt(i++);
// still accumulate escapes at this point, but we do ignore
// starts that are escaped
if (escaping || c === '\\') {
escaping = !escaping;
acc += c;
continue;
}
if (inBrace) {
if (i === braceStart + 1) {
if (c === '^' || c === '!') {
braceNeg = true;
}
}
else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {
inBrace = false;
}
acc += c;
continue;
}
else if (c === '[') {
inBrace = true;
braceStart = i;
braceNeg = false;
acc += c;
continue;
}
const doRecurse = isExtglobType(c) &&
str.charAt(i) === '(' &&
/* c8 ignore start - the maxDepth is sufficient here */
(extDepth <= maxDepth || (ast && ast.#canAdoptType(c)));
/* c8 ignore stop */
if (doRecurse) {
const depthAdd = ast && ast.#canAdoptType(c) ? 0 : 1;
part.push(acc);
acc = '';
const ext = new _a(c, part);
part.push(ext);
i = _a.#parseAST(str, ext, i, opt, extDepth + depthAdd);
continue;
}
if (c === '|') {
part.push(acc);
acc = '';
parts.push(part);
part = new _a(null, ast);
continue;
}
if (c === ')') {
if (acc === '' && ast.#parts.length === 0) {
ast.#emptyExt = true;
}
part.push(acc);
acc = '';
ast.push(...parts, part);
return i;
}
acc += c;
}
// unfinished extglob
// if we got here, it was a malformed extglob! not an extglob, but
// maybe something else in there.
ast.type = null;
ast.#hasMagic = undefined;
ast.#parts = [str.substring(pos - 1)];
return i;
}
#canAdoptWithSpace(child) {
return this.#canAdopt(child, adoptionWithSpaceMap);
}
#canAdopt(child, map = adoptionMap) {
if (!child ||
typeof child !== 'object' ||
child.type !== null ||
child.#parts.length !== 1 ||
this.type === null) {
return false;
}
const gc = child.#parts[0];
if (!gc || typeof gc !== 'object' || gc.type === null) {
return false;
}
return this.#canAdoptType(gc.type, map);
}
#canAdoptType(c, map = adoptionAnyMap) {
return !!map.get(this.type)?.includes(c);
}
#adoptWithSpace(child, index) {
const gc = child.#parts[0];
const blank = new _a(null, gc, this.options);
blank.#parts.push('');
gc.push(blank);
this.#adopt(child, index);
}
#adopt(child, index) {
const gc = child.#parts[0];
this.#parts.splice(index, 1, ...gc.#parts);
for (const p of gc.#parts) {
if (typeof p === 'object')
p.#parent = this;
}
this.#toString = undefined;
}
#canUsurpType(c) {
const m = usurpMap.get(this.type);
return !!(m?.has(c));
}
#canUsurp(child) {
if (!child ||
typeof child !== 'object' ||
child.type !== null ||
child.#parts.length !== 1 ||
this.type === null ||
this.#parts.length !== 1) {
return false;
}
const gc = child.#parts[0];
if (!gc || typeof gc !== 'object' || gc.type === null) {
return false;
}
return this.#canUsurpType(gc.type);
}
#usurp(child) {
const m = usurpMap.get(this.type);
const gc = child.#parts[0];
const nt = m?.get(gc.type);
/* c8 ignore start - impossible */
if (!nt)
return false;
/* c8 ignore stop */
this.#parts = gc.#parts;
for (const p of this.#parts) {
if (typeof p === 'object')
p.#parent = this;
}
this.type = nt;
this.#toString = undefined;
this.#emptyExt = false;
}
#flatten() {
if (!isExtglobAST(this)) {
for (const p of this.#parts) {
if (typeof p === 'object')
p.#flatten();
}
}
else {
let iterations = 0;
let done = false;
do {
done = true;
for (let i = 0; i < this.#parts.length; i++) {
const c = this.#parts[i];
if (typeof c === 'object') {
c.#flatten();
if (this.#canAdopt(c)) {
done = false;
this.#adopt(c, i);
}
else if (this.#canAdoptWithSpace(c)) {
done = false;
this.#adoptWithSpace(c, i);
}
else if (this.#canUsurp(c)) {
done = false;
this.#usurp(c);
}
}
}
} while (!done && ++iterations < 10);
}
this.#toString = undefined;
}
static fromGlob(pattern, options = {}) {
const ast = new _a(null, undefined, options);
_a.#parseAST(pattern, ast, 0, options, 0);
return ast;
}
// returns the regular expression if there's magic, or the unescaped
// string if not.
toMMPattern() {
// should only be called on root
/* c8 ignore start */
if (this !== this.#root)
return this.#root.toMMPattern();
/* c8 ignore stop */
const glob = this.toString();
const [re, body, hasMagic, uflag] = this.toRegExpSource();
// if we're in nocase mode, and not nocaseMagicOnly, then we do
// still need a regular expression if we have to case-insensitively
// match capital/lowercase characters.
const anyMagic = hasMagic ||
this.#hasMagic ||
(this.#options.nocase &&
!this.#options.nocaseMagicOnly &&
glob.toUpperCase() !== glob.toLowerCase());
if (!anyMagic) {
return body;
}
const flags = (this.#options.nocase ? 'i' : '') + (uflag ? 'u' : '');
return Object.assign(new RegExp(`^${re}$`, flags), {
_src: re,
_glob: glob,
});
}
get options() {
return this.#options;
}
// returns the string match, the regexp source, whether there's magic
// in the regexp (so a regular expression is required) and whether or
// not the uflag is needed for the regular expression (for posix classes)
// TODO: instead of injecting the start/end at this point, just return
// the BODY of the regexp, along with the start/end portions suitable
// for binding the start/end in either a joined full-path makeRe context
// (where we bind to (^|/), or a standalone matchPart context (where
// we bind to ^, and not /). Otherwise slashes get duped!
//
// In part-matching mode, the start is:
// - if not isStart: nothing
// - if traversal possible, but not allowed: ^(?!\.\.?$)
// - if dots allowed or not possible: ^
// - if dots possible and not allowed: ^(?!\.)
// end is:
// - if not isEnd(): nothing
// - else: $
//
// In full-path matching mode, we put the slash at the START of the
// pattern, so start is:
// - if first pattern: same as part-matching mode
// - if not isStart(): nothing
// - if traversal possible, but not allowed: /(?!\.\.?(?:$|/))
// - if dots allowed or not possible: /
// - if dots possible and not allowed: /(?!\.)
// end is:
// - if last pattern, same as part-matching mode
// - else nothing
//
// Always put the (?:$|/) on negated tails, though, because that has to be
// there to bind the end of the negated pattern portion, and it's easier to
// just stick it in now rather than try to inject it later in the middle of
// the pattern.
//
// We can just always return the same end, and leave it up to the caller
// to know whether it's going to be used joined or in parts.
// And, if the start is adjusted slightly, can do the same there:
// - if not isStart: nothing
// - if traversal possible, but not allowed: (?:/|^)(?!\.\.?$)
// - if dots allowed or not possible: (?:/|^)
// - if dots possible and not allowed: (?:/|^)(?!\.)
//
// But it's better to have a simpler binding without a conditional, for
// performance, so probably better to return both start options.
//
// Then the caller just ignores the end if it's not the first pattern,
// and the start always gets applied.
//
// But that's always going to be $ if it's the ending pattern, or nothing,
// so the caller can just attach $ at the end of the pattern when building.
//
// So the todo is:
// - better detect what kind of start is needed
// - return both flavors of starting pattern
// - attach $ at the end of the pattern when creating the actual RegExp
//
// Ah, but wait, no, that all only applies to the root when the first pattern
// is not an extglob. If the first pattern IS an extglob, then we need all
// that dot prevention biz to live in the extglob portions, because eg
// +(*|.x*) can match .xy but not .yx.
//
// So, return the two flavors if it's #root and the first child is not an
// AST, otherwise leave it to the child AST to handle it, and there,
// use the (?:^|/) style of start binding.
//
// Even simplified further:
// - Since the start for a join is eg /(?!\.) and the start for a part
// is ^(?!\.), we can just prepend (?!\.) to the pattern (either root
// or start or whatever) and prepend ^ or / at the Regexp construction.
toRegExpSource(allowDot) {
const dot = allowDot ?? !!this.#options.dot;
if (this.#root === this) {
this.#flatten();
this.#fillNegs();
}
if (!isExtglobAST(this)) {
const noEmpty = this.isStart() && this.isEnd();
const src = this.#parts
.map(p => {
const [re, _, hasMagic, uflag] = typeof p === 'string'
? _a.#parseGlob(p, this.#hasMagic, noEmpty)
: p.toRegExpSource(allowDot);
this.#hasMagic = this.#hasMagic || hasMagic;
this.#uflag = this.#uflag || uflag;
return re;
})
.join('');
let start = '';
if (this.isStart()) {
if (typeof this.#parts[0] === 'string') {
// this is the string that will match the start of the pattern,
// so we need to protect against dots and such.
// '.' and '..' cannot match unless the pattern is that exactly,
// even if it starts with . or dot:true is set.
const dotTravAllowed = this.#parts.length === 1 && justDots.has(this.#parts[0]);
if (!dotTravAllowed) {
const aps = addPatternStart;
// check if we have a possibility of matching . or ..,
// and prevent that.
const needNoTrav =
// dots are allowed, and the pattern starts with [ or .
(dot && aps.has(src.charAt(0))) ||
// the pattern starts with \., and then [ or .
(src.startsWith('\\.') && aps.has(src.charAt(2))) ||
// the pattern starts with \.\., and then [ or .
(src.startsWith('\\.\\.') && aps.has(src.charAt(4)));
// no need to prevent dots if it can't match a dot, or if a
// sub-pattern will be preventing it anyway.
const needNoDot = !dot && !allowDot && aps.has(src.charAt(0));
start = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : '';
}
}
}
// append the "end of path portion" pattern to negation tails
let end = '';
if (this.isEnd() &&
this.#root.#filledNegs &&
this.#parent?.type === '!') {
end = '(?:$|\\/)';
}
const final = start + src + end;
return [
final,
unescape(src),
(this.#hasMagic = !!this.#hasMagic),
this.#uflag,
];
}
// We need to calculate the body *twice* if it's a repeat pattern
// at the start, once in nodot mode, then again in dot mode, so a
// pattern like *(?) can match 'x.y'
const repeated = this.type === '*' || this.type === '+';
// some kind of extglob
const start = this.type === '!' ? '(?:(?!(?:' : '(?:';
let body = this.#partsToRegExp(dot);
if (this.isStart() && this.isEnd() && !body && this.type !== '!') {
// invalid extglob, has to at least be *something* present, if it's
// the entire path portion.
const s = this.toString();
const me = this;
me.#parts = [s];
me.type = null;
me.#hasMagic = undefined;
return [s, unescape(this.toString()), false, false];
}
// XXX abstract out this map method
let bodyDotAllowed = !repeated || allowDot || dot || !startNoDot
? ''
: this.#partsToRegExp(true);
if (bodyDotAllowed === body) {
bodyDotAllowed = '';
}
if (bodyDotAllowed) {
body = `(?:${body})(?:${bodyDotAllowed})*?`;
}
// an empty !() is exactly equivalent to a starNoEmpty
let final = '';
if (this.type === '!' && this.#emptyExt) {
final = (this.isStart() && !dot ? startNoDot : '') + starNoEmpty;
}
else {
const close = this.type === '!'
? // !() must match something,but !(x) can match ''
'))' +
(this.isStart() && !dot && !allowDot ? startNoDot : '') +
star +
')'
: this.type === '@'
? ')'
: this.type === '?'
? ')?'
: this.type === '+' && bodyDotAllowed
? ')'
: this.type === '*' && bodyDotAllowed
? `)?`
: `)${this.type}`;
final = start + body + close;
}
return [
final,
unescape(body),
(this.#hasMagic = !!this.#hasMagic),
this.#uflag,
];
}
#partsToRegExp(dot) {
return this.#parts
.map(p => {
// extglob ASTs should only contain parent ASTs
/* c8 ignore start */
if (typeof p === 'string') {
throw new Error('string type in extglob ast??');
}
/* c8 ignore stop */
// can ignore hasMagic, because extglobs are already always magic
const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot);
this.#uflag = this.#uflag || uflag;
return re;
})
.filter(p => !(this.isStart() && this.isEnd()) || !!p)
.join('|');
}
static #parseGlob(glob, hasMagic, noEmpty = false) {
let escaping = false;
let re = '';
let uflag = false;
// multiple stars that aren't globstars coalesce into one *
let inStar = false;
for (let i = 0; i < glob.length; i++) {
const c = glob.charAt(i);
if (escaping) {
escaping = false;
re += (reSpecials.has(c) ? '\\' : '') + c;
inStar = false;
continue;
}
if (c === '\\') {
if (i === glob.length - 1) {
re += '\\\\';
}
else {
escaping = true;
}
continue;
}
if (c === '[') {
const [src, needUflag, consumed, magic] = parseClass(glob, i);
if (consumed) {
re += src;
uflag = uflag || needUflag;
i += consumed - 1;
hasMagic = hasMagic || magic;
inStar = false;
continue;
}
}
if (c === '*') {
if (inStar)
continue;
inStar = true;
re += noEmpty && /^[*]+$/.test(glob) ? starNoEmpty : star;
hasMagic = true;
continue;
}
else {
inStar = false;
}
if (c === '?') {
re += qmark;
hasMagic = true;
continue;
}
re += regExpEscape(c);
}
return [re, unescape(glob), !!hasMagic, uflag];
}
}
_a = AST;
//# sourceMappingURL=ast.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
export type ParseClassResult = [
src: string,
uFlag: boolean,
consumed: number,
hasMagic: boolean
];
export declare const parseClass: (glob: string, position: number) => ParseClassResult;
//# sourceMappingURL=brace-expressions.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"brace-expressions.d.ts","sourceRoot":"","sources":["../../src/brace-expressions.ts"],"names":[],"mappings":"AA+BA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM;IACX,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,OAAO;CAClB,CAAA;AAQD,eAAO,MAAM,UAAU,GACrB,MAAM,MAAM,EACZ,UAAU,MAAM,KACf,gBA6HF,CAAA"}
@@ -0,0 +1,148 @@
// translate the various posix character classes into unicode properties
// this works across all unicode locales
// { <posix class>: [<translation>, /u flag required, negated]
const posixClasses = {
'[:alnum:]': ['\\p{L}\\p{Nl}\\p{Nd}', true],
'[:alpha:]': ['\\p{L}\\p{Nl}', true],
'[:ascii:]': ['\\x' + '00-\\x' + '7f', false],
'[:blank:]': ['\\p{Zs}\\t', true],
'[:cntrl:]': ['\\p{Cc}', true],
'[:digit:]': ['\\p{Nd}', true],
'[:graph:]': ['\\p{Z}\\p{C}', true, true],
'[:lower:]': ['\\p{Ll}', true],
'[:print:]': ['\\p{C}', true],
'[:punct:]': ['\\p{P}', true],
'[:space:]': ['\\p{Z}\\t\\r\\n\\v\\f', true],
'[:upper:]': ['\\p{Lu}', true],
'[:word:]': ['\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}', true],
'[:xdigit:]': ['A-Fa-f0-9', false],
};
// only need to escape a few things inside of brace expressions
// escapes: [ \ ] -
const braceEscape = (s) => s.replace(/[[\]\\-]/g, '\\$&');
// escape all regexp magic characters
const regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
// everything has already been escaped, we just have to join
const rangesToString = (ranges) => ranges.join('');
// takes a glob string at a posix brace expression, and returns
// an equivalent regular expression source, and boolean indicating
// whether the /u flag needs to be applied, and the number of chars
// consumed to parse the character class.
// This also removes out of order ranges, and returns ($.) if the
// entire class just no good.
export const parseClass = (glob, position) => {
const pos = position;
/* c8 ignore start */
if (glob.charAt(pos) !== '[') {
throw new Error('not in a brace expression');
}
/* c8 ignore stop */
const ranges = [];
const negs = [];
let i = pos + 1;
let sawStart = false;
let uflag = false;
let escaping = false;
let negate = false;
let endPos = pos;
let rangeStart = '';
WHILE: while (i < glob.length) {
const c = glob.charAt(i);
if ((c === '!' || c === '^') && i === pos + 1) {
negate = true;
i++;
continue;
}
if (c === ']' && sawStart && !escaping) {
endPos = i + 1;
break;
}
sawStart = true;
if (c === '\\') {
if (!escaping) {
escaping = true;
i++;
continue;
}
// escaped \ char, fall through and treat like normal char
}
if (c === '[' && !escaping) {
// either a posix class, a collation equivalent, or just a [
for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {
if (glob.startsWith(cls, i)) {
// invalid, [a-[] is fine, but not [a-[:alpha]]
if (rangeStart) {
return ['$.', false, glob.length - pos, true];
}
i += cls.length;
if (neg)
negs.push(unip);
else
ranges.push(unip);
uflag = uflag || u;
continue WHILE;
}
}
}
// now it's just a normal character, effectively
escaping = false;
if (rangeStart) {
// throw this range away if it's not valid, but others
// can still match.
if (c > rangeStart) {
ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c));
}
else if (c === rangeStart) {
ranges.push(braceEscape(c));
}
rangeStart = '';
i++;
continue;
}
// now might be the start of a range.
// can be either c-d or c-] or c<more...>] or c] at this point
if (glob.startsWith('-]', i + 1)) {
ranges.push(braceEscape(c + '-'));
i += 2;
continue;
}
if (glob.startsWith('-', i + 1)) {
rangeStart = c;
i += 2;
continue;
}
// not the start of a range, just a single character
ranges.push(braceEscape(c));
i++;
}
if (endPos < i) {
// didn't see the end of the class, not a valid class,
// but might still be valid as a literal match.
return ['', false, 0, false];
}
// if we got no ranges and no negates, then we have a range that
// cannot possibly match anything, and that poisons the whole glob
if (!ranges.length && !negs.length) {
return ['$.', false, glob.length - pos, true];
}
// if we got one positive range, and it's a single character, then that's
// not actually a magic pattern, it's just that one literal character.
// we should not treat that as "magic", we should just return the literal
// character. [_] is a perfectly valid way to escape glob magic chars.
if (negs.length === 0 &&
ranges.length === 1 &&
/^\\?.$/.test(ranges[0]) &&
!negate) {
const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0];
return [regexpEscape(r), false, endPos - pos, false];
}
const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']';
const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']';
const comb = ranges.length && negs.length
? '(' + sranges + '|' + snegs + ')'
: ranges.length
? sranges
: snegs;
return [comb, uflag, endPos - pos, true];
};
//# sourceMappingURL=brace-expressions.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,12 @@
import { MinimatchOptions } from './index.js';
/**
* Escape all magic characters in a glob pattern.
*
* If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape}
* option is used, then characters are escaped by wrapping in `[]`, because
* a magic character wrapped in a character class can only be satisfied by
* that exact character. In this mode, `\` is _not_ escaped, because it is
* not interpreted as a magic character, but instead as a path separator.
*/
export declare const escape: (s: string, { windowsPathsNoEscape, }?: Pick<MinimatchOptions, "windowsPathsNoEscape">) => string;
//# sourceMappingURL=escape.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"escape.d.ts","sourceRoot":"","sources":["../../src/escape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM,GACjB,GAAG,MAAM,EACT,4BAEG,IAAI,CAAC,gBAAgB,EAAE,sBAAsB,CAAM,WAQvD,CAAA"}
@@ -0,0 +1,18 @@
/**
* Escape all magic characters in a glob pattern.
*
* If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape}
* option is used, then characters are escaped by wrapping in `[]`, because
* a magic character wrapped in a character class can only be satisfied by
* that exact character. In this mode, `\` is _not_ escaped, because it is
* not interpreted as a magic character, but instead as a path separator.
*/
export const escape = (s, { windowsPathsNoEscape = false, } = {}) => {
// don't need to escape +@! because we escape the parens
// that make those magic, and escaping ! as [!] isn't valid,
// because [!]] is a valid glob class meaning not ']'.
return windowsPathsNoEscape
? s.replace(/[?*()[\]]/g, '[$&]')
: s.replace(/[?*()[\]\\]/g, '\\$&');
};
//# sourceMappingURL=escape.js.map
@@ -0,0 +1 @@
{"version":3,"file":"escape.js","sourceRoot":"","sources":["../../src/escape.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CACpB,CAAS,EACT,EACE,oBAAoB,GAAG,KAAK,MACsB,EAAE,EACtD,EAAE;IACF,wDAAwD;IACxD,4DAA4D;IAC5D,sDAAsD;IACtD,OAAO,oBAAoB;QACzB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC;QACjC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;AACvC,CAAC,CAAA","sourcesContent":["import { MinimatchOptions } from './index.js'\n/**\n * Escape all magic characters in a glob pattern.\n *\n * If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape}\n * option is used, then characters are escaped by wrapping in `[]`, because\n * a magic character wrapped in a character class can only be satisfied by\n * that exact character. In this mode, `\\` is _not_ escaped, because it is\n * not interpreted as a magic character, but instead as a path separator.\n */\nexport const escape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape'> = {}\n) => {\n // don't need to escape +@! because we escape the parens\n // that make those magic, and escaping ! as [!] isn't valid,\n // because [!]] is a valid glob class meaning not ']'.\n return windowsPathsNoEscape\n ? s.replace(/[?*()[\\]]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\]/g, '\\\\$&')\n}\n"]}
@@ -0,0 +1,98 @@
import { AST } from './ast.js';
type Platform = 'aix' | 'android' | 'darwin' | 'freebsd' | 'haiku' | 'linux' | 'openbsd' | 'sunos' | 'win32' | 'cygwin' | 'netbsd';
export interface MinimatchOptions {
nobrace?: boolean;
nocomment?: boolean;
nonegate?: boolean;
debug?: boolean;
noglobstar?: boolean;
noext?: boolean;
nonull?: boolean;
windowsPathsNoEscape?: boolean;
allowWindowsEscape?: boolean;
partial?: boolean;
dot?: boolean;
nocase?: boolean;
nocaseMagicOnly?: boolean;
magicalBraces?: boolean;
matchBase?: boolean;
flipNegate?: boolean;
preserveMultipleSlashes?: boolean;
optimizationLevel?: number;
platform?: Platform;
windowsNoMagicRoot?: boolean;
maxGlobstarRecursion?: number;
maxExtglobRecursion?: number;
}
export declare const minimatch: {
(p: string, pattern: string, options?: MinimatchOptions): boolean;
sep: Sep;
GLOBSTAR: typeof GLOBSTAR;
filter: (pattern: string, options?: MinimatchOptions) => (p: string) => boolean;
defaults: (def: MinimatchOptions) => typeof minimatch;
braceExpand: (pattern: string, options?: MinimatchOptions) => string[];
makeRe: (pattern: string, options?: MinimatchOptions) => false | MMRegExp;
match: (list: string[], pattern: string, options?: MinimatchOptions) => string[];
AST: typeof AST;
Minimatch: typeof Minimatch;
escape: (s: string, { windowsPathsNoEscape, }?: Pick<MinimatchOptions, "windowsPathsNoEscape">) => string;
unescape: (s: string, { windowsPathsNoEscape, }?: Pick<MinimatchOptions, "windowsPathsNoEscape">) => string;
};
type Sep = '\\' | '/';
export declare const sep: Sep;
export declare const GLOBSTAR: unique symbol;
export declare const filter: (pattern: string, options?: MinimatchOptions) => (p: string) => boolean;
export declare const defaults: (def: MinimatchOptions) => typeof minimatch;
export declare const braceExpand: (pattern: string, options?: MinimatchOptions) => string[];
export declare const makeRe: (pattern: string, options?: MinimatchOptions) => false | MMRegExp;
export declare const match: (list: string[], pattern: string, options?: MinimatchOptions) => string[];
export type MMRegExp = RegExp & {
_src?: string;
_glob?: string;
};
export type ParseReturnFiltered = string | MMRegExp | typeof GLOBSTAR;
export type ParseReturn = ParseReturnFiltered | false;
export declare class Minimatch {
#private;
options: MinimatchOptions;
set: ParseReturnFiltered[][];
pattern: string;
windowsPathsNoEscape: boolean;
nonegate: boolean;
negate: boolean;
comment: boolean;
empty: boolean;
preserveMultipleSlashes: boolean;
partial: boolean;
globSet: string[];
globParts: string[][];
nocase: boolean;
isWindows: boolean;
platform: Platform;
windowsNoMagicRoot: boolean;
maxGlobstarRecursion: number;
regexp: false | null | MMRegExp;
constructor(pattern: string, options?: MinimatchOptions);
hasMagic(): boolean;
debug(..._: any[]): void;
make(): void;
preprocess(globParts: string[][]): string[][];
adjascentGlobstarOptimize(globParts: string[][]): string[][];
levelOneOptimize(globParts: string[][]): string[][];
levelTwoFileOptimize(parts: string | string[]): string[];
firstPhasePreProcess(globParts: string[][]): string[][];
secondPhasePreProcess(globParts: string[][]): string[][];
partsMatch(a: string[], b: string[], emptyGSMatch?: boolean): false | string[];
parseNegate(): void;
matchOne(file: string[], pattern: ParseReturn[], partial?: boolean): boolean;
braceExpand(): string[];
parse(pattern: string): ParseReturn;
makeRe(): false | MMRegExp;
slashSplit(p: string): string[];
match(f: string, partial?: boolean): boolean;
static defaults(def: MinimatchOptions): typeof Minimatch;
}
export { AST } from './ast.js';
export { escape } from './escape.js';
export { unescape } from './unescape.js';
//# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAe,MAAM,UAAU,CAAA;AAI3C,KAAK,QAAQ,GACT,KAAK,GACL,SAAS,GACT,QAAQ,GACR,SAAS,GACT,OAAO,GACP,OAAO,GACP,SAAS,GACT,OAAO,GACP,OAAO,GACP,QAAQ,GACR,QAAQ,CAAA;AAEZ,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,eAAO,MAAM,SAAS;QACjB,MAAM,WACA,MAAM,YACN,gBAAgB;;;sBAuGf,MAAM,YAAW,gBAAgB,MAC1C,GAAG,MAAM;oBAOkB,gBAAgB,KAAG,OAAO,SAAS;2BA6EtD,MAAM,YACN,gBAAgB;sBA2BK,MAAM,YAAW,gBAAgB;kBAKzD,MAAM,EAAE,WACL,MAAM,YACN,gBAAgB;;;;;CArN1B,CAAA;AA+DD,KAAK,GAAG,GAAG,IAAI,GAAG,GAAG,CAAA;AAOrB,eAAO,MAAM,GAAG,KAAgE,CAAA;AAGhF,eAAO,MAAM,QAAQ,eAAwB,CAAA;AAmB7C,eAAO,MAAM,MAAM,GAChB,SAAS,MAAM,EAAE,UAAS,gBAAqB,MAC/C,GAAG,MAAM,YACsB,CAAA;AAMlC,eAAO,MAAM,QAAQ,GAAI,KAAK,gBAAgB,KAAG,OAAO,SA+DvD,CAAA;AAaD,eAAO,MAAM,WAAW,GACtB,SAAS,MAAM,EACf,UAAS,gBAAqB,aAY/B,CAAA;AAeD,eAAO,MAAM,MAAM,GAAI,SAAS,MAAM,EAAE,UAAS,gBAAqB,qBAC5B,CAAA;AAG1C,eAAO,MAAM,KAAK,GAChB,MAAM,MAAM,EAAE,EACd,SAAS,MAAM,EACf,UAAS,gBAAqB,aAQ/B,CAAA;AAQD,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,QAAQ,CAAA;AACrE,MAAM,MAAM,WAAW,GAAG,mBAAmB,GAAG,KAAK,CAAA;AAErD,qBAAa,SAAS;;IACpB,OAAO,EAAE,gBAAgB,CAAA;IACzB,GAAG,EAAE,mBAAmB,EAAE,EAAE,CAAA;IAC5B,OAAO,EAAE,MAAM,CAAA;IAEf,oBAAoB,EAAE,OAAO,CAAA;IAC7B,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;IACd,uBAAuB,EAAE,OAAO,CAAA;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,MAAM,EAAE,EAAE,CAAA;IACrB,MAAM,EAAE,OAAO,CAAA;IAEf,SAAS,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,QAAQ,CAAA;IAClB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,oBAAoB,EAAE,MAAM,CAAA;IAE5B,MAAM,EAAE,KAAK,GAAG,IAAI,GAAG,QAAQ,CAAA;gBACnB,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;IAmC3D,QAAQ,IAAI,OAAO;IAYnB,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE;IAEjB,IAAI;IA0FJ,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE;IA8BhC,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE;IAiB/C,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE;IAoBtC,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IA6D7C,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE;IA0F1C,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,EAAE;IAkBxD,UAAU,CACR,CAAC,EAAE,MAAM,EAAE,EACX,CAAC,EAAE,MAAM,EAAE,EACX,YAAY,GAAE,OAAe,GAC5B,KAAK,GAAG,MAAM,EAAE;IA+CnB,WAAW;IAqBX,QAAQ,CACN,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,WAAW,EAAE,EACtB,OAAO,GAAE,OAAe;IAuP1B,WAAW,IAAI,MAAM,EAAE;IAIvB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW;IAiDnC,MAAM;IAsFN,UAAU,CAAC,CAAC,EAAE,MAAM;IAepB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,UAAe;IAiEvC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,gBAAgB;CAGtC;AAED,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA"}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
{
"type": "module"
}
@@ -0,0 +1,17 @@
import { MinimatchOptions } from './index.js';
/**
* Un-escape a string that has been escaped with {@link escape}.
*
* If the {@link windowsPathsNoEscape} option is used, then square-brace
* escapes are removed, but not backslash escapes. For example, it will turn
* the string `'[*]'` into `*`, but it will not turn `'\\*'` into `'*'`,
* becuase `\` is a path separator in `windowsPathsNoEscape` mode.
*
* When `windowsPathsNoEscape` is not set, then both brace escapes and
* backslash escapes are removed.
*
* Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped
* or unescaped.
*/
export declare const unescape: (s: string, { windowsPathsNoEscape, }?: Pick<MinimatchOptions, "windowsPathsNoEscape">) => string;
//# sourceMappingURL=unescape.d.ts.map
@@ -0,0 +1 @@
{"version":3,"file":"unescape.d.ts","sourceRoot":"","sources":["../../src/unescape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,QAAQ,GACnB,GAAG,MAAM,EACT,4BAEG,IAAI,CAAC,gBAAgB,EAAE,sBAAsB,CAAM,WAKvD,CAAA"}
@@ -0,0 +1,20 @@
/**
* Un-escape a string that has been escaped with {@link escape}.
*
* If the {@link windowsPathsNoEscape} option is used, then square-brace
* escapes are removed, but not backslash escapes. For example, it will turn
* the string `'[*]'` into `*`, but it will not turn `'\\*'` into `'*'`,
* becuase `\` is a path separator in `windowsPathsNoEscape` mode.
*
* When `windowsPathsNoEscape` is not set, then both brace escapes and
* backslash escapes are removed.
*
* Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped
* or unescaped.
*/
export const unescape = (s, { windowsPathsNoEscape = false, } = {}) => {
return windowsPathsNoEscape
? s.replace(/\[([^\/\\])\]/g, '$1')
: s.replace(/((?!\\).|^)\[([^\/\\])\]/g, '$1$2').replace(/\\([^\/])/g, '$1');
};
//# sourceMappingURL=unescape.js.map
@@ -0,0 +1 @@
{"version":3,"file":"unescape.js","sourceRoot":"","sources":["../../src/unescape.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,CAAS,EACT,EACE,oBAAoB,GAAG,KAAK,MACsB,EAAE,EACtD,EAAE;IACF,OAAO,oBAAoB;QACzB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC;QACnC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,2BAA2B,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;AAChF,CAAC,CAAA","sourcesContent":["import { MinimatchOptions } from './index.js'\n/**\n * Un-escape a string that has been escaped with {@link escape}.\n *\n * If the {@link windowsPathsNoEscape} option is used, then square-brace\n * escapes are removed, but not backslash escapes. For example, it will turn\n * the string `'[*]'` into `*`, but it will not turn `'\\\\*'` into `'*'`,\n * becuase `\\` is a path separator in `windowsPathsNoEscape` mode.\n *\n * When `windowsPathsNoEscape` is not set, then both brace escapes and\n * backslash escapes are removed.\n *\n * Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped\n * or unescaped.\n */\nexport const unescape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape'> = {}\n) => {\n return windowsPathsNoEscape\n ? s.replace(/\\[([^\\/\\\\])\\]/g, '$1')\n : s.replace(/((?!\\\\).|^)\\[([^\\/\\\\])\\]/g, '$1$2').replace(/\\\\([^\\/])/g, '$1')\n}\n"]}
+82
View File
@@ -0,0 +1,82 @@
{
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
"name": "minimatch",
"description": "a glob matcher in javascript",
"version": "9.0.9",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/minimatch.git"
},
"main": "./dist/commonjs/index.js",
"types": "./dist/commonjs/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/commonjs/index.d.ts",
"default": "./dist/commonjs/index.js"
}
}
},
"files": [
"dist"
],
"scripts": {
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"prepare": "tshy",
"pretest": "npm run prepare",
"presnap": "npm run prepare",
"test": "tap",
"snap": "tap",
"format": "prettier --write . --loglevel warn",
"benchmark": "node benchmark/index.js",
"typedoc": "typedoc --tsconfig tsconfig-esm.json ./src/*.ts"
},
"prettier": {
"semi": false,
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"jsxSingleQuote": false,
"bracketSameLine": true,
"arrowParens": "avoid",
"endOfLine": "lf"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"dependencies": {
"brace-expansion": "^2.0.2"
},
"devDependencies": {
"@types/brace-expansion": "^1.1.2",
"@types/node": "^25.3.0",
"mkdirp": "^3.0.1",
"prettier": "^3.8.1",
"tap": "^21.6.1",
"tshy": "^3.3.2",
"typescript": "^5.5.3"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"license": "ISC",
"tshy": {
"exports": {
"./package.json": "./package.json",
".": "./src/index.ts"
}
},
"type": "module",
"publishConfig": {
"tag": "legacy-v9"
},
"module": "./dist/esm/index.js"
}
+15
View File
@@ -0,0 +1,15 @@
import { FileRangeCapabilities, MirrorBehaviorCapabilities } from '@volar/language-core';
import * as SourceMaps from '@volar/source-map';
import type * as ts from 'typescript/lib/tsserverlibrary';
import type * as templateGen from '../generators/template';
import type { ScriptRanges } from '../parsers/scriptRanges';
import type { ScriptSetupRanges } from '../parsers/scriptSetupRanges';
import type { VueCompilerOptions } from '../types';
import { Sfc } from '../types';
export declare function generate(ts: typeof import('typescript/lib/tsserverlibrary'), fileName: string, script: Sfc['script'], scriptSetup: Sfc['scriptSetup'], styles: Sfc['styles'], // TODO: computed it
lang: string, scriptRanges: ScriptRanges | undefined, scriptSetupRanges: ScriptSetupRanges | undefined, htmlGen: ReturnType<typeof templateGen['generate']> | undefined, compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions, codegenStack: boolean): {
codes: SourceMaps.Segment<FileRangeCapabilities>[];
codeStacks: SourceMaps.StackNode[];
mirrorBehaviorMappings: SourceMaps.Mapping<[MirrorBehaviorCapabilities, MirrorBehaviorCapabilities]>[];
};
//# sourceMappingURL=script.d.ts.map
+870
View File
@@ -0,0 +1,870 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generate = void 0;
const language_core_1 = require("@volar/language-core");
const source_map_1 = require("@volar/source-map");
const muggle = require("muggle-string");
const path = require("path-browserify");
const shared_1 = require("../utils/shared");
const transform_1 = require("../utils/transform");
function generate(ts, fileName, script, scriptSetup, styles, // TODO: computed it
lang, scriptRanges, scriptSetupRanges, htmlGen, compilerOptions, vueCompilerOptions, codegenStack) {
const [codes, codeStacks] = codegenStack ? muggle.track([]) : [[], []];
const mirrorBehaviorMappings = [];
//#region monkey fix: https://github.com/vuejs/language-tools/pull/2113
if (!script && !scriptSetup) {
scriptSetup = {
content: '',
lang: 'ts',
name: '',
start: 0,
end: 0,
startTagEnd: 0,
endTagStart: 0,
generic: undefined,
genericOffset: 0,
attrs: {},
ast: ts.createSourceFile('', '', ts.ScriptTarget.Latest, false, ts.ScriptKind.TS),
};
scriptSetupRanges = {
bindings: [],
props: {},
emits: {},
expose: {},
slots: {},
defineProp: [],
importSectionEndOffset: 0,
leadingCommentEndOffset: 0,
};
}
//#endregion
const bindingNames = new Set([
...scriptRanges?.bindings.map(range => script.content.substring(range.start, range.end)) ?? [],
...scriptSetupRanges?.bindings.map(range => scriptSetup.content.substring(range.start, range.end)) ?? [],
]);
const bypassDefineComponent = lang === 'js' || lang === 'jsx';
const usedHelperTypes = {
DefinePropsToOptions: false,
MergePropDefaults: false,
WithTemplateSlots: false,
PropsChildren: false,
};
codes.push(`/* __placeholder__ */\n`);
let generatedTemplate = false;
generateSrc();
generateScriptSetupImports();
generateScriptContentBeforeExportDefault();
generateScriptSetupAndTemplate();
generateHelperTypes();
generateScriptContentAfterExportDefault();
if (!generatedTemplate) {
generateTemplate(false);
}
if (scriptSetup) {
// for code action edits
codes.push([
'',
'scriptSetup',
scriptSetup.content.length,
{},
]);
}
return {
codes,
codeStacks,
mirrorBehaviorMappings,
};
function generateHelperTypes() {
if (usedHelperTypes.DefinePropsToOptions) {
if (compilerOptions.exactOptionalPropertyTypes) {
codes.push(`type __VLS_TypePropsToRuntimeProps<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? { type: import('${vueCompilerOptions.lib}').PropType<T[K]> } : { type: import('${vueCompilerOptions.lib}').PropType<T[K]>, required: true } };\n`);
}
else {
codes.push(`type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;\n`);
codes.push(`type __VLS_TypePropsToRuntimeProps<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? { type: import('${vueCompilerOptions.lib}').PropType<__VLS_NonUndefinedable<T[K]>> } : { type: import('${vueCompilerOptions.lib}').PropType<T[K]>, required: true } };\n`);
}
}
if (usedHelperTypes.MergePropDefaults) {
codes.push(`type __VLS_WithDefaults<P, D> = {
// use 'keyof Pick<P, keyof P>' instead of 'keyof P' to keep props jsdoc
[K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
default: D[K]
}> : P[K]
};\n`);
codes.push(`type __VLS_Prettify<T> = { [K in keyof T]: T[K]; } & {};\n`);
}
if (usedHelperTypes.WithTemplateSlots) {
codes.push(`type __VLS_WithTemplateSlots<T, S> = T & { new(): {\n`, `${(0, shared_1.getSlotsPropertyName)(vueCompilerOptions.target)}: S;\n`);
if (vueCompilerOptions.jsxSlots) {
usedHelperTypes.PropsChildren = true;
codes.push(`$props: __VLS_PropsChildren<S>;\n`);
}
codes.push(`} };\n`);
}
if (usedHelperTypes.PropsChildren) {
codes.push(`type __VLS_PropsChildren<S> = { [K in keyof (boolean extends (JSX.ElementChildrenAttribute extends never ? true : false) ? never : JSX.ElementChildrenAttribute)]?: S; };\n`);
}
}
function generateSrc() {
if (!script?.src)
return;
let src = script.src;
if (src.endsWith('.d.ts'))
src = src.substring(0, src.length - '.d.ts'.length);
else if (src.endsWith('.ts'))
src = src.substring(0, src.length - '.ts'.length);
else if (src.endsWith('.tsx'))
src = src.substring(0, src.length - '.tsx'.length) + '.jsx';
if (!src.endsWith('.js') && !src.endsWith('.jsx'))
src = src + '.js';
codes.push(`export * from `);
codes.push([
`'${src}'`,
'script',
[script.srcOffset - 1, script.srcOffset + script.src.length + 1],
{
...language_core_1.FileRangeCapabilities.full,
rename: src === script.src ? true : {
normalize: undefined,
apply(newName) {
if (newName.endsWith('.jsx')
|| newName.endsWith('.js')) {
newName = newName.split('.').slice(0, -1).join('.');
}
if (script?.src?.endsWith('.d.ts')) {
newName = newName + '.d.ts';
}
else if (script?.src?.endsWith('.ts')) {
newName = newName + '.ts';
}
else if (script?.src?.endsWith('.tsx')) {
newName = newName + '.tsx';
}
return newName;
},
},
},
]);
codes.push(`;\n`);
codes.push(`export { default } from '${src}';\n`);
}
function generateScriptContentBeforeExportDefault() {
if (!script)
return;
if (!!scriptSetup && scriptRanges?.exportDefault) {
addVirtualCode('script', 0, scriptRanges.exportDefault.expression.start);
}
else {
let isExportRawObject = false;
if (scriptRanges?.exportDefault) {
isExportRawObject = script.content.substring(scriptRanges.exportDefault.expression.start, scriptRanges.exportDefault.expression.end).startsWith('{');
}
if (isExportRawObject && vueCompilerOptions.optionsWrapper.length === 2 && scriptRanges?.exportDefault) {
addVirtualCode('script', 0, scriptRanges.exportDefault.expression.start);
codes.push(vueCompilerOptions.optionsWrapper[0]);
{
codes.push(['', 'script', scriptRanges.exportDefault.expression.start, {
__hint: {
setting: 'vue.inlayHints.optionsWrapper',
label: vueCompilerOptions.optionsWrapper[0],
tooltip: [
'This is virtual code that is automatically wrapped for type support, it does not affect your runtime behavior, you can customize it via `vueCompilerOptions.optionsWrapper` option in tsconfig / jsconfig.',
'To hide it, you can set `"vue.inlayHints.optionsWrapper": false` in IDE settings.',
].join('\n\n'),
}
}]);
addVirtualCode('script', scriptRanges.exportDefault.expression.start, scriptRanges.exportDefault.expression.end);
codes.push(['', 'script', scriptRanges.exportDefault.expression.end, {
__hint: {
setting: 'vue.inlayHints.optionsWrapper',
label: vueCompilerOptions.optionsWrapper[1],
tooltip: '',
}
}]);
}
codes.push(vueCompilerOptions.optionsWrapper[1]);
addVirtualCode('script', scriptRanges.exportDefault.expression.end, script.content.length);
}
else {
addVirtualCode('script', 0, script.content.length);
}
}
}
function generateScriptContentAfterExportDefault() {
if (!script)
return;
if (!!scriptSetup && scriptRanges?.exportDefault) {
addVirtualCode('script', scriptRanges.exportDefault.expression.end, script.content.length);
}
}
function generateScriptSetupImports() {
if (!scriptSetup)
return;
if (!scriptSetupRanges)
return;
codes.push([
scriptSetup.content.substring(0, Math.max(scriptSetupRanges.importSectionEndOffset, scriptSetupRanges.leadingCommentEndOffset)) + '\n',
'scriptSetup',
0,
language_core_1.FileRangeCapabilities.full,
]);
}
function generateScriptSetupAndTemplate() {
if (!scriptSetup || !scriptSetupRanges) {
return;
}
const definePropMirrors = {};
let scriptSetupGeneratedOffset;
if (scriptSetup.generic) {
if (!scriptRanges?.exportDefault) {
codes.push('export default ');
}
codes.push(`(<`);
codes.push([
scriptSetup.generic,
scriptSetup.name,
scriptSetup.genericOffset,
language_core_1.FileRangeCapabilities.full,
]);
if (!scriptSetup.generic.endsWith(',')) {
codes.push(`,`);
}
codes.push(`>`);
codes.push('(\n');
codes.push(`__VLS_props: Awaited<typeof __VLS_setup>['props'],\n`);
codes.push(`__VLS_ctx?: __VLS_Prettify<Pick<Awaited<typeof __VLS_setup>, 'attrs' | 'emit' | 'slots'>>,\n`); // use __VLS_Prettify for less dts code
codes.push(`__VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>['expose'],\n`);
codes.push('__VLS_setup = (async () => {\n');
scriptSetupGeneratedOffset = generateSetupFunction(true, 'none', definePropMirrors);
//#region props
codes.push(`const __VLS_fnComponent = `);
codes.push(`(await import('${vueCompilerOptions.lib}')).defineComponent({\n`);
if (scriptSetupRanges.props.define?.arg) {
codes.push(`props: `);
addExtraReferenceVirtualCode('scriptSetup', scriptSetupRanges.props.define.arg.start, scriptSetupRanges.props.define.arg.end);
codes.push(`,\n`);
}
if (scriptSetupRanges.emits.define) {
codes.push(`emits: ({} as __VLS_NormalizeEmits<typeof `, scriptSetupRanges.emits.name ?? '__VLS_emit', `>),\n`);
}
codes.push(`});\n`);
if (scriptSetupRanges.defineProp.length) {
codes.push(`const __VLS_defaults = {\n`);
for (const defineProp of scriptSetupRanges.defineProp) {
if (defineProp.defaultValue) {
if (defineProp.name) {
codes.push(scriptSetup.content.substring(defineProp.name.start, defineProp.name.end));
}
else {
codes.push('modelValue');
}
codes.push(`: `);
codes.push(scriptSetup.content.substring(defineProp.defaultValue.start, defineProp.defaultValue.end));
codes.push(`,\n`);
}
}
codes.push(`};\n`);
}
codes.push(`let __VLS_fnPropsTypeOnly!: {}`); // TODO: reuse __VLS_fnPropsTypeOnly even without generic, and remove __VLS_propsOption_defineProp
if (scriptSetupRanges.props.define?.typeArg) {
codes.push(` & `);
addVirtualCode('scriptSetup', scriptSetupRanges.props.define.typeArg.start, scriptSetupRanges.props.define.typeArg.end);
}
if (scriptSetupRanges.defineProp.length) {
codes.push(` & {\n`);
for (const defineProp of scriptSetupRanges.defineProp) {
let propName = 'modelValue';
if (defineProp.name) {
propName = scriptSetup.content.substring(defineProp.name.start, defineProp.name.end);
const propMirrorStart = muggle.getLength(codes);
definePropMirrors[propName] = [propMirrorStart, propMirrorStart + propName.length];
}
codes.push(`${propName}${defineProp.required ? '' : '?'}: `);
if (defineProp.type) {
codes.push(scriptSetup.content.substring(defineProp.type.start, defineProp.type.end));
}
else if (defineProp.defaultValue) {
codes.push(`typeof __VLS_defaults['`);
codes.push(propName);
codes.push(`']`);
}
else {
codes.push(`any`);
}
codes.push(',\n');
}
codes.push(`}`);
}
codes.push(`;\n`);
codes.push(`let __VLS_fnPropsDefineComponent!: InstanceType<typeof __VLS_fnComponent>['$props']`);
codes.push(`;\n`);
codes.push(`let __VLS_fnPropsSlots!: `);
if (scriptSetupRanges.slots.define && vueCompilerOptions.jsxSlots) {
usedHelperTypes.PropsChildren = true;
codes.push(`__VLS_PropsChildren<typeof __VLS_slots>`);
}
else {
codes.push(`{}`);
}
codes.push(`;\n`);
codes.push(`let __VLS_defaultProps!: `, `import('${vueCompilerOptions.lib}').VNodeProps`, `& import('${vueCompilerOptions.lib}').AllowedComponentProps`, `& import('${vueCompilerOptions.lib}').ComponentCustomProps`, `;\n`);
//#endregion
codes.push('return {} as {\n');
codes.push(`props: __VLS_Prettify<__VLS_OmitKeepDiscriminatedUnion<typeof __VLS_fnPropsDefineComponent & typeof __VLS_fnPropsTypeOnly, keyof typeof __VLS_defaultProps>> & typeof __VLS_fnPropsSlots & typeof __VLS_defaultProps,\n`);
codes.push(`expose(exposed: import('${vueCompilerOptions.lib}').ShallowUnwrapRef<${scriptSetupRanges.expose.define ? 'typeof __VLS_exposed' : '{}'}>): void,\n`);
codes.push('attrs: any,\n');
codes.push('slots: ReturnType<typeof __VLS_template>,\n');
codes.push(`emit: typeof ${scriptSetupRanges.emits.name ?? '__VLS_emit'},\n`);
codes.push('};\n');
codes.push('})(),\n');
codes.push(`) => ({} as import('${vueCompilerOptions.lib}').VNode & { __ctx?: Awaited<typeof __VLS_setup> }))`);
}
else if (!script) {
// no script block, generate script setup code at root
scriptSetupGeneratedOffset = generateSetupFunction(false, 'export', definePropMirrors);
}
else {
if (!scriptRanges?.exportDefault) {
codes.push('export default ');
}
codes.push('await (async () => {\n');
scriptSetupGeneratedOffset = generateSetupFunction(false, 'return', definePropMirrors);
codes.push(`})()`);
}
if (scriptSetupGeneratedOffset !== undefined) {
for (const defineProp of scriptSetupRanges.defineProp) {
if (!defineProp.name) {
continue;
}
const propName = scriptSetup.content.substring(defineProp.name.start, defineProp.name.end);
const propMirror = definePropMirrors[propName];
if (propMirror) {
mirrorBehaviorMappings.push({
sourceRange: [defineProp.name.start + scriptSetupGeneratedOffset, defineProp.name.end + scriptSetupGeneratedOffset],
generatedRange: propMirror,
data: [
language_core_1.MirrorBehaviorCapabilities.full,
language_core_1.MirrorBehaviorCapabilities.full,
],
});
}
}
}
}
function generateSetupFunction(functional, mode, definePropMirrors) {
if (!scriptSetupRanges || !scriptSetup) {
return;
}
const definePropProposalA = scriptSetup.content.trimStart().startsWith('// @experimentalDefinePropProposal=kevinEdition') || vueCompilerOptions.experimentalDefinePropProposal === 'kevinEdition';
const definePropProposalB = scriptSetup.content.trimStart().startsWith('// @experimentalDefinePropProposal=johnsonEdition') || vueCompilerOptions.experimentalDefinePropProposal === 'johnsonEdition';
if (vueCompilerOptions.target >= 3.3) {
codes.push('const { ');
for (const macro of Object.keys(vueCompilerOptions.macros)) {
if (!bindingNames.has(macro)) {
codes.push(macro, ', ');
}
}
codes.push(`} = await import('${vueCompilerOptions.lib}');\n`);
}
if (definePropProposalA) {
codes.push(`
declare function defineProp<T>(name: string, options: { required: true } & Record<string, unknown>): import('${vueCompilerOptions.lib}').ComputedRef<T>;
declare function defineProp<T>(name: string, options: { default: any } & Record<string, unknown>): import('${vueCompilerOptions.lib}').ComputedRef<T>;
declare function defineProp<T>(name?: string, options?: any): import('${vueCompilerOptions.lib}').ComputedRef<T | undefined>;
`.trim() + '\n');
}
if (definePropProposalB) {
codes.push(`
declare function defineProp<T>(value: T | (() => T), required?: boolean, rest?: any): import('${vueCompilerOptions.lib}').ComputedRef<T>;
declare function defineProp<T>(value: T | (() => T) | undefined, required: true, rest?: any): import('${vueCompilerOptions.lib}').ComputedRef<T>;
declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?: any): import('${vueCompilerOptions.lib}').ComputedRef<T | undefined>;
`.trim() + '\n');
}
const scriptSetupGeneratedOffset = muggle.getLength(codes) - scriptSetupRanges.importSectionEndOffset;
let setupCodeModifies = [];
if (scriptSetupRanges.props.define && !scriptSetupRanges.props.name) {
const range = scriptSetupRanges.props.withDefaults ?? scriptSetupRanges.props.define;
const statement = scriptSetupRanges.props.define.statement;
if (statement.start === range.start && statement.end === range.end) {
setupCodeModifies.push([() => codes.push(`const __VLS_props = `), range.start, range.start]);
}
else {
setupCodeModifies.push([() => {
codes.push(`const __VLS_props = `);
addVirtualCode('scriptSetup', range.start, range.end);
codes.push(`;\n`);
addVirtualCode('scriptSetup', statement.start, range.start);
codes.push(`__VLS_props`);
}, statement.start, range.end]);
}
}
if (scriptSetupRanges.slots.define && !scriptSetupRanges.slots.name) {
setupCodeModifies.push([() => codes.push(`const __VLS_slots = `), scriptSetupRanges.slots.define.start, scriptSetupRanges.slots.define.start]);
}
if (scriptSetupRanges.emits.define && !scriptSetupRanges.emits.name) {
setupCodeModifies.push([() => codes.push(`const __VLS_emit = `), scriptSetupRanges.emits.define.start, scriptSetupRanges.emits.define.start]);
}
if (scriptSetupRanges.expose.define) {
setupCodeModifies.push([() => {
if (scriptSetupRanges?.expose.define?.typeArg) {
codes.push(`let __VLS_exposed!: `);
addExtraReferenceVirtualCode('scriptSetup', scriptSetupRanges.expose.define.typeArg.start, scriptSetupRanges.expose.define.typeArg.end);
codes.push(`;\n`);
}
else if (scriptSetupRanges?.expose.define?.arg) {
codes.push(`const __VLS_exposed = `);
addExtraReferenceVirtualCode('scriptSetup', scriptSetupRanges.expose.define.arg.start, scriptSetupRanges.expose.define.arg.end);
codes.push(`;\n`);
}
else {
codes.push(`const __VLS_exposed = {};\n`);
}
}, scriptSetupRanges.expose.define.start, scriptSetupRanges.expose.define.start]);
}
setupCodeModifies = setupCodeModifies.sort((a, b) => a[1] - b[1]);
if (setupCodeModifies.length) {
addVirtualCode('scriptSetup', scriptSetupRanges.importSectionEndOffset, setupCodeModifies[0][1]);
while (setupCodeModifies.length) {
const [generate, _, end] = setupCodeModifies.shift();
generate();
if (setupCodeModifies.length) {
const nextStart = setupCodeModifies[0][1];
addVirtualCode('scriptSetup', end, nextStart);
}
else {
addVirtualCode('scriptSetup', end);
}
}
}
else {
addVirtualCode('scriptSetup', scriptSetupRanges.importSectionEndOffset);
}
if (scriptSetupRanges.props.define?.typeArg && scriptSetupRanges.props.withDefaults?.arg) {
// fix https://github.com/vuejs/language-tools/issues/1187
codes.push(`const __VLS_withDefaultsArg = (function <T>(t: T) { return t })(`);
addExtraReferenceVirtualCode('scriptSetup', scriptSetupRanges.props.withDefaults.arg.start, scriptSetupRanges.props.withDefaults.arg.end);
codes.push(`);\n`);
}
if (!functional && scriptSetupRanges.defineProp.length) {
codes.push(`let __VLS_propsOption_defineProp!: {\n`);
for (const defineProp of scriptSetupRanges.defineProp) {
let propName = 'modelValue';
if (defineProp.name && defineProp.nameIsString) {
// renaming support
addExtraReferenceVirtualCode('scriptSetup', defineProp.name.start, defineProp.name.end);
}
else if (defineProp.name) {
propName = scriptSetup.content.substring(defineProp.name.start, defineProp.name.end);
const start = muggle.getLength(codes);
definePropMirrors[propName] = [start, start + propName.length];
codes.push(propName);
}
else {
codes.push(propName);
}
codes.push(`: `);
let type = 'any';
if (!defineProp.nameIsString) {
type = `NonNullable<typeof ${propName}['value']>`;
}
else if (defineProp.type) {
type = scriptSetup.content.substring(defineProp.type.start, defineProp.type.end);
}
if (defineProp.required) {
codes.push(`{ required: true, type: import('${vueCompilerOptions.lib}').PropType<${type}> },\n`);
}
else {
codes.push(`import('${vueCompilerOptions.lib}').PropType<${type}>,\n`);
}
}
codes.push(`};\n`);
}
generateTemplate(functional);
if (mode === 'return' || mode === 'export') {
if (!vueCompilerOptions.skipTemplateCodegen && (htmlGen?.hasSlot || scriptSetupRanges?.slots.define)) {
usedHelperTypes.WithTemplateSlots = true;
codes.push(`const __VLS_component = `);
generateComponent(functional);
codes.push(`;\n`);
codes.push(mode === 'return' ? 'return ' : 'export default ');
codes.push(`{} as __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;\n`);
}
else {
codes.push(mode === 'return' ? 'return ' : 'export default ');
generateComponent(functional);
codes.push(`;\n`);
}
}
return scriptSetupGeneratedOffset;
}
function generateComponent(functional) {
if (!scriptSetupRanges)
return;
if (scriptRanges?.exportDefault && scriptRanges.exportDefault.expression.start !== scriptRanges.exportDefault.args.start) {
// use defineComponent() from user space code if it exist
addVirtualCode('script', scriptRanges.exportDefault.expression.start, scriptRanges.exportDefault.args.start);
codes.push(`{\n`);
}
else {
codes.push(`(await import('${vueCompilerOptions.lib}')).defineComponent({\n`);
}
codes.push(`setup() {\n`);
codes.push(`return {\n`);
generateSetupReturns();
if (scriptSetupRanges.expose.define) {
codes.push(`...__VLS_exposed,\n`);
}
codes.push(`};\n`);
codes.push(`},\n`);
generateComponentOptions(functional);
codes.push(`})`);
}
function generateComponentOptions(functional) {
if (scriptSetupRanges && !bypassDefineComponent) {
const ranges = scriptSetupRanges;
const propsCodegens = [];
if (ranges.props.define?.arg) {
const arg = ranges.props.define.arg;
propsCodegens.push(() => {
addExtraReferenceVirtualCode('scriptSetup', arg.start, arg.end);
});
}
if (ranges.props.define?.typeArg) {
const typeArg = ranges.props.define.typeArg;
propsCodegens.push(() => {
usedHelperTypes.DefinePropsToOptions = true;
codes.push(`{} as `);
if (ranges.props.withDefaults?.arg) {
usedHelperTypes.MergePropDefaults = true;
codes.push(`__VLS_WithDefaults<`);
}
codes.push(`__VLS_TypePropsToRuntimeProps<`);
if (functional) {
codes.push(`typeof __VLS_fnPropsTypeOnly`);
}
else {
addExtraReferenceVirtualCode('scriptSetup', typeArg.start, typeArg.end);
}
codes.push(`>`);
if (ranges.props.withDefaults?.arg) {
codes.push(`, typeof __VLS_withDefaultsArg`);
codes.push(`>`);
}
});
}
if (!functional && ranges.defineProp.length) {
propsCodegens.push(() => {
codes.push(`__VLS_propsOption_defineProp`);
});
}
if (propsCodegens.length === 1) {
codes.push(`props: `);
for (const generate of propsCodegens) {
generate();
}
codes.push(`,\n`);
}
else if (propsCodegens.length >= 2) {
codes.push(`props: {\n`);
for (const generate of propsCodegens) {
codes.push('...');
generate();
codes.push(',\n');
}
codes.push(`},\n`);
}
if (ranges.emits.define) {
codes.push(`emits: ({} as __VLS_NormalizeEmits<typeof `, ranges.emits.name ?? '__VLS_emit', `>),\n`);
}
}
if (scriptRanges?.exportDefault?.args) {
addVirtualCode('script', scriptRanges.exportDefault.args.start + 1, scriptRanges.exportDefault.args.end - 1);
}
}
function generateSetupReturns() {
if (scriptSetupRanges && bypassDefineComponent) {
// fill $props
if (scriptSetupRanges.props.define) {
// NOTE: defineProps is inaccurate for $props
codes.push(`$props: __VLS_makeOptional(${scriptSetupRanges.props.name ?? `__VLS_props`}),\n`);
codes.push(`...${scriptSetupRanges.props.name ?? `__VLS_props`},\n`);
}
// fill $emit
if (scriptSetupRanges.emits.define) {
codes.push(`$emit: ${scriptSetupRanges.emits.name ?? '__VLS_emit'},\n`);
}
}
}
function generateTemplate(functional) {
generatedTemplate = true;
if (!vueCompilerOptions.skipTemplateCodegen) {
generateExportOptions();
generateConstNameOption();
codes.push(`function __VLS_template() {\n`);
const templateGened = generateTemplateContext();
codes.push(`}\n`);
generateComponentForTemplateUsage(functional, templateGened.cssIds);
}
else {
codes.push(`function __VLS_template() {\n`);
const templateUsageVars = [...getTemplateUsageVars()];
codes.push(`// @ts-ignore\n`);
codes.push(`[${templateUsageVars.join(', ')}]\n`);
codes.push(`return {};\n`);
codes.push(`}\n`);
}
}
function generateComponentForTemplateUsage(functional, cssIds) {
if (scriptSetup && scriptSetupRanges) {
codes.push(`const __VLS_internalComponent = (await import('${vueCompilerOptions.lib}')).defineComponent({\n`);
codes.push(`setup() {\n`);
codes.push(`return {\n`);
generateSetupReturns();
// bindings
const templateUsageVars = getTemplateUsageVars();
for (const [content, bindings] of [
[scriptSetup.content, scriptSetupRanges.bindings],
scriptRanges && script
? [script.content, scriptRanges.bindings]
: ['', []],
]) {
for (const expose of bindings) {
const varName = content.substring(expose.start, expose.end);
if (!templateUsageVars.has(varName) && !cssIds.has(varName)) {
continue;
}
const templateStart = (0, source_map_1.getLength)(codes);
codes.push(varName);
const templateEnd = (0, source_map_1.getLength)(codes);
codes.push(`: ${varName} as typeof `);
const scriptStart = (0, source_map_1.getLength)(codes);
codes.push(varName);
const scriptEnd = (0, source_map_1.getLength)(codes);
codes.push(',\n');
mirrorBehaviorMappings.push({
sourceRange: [scriptStart, scriptEnd],
generatedRange: [templateStart, templateEnd],
data: [
language_core_1.MirrorBehaviorCapabilities.full,
language_core_1.MirrorBehaviorCapabilities.full,
],
});
}
}
codes.push(`};\n`); // return {
codes.push(`},\n`); // setup() {
generateComponentOptions(functional);
codes.push(`});\n`); // defineComponent({
}
else if (script) {
codes.push(`let __VLS_internalComponent!: typeof import('./${path.basename(fileName)}')['default'];\n`);
}
else {
codes.push(`const __VLS_internalComponent = (await import('${vueCompilerOptions.lib}')).defineComponent({});\n`);
}
}
function generateExportOptions() {
codes.push(`\n`);
codes.push(`const __VLS_componentsOption = `);
if (script && scriptRanges?.exportDefault?.componentsOption) {
const componentsOption = scriptRanges.exportDefault.componentsOption;
codes.push([
script.content.substring(componentsOption.start, componentsOption.end),
'script',
componentsOption.start,
{
references: true,
rename: true,
},
]);
}
else {
codes.push('{}');
}
codes.push(`;\n`);
}
function generateConstNameOption() {
codes.push(`\n`);
if (script && scriptRanges?.exportDefault?.nameOption) {
const nameOption = scriptRanges.exportDefault.nameOption;
codes.push(`const __VLS_name = `);
codes.push(`${script.content.substring(nameOption.start, nameOption.end)} as const`);
codes.push(`;\n`);
}
else if (scriptSetup) {
codes.push(`let __VLS_name!: '${path.basename(fileName.substring(0, fileName.lastIndexOf('.')))}';\n`);
}
else {
codes.push(`const __VLS_name = undefined;\n`);
}
}
function generateTemplateContext() {
const useGlobalThisTypeInCtx = fileName.endsWith('.html');
codes.push(`let __VLS_ctx!: ${useGlobalThisTypeInCtx ? 'typeof globalThis &' : ''}`);
codes.push(`InstanceType<__VLS_PickNotAny<typeof __VLS_internalComponent, new () => {}>> & {\n`);
/* CSS Module */
for (let i = 0; i < styles.length; i++) {
const style = styles[i];
if (style.module) {
codes.push(`${style.module}: Record<string, string> & __VLS_Prettify<{}`);
for (const className of style.classNames) {
generateCssClassProperty(i, className.text.substring(1), { start: className.offset, end: className.offset + className.text.length }, 'string', false, true);
}
codes.push('>;\n');
}
}
codes.push(`};\n`);
/* Components */
codes.push('/* Components */\n');
codes.push(`let __VLS_otherComponents!: NonNullable<typeof __VLS_internalComponent extends { components: infer C } ? C : {}> & typeof __VLS_componentsOption;\n`);
codes.push(`let __VLS_own!: __VLS_SelfComponent<typeof __VLS_name, typeof __VLS_internalComponent & (new () => { ${(0, shared_1.getSlotsPropertyName)(vueCompilerOptions.target)}: typeof ${scriptSetupRanges?.slots?.name ?? '__VLS_slots'} })>;\n`);
codes.push(`let __VLS_localComponents!: typeof __VLS_otherComponents & Omit<typeof __VLS_own, keyof typeof __VLS_otherComponents>;\n`);
codes.push(`let __VLS_components!: typeof __VLS_localComponents & __VLS_GlobalComponents & typeof __VLS_ctx;\n`); // for html completion, TS references...
/* Style Scoped */
codes.push('/* Style Scoped */\n');
codes.push('type __VLS_StyleScopedClasses = {}');
for (let i = 0; i < styles.length; i++) {
const style = styles[i];
const option = vueCompilerOptions.experimentalResolveStyleCssClasses;
if (option === 'always' || (option === 'scoped' && style.scoped)) {
for (const className of style.classNames) {
generateCssClassProperty(i, className.text.substring(1), { start: className.offset, end: className.offset + className.text.length }, 'boolean', true, !style.module);
}
}
}
codes.push(';\n');
codes.push('let __VLS_styleScopedClasses!: __VLS_StyleScopedClasses | keyof __VLS_StyleScopedClasses | (keyof __VLS_StyleScopedClasses)[];\n');
codes.push(`/* CSS variable injection */\n`);
const cssIds = generateCssVars();
codes.push(`/* CSS variable injection end */\n`);
if (htmlGen) {
muggle.setTracking(false);
for (const s of htmlGen.codes) {
codes.push(s);
}
muggle.setTracking(true);
for (const s of htmlGen.codeStacks) {
codeStacks.push(s);
}
}
if (!htmlGen) {
codes.push(`// no template\n`);
if (!scriptSetupRanges?.slots.define) {
codes.push(`const __VLS_slots = {};\n`);
}
}
codes.push(`return ${scriptSetupRanges?.slots.name ?? '__VLS_slots'};\n`);
return { cssIds };
function generateCssClassProperty(styleIndex, className, classRange, propertyType, optional, referencesCodeLens) {
codes.push(`\n & { `);
codes.push([
'',
'style_' + styleIndex,
classRange.start,
{
references: true,
referencesCodeLens,
},
]);
codes.push(`'`);
codes.push([
className,
'style_' + styleIndex,
[classRange.start, classRange.end],
{
references: true,
rename: {
normalize: normalizeCssRename,
apply: applyCssRename,
},
},
]);
codes.push(`'`);
codes.push([
'',
'style_' + styleIndex,
classRange.end,
{},
]);
codes.push(`${optional ? '?' : ''}: ${propertyType}`);
codes.push(` }`);
}
function generateCssVars() {
const emptyLocalVars = new Map();
const identifiers = new Set();
for (const style of styles) {
for (const cssBind of style.cssVars) {
(0, transform_1.walkInterpolationFragment)(ts, cssBind.text, ts.createSourceFile('/a.txt', cssBind.text, ts.ScriptTarget.ESNext), (frag, fragOffset, onlyForErrorMapping) => {
if (fragOffset === undefined) {
codes.push(frag);
}
else {
codes.push([
frag,
style.name,
cssBind.offset + fragOffset,
onlyForErrorMapping
? { diagnostic: true }
: language_core_1.FileRangeCapabilities.full,
]);
}
}, emptyLocalVars, identifiers, vueCompilerOptions);
codes.push(';\n');
}
}
return identifiers;
}
}
function getTemplateUsageVars() {
const usageVars = new Set();
if (htmlGen) {
// fix import components unused report
for (const varName of bindingNames) {
if (!!htmlGen.tagNames[varName] || !!htmlGen.tagNames[(0, shared_1.hyphenateTag)(varName)]) {
usageVars.add(varName);
}
}
for (const tag of Object.keys(htmlGen.tagNames)) {
if (tag.indexOf('.') >= 0) {
usageVars.add(tag.split('.')[0]);
}
}
for (const _id of htmlGen.accessedGlobalVariables) {
usageVars.add(_id);
}
}
return usageVars;
}
function addVirtualCode(vueTag, start, end) {
muggle.offsetStack();
codes.push([
(vueTag === 'script' ? script : scriptSetup).content.substring(start, end),
vueTag,
start,
language_core_1.FileRangeCapabilities.full, // diagnostic also working for setup() returns unused in template checking
]);
muggle.resetOffsetStack();
}
function addExtraReferenceVirtualCode(vueTag, start, end) {
muggle.offsetStack();
codes.push([
(vueTag === 'script' ? script : scriptSetup).content.substring(start, end),
vueTag,
start,
{
references: true,
definition: true,
rename: true,
},
]);
muggle.resetOffsetStack();
}
}
exports.generate = generate;
function normalizeCssRename(newName) {
return newName.startsWith('.') ? newName.slice(1) : newName;
}
function applyCssRename(newName) {
return '.' + newName;
}
//# sourceMappingURL=script.js.map
+21
View File
@@ -0,0 +1,21 @@
import { FileRangeCapabilities } from '@volar/language-core';
import { Segment } from '@volar/source-map';
import * as CompilerDOM from '@vue/compiler-dom';
import * as muggle from 'muggle-string';
import type * as ts from 'typescript/lib/tsserverlibrary';
import { Sfc, VueCompilerOptions } from '../types';
type Code = Segment<FileRangeCapabilities>;
export declare function generate(ts: typeof import('typescript/lib/tsserverlibrary'), compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions, template: NonNullable<Sfc['template']>, shouldGenerateScopedClasses: boolean, stylesScopedClasses: Set<string>, hasScriptSetupSlots: boolean, slotsAssignName: string | undefined, propsAssignName: string | undefined, codegenStack: boolean): {
codes: Code[];
codeStacks: muggle.StackNode[];
formatCodes: Code[];
formatCodeStacks: muggle.StackNode[];
cssCodes: Code[];
cssCodeStacks: muggle.StackNode[];
tagNames: Record<string, number[]>;
accessedGlobalVariables: Set<string>;
hasSlot: boolean;
};
export declare function walkElementNodes(node: CompilerDOM.RootNode | CompilerDOM.TemplateChildNode, cb: (node: CompilerDOM.ElementNode) => void): void;
export {};
//# sourceMappingURL=template.d.ts.map
File diff suppressed because it is too large Load Diff
+16
View File
@@ -0,0 +1,16 @@
export * from './generators/template';
export * from './languageModule';
export * from './parsers/scriptSetupRanges';
export * from './plugins';
export * from './virtualFile/vueFile';
export * from './types';
export * from './utils/ts';
export * from './utils/parseSfc';
export * as scriptRanges from './parsers/scriptRanges';
export * as sharedTypes from './utils/globalTypes';
export * from './utils/shared';
export { tsCodegen } from './plugins/vue-tsx';
export * from '@volar/language-core';
export * from '@volar/source-map';
export type * as CompilerDOM from '@vue/compiler-dom';
//# sourceMappingURL=index.d.ts.map
+33
View File
@@ -0,0 +1,33 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.tsCodegen = exports.sharedTypes = exports.scriptRanges = void 0;
__exportStar(require("./generators/template"), exports);
__exportStar(require("./languageModule"), exports);
__exportStar(require("./parsers/scriptSetupRanges"), exports);
__exportStar(require("./plugins"), exports);
__exportStar(require("./virtualFile/vueFile"), exports);
__exportStar(require("./types"), exports);
__exportStar(require("./utils/ts"), exports);
__exportStar(require("./utils/parseSfc"), exports);
exports.scriptRanges = require("./parsers/scriptRanges");
exports.sharedTypes = require("./utils/globalTypes");
__exportStar(require("./utils/shared"), exports);
var vue_tsx_1 = require("./plugins/vue-tsx");
Object.defineProperty(exports, "tsCodegen", { enumerable: true, get: function () { return vue_tsx_1.tsCodegen; } });
__exportStar(require("@volar/language-core"), exports);
__exportStar(require("@volar/source-map"), exports);
//# sourceMappingURL=index.js.map
+10
View File
@@ -0,0 +1,10 @@
import type { Language } from '@volar/language-core';
import { VueFile } from './virtualFile/vueFile';
import { VueCompilerOptions } from './types';
import type * as ts from 'typescript/lib/tsserverlibrary';
export declare function createVueLanguage(ts: typeof import('typescript/lib/tsserverlibrary'), compilerOptions?: ts.CompilerOptions, _vueCompilerOptions?: Partial<VueCompilerOptions>, codegenStack?: boolean): Language<VueFile>;
/**
* @deprecated planed to remove in 2.0, please use createVueLanguage instead of
*/
export declare function createLanguages(ts: typeof import('typescript/lib/tsserverlibrary'), compilerOptions?: ts.CompilerOptions, vueCompilerOptions?: Partial<VueCompilerOptions>, codegenStack?: boolean): Language[];
//# sourceMappingURL=languageModule.d.ts.map
+99
View File
@@ -0,0 +1,99 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLanguages = exports.createVueLanguage = void 0;
const path = require("path-browserify");
const plugins_1 = require("./plugins");
const vueFile_1 = require("./virtualFile/vueFile");
const sharedTypes = require("./utils/globalTypes");
const ts_1 = require("./utils/ts");
const fileRegistries = [];
function getVueFileRegistry(key, plugins) {
let fileRegistry = fileRegistries.find(r => r.key === key
&& r.plugins.length === plugins.length
&& r.plugins.every(plugin => plugins.includes(plugin)))?.files;
if (!fileRegistry) {
fileRegistry = new Map();
fileRegistries.push({
key: key,
plugins: plugins,
files: fileRegistry,
});
}
return fileRegistry;
}
function createVueLanguage(ts, compilerOptions = {}, _vueCompilerOptions = {}, codegenStack = false) {
const vueCompilerOptions = (0, ts_1.resolveVueCompilerOptions)(_vueCompilerOptions);
const plugins = (0, plugins_1.getDefaultVueLanguagePlugins)(ts, compilerOptions, vueCompilerOptions, codegenStack);
const keys = [
...Object.keys(vueCompilerOptions)
.sort()
.filter(key => key !== 'plugins')
.map(key => [key, vueCompilerOptions[key]]),
[...new Set(plugins.map(plugin => plugin.requiredCompilerOptions ?? []).flat())]
.sort()
.map(key => [key, compilerOptions[key]]),
];
const fileRegistry = getVueFileRegistry(JSON.stringify(keys), _vueCompilerOptions.plugins ?? []);
const allowLanguageIds = new Set(['vue']);
if (vueCompilerOptions.extensions.includes('.md')) {
allowLanguageIds.add('markdown');
}
if (vueCompilerOptions.extensions.includes('.html')) {
allowLanguageIds.add('html');
}
return {
createVirtualFile(fileName, snapshot, languageId) {
if ((languageId && allowLanguageIds.has(languageId))
|| (!languageId && vueCompilerOptions.extensions.some(ext => fileName.endsWith(ext)))) {
if (fileRegistry.has(fileName)) {
const reusedVueFile = fileRegistry.get(fileName);
reusedVueFile.update(snapshot);
return reusedVueFile;
}
const vueFile = new vueFile_1.VueFile(fileName, snapshot, vueCompilerOptions, plugins, ts, codegenStack);
fileRegistry.set(fileName, vueFile);
return vueFile;
}
},
updateVirtualFile(sourceFile, snapshot) {
sourceFile.update(snapshot);
},
resolveHost(host) {
const sharedTypesSnapshot = ts.ScriptSnapshot.fromString(sharedTypes.getTypesCode(vueCompilerOptions));
const sharedTypesFileName = path.join(host.rootPath, sharedTypes.baseName);
return {
...host,
resolveModuleName(moduleName, impliedNodeFormat) {
if (impliedNodeFormat === ts.ModuleKind.ESNext && vueCompilerOptions.extensions.some(ext => moduleName.endsWith(ext))) {
return `${moduleName}.js`;
}
return host.resolveModuleName?.(moduleName, impliedNodeFormat) ?? moduleName;
},
getScriptFileNames() {
return [
sharedTypesFileName,
...host.getScriptFileNames(),
];
},
getScriptSnapshot(fileName) {
if (fileName === sharedTypesFileName) {
return sharedTypesSnapshot;
}
return host.getScriptSnapshot(fileName);
},
};
},
};
}
exports.createVueLanguage = createVueLanguage;
/**
* @deprecated planed to remove in 2.0, please use createVueLanguage instead of
*/
function createLanguages(ts, compilerOptions = {}, vueCompilerOptions = {}, codegenStack = false) {
return [
createVueLanguage(ts, compilerOptions, vueCompilerOptions, codegenStack),
...vueCompilerOptions.experimentalAdditionalLanguageModules?.map(module => require(module)) ?? [],
];
}
exports.createLanguages = createLanguages;
//# sourceMappingURL=languageModule.js.map
+16
View File
@@ -0,0 +1,16 @@
import type { TextRange } from '../types';
import type * as ts from 'typescript/lib/tsserverlibrary';
export interface ScriptRanges extends ReturnType<typeof parseScriptRanges> {
}
export declare function parseScriptRanges(ts: typeof import('typescript/lib/tsserverlibrary'), ast: ts.SourceFile, hasScriptSetup: boolean, withNode: boolean): {
exportDefault: (TextRange & {
expression: TextRange;
args: TextRange;
argsNode: ts.ObjectLiteralExpression | undefined;
componentsOption: TextRange | undefined;
componentsOptionNode: ts.ObjectLiteralExpression | undefined;
nameOption: TextRange | undefined;
}) | undefined;
bindings: TextRange[];
};
//# sourceMappingURL=scriptRanges.d.ts.map
+58
View File
@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseScriptRanges = void 0;
const scriptSetupRanges_1 = require("./scriptSetupRanges");
function parseScriptRanges(ts, ast, hasScriptSetup, withNode) {
let exportDefault;
const bindings = hasScriptSetup ? (0, scriptSetupRanges_1.parseBindingRanges)(ts, ast) : [];
ast.forEachChild(raw => {
if (ts.isExportAssignment(raw)) {
let node = raw;
while (ts.isAsExpression(node.expression) || ts.isParenthesizedExpression(node.expression)) { // fix https://github.com/vuejs/language-tools/issues/1882
node = node.expression;
}
let obj;
if (ts.isObjectLiteralExpression(node.expression)) {
obj = node.expression;
}
else if (ts.isCallExpression(node.expression) && node.expression.arguments.length) {
const arg0 = node.expression.arguments[0];
if (ts.isObjectLiteralExpression(arg0)) {
obj = arg0;
}
}
if (obj) {
let componentsOptionNode;
let nameOptionNode;
obj.forEachChild(node => {
if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name)) {
if (node.name.escapedText === 'components' && ts.isObjectLiteralExpression(node.initializer)) {
componentsOptionNode = node.initializer;
}
if (node.name.escapedText === 'name') {
nameOptionNode = node.initializer;
}
}
});
exportDefault = {
..._getStartEnd(raw),
expression: _getStartEnd(node.expression),
args: _getStartEnd(obj),
argsNode: withNode ? obj : undefined,
componentsOption: componentsOptionNode ? _getStartEnd(componentsOptionNode) : undefined,
componentsOptionNode: withNode ? componentsOptionNode : undefined,
nameOption: nameOptionNode ? _getStartEnd(nameOptionNode) : undefined,
};
}
}
});
return {
exportDefault,
bindings,
};
function _getStartEnd(node) {
return (0, scriptSetupRanges_1.getStartEnd)(node, ast);
}
}
exports.parseScriptRanges = parseScriptRanges;
//# sourceMappingURL=scriptRanges.js.map
+56
View File
@@ -0,0 +1,56 @@
import type * as ts from 'typescript/lib/tsserverlibrary';
import type { VueCompilerOptions, TextRange } from '../types';
export interface ScriptSetupRanges extends ReturnType<typeof parseScriptSetupRanges> {
}
export declare function parseScriptSetupRanges(ts: typeof import('typescript/lib/tsserverlibrary'), ast: ts.SourceFile, vueCompilerOptions: VueCompilerOptions): {
leadingCommentEndOffset: number;
importSectionEndOffset: number;
bindings: TextRange[];
props: {
name?: string | undefined;
define?: (TextRange & {
arg?: TextRange | undefined;
typeArg?: TextRange | undefined;
} & {
statement: TextRange;
}) | undefined;
withDefaults?: (TextRange & {
arg?: TextRange | undefined;
}) | undefined;
};
slots: {
name?: string | undefined;
define?: (TextRange & {
arg?: TextRange | undefined;
typeArg?: TextRange | undefined;
}) | undefined;
};
emits: {
name?: string | undefined;
define?: (TextRange & {
arg?: TextRange | undefined;
typeArg?: TextRange | undefined;
}) | undefined;
};
expose: {
name?: string | undefined;
define?: (TextRange & {
arg?: TextRange | undefined;
typeArg?: TextRange | undefined;
}) | undefined;
};
defineProp: {
name: TextRange | undefined;
nameIsString: boolean;
type: TextRange | undefined;
defaultValue: TextRange | undefined;
required: boolean;
}[];
};
export declare function parseBindingRanges(ts: typeof import('typescript/lib/tsserverlibrary'), sourceFile: ts.SourceFile): TextRange[];
export declare function findBindingVars(ts: typeof import('typescript/lib/tsserverlibrary'), left: ts.BindingName, sourceFile: ts.SourceFile): TextRange[];
export declare function getStartEnd(node: ts.Node, sourceFile: ts.SourceFile): {
start: number;
end: number;
};
//# sourceMappingURL=scriptSetupRanges.d.ts.map
+292
View File
@@ -0,0 +1,292 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStartEnd = exports.findBindingVars = exports.parseBindingRanges = exports.parseScriptSetupRanges = void 0;
function parseScriptSetupRanges(ts, ast, vueCompilerOptions) {
let foundNonImportExportNode = false;
let importSectionEndOffset = 0;
const props = {};
const slots = {};
const emits = {};
const expose = {};
const definePropProposalA = vueCompilerOptions.experimentalDefinePropProposal === 'kevinEdition' || ast.getFullText().trimStart().startsWith('// @experimentalDefinePropProposal=kevinEdition');
const definePropProposalB = vueCompilerOptions.experimentalDefinePropProposal === 'johnsonEdition' || ast.getFullText().trimStart().startsWith('// @experimentalDefinePropProposal=johnsonEdition');
const defineProp = [];
const bindings = parseBindingRanges(ts, ast);
const text = ast.getFullText();
const leadingCommentEndOffset = ts.getLeadingCommentRanges(text, 0)?.reverse()[0].end ?? 0;
ast.forEachChild(node => {
const isTypeExport = (ts.isTypeAliasDeclaration(node) || ts.isInterfaceDeclaration(node)) && node.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword);
if (!foundNonImportExportNode
&& !ts.isImportDeclaration(node)
&& !isTypeExport
&& !ts.isEmptyStatement(node)
// fix https://github.com/vuejs/language-tools/issues/1223
&& !ts.isImportEqualsDeclaration(node)) {
const commentRanges = ts.getLeadingCommentRanges(text, node.getFullStart());
if (commentRanges?.length) {
const commentRange = commentRanges.sort((a, b) => a.pos - b.pos)[0];
importSectionEndOffset = commentRange.pos;
}
else {
importSectionEndOffset = node.getStart(ast);
}
foundNonImportExportNode = true;
}
});
ast.forEachChild(child => visitNode(child, [ast]));
return {
leadingCommentEndOffset,
importSectionEndOffset,
bindings,
props,
slots,
emits,
expose,
defineProp,
};
function _getStartEnd(node) {
return getStartEnd(node, ast);
}
function parseDefineFunction(node) {
return {
..._getStartEnd(node),
arg: node.arguments.length ? _getStartEnd(node.arguments[0]) : undefined,
typeArg: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined,
};
}
function visitNode(node, parents) {
const parent = parents[parents.length - 1];
if (ts.isCallExpression(node)
&& ts.isIdentifier(node.expression)) {
const callText = node.expression.getText(ast);
if (vueCompilerOptions.macros.defineModel.includes(callText)) {
let name;
let options;
if (node.arguments.length >= 2) {
name = _getStartEnd(node.arguments[0]);
options = node.arguments[1];
}
else if (node.arguments.length >= 1) {
if (ts.isStringLiteral(node.arguments[0])) {
name = _getStartEnd(node.arguments[0]);
}
else {
options = node.arguments[0];
}
}
let required = false;
if (options && ts.isObjectLiteralExpression(options)) {
for (const property of options.properties) {
if (ts.isPropertyAssignment(property) && ts.isIdentifier(property.name) && property.name.getText(ast) === 'required' && property.initializer.kind === ts.SyntaxKind.TrueKeyword) {
required = true;
break;
}
}
}
defineProp.push({
name,
nameIsString: true,
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined,
defaultValue: undefined,
required,
});
}
else if (callText === 'defineProp') {
if (definePropProposalA) {
let required = false;
if (node.arguments.length >= 2) {
const secondArg = node.arguments[1];
if (ts.isObjectLiteralExpression(secondArg)) {
for (const property of secondArg.properties) {
if (ts.isPropertyAssignment(property) && ts.isIdentifier(property.name) && property.name.getText(ast) === 'required' && property.initializer.kind === ts.SyntaxKind.TrueKeyword) {
required = true;
break;
}
}
}
}
if (node.arguments.length >= 1) {
defineProp.push({
name: _getStartEnd(node.arguments[0]),
nameIsString: true,
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined,
defaultValue: undefined,
required,
});
}
else if (ts.isVariableDeclaration(parent)) {
defineProp.push({
name: _getStartEnd(parent.name),
nameIsString: false,
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined,
defaultValue: undefined,
required,
});
}
}
else if (definePropProposalB && ts.isVariableDeclaration(parent)) {
defineProp.push({
name: _getStartEnd(parent.name),
nameIsString: false,
defaultValue: node.arguments.length >= 1 ? _getStartEnd(node.arguments[0]) : undefined,
type: node.typeArguments?.length ? _getStartEnd(node.typeArguments[0]) : undefined,
required: node.arguments.length >= 2 && node.arguments[1].kind === ts.SyntaxKind.TrueKeyword,
});
}
}
else if (vueCompilerOptions.macros.defineSlots.includes(callText)) {
slots.define = parseDefineFunction(node);
if (ts.isVariableDeclaration(parent)) {
slots.name = parent.name.getText(ast);
}
}
else if (vueCompilerOptions.macros.defineEmits.includes(callText)) {
emits.define = parseDefineFunction(node);
if (ts.isVariableDeclaration(parent)) {
emits.name = parent.name.getText(ast);
}
}
else if (vueCompilerOptions.macros.defineExpose.includes(callText)) {
expose.define = parseDefineFunction(node);
}
else if (vueCompilerOptions.macros.defineProps.includes(callText)) {
let statementRange;
for (let i = parents.length - 1; i >= 0; i--) {
if (ts.isStatement(parents[i])) {
const statement = parents[i];
statement.forEachChild(child => {
const range = _getStartEnd(child);
statementRange ??= range;
statementRange.end = range.end;
});
break;
}
}
if (!statementRange) {
statementRange = _getStartEnd(node);
}
props.define = {
...parseDefineFunction(node),
statement: statementRange,
};
if (ts.isVariableDeclaration(parent)) {
props.name = parent.name.getText(ast);
}
if (node.arguments.length) {
props.define.arg = _getStartEnd(node.arguments[0]);
}
if (node.typeArguments?.length) {
props.define.typeArg = _getStartEnd(node.typeArguments[0]);
}
}
else if (vueCompilerOptions.macros.withDefaults.includes(callText)) {
props.withDefaults = _getStartEnd(node);
if (node.arguments.length >= 2) {
const arg = node.arguments[1];
props.withDefaults.arg = _getStartEnd(arg);
}
if (ts.isVariableDeclaration(parent)) {
props.name = parent.name.getText(ast);
}
}
}
node.forEachChild(child => {
parents.push(node);
visitNode(child, parents);
parents.pop();
});
}
}
exports.parseScriptSetupRanges = parseScriptSetupRanges;
function parseBindingRanges(ts, sourceFile) {
const bindings = [];
sourceFile.forEachChild(node => {
if (ts.isVariableStatement(node)) {
for (const node_2 of node.declarationList.declarations) {
const vars = _findBindingVars(node_2.name);
for (const _var of vars) {
bindings.push(_var);
}
}
}
else if (ts.isFunctionDeclaration(node)) {
if (node.name && ts.isIdentifier(node.name)) {
bindings.push(_getStartEnd(node.name));
}
}
else if (ts.isClassDeclaration(node)) {
if (node.name) {
bindings.push(_getStartEnd(node.name));
}
}
else if (ts.isEnumDeclaration(node)) {
bindings.push(_getStartEnd(node.name));
}
if (ts.isImportDeclaration(node)) {
if (node.importClause && !node.importClause.isTypeOnly) {
if (node.importClause.name) {
bindings.push(_getStartEnd(node.importClause.name));
}
if (node.importClause.namedBindings) {
if (ts.isNamedImports(node.importClause.namedBindings)) {
for (const element of node.importClause.namedBindings.elements) {
bindings.push(_getStartEnd(element.name));
}
}
else if (ts.isNamespaceImport(node.importClause.namedBindings)) {
bindings.push(_getStartEnd(node.importClause.namedBindings.name));
}
}
}
}
});
return bindings;
function _getStartEnd(node) {
return getStartEnd(node, sourceFile);
}
function _findBindingVars(left) {
return findBindingVars(ts, left, sourceFile);
}
}
exports.parseBindingRanges = parseBindingRanges;
function findBindingVars(ts, left, sourceFile) {
const vars = [];
worker(left);
return vars;
function worker(_node) {
if (ts.isIdentifier(_node)) {
vars.push(getStartEnd(_node, sourceFile));
}
// { ? } = ...
// [ ? ] = ...
else if (ts.isObjectBindingPattern(_node) || ts.isArrayBindingPattern(_node)) {
for (const property of _node.elements) {
if (ts.isBindingElement(property)) {
worker(property.name);
}
}
}
// { foo: ? } = ...
else if (ts.isPropertyAssignment(_node)) {
worker(_node.initializer);
}
// { foo } = ...
else if (ts.isShorthandPropertyAssignment(_node)) {
vars.push(getStartEnd(_node.name, sourceFile));
}
// { ...? } = ...
// [ ...? ] = ...
else if (ts.isSpreadAssignment(_node) || ts.isSpreadElement(_node)) {
worker(_node.expression);
}
}
}
exports.findBindingVars = findBindingVars;
function getStartEnd(node, sourceFile) {
return {
start: node.getStart(sourceFile),
end: node.getEnd(),
};
}
exports.getStartEnd = getStartEnd;
//# sourceMappingURL=scriptSetupRanges.js.map
+25
View File
@@ -0,0 +1,25 @@
import type * as ts from 'typescript/lib/tsserverlibrary';
import { VueCompilerOptions } from './types';
import * as CompilerDOM from '@vue/compiler-dom';
export declare function getDefaultVueLanguagePlugins(ts: typeof import('typescript/lib/tsserverlibrary'), compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions, codegenStack: boolean): {
version: 1;
name?: string | undefined;
order?: number | undefined;
requiredCompilerOptions?: string[] | undefined;
parseSFC?(fileName: string, content: string): import("@vue/compiler-sfc").SFCParseResult | undefined;
updateSFC?(oldResult: import("@vue/compiler-sfc").SFCParseResult, textChange: {
start: number;
end: number;
newText: string;
}): import("@vue/compiler-sfc").SFCParseResult | undefined;
resolveTemplateCompilerOptions?(options: CompilerDOM.CompilerOptions): CompilerDOM.CompilerOptions;
compileSFCTemplate?(lang: string, template: string, options: CompilerDOM.CompilerOptions): CompilerDOM.CodegenResult | undefined;
updateSFCTemplate?(oldResult: CompilerDOM.CodegenResult, textChange: {
start: number;
end: number;
newText: string;
}): CompilerDOM.CodegenResult | undefined;
getEmbeddedFileNames?(fileName: string, sfc: import("./types").Sfc): string[];
resolveEmbeddedFile?(fileName: string, sfc: import("./types").Sfc, embeddedFile: import("./virtualFile/embeddedFile").VueEmbeddedFile): void;
}[];
//# sourceMappingURL=plugins.d.ts.map
+58
View File
@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDefaultVueLanguagePlugins = void 0;
const file_html_1 = require("./plugins/file-html");
const file_md_1 = require("./plugins/file-md");
const file_vue_1 = require("./plugins/file-vue");
const vue_sfc_customblocks_1 = require("./plugins/vue-sfc-customblocks");
const vue_sfc_scripts_1 = require("./plugins/vue-sfc-scripts");
const vue_sfc_styles_1 = require("./plugins/vue-sfc-styles");
const vue_sfc_template_1 = require("./plugins/vue-sfc-template");
const vue_template_html_1 = require("./plugins/vue-template-html");
const vue_tsx_1 = require("./plugins/vue-tsx");
const CompilerDOM = require("@vue/compiler-dom");
const CompilerVue2 = require("./utils/vue2TemplateCompiler");
function getDefaultVueLanguagePlugins(ts, compilerOptions, vueCompilerOptions, codegenStack) {
const plugins = [
file_md_1.default, // .md for VitePress
file_html_1.default, // .html for PetiteVue
file_vue_1.default, // .vue and others for Vue
vue_template_html_1.default,
vue_sfc_styles_1.default,
vue_sfc_customblocks_1.default,
vue_sfc_scripts_1.default,
vue_sfc_template_1.default,
vue_tsx_1.default,
...vueCompilerOptions.plugins,
];
const pluginCtx = {
modules: {
'@vue/compiler-dom': vueCompilerOptions.target < 3
? {
...CompilerDOM,
compile: CompilerVue2.compile,
}
: CompilerDOM,
typescript: ts,
},
compilerOptions,
vueCompilerOptions,
codegenStack,
};
const pluginInstances = plugins
.map(plugin => plugin(pluginCtx))
.sort((a, b) => {
const aOrder = a.order ?? 0;
const bOrder = b.order ?? 0;
return aOrder - bOrder;
});
return pluginInstances.filter((plugin) => {
const valid = plugin.version >= 1 && plugin.version < 2;
if (!valid) {
console.warn(`Plugin ${JSON.stringify(plugin.name)} API version incompatible, expected 1.x but got ${JSON.stringify(plugin.version)}`);
}
return valid;
});
}
exports.getDefaultVueLanguagePlugins = getDefaultVueLanguagePlugins;
//# sourceMappingURL=plugins.js.map
+4
View File
@@ -0,0 +1,4 @@
import { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;
//# sourceMappingURL=file-html.d.ts.map
+81
View File
@@ -0,0 +1,81 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const sfcBlockReg = /\<(script|style)\b([\s\S]*?)\>([\s\S]*?)\<\/\1\>/g;
const langReg = /\blang\s*=\s*(['\"]?)(\S*)\b\1/;
const plugin = () => {
return {
version: 1,
parseSFC(fileName, content) {
if (fileName.endsWith('.html')) {
let sfc = {
descriptor: {
filename: fileName,
source: content,
template: null,
script: null,
scriptSetup: null,
styles: [],
customBlocks: [],
cssVars: [],
shouldForceReload: () => false,
slotted: false,
},
errors: [],
};
let templateContent = content;
for (const match of content.matchAll(sfcBlockReg)) {
const matchText = match[0];
const tag = match[1];
const attrs = match[2];
const lang = attrs.match(langReg)?.[2];
const content = match[3];
const contentStart = match.index + matchText.indexOf(content);
if (tag === 'style') {
sfc.descriptor.styles.push({
attrs: {},
content,
loc: {
start: { column: -1, line: -1, offset: contentStart },
end: { column: -1, line: -1, offset: contentStart + content.length },
source: content,
},
type: 'style',
lang,
});
}
// ignore `<script src="...">`
else if (tag === 'script' && attrs.indexOf('src=') === -1) {
let type = attrs.indexOf('type=') >= 0 ? 'scriptSetup' : 'script';
sfc.descriptor[type] = {
attrs: {},
content,
loc: {
start: { column: -1, line: -1, offset: contentStart },
end: { column: -1, line: -1, offset: contentStart + content.length },
source: content,
},
type: 'script',
lang,
};
}
templateContent = templateContent.substring(0, match.index) + ' '.repeat(matchText.length) + templateContent.substring(match.index + matchText.length);
}
sfc.descriptor.template = {
attrs: {},
content: templateContent,
loc: {
start: { column: -1, line: -1, offset: 0 },
end: { column: -1, line: -1, offset: templateContent.length },
source: templateContent,
},
type: 'template',
ast: {},
};
return sfc;
}
;
}
};
};
exports.default = plugin;
//# sourceMappingURL=file-html.js.map
+4
View File
@@ -0,0 +1,4 @@
import { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;
//# sourceMappingURL=file-md.d.ts.map
+71
View File
@@ -0,0 +1,71 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const source_map_1 = require("@volar/source-map");
const parseSfc_1 = require("../utils/parseSfc");
const codeblockReg = /```[\s\S]+?```/g;
const inlineCodeblockReg = /`[^\n`]+?`/g;
const scriptSetupReg = /\\\<[\s\S]+?\>\n?/g;
const sfcBlockReg = /\<(script|style)\b[\s\S]*?\>([\s\S]*?)\<\/\1\>/g;
const angleBracketReg = /\<\S*\:\S*\>/g;
const linkReg = /\[[\s\S]*?\]\([\s\S]*?\)/g;
const codeSnippetImportReg = /^\s*<<<\s*.+/gm;
const plugin = () => {
return {
version: 1,
parseSFC(fileName, content) {
if (fileName.endsWith('.md')) {
content = content
// code block
.replace(codeblockReg, match => '```' + ' '.repeat(match.length - 6) + '```')
// inline code block
.replace(inlineCodeblockReg, match => `\`${' '.repeat(match.length - 2)}\``)
// # \<script setup>
.replace(scriptSetupReg, match => ' '.repeat(match.length))
// <<< https://vitepress.dev/guide/markdown#import-code-snippets
.replace(codeSnippetImportReg, match => ' '.repeat(match.length));
const codes = [];
for (const match of content.matchAll(sfcBlockReg)) {
if (match.index !== undefined) {
const matchText = match[0];
codes.push([matchText, undefined, match.index]);
codes.push('\n\n');
content = content.substring(0, match.index) + ' '.repeat(matchText.length) + content.substring(match.index + matchText.length);
}
}
content = content
// angle bracket: <http://foo.com>
.replace(angleBracketReg, match => ' '.repeat(match.length))
// [foo](http://foo.com)
.replace(linkReg, match => ' '.repeat(match.length));
codes.push('<template>\n');
codes.push([content, undefined, 0]);
codes.push('\n</template>');
const file2VueSourceMap = new source_map_1.SourceMap((0, source_map_1.buildMappings)(codes));
const sfc = (0, parseSfc_1.parse)((0, source_map_1.toString)(codes));
if (sfc.descriptor.template) {
transformRange(sfc.descriptor.template);
}
if (sfc.descriptor.script) {
transformRange(sfc.descriptor.script);
}
if (sfc.descriptor.scriptSetup) {
transformRange(sfc.descriptor.scriptSetup);
}
for (const style of sfc.descriptor.styles) {
transformRange(style);
}
for (const customBlock of sfc.descriptor.customBlocks) {
transformRange(customBlock);
}
return sfc;
function transformRange(block) {
block.loc.start.offset = file2VueSourceMap.toSourceOffset(block.loc.start.offset)?.[0] ?? -1;
block.loc.end.offset = file2VueSourceMap.toSourceOffset(block.loc.end.offset)?.[0] ?? -1;
}
}
;
}
};
};
exports.default = plugin;
//# sourceMappingURL=file-md.js.map
+4
View File
@@ -0,0 +1,4 @@
import { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;
//# sourceMappingURL=file-vue.d.ts.map
+47
View File
@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const parseSfc_1 = require("../utils/parseSfc");
const plugin = (_ctx) => {
return {
version: 1,
parseSFC(_fileName, content) {
return (0, parseSfc_1.parse)(content);
},
updateSFC(sfc, change) {
const blocks = [
sfc.descriptor.template,
sfc.descriptor.script,
sfc.descriptor.scriptSetup,
...sfc.descriptor.styles,
...sfc.descriptor.customBlocks,
].filter((block) => !!block);
const hitBlock = blocks.find(block => change.start >= block.loc.start.offset && change.end <= block.loc.end.offset);
if (!hitBlock) {
return;
}
const oldContent = hitBlock.content;
const newContent = hitBlock.content =
hitBlock.content.substring(0, change.start - hitBlock.loc.start.offset)
+ change.newText
+ hitBlock.content.substring(change.end - hitBlock.loc.start.offset);
// #3449
const endTagRegex = new RegExp(`</\\s*${hitBlock.type}\\s*>`);
const insertedEndTag = !!oldContent.match(endTagRegex) !== !!newContent.match(endTagRegex);
if (insertedEndTag) {
return;
}
const lengthDiff = change.newText.length - (change.end - change.start);
for (const block of blocks) {
if (block.loc.start.offset > change.end) {
block.loc.start.offset += lengthDiff;
}
if (block.loc.end.offset >= change.end) {
block.loc.end.offset += lengthDiff;
}
}
return sfc;
},
};
};
exports.default = plugin;
//# sourceMappingURL=file-vue.js.map
@@ -0,0 +1,4 @@
import { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;
//# sourceMappingURL=vue-sfc-customblocks.d.ts.map
+33
View File
@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const language_core_1 = require("@volar/language-core");
const customBlockReg = /^(.*)\.customBlock_([^_]+)_(\d+)\.([^.]+)$/;
const plugin = () => {
return {
version: 1,
getEmbeddedFileNames(fileName, sfc) {
const names = [];
for (let i = 0; i < sfc.customBlocks.length; i++) {
const customBlock = sfc.customBlocks[i];
names.push(fileName + '.customBlock_' + customBlock.type + '_' + i + '.' + customBlock.lang);
}
return names;
},
resolveEmbeddedFile(_fileName, sfc, embeddedFile) {
const match = embeddedFile.fileName.match(customBlockReg);
if (match) {
const index = parseInt(match[3]);
const customBlock = sfc.customBlocks[index];
embeddedFile.capabilities = language_core_1.FileCapabilities.full;
embeddedFile.content.push([
customBlock.content,
customBlock.name,
0,
language_core_1.FileRangeCapabilities.full,
]);
}
},
};
};
exports.default = plugin;
//# sourceMappingURL=vue-sfc-customblocks.js.map
+4
View File
@@ -0,0 +1,4 @@
import { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;
//# sourceMappingURL=vue-sfc-scripts.d.ts.map
+42
View File
@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const language_core_1 = require("@volar/language-core");
const scriptFormatReg = /^(.*)\.script_format\.([^.]+)$/;
const scriptSetupFormatReg = /^(.*)\.scriptSetup_format\.([^.]+)$/;
const plugin = () => {
return {
version: 1,
getEmbeddedFileNames(fileName, sfc) {
const names = [];
if (sfc.script) {
names.push(fileName + '.script_format.' + sfc.script.lang);
}
if (sfc.scriptSetup) {
names.push(fileName + '.scriptSetup_format.' + sfc.scriptSetup.lang);
}
return names;
},
resolveEmbeddedFile(_fileName, sfc, embeddedFile) {
const scriptMatch = embeddedFile.fileName.match(scriptFormatReg);
const scriptSetupMatch = embeddedFile.fileName.match(scriptSetupFormatReg);
const script = scriptMatch ? sfc.script : scriptSetupMatch ? sfc.scriptSetup : undefined;
if (script) {
embeddedFile.kind = language_core_1.FileKind.TextFile;
embeddedFile.capabilities = {
...language_core_1.FileCapabilities.full,
diagnostic: false,
codeAction: false,
inlayHint: false,
};
embeddedFile.content.push([
script.content,
script.name,
0,
{},
]);
}
},
};
};
exports.default = plugin;
//# sourceMappingURL=vue-sfc-scripts.js.map
+4
View File
@@ -0,0 +1,4 @@
import { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;
//# sourceMappingURL=vue-sfc-styles.d.ts.map
+33
View File
@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const language_core_1 = require("@volar/language-core");
const styleReg = /^(.*)\.style_(\d+)\.([^.]+)$/;
const plugin = () => {
return {
version: 1,
getEmbeddedFileNames(fileName, sfc) {
const names = [];
for (let i = 0; i < sfc.styles.length; i++) {
const style = sfc.styles[i];
names.push(fileName + '.style_' + i + '.' + style.lang);
}
return names;
},
resolveEmbeddedFile(_fileName, sfc, embeddedFile) {
const match = embeddedFile.fileName.match(styleReg);
if (match) {
const index = parseInt(match[2]);
const style = sfc.styles[index];
embeddedFile.capabilities = language_core_1.FileCapabilities.full;
embeddedFile.content.push([
style.content,
style.name,
0,
language_core_1.FileRangeCapabilities.full,
]);
}
},
};
};
exports.default = plugin;
//# sourceMappingURL=vue-sfc-styles.js.map
+4
View File
@@ -0,0 +1,4 @@
import { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;
//# sourceMappingURL=vue-sfc-template.d.ts.map
+29
View File
@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const language_core_1 = require("@volar/language-core");
const templateReg = /^(.*)\.template\.([^.]+)$/;
const plugin = () => {
return {
version: 1,
getEmbeddedFileNames(fileName, sfc) {
if (sfc.template) {
return [fileName + '.template.' + sfc.template.lang];
}
return [];
},
resolveEmbeddedFile(_fileName, sfc, embeddedFile) {
const match = embeddedFile.fileName.match(templateReg);
if (match && sfc.template) {
embeddedFile.capabilities = language_core_1.FileCapabilities.full;
embeddedFile.content.push([
sfc.template.content,
sfc.template.name,
0,
language_core_1.FileRangeCapabilities.full,
]);
}
},
};
};
exports.default = plugin;
//# sourceMappingURL=vue-sfc-template.js.map
+4
View File
@@ -0,0 +1,4 @@
import { VueLanguagePlugin } from '../types';
declare const plugin: VueLanguagePlugin;
export default plugin;
//# sourceMappingURL=vue-template-html.d.ts.map
+169
View File
@@ -0,0 +1,169 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const plugin = ({ modules }) => {
return {
version: 1,
compileSFCTemplate(lang, template, options) {
if (lang === 'html') {
const compiler = modules['@vue/compiler-dom'];
return compiler.compile(template, {
...options,
comments: true,
});
}
},
updateSFCTemplate(oldResult, change) {
const CompilerDOM = modules['@vue/compiler-dom'];
const lengthDiff = change.newText.length - (change.end - change.start);
let hitNodes = [];
if (tryUpdateNode(oldResult.ast) && hitNodes.length) {
hitNodes = hitNodes.sort((a, b) => a.loc.source.length - b.loc.source.length);
const hitNode = hitNodes[0];
if (hitNode.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) {
return oldResult;
}
}
function tryUpdateNode(node) {
if (withinChangeRange(node.loc)) {
hitNodes.push(node);
}
if (tryUpdateNodeLoc(node.loc)) {
if (node.type === 0 /* CompilerDOM.NodeTypes.ROOT */) {
for (const child of node.children) {
if (!tryUpdateNode(child)) {
return false;
}
}
}
else if (node.type === 1 /* CompilerDOM.NodeTypes.ELEMENT */) {
if (withinChangeRange(node.loc)) {
// if not self closing, should not hit tag name
const start = node.loc.start.offset + 2;
const end = node.loc.start.offset + node.loc.source.lastIndexOf('</');
if (!withinChangeRange({ start: { offset: start }, end: { offset: end }, source: '' })) {
return false;
}
}
for (const prop of node.props) {
if (!tryUpdateNode(prop)) {
return false;
}
}
for (const child of node.children) {
if (!tryUpdateNode(child)) {
return false;
}
}
}
else if (node.type === 6 /* CompilerDOM.NodeTypes.ATTRIBUTE */) {
if (node.value && !tryUpdateNode(node.value)) {
return false;
}
}
else if (node.type === 7 /* CompilerDOM.NodeTypes.DIRECTIVE */) {
if (node.arg && withinChangeRange(node.arg.loc) && node.name === 'slot') {
return false;
}
if (node.exp && withinChangeRange(node.exp.loc) && node.name === 'for') { // #2266
return false;
}
if (node.arg && !tryUpdateNode(node.arg)) {
return false;
}
if (node.exp && !tryUpdateNode(node.exp)) {
return false;
}
}
else if (node.type === 12 /* CompilerDOM.NodeTypes.TEXT_CALL */) {
if (!tryUpdateNode(node.content)) {
return false;
}
}
else if (node.type === 8 /* CompilerDOM.NodeTypes.COMPOUND_EXPRESSION */) {
for (const childNode of node.children) {
if (typeof childNode === 'object') {
if (!tryUpdateNode(childNode)) {
return false;
}
}
}
}
else if (node.type === 9 /* CompilerDOM.NodeTypes.IF */) {
for (const branch of node.branches) {
if (branch.condition && !tryUpdateNode(branch.condition)) {
return false;
}
for (const child of branch.children) {
if (!tryUpdateNode(child)) {
return false;
}
}
}
}
else if (node.type === 11 /* CompilerDOM.NodeTypes.FOR */) {
for (const child of [
node.parseResult.source,
node.parseResult.value,
node.parseResult.key,
node.parseResult.index,
]) {
if (child && !tryUpdateNode(child)) {
return false;
}
}
for (const child of node.children) {
if (!tryUpdateNode(child)) {
return false;
}
}
}
else if (node.type === 5 /* CompilerDOM.NodeTypes.INTERPOLATION */) {
if (!tryUpdateNode(node.content)) {
return false;
}
}
else if (node.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */) {
if (withinChangeRange(node.loc)) { // TODO: review this (slot name?)
if (node.isStatic) {
return false;
}
else {
node.content = node.loc.source;
}
}
}
return true;
}
return false;
}
function tryUpdateNodeLoc(loc) {
delete loc.__endOffset;
if (withinChangeRange(loc)) {
loc.source =
loc.source.substring(0, change.start - loc.start.offset)
+ change.newText
+ loc.source.substring(change.end - loc.start.offset);
loc.__endOffset = loc.end.offset;
loc.end.offset += lengthDiff;
return true;
}
else if (change.end <= loc.start.offset) {
loc.__endOffset = loc.end.offset;
loc.start.offset += lengthDiff;
loc.end.offset += lengthDiff;
return true;
}
else if (change.start >= loc.end.offset) {
return true; // no need update
}
return false;
}
function withinChangeRange(loc) {
const originalLocEnd = loc.__endOffset ?? loc.end.offset;
return change.start >= loc.start.offset && change.end <= originalLocEnd;
}
},
};
};
exports.default = plugin;
//# sourceMappingURL=vue-template-html.js.map
+80
View File
@@ -0,0 +1,80 @@
import { Sfc, VueLanguagePlugin } from '../types';
import * as muggle from 'muggle-string';
export declare const tsCodegen: WeakMap<Sfc, {
scriptRanges: () => {
exportDefault: (import("../types").TextRange & {
expression: import("../types").TextRange;
args: import("../types").TextRange;
argsNode: import("typescript").ObjectLiteralExpression | undefined;
componentsOption: import("../types").TextRange | undefined;
componentsOptionNode: import("typescript").ObjectLiteralExpression | undefined;
nameOption: import("../types").TextRange | undefined;
}) | undefined;
bindings: import("../types").TextRange[];
} | undefined;
scriptSetupRanges: () => {
leadingCommentEndOffset: number;
importSectionEndOffset: number;
bindings: import("../types").TextRange[];
props: {
name?: string | undefined;
define?: (import("../types").TextRange & {
arg?: import("../types").TextRange | undefined;
typeArg?: import("../types").TextRange | undefined;
} & {
statement: import("../types").TextRange;
}) | undefined;
withDefaults?: (import("../types").TextRange & {
arg?: import("../types").TextRange | undefined;
}) | undefined;
};
slots: {
name?: string | undefined;
define?: (import("../types").TextRange & {
arg?: import("../types").TextRange | undefined;
typeArg?: import("../types").TextRange | undefined;
}) | undefined;
};
emits: {
name?: string | undefined;
define?: (import("../types").TextRange & {
arg?: import("../types").TextRange | undefined;
typeArg?: import("../types").TextRange | undefined;
}) | undefined;
};
expose: {
name?: string | undefined;
define?: (import("../types").TextRange & {
arg?: import("../types").TextRange | undefined;
typeArg?: import("../types").TextRange | undefined;
}) | undefined;
};
defineProp: {
name: import("../types").TextRange | undefined;
nameIsString: boolean;
type: import("../types").TextRange | undefined;
defaultValue: import("../types").TextRange | undefined;
required: boolean;
}[];
} | undefined;
lang: () => string;
generatedScript: () => {
codes: muggle.Segment<import("@volar/language-core").FileRangeCapabilities>[];
codeStacks: muggle.StackNode[];
mirrorBehaviorMappings: import("@volar/source-map").Mapping<[import("@volar/language-core").MirrorBehaviorCapabilities, import("@volar/language-core").MirrorBehaviorCapabilities]>[];
};
generatedTemplate: () => {
codes: (string | [string, string | undefined, number | [number, number], import("@volar/language-core").FileRangeCapabilities])[];
codeStacks: muggle.StackNode[];
formatCodes: (string | [string, string | undefined, number | [number, number], import("@volar/language-core").FileRangeCapabilities])[];
formatCodeStacks: muggle.StackNode[];
cssCodes: (string | [string, string | undefined, number | [number, number], import("@volar/language-core").FileRangeCapabilities])[];
cssCodeStacks: muggle.StackNode[];
tagNames: Record<string, number[]>;
accessedGlobalVariables: Set<string>;
hasSlot: boolean;
} | undefined;
}>;
declare const plugin: VueLanguagePlugin;
export default plugin;
//# sourceMappingURL=vue-tsx.d.ts.map
+159
View File
@@ -0,0 +1,159 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tsCodegen = void 0;
const computeds_1 = require("computeds");
const script_1 = require("../generators/script");
const template_1 = require("../generators/template");
const scriptRanges_1 = require("../parsers/scriptRanges");
const scriptSetupRanges_1 = require("../parsers/scriptSetupRanges");
const language_core_1 = require("@volar/language-core");
const muggle = require("muggle-string");
const templateFormatReg = /^\.template_format\.ts$/;
const templateStyleCssReg = /^\.template_style\.css$/;
exports.tsCodegen = new WeakMap();
const plugin = (ctx) => {
return {
version: 1,
requiredCompilerOptions: [
'noPropertyAccessFromIndexSignature',
'exactOptionalPropertyTypes',
],
getEmbeddedFileNames(fileName, sfc) {
const tsx = useTsx(fileName, sfc);
const fileNames = [];
if (['js', 'ts', 'jsx', 'tsx'].includes(tsx.lang())) {
fileNames.push(fileName + '.' + tsx.lang());
}
if (sfc.template) {
fileNames.push(fileName + '.template_format.ts');
fileNames.push(fileName + '.template_style.css');
}
return fileNames;
},
resolveEmbeddedFile(fileName, sfc, embeddedFile) {
const _tsx = useTsx(fileName, sfc);
const suffix = embeddedFile.fileName.replace(fileName, '');
if (suffix === '.' + _tsx.lang()) {
embeddedFile.kind = language_core_1.FileKind.TypeScriptHostFile;
embeddedFile.capabilities = {
...language_core_1.FileCapabilities.full,
foldingRange: false,
documentFormatting: false,
documentSymbol: false,
};
const tsx = _tsx.generatedScript();
if (tsx) {
const [content, contentStacks] = ctx.codegenStack ? muggle.track([...tsx.codes], [...tsx.codeStacks]) : [[...tsx.codes], [...tsx.codeStacks]];
embeddedFile.content = content;
embeddedFile.contentStacks = contentStacks;
embeddedFile.mirrorBehaviorMappings = [...tsx.mirrorBehaviorMappings];
}
}
else if (suffix.match(templateFormatReg)) {
embeddedFile.parentFileName = fileName + '.template.' + sfc.template?.lang;
embeddedFile.kind = language_core_1.FileKind.TextFile;
embeddedFile.capabilities = {
...language_core_1.FileCapabilities.full,
diagnostic: false,
foldingRange: false,
codeAction: false,
inlayHint: false,
};
const template = _tsx.generatedTemplate();
if (template) {
const [content, contentStacks] = ctx.codegenStack
? muggle.track([...template.formatCodes], [...template.formatCodeStacks])
: [[...template.formatCodes], [...template.formatCodeStacks]];
embeddedFile.content = content;
embeddedFile.contentStacks = contentStacks;
}
for (const style of sfc.styles) {
embeddedFile.content.push('\n\n');
for (const cssVar of style.cssVars) {
embeddedFile.content.push('(');
embeddedFile.content.push([
cssVar.text,
style.name,
cssVar.offset,
{},
]);
embeddedFile.content.push(');\n');
}
}
}
else if (suffix.match(templateStyleCssReg)) {
embeddedFile.parentFileName = fileName + '.template.' + sfc.template?.lang;
const template = _tsx.generatedTemplate();
if (template) {
const [content, contentStacks] = ctx.codegenStack
? muggle.track([...template.cssCodes], [...template.cssCodeStacks])
: [[...template.cssCodes], [...template.cssCodeStacks]];
embeddedFile.content = content;
embeddedFile.contentStacks = contentStacks;
}
// for color pickers support
embeddedFile.capabilities.documentSymbol = true;
}
},
};
function useTsx(fileName, sfc) {
if (!exports.tsCodegen.has(sfc)) {
exports.tsCodegen.set(sfc, createTsx(fileName, sfc, ctx));
}
return exports.tsCodegen.get(sfc);
}
};
exports.default = plugin;
function createTsx(fileName, _sfc, { vueCompilerOptions, compilerOptions, codegenStack, modules }) {
const ts = modules.typescript;
const lang = (0, computeds_1.computed)(() => {
return !_sfc.script && !_sfc.scriptSetup ? 'ts'
: _sfc.scriptSetup && _sfc.scriptSetup.lang !== 'js' ? _sfc.scriptSetup.lang
: _sfc.script && _sfc.script.lang !== 'js' ? _sfc.script.lang
: 'js';
});
const scriptRanges = (0, computeds_1.computed)(() => _sfc.script
? (0, scriptRanges_1.parseScriptRanges)(ts, _sfc.script.ast, !!_sfc.scriptSetup, false)
: undefined);
const scriptSetupRanges = (0, computeds_1.computed)(() => _sfc.scriptSetup
? (0, scriptSetupRanges_1.parseScriptSetupRanges)(ts, _sfc.scriptSetup.ast, vueCompilerOptions)
: undefined);
const shouldGenerateScopedClasses = (0, computeds_1.computed)(() => {
const option = vueCompilerOptions.experimentalResolveStyleCssClasses;
return _sfc.styles.some(s => {
return option === 'always' || (option === 'scoped' && s.scoped);
});
});
const stylesScopedClasses = (0, computeds_1.computedSet)(() => {
const classes = new Set();
if (!shouldGenerateScopedClasses()) {
return classes;
}
for (const style of _sfc.styles) {
const option = vueCompilerOptions.experimentalResolveStyleCssClasses;
if (option === 'always' || (option === 'scoped' && style.scoped)) {
for (const className of style.classNames) {
classes.add(className.text.substring(1));
}
}
}
return classes;
});
const generatedTemplate = (0, computeds_1.computed)(() => {
if (!_sfc.template)
return;
return (0, template_1.generate)(ts, compilerOptions, vueCompilerOptions, _sfc.template, shouldGenerateScopedClasses(), stylesScopedClasses(), hasScriptSetupSlots(), slotsAssignName(), propsAssignName(), codegenStack);
});
const hasScriptSetupSlots = (0, computeds_1.computed)(() => !!scriptSetupRanges()?.slots.define);
const slotsAssignName = (0, computeds_1.computed)(() => scriptSetupRanges()?.slots.name);
const propsAssignName = (0, computeds_1.computed)(() => scriptSetupRanges()?.props.name);
const generatedScript = (0, computeds_1.computed)(() => (0, script_1.generate)(ts, fileName, _sfc.script, _sfc.scriptSetup, _sfc.styles, lang(), scriptRanges(), scriptSetupRanges(), generatedTemplate(), compilerOptions, vueCompilerOptions, codegenStack));
return {
scriptRanges,
scriptSetupRanges,
lang,
generatedScript,
generatedTemplate,
};
}
//# sourceMappingURL=vue-tsx.js.map
+125
View File
@@ -0,0 +1,125 @@
import type * as CompilerDOM from '@vue/compiler-dom';
import type { SFCParseResult } from '@vue/compiler-sfc';
import type * as ts from 'typescript/lib/tsserverlibrary';
import type { VueEmbeddedFile } from './virtualFile/embeddedFile';
export type { SFCParseResult } from '@vue/compiler-sfc';
export type RawVueCompilerOptions = Partial<Omit<VueCompilerOptions, 'target' | 'plugins'>> & {
target?: 'auto' | 2 | 2.7 | 3 | 3.3;
plugins?: string[];
};
export interface VueCompilerOptions {
target: number;
lib: string;
extensions: string[];
jsxSlots: boolean;
strictTemplates: boolean;
skipTemplateCodegen: boolean;
nativeTags: string[];
dataAttributes: string[];
htmlAttributes: string[];
optionsWrapper: [string, string] | [];
macros: {
defineProps: string[];
defineSlots: string[];
defineEmits: string[];
defineExpose: string[];
defineModel: string[];
defineOptions: string[];
withDefaults: string[];
};
plugins: VueLanguagePlugin[];
hooks: string[];
experimentalDefinePropProposal: 'kevinEdition' | 'johnsonEdition' | false;
experimentalResolveStyleCssClasses: 'scoped' | 'always' | 'never';
experimentalModelPropName: Record<string, Record<string, boolean | Record<string, string> | Record<string, string>[]>>;
experimentalUseElementAccessInTemplate: boolean;
experimentalAdditionalLanguageModules: string[];
}
export type VueLanguagePlugin = (ctx: {
modules: {
typescript: typeof import('typescript/lib/tsserverlibrary');
'@vue/compiler-dom': typeof import('@vue/compiler-dom');
};
compilerOptions: ts.CompilerOptions;
vueCompilerOptions: VueCompilerOptions;
codegenStack: boolean;
}) => {
version: 1;
name?: string;
order?: number;
requiredCompilerOptions?: string[];
parseSFC?(fileName: string, content: string): SFCParseResult | undefined;
updateSFC?(oldResult: SFCParseResult, textChange: {
start: number;
end: number;
newText: string;
}): SFCParseResult | undefined;
resolveTemplateCompilerOptions?(options: CompilerDOM.CompilerOptions): CompilerDOM.CompilerOptions;
compileSFCTemplate?(lang: string, template: string, options: CompilerDOM.CompilerOptions): CompilerDOM.CodegenResult | undefined;
updateSFCTemplate?(oldResult: CompilerDOM.CodegenResult, textChange: {
start: number;
end: number;
newText: string;
}): CompilerDOM.CodegenResult | undefined;
getEmbeddedFileNames?(fileName: string, sfc: Sfc): string[];
resolveEmbeddedFile?(fileName: string, sfc: Sfc, embeddedFile: VueEmbeddedFile): void;
};
export interface SfcBlock {
name: string;
start: number;
end: number;
startTagEnd: number;
endTagStart: number;
lang: string;
content: string;
attrs: Record<string, string | true>;
}
export interface Sfc {
template: SfcBlock & {
ast: CompilerDOM.RootNode | undefined;
errors: CompilerDOM.CompilerError[];
warnings: CompilerDOM.CompilerError[];
} | undefined;
script: (SfcBlock & {
src: string | undefined;
srcOffset: number;
ast: ts.SourceFile;
}) | undefined;
scriptSetup: SfcBlock & {
generic: string | undefined;
genericOffset: number;
ast: ts.SourceFile;
} | undefined;
styles: readonly (SfcBlock & {
module: string | undefined;
scoped: boolean;
cssVars: {
text: string;
offset: number;
}[];
classNames: {
text: string;
offset: number;
}[];
})[];
customBlocks: readonly (SfcBlock & {
type: string;
})[];
/**
* @deprecated use `template.ast` instead
*/
templateAst: CompilerDOM.RootNode | undefined;
/**
* @deprecated use `script.ast` instead
*/
scriptAst: ts.SourceFile | undefined;
/**
* @deprecated use `scriptSetup.ast` instead
*/
scriptSetupAst: ts.SourceFile | undefined;
}
export interface TextRange {
start: number;
end: number;
}
//# sourceMappingURL=types.d.ts.map
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map
+4
View File
@@ -0,0 +1,4 @@
import { VueCompilerOptions } from '../types';
export declare const baseName = "__VLS_types.d.ts";
export declare function getTypesCode(vueCompilerOptions: VueCompilerOptions): string;
//# sourceMappingURL=globalTypes.d.ts.map
+135
View File
@@ -0,0 +1,135 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTypesCode = exports.baseName = void 0;
const shared_1 = require("./shared");
exports.baseName = '__VLS_types.d.ts';
function getTypesCode(vueCompilerOptions) {
return `
// @ts-nocheck
type __VLS_IntrinsicElements = __VLS_PickNotAny<import('vue/jsx-runtime').JSX.IntrinsicElements, __VLS_PickNotAny<JSX.IntrinsicElements, Record<string, any>>>;
type __VLS_Element = __VLS_PickNotAny<import('vue/jsx-runtime').JSX.Element, JSX.Element>;
type __VLS_IsAny<T> = 0 extends 1 & T ? true : false;
type __VLS_PickNotAny<A, B> = __VLS_IsAny<A> extends true ? B : A;
type __VLS_Prettify<T> = { [K in keyof T]: T[K]; } & {};
type __VLS_OmitKeepDiscriminatedUnion<T, K extends keyof any> =
T extends any
? Pick<T, Exclude<keyof T, K>>
: never;
type __VLS_GlobalComponents =
__VLS_PickNotAny<import('vue').GlobalComponents, {}>
& __VLS_PickNotAny<import('@vue/runtime-core').GlobalComponents, {}>
& __VLS_PickNotAny<import('@vue/runtime-dom').GlobalComponents, {}>
& Pick<typeof import('${vueCompilerOptions.lib}'),
'Transition'
| 'TransitionGroup'
| 'KeepAlive'
| 'Suspense'
| 'Teleport'
>;
declare const __VLS_intrinsicElements: __VLS_IntrinsicElements;
// v-for
declare function __VLS_getVForSourceType(source: number): [number, number, number][];
declare function __VLS_getVForSourceType(source: string): [string, number, number][];
declare function __VLS_getVForSourceType<T extends any[]>(source: T): [
T[number], // item
number, // key
number, // index
][];
declare function __VLS_getVForSourceType<T extends { [Symbol.iterator](): Iterator<any> }>(source: T): [
T extends { [Symbol.iterator](): Iterator<infer T1> } ? T1 : never, // item
number, // key
undefined, // index
][];
declare function __VLS_getVForSourceType<T>(source: T): [
T[keyof T], // item
keyof T, // key
number, // index
][];
declare function __VLS_getSlotParams<T>(slot: T): Parameters<__VLS_PickNotAny<NonNullable<T>, (...args: any[]) => any>>;
declare function __VLS_getSlotParam<T>(slot: T): Parameters<__VLS_PickNotAny<NonNullable<T>, (...args: any[]) => any>>[0];
declare function __VLS_directiveFunction<T>(dir: T):
T extends import('${vueCompilerOptions.lib}').ObjectDirective<infer E, infer V> | import('${vueCompilerOptions.lib}').FunctionDirective<infer E, infer V> ? (value: V) => void
: T;
declare function __VLS_withScope<T, K>(ctx: T, scope: K): ctx is T & K;
declare function __VLS_makeOptional<T>(t: T): { [K in keyof T]?: T[K] };
type __VLS_SelfComponent<N, C> = string extends N ? {} : N extends string ? { [P in N]: C } : {};
type __VLS_WithComponent<N0 extends string, LocalComponents, N1 extends string, N2 extends string, N3 extends string> =
N1 extends keyof LocalComponents ? N1 extends N0 ? Pick<LocalComponents, N0> : { [K in N0]: LocalComponents[N1] } :
N2 extends keyof LocalComponents ? N2 extends N0 ? Pick<LocalComponents, N0> : { [K in N0]: LocalComponents[N2] } :
N3 extends keyof LocalComponents ? N3 extends N0 ? Pick<LocalComponents, N0> : { [K in N0]: LocalComponents[N3] } :
N1 extends keyof __VLS_GlobalComponents ? N1 extends N0 ? Pick<__VLS_GlobalComponents, N0> : { [K in N0]: __VLS_GlobalComponents[N1] } :
N2 extends keyof __VLS_GlobalComponents ? N2 extends N0 ? Pick<__VLS_GlobalComponents, N0> : { [K in N0]: __VLS_GlobalComponents[N2] } :
N3 extends keyof __VLS_GlobalComponents ? N3 extends N0 ? Pick<__VLS_GlobalComponents, N0> : { [K in N0]: __VLS_GlobalComponents[N3] } :
${vueCompilerOptions.strictTemplates ? '{}' : '{ [K in N0]: unknown }'}
type __VLS_FillingEventArg_ParametersLength<E extends (...args: any) => any> = __VLS_IsAny<Parameters<E>> extends true ? -1 : Parameters<E>['length'];
type __VLS_FillingEventArg<E> = E extends (...args: any) => any ? __VLS_FillingEventArg_ParametersLength<E> extends 0 ? ($event?: undefined) => ReturnType<E> : E : E;
declare function __VLS_asFunctionalComponent<T, K = T extends new (...args: any) => any ? InstanceType<T> : unknown>(t: T, instance?: K):
T extends new (...args: any) => any
? (props: (K extends { $props: infer Props } ? Props : any)${vueCompilerOptions.strictTemplates ? '' : ' & Record<string, unknown>'}, ctx?: {
attrs?: any,
slots?: K extends { ${(0, shared_1.getSlotsPropertyName)(vueCompilerOptions.target)}: infer Slots } ? Slots : any,
emit?: K extends { $emit: infer Emit } ? Emit : any
}) => __VLS_Element & { __ctx?: typeof ctx & { props?: typeof props; expose?(exposed: K): void; } }
: T extends () => any ? (props: {}, ctx?: any) => ReturnType<T>
: T extends (...args: any) => any ? T
: (_: {}${vueCompilerOptions.strictTemplates ? '' : ' & Record<string, unknown>'}, ctx?: any) => { __ctx?: { attrs?: any, expose?: any, slots?: any, emit?: any, props?: {}${vueCompilerOptions.strictTemplates ? '' : ' & Record<string, unknown>'} } };
declare function __VLS_elementAsFunctionalComponent<T>(t: T): (_: T${vueCompilerOptions.strictTemplates ? '' : ' & Record<string, unknown>'}, ctx?: any) => { __ctx?: { attrs?: any, expose?: any, slots?: any, emit?: any, props?: T${vueCompilerOptions.strictTemplates ? '' : ' & Record<string, unknown>'} } };
declare function __VLS_functionalComponentArgsRest<T extends (...args: any) => any>(t: T): Parameters<T>['length'] extends 2 ? [any] : [];
declare function __VLS_pickEvent<E1, E2>(emitEvent: E1, propEvent: E2): __VLS_FillingEventArg<
__VLS_PickNotAny<
__VLS_AsFunctionOrAny<E2>,
__VLS_AsFunctionOrAny<E1>
>
> | undefined;
declare function __VLS_pickFunctionalComponentCtx<T, K>(comp: T, compInstance: K): __VLS_PickNotAny<
'__ctx' extends keyof __VLS_PickNotAny<K, {}> ? K extends { __ctx?: infer Ctx } ? Ctx : never : any
, T extends (props: any, ctx: infer Ctx) => any ? Ctx : any
>;
type __VLS_FunctionalComponentProps<T, K> =
'__ctx' extends keyof __VLS_PickNotAny<K, {}> ? K extends { __ctx?: { props?: infer P } } ? NonNullable<P> : never
: T extends (props: infer P, ...args: any) => any ? P :
{};
type __VLS_AsFunctionOrAny<F> = unknown extends F ? any : ((...args: any) => any) extends F ? F : any;
declare function __VLS_normalizeSlot<S>(s: S): S extends () => infer R ? (props: {}) => R : S;
/**
* emit
*/
// fix https://github.com/vuejs/language-tools/issues/926
type __VLS_UnionToIntersection<U> = (U extends unknown ? (arg: U) => unknown : never) extends ((arg: infer P) => unknown) ? P : never;
type __VLS_OverloadUnionInner<T, U = unknown> = U & T extends (...args: infer A) => infer R
? U extends T
? never
: __VLS_OverloadUnionInner<T, Pick<T, keyof T> & U & ((...args: A) => R)> | ((...args: A) => R)
: never;
type __VLS_OverloadUnion<T> = Exclude<
__VLS_OverloadUnionInner<(() => never) & T>,
T extends () => never ? never : () => never
>;
type __VLS_ConstructorOverloads<T> = __VLS_OverloadUnion<T> extends infer F
? F extends (event: infer E, ...args: infer A) => any
? { [K in E & string]: (...args: A) => void; }
: never
: never;
type __VLS_NormalizeEmits<T> = __VLS_Prettify<
__VLS_UnionToIntersection<
__VLS_ConstructorOverloads<T> & {
[K in keyof T]: T[K] extends any[] ? { (...args: T[K]): void } : never
}
>
>;
`.trim();
}
exports.getTypesCode = getTypesCode;
//# sourceMappingURL=globalTypes.js.map
+5
View File
@@ -0,0 +1,5 @@
export declare function parseCssClassNames(styleContent: string): Generator<{
offset: number;
text: string;
}, void, unknown>;
//# sourceMappingURL=parseCssClassNames.d.ts.map
+19
View File
@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseCssClassNames = void 0;
const parseCssVars_1 = require("./parseCssVars");
const cssClassNameReg = /(?=([\.]{1}[a-zA-Z_]+[\w\_\-]*)[\s\.\+\{\>#\:]{1})/g;
function* parseCssClassNames(styleContent) {
styleContent = (0, parseCssVars_1.clearComments)(styleContent);
const matches = styleContent.matchAll(cssClassNameReg);
for (const match of matches) {
if (match.index !== undefined) {
const matchText = match[1];
if (matchText !== undefined) {
yield { offset: match.index, text: matchText };
}
}
}
}
exports.parseCssClassNames = parseCssClassNames;
//# sourceMappingURL=parseCssClassNames.js.map
+6
View File
@@ -0,0 +1,6 @@
export declare function parseCssVars(styleContent: string): Generator<{
offset: number;
text: string;
}, void, unknown>;
export declare function clearComments(css: string): string;
//# sourceMappingURL=parseCssVars.d.ts.map
+28
View File
@@ -0,0 +1,28 @@
"use strict";
// https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/cssVars.ts#L47-L61
Object.defineProperty(exports, "__esModule", { value: true });
exports.clearComments = exports.parseCssVars = void 0;
const vBindCssVarReg = /\bv-bind\(\s*(?:'([^']+)'|"([^"]+)"|([^'"][^)]*))\s*\)/g;
const commentReg1 = /\/\*([\s\S]*?)\*\//g;
const commentReg2 = /\/\/([\s\S]*?)\n/g;
function* parseCssVars(styleContent) {
styleContent = clearComments(styleContent);
const matchs = styleContent.matchAll(vBindCssVarReg);
for (const match of matchs) {
if (match.index !== undefined) {
const matchText = match[1] ?? match[2] ?? match[3];
if (matchText !== undefined) {
const offset = match.index + styleContent.slice(match.index).indexOf(matchText);
yield { offset, text: matchText };
}
}
}
}
exports.parseCssVars = parseCssVars;
function clearComments(css) {
return css
.replace(commentReg1, match => `/*${' '.repeat(match.length - 4)}*/`)
.replace(commentReg2, match => `//${' '.repeat(match.length - 3)}\n`);
}
exports.clearComments = clearComments;
//# sourceMappingURL=parseCssVars.js.map
+3
View File
@@ -0,0 +1,3 @@
import type { SFCParseResult } from '@vue/compiler-sfc';
export declare function parse(source: string): SFCParseResult;
//# sourceMappingURL=parseSfc.d.ts.map

Some files were not shown because too many files have changed in this diff Show More