update
This commit is contained in:
Binary file not shown.
@@ -0,0 +1 @@
|
||||
module.exports={A:{A:{"132":"K D E F A B mC"},B:{"132":"0 9 C L M G N O P Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I"},C:{"132":"0 1 2 3 4 5 6 7 8 9 nC LC J PB K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC oC pC qC rC"},D:{"132":"0 9 J PB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC","388":"1 2 3 4 5 6 7 8 K D E F A B C L M G N O P QB RB SB TB"},E:{"132":"J PB K D E F A B C L M G sC SC tC uC vC wC TC FC GC xC yC zC UC VC HC 0C IC WC XC YC ZC aC 1C JC bC cC dC eC fC 2C KC gC hC iC jC 3C"},F:{"132":"0 1 2 3 4 5 6 7 8 F B C G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB wB xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z 4C 5C 6C 7C FC kC 8C GC"},G:{"132":"E SC 9C lC AD BD CD DD ED FD GD HD ID JD KD LD MD ND OD PD QD RD SD UC VC HC TD IC WC XC YC ZC aC UD JC bC cC dC eC fC VD KC gC hC iC jC"},H:{"132":"WD"},I:{"132":"LC J I XD YD ZD aD lC bD cD"},J:{"132":"D A"},K:{"132":"A B C H FC kC GC"},L:{"132":"I"},M:{"132":"EC"},N:{"132":"A B"},O:{"132":"HC"},P:{"132":"1 2 3 4 5 6 7 8 J dD eD fD gD hD TC iD jD kD lD mD IC JC KC nD"},Q:{"132":"oD"},R:{"132":"pD"},S:{"132":"qD rD"}},B:6,C:"DNSSEC and DANE",D:true};
|
||||
@@ -0,0 +1,13 @@
|
||||
function notFound(options = {}) {
|
||||
options.isNotFound = true;
|
||||
if (options.throw) throw options;
|
||||
return options;
|
||||
}
|
||||
function isNotFound(obj) {
|
||||
return !!(obj == null ? void 0 : obj.isNotFound);
|
||||
}
|
||||
export {
|
||||
isNotFound,
|
||||
notFound
|
||||
};
|
||||
//# sourceMappingURL=not-found.js.map
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_core","require","_normalizeAndLoadMetadata","toGetWrapperPayload","lazy","source","metadata","isSideEffectImport","reexportAll","includes","Array","isArray","Error","wrapReference","ref","payload","t","callExpression"],"sources":["../src/lazy-modules.ts"],"sourcesContent":["// TODO: Move `lazy` implementation logic into the CommonJS plugin, since other\n// modules systems do not support `lazy`.\n\nimport { types as t } from \"@babel/core\";\nimport {\n type SourceModuleMetadata,\n isSideEffectImport,\n} from \"./normalize-and-load-metadata.ts\";\n\nexport type Lazy = boolean | string[] | ((source: string) => boolean);\n\nexport function toGetWrapperPayload(lazy: Lazy) {\n return (source: string, metadata: SourceModuleMetadata): null | \"lazy\" => {\n if (lazy === false) return null;\n if (isSideEffectImport(metadata) || metadata.reexportAll) return null;\n if (lazy === true) {\n // 'true' means that local relative files are eagerly loaded and\n // dependency modules are loaded lazily.\n return source.includes(\".\") ? null : \"lazy\";\n }\n if (Array.isArray(lazy)) {\n return !lazy.includes(source) ? null : \"lazy\";\n }\n if (typeof lazy === \"function\") {\n return lazy(source) ? \"lazy\" : null;\n }\n throw new Error(`.lazy must be a boolean, string array, or function`);\n };\n}\n\nexport function wrapReference(\n ref: t.Identifier,\n payload: unknown,\n): t.Expression | null {\n if (payload === \"lazy\") return t.callExpression(ref, []);\n return null;\n}\n"],"mappings":";;;;;;;AAGA,IAAAA,KAAA,GAAAC,OAAA;AACA,IAAAC,yBAAA,GAAAD,OAAA;AAOO,SAASE,mBAAmBA,CAACC,IAAU,EAAE;EAC9C,OAAO,CAACC,MAAc,EAAEC,QAA8B,KAAoB;IACxE,IAAIF,IAAI,KAAK,KAAK,EAAE,OAAO,IAAI;IAC/B,IAAI,IAAAG,4CAAkB,EAACD,QAAQ,CAAC,IAAIA,QAAQ,CAACE,WAAW,EAAE,OAAO,IAAI;IACrE,IAAIJ,IAAI,KAAK,IAAI,EAAE;MAGjB,OAAOC,MAAM,CAACI,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,MAAM;IAC7C;IACA,IAAIC,KAAK,CAACC,OAAO,CAACP,IAAI,CAAC,EAAE;MACvB,OAAO,CAACA,IAAI,CAACK,QAAQ,CAACJ,MAAM,CAAC,GAAG,IAAI,GAAG,MAAM;IAC/C;IACA,IAAI,OAAOD,IAAI,KAAK,UAAU,EAAE;MAC9B,OAAOA,IAAI,CAACC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI;IACrC;IACA,MAAM,IAAIO,KAAK,CAAC,oDAAoD,CAAC;EACvE,CAAC;AACH;AAEO,SAASC,aAAaA,CAC3BC,GAAiB,EACjBC,OAAgB,EACK;EACrB,IAAIA,OAAO,KAAK,MAAM,EAAE,OAAOC,WAAC,CAACC,cAAc,CAACH,GAAG,EAAE,EAAE,CAAC;EACxD,OAAO,IAAI;AACb","ignoreList":[]}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Parser } from "../index.js";
|
||||
|
||||
export declare const parsers: {
|
||||
yaml: Parser;
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "@jridgewell/set-array",
|
||||
"version": "1.2.1",
|
||||
"description": "Like a Set, but provides the index of the `key` in the backing array",
|
||||
"keywords": [],
|
||||
"author": "Justin Ridgewell <justin@ridgewell.name>",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/jridgewell/set-array",
|
||||
"main": "dist/set-array.umd.js",
|
||||
"module": "dist/set-array.mjs",
|
||||
"typings": "dist/types/set-array.d.ts",
|
||||
"exports": {
|
||||
".": [
|
||||
{
|
||||
"types": "./dist/types/set-array.d.ts",
|
||||
"browser": "./dist/set-array.umd.js",
|
||||
"require": "./dist/set-array.umd.js",
|
||||
"import": "./dist/set-array.mjs"
|
||||
},
|
||||
"./dist/set-array.umd.js"
|
||||
],
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"prebuild": "rm -rf dist",
|
||||
"build": "run-s -n build:*",
|
||||
"build:rollup": "rollup -c rollup.config.js",
|
||||
"build:ts": "tsc --project tsconfig.build.json",
|
||||
"lint": "run-s -n lint:*",
|
||||
"lint:prettier": "npm run test:lint:prettier -- --write",
|
||||
"lint:ts": "npm run test:lint:ts -- --fix",
|
||||
"test": "run-s -n test:lint test:only",
|
||||
"test:debug": "mocha --inspect-brk",
|
||||
"test:lint": "run-s -n test:lint:*",
|
||||
"test:lint:prettier": "prettier --check '{src,test}/**/*.ts'",
|
||||
"test:lint:ts": "eslint '{src,test}/**/*.ts'",
|
||||
"test:only": "mocha",
|
||||
"test:coverage": "c8 mocha",
|
||||
"test:watch": "mocha --watch",
|
||||
"prepublishOnly": "npm run preversion",
|
||||
"preversion": "run-s test build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-typescript": "8.3.0",
|
||||
"@types/mocha": "9.1.1",
|
||||
"@types/node": "17.0.29",
|
||||
"@typescript-eslint/eslint-plugin": "5.10.0",
|
||||
"@typescript-eslint/parser": "5.10.0",
|
||||
"c8": "7.11.0",
|
||||
"eslint": "8.7.0",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
"mocha": "9.2.0",
|
||||
"npm-run-all": "4.1.5",
|
||||
"prettier": "2.5.1",
|
||||
"rollup": "2.66.0",
|
||||
"tsx": "4.7.1",
|
||||
"typescript": "4.5.5"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
# cookie
|
||||
|
||||
[![NPM Version][npm-version-image]][npm-url]
|
||||
[![NPM Downloads][npm-downloads-image]][npm-url]
|
||||
[![Build Status][ci-image]][ci-url]
|
||||
[![Coverage Status][coverage-image]][coverage-url]
|
||||
|
||||
Basic HTTP cookie parser and serializer for HTTP servers.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
$ npm install cookie
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
const cookie = require("cookie");
|
||||
// import * as cookie from 'cookie';
|
||||
```
|
||||
|
||||
### cookie.parse(str, options)
|
||||
|
||||
Parse a HTTP `Cookie` header string and returning an object of all cookie name-value pairs.
|
||||
The `str` argument is the string representing a `Cookie` header value and `options` is an
|
||||
optional object containing additional parsing options.
|
||||
|
||||
```js
|
||||
const cookies = cookie.parse("foo=bar; equation=E%3Dmc%5E2");
|
||||
// { foo: 'bar', equation: 'E=mc^2' }
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
`cookie.parse` accepts these properties in the options object.
|
||||
|
||||
##### decode
|
||||
|
||||
Specifies a function that will be used to decode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1).
|
||||
Since the value of a cookie has a limited character set (and must be a simple string), this function can be used to decode
|
||||
a previously-encoded cookie value into a JavaScript string.
|
||||
|
||||
The default function is the global `decodeURIComponent`, wrapped in a `try..catch`. If an error
|
||||
is thrown it will return the cookie's original value. If you provide your own encode/decode
|
||||
scheme you must ensure errors are appropriately handled.
|
||||
|
||||
### cookie.serialize(name, value, options)
|
||||
|
||||
Serialize a cookie name-value pair into a `Set-Cookie` header string. The `name` argument is the
|
||||
name for the cookie, the `value` argument is the value to set the cookie to, and the `options`
|
||||
argument is an optional object containing additional serialization options.
|
||||
|
||||
```js
|
||||
const setCookie = cookie.serialize("foo", "bar");
|
||||
// foo=bar
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
`cookie.serialize` accepts these properties in the options object.
|
||||
|
||||
##### encode
|
||||
|
||||
Specifies a function that will be used to encode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1).
|
||||
Since value of a cookie has a limited character set (and must be a simple string), this function can be used to encode
|
||||
a value into a string suited for a cookie's value, and should mirror `decode` when parsing.
|
||||
|
||||
The default function is the global `encodeURIComponent`.
|
||||
|
||||
##### maxAge
|
||||
|
||||
Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.2).
|
||||
|
||||
The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and
|
||||
`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
|
||||
so if both are set, they should point to the same date and time.
|
||||
|
||||
##### expires
|
||||
|
||||
Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.1).
|
||||
When no expiration is set clients consider this a "non-persistent cookie" and delete it the current session is over.
|
||||
|
||||
The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and
|
||||
`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
|
||||
so if both are set, they should point to the same date and time.
|
||||
|
||||
##### domain
|
||||
|
||||
Specifies the value for the [`Domain` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.3).
|
||||
When no domain is set clients consider the cookie to apply to the current domain only.
|
||||
|
||||
##### path
|
||||
|
||||
Specifies the value for the [`Path` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.4).
|
||||
When no path is set, the path is considered the ["default path"](https://tools.ietf.org/html/rfc6265#section-5.1.4).
|
||||
|
||||
##### httpOnly
|
||||
|
||||
Enables the [`HttpOnly` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.6).
|
||||
When enabled, clients will not allow client-side JavaScript to see the cookie in `document.cookie`.
|
||||
|
||||
##### secure
|
||||
|
||||
Enables the [`Secure` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.5).
|
||||
When enabled, clients will only send the cookie back if the browser has a HTTPS connection.
|
||||
|
||||
##### partitioned
|
||||
|
||||
Enables the [`Partitioned` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/).
|
||||
When enabled, clients will only send the cookie back when the current domain _and_ top-level domain matches.
|
||||
|
||||
This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||
This also means clients may ignore this attribute until they understand it. More information
|
||||
about can be found in [the proposal](https://github.com/privacycg/CHIPS).
|
||||
|
||||
##### priority
|
||||
|
||||
Specifies the value for the [`Priority` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).
|
||||
|
||||
- `'low'` will set the `Priority` attribute to `Low`.
|
||||
- `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
|
||||
- `'high'` will set the `Priority` attribute to `High`.
|
||||
|
||||
More information about priority levels can be found in [the specification](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).
|
||||
|
||||
##### sameSite
|
||||
|
||||
Specifies the value for the [`SameSite` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).
|
||||
|
||||
- `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
||||
- `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
|
||||
- `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
|
||||
- `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
||||
|
||||
More information about enforcement levels can be found in [the specification](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).
|
||||
|
||||
## Example
|
||||
|
||||
The following example uses this module in conjunction with the Node.js core HTTP server
|
||||
to prompt a user for their name and display it back on future visits.
|
||||
|
||||
```js
|
||||
var cookie = require("cookie");
|
||||
var escapeHtml = require("escape-html");
|
||||
var http = require("http");
|
||||
var url = require("url");
|
||||
|
||||
function onRequest(req, res) {
|
||||
// Parse the query string
|
||||
var query = url.parse(req.url, true, true).query;
|
||||
|
||||
if (query && query.name) {
|
||||
// Set a new cookie with the name
|
||||
res.setHeader(
|
||||
"Set-Cookie",
|
||||
cookie.serialize("name", String(query.name), {
|
||||
httpOnly: true,
|
||||
maxAge: 60 * 60 * 24 * 7, // 1 week
|
||||
}),
|
||||
);
|
||||
|
||||
// Redirect back after setting cookie
|
||||
res.statusCode = 302;
|
||||
res.setHeader("Location", req.headers.referer || "/");
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the cookies on the request
|
||||
var cookies = cookie.parse(req.headers.cookie || "");
|
||||
|
||||
// Get the visitor name set in the cookie
|
||||
var name = cookies.name;
|
||||
|
||||
res.setHeader("Content-Type", "text/html; charset=UTF-8");
|
||||
|
||||
if (name) {
|
||||
res.write("<p>Welcome back, <b>" + escapeHtml(name) + "</b>!</p>");
|
||||
} else {
|
||||
res.write("<p>Hello, new visitor!</p>");
|
||||
}
|
||||
|
||||
res.write('<form method="GET">');
|
||||
res.write(
|
||||
'<input placeholder="enter your name" name="name"> <input type="submit" value="Set Name">',
|
||||
);
|
||||
res.end("</form>");
|
||||
}
|
||||
|
||||
http.createServer(onRequest).listen(3000);
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```sh
|
||||
npm test
|
||||
```
|
||||
|
||||
## Benchmark
|
||||
|
||||
```sh
|
||||
npm run bench
|
||||
```
|
||||
|
||||
```
|
||||
name hz min max mean p75 p99 p995 p999 rme samples
|
||||
· simple 8,566,313.09 0.0000 0.3694 0.0001 0.0001 0.0002 0.0002 0.0003 ±0.64% 4283157 fastest
|
||||
· decode 3,834,348.85 0.0001 0.2465 0.0003 0.0003 0.0003 0.0004 0.0006 ±0.38% 1917175
|
||||
· unquote 8,315,355.96 0.0000 0.3824 0.0001 0.0001 0.0002 0.0002 0.0003 ±0.72% 4157880
|
||||
· duplicates 1,944,765.97 0.0004 0.2959 0.0005 0.0005 0.0006 0.0006 0.0008 ±0.24% 972384
|
||||
· 10 cookies 675,345.67 0.0012 0.4328 0.0015 0.0015 0.0019 0.0020 0.0058 ±0.75% 337673
|
||||
· 100 cookies 61,040.71 0.0152 0.4092 0.0164 0.0160 0.0196 0.0228 0.2260 ±0.71% 30521 slowest
|
||||
✓ parse top-sites (15) 22945ms
|
||||
name hz min max mean p75 p99 p995 p999 rme samples
|
||||
· parse accounts.google.com 7,164,349.17 0.0000 0.0929 0.0001 0.0002 0.0002 0.0002 0.0003 ±0.09% 3582184
|
||||
· parse apple.com 7,817,686.84 0.0000 0.6048 0.0001 0.0001 0.0002 0.0002 0.0003 ±1.05% 3908844
|
||||
· parse cloudflare.com 7,189,841.70 0.0000 0.0390 0.0001 0.0002 0.0002 0.0002 0.0003 ±0.06% 3594921
|
||||
· parse docs.google.com 7,051,765.61 0.0000 0.0296 0.0001 0.0002 0.0002 0.0002 0.0003 ±0.06% 3525883
|
||||
· parse drive.google.com 7,349,104.77 0.0000 0.0368 0.0001 0.0001 0.0002 0.0002 0.0003 ±0.05% 3674553
|
||||
· parse en.wikipedia.org 1,929,909.49 0.0004 0.3598 0.0005 0.0005 0.0007 0.0007 0.0012 ±0.16% 964955
|
||||
· parse linkedin.com 2,225,658.01 0.0003 0.0595 0.0004 0.0005 0.0005 0.0005 0.0006 ±0.06% 1112830
|
||||
· parse maps.google.com 4,423,511.68 0.0001 0.0942 0.0002 0.0003 0.0003 0.0003 0.0005 ±0.08% 2211756
|
||||
· parse microsoft.com 3,387,601.88 0.0002 0.0725 0.0003 0.0003 0.0004 0.0004 0.0005 ±0.09% 1693801
|
||||
· parse play.google.com 7,375,980.86 0.0000 0.1994 0.0001 0.0001 0.0002 0.0002 0.0003 ±0.12% 3687991
|
||||
· parse support.google.com 4,912,267.94 0.0001 2.8958 0.0002 0.0002 0.0003 0.0003 0.0005 ±1.28% 2456134
|
||||
· parse www.google.com 3,443,035.87 0.0002 0.2783 0.0003 0.0003 0.0004 0.0004 0.0007 ±0.51% 1721518
|
||||
· parse youtu.be 1,910,492.87 0.0004 0.3490 0.0005 0.0005 0.0007 0.0007 0.0011 ±0.46% 955247
|
||||
· parse youtube.com 1,895,082.62 0.0004 0.7454 0.0005 0.0005 0.0006 0.0007 0.0013 ±0.64% 947542 slowest
|
||||
· parse example.com 21,582,835.27 0.0000 0.1095 0.0000 0.0000 0.0001 0.0001 0.0001 ±0.13% 10791418
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [RFC 6265: HTTP State Management Mechanism](https://tools.ietf.org/html/rfc6265)
|
||||
- [Same-site Cookies](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7)
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[ci-image]: https://img.shields.io/github/actions/workflow/status/jshttp/cookie/ci.yml
|
||||
[ci-url]: https://github.com/jshttp/cookie/actions/workflows/ci.yml?query=branch%3Amaster
|
||||
[coverage-image]: https://img.shields.io/codecov/c/github/jshttp/cookie/master
|
||||
[coverage-url]: https://app.codecov.io/gh/jshttp/cookie
|
||||
[npm-downloads-image]: https://img.shields.io/npm/dm/cookie
|
||||
[npm-url]: https://npmjs.org/package/cookie
|
||||
[npm-version-image]: https://img.shields.io/npm/v/cookie
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const Hook = require("./Hook");
|
||||
|
||||
class MultiHook {
|
||||
constructor(hooks, name = undefined) {
|
||||
this.hooks = hooks;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
tap(options, fn) {
|
||||
for (const hook of this.hooks) {
|
||||
hook.tap(options, fn);
|
||||
}
|
||||
}
|
||||
|
||||
tapAsync(options, fn) {
|
||||
for (const hook of this.hooks) {
|
||||
hook.tapAsync(options, fn);
|
||||
}
|
||||
}
|
||||
|
||||
tapPromise(options, fn) {
|
||||
for (const hook of this.hooks) {
|
||||
hook.tapPromise(options, fn);
|
||||
}
|
||||
}
|
||||
|
||||
isUsed() {
|
||||
for (const hook of this.hooks) {
|
||||
if (hook.isUsed()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
intercept(interceptor) {
|
||||
for (const hook of this.hooks) {
|
||||
hook.intercept(interceptor);
|
||||
}
|
||||
}
|
||||
|
||||
withOptions(options) {
|
||||
return new MultiHook(
|
||||
this.hooks.map(h => h.withOptions(options)),
|
||||
this.name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MultiHook;
|
||||
@@ -0,0 +1,331 @@
|
||||
import * as React from 'react'
|
||||
import invariant from 'tiny-invariant'
|
||||
import warning from 'tiny-warning'
|
||||
import {
|
||||
createControlledPromise,
|
||||
getLocationChangeInfo,
|
||||
isNotFound,
|
||||
isRedirect,
|
||||
pick,
|
||||
rootRouteId,
|
||||
} from '@tanstack/router-core'
|
||||
import { CatchBoundary, ErrorComponent } from './CatchBoundary'
|
||||
import { useRouterState } from './useRouterState'
|
||||
import { useRouter } from './useRouter'
|
||||
import { CatchNotFound } from './not-found'
|
||||
import { matchContext } from './matchContext'
|
||||
import { SafeFragment } from './SafeFragment'
|
||||
import { renderRouteNotFound } from './renderRouteNotFound'
|
||||
import { ScrollRestoration } from './scroll-restoration'
|
||||
import type { AnyRoute, ParsedLocation } from '@tanstack/router-core'
|
||||
|
||||
export const Match = React.memo(function MatchImpl({
|
||||
matchId,
|
||||
}: {
|
||||
matchId: string
|
||||
}) {
|
||||
const router = useRouter()
|
||||
const routeId = useRouterState({
|
||||
select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,
|
||||
})
|
||||
|
||||
invariant(
|
||||
routeId,
|
||||
`Could not find routeId for matchId "${matchId}". Please file an issue!`,
|
||||
)
|
||||
|
||||
const route: AnyRoute = router.routesById[routeId]
|
||||
|
||||
const PendingComponent =
|
||||
route.options.pendingComponent ?? router.options.defaultPendingComponent
|
||||
|
||||
const pendingElement = PendingComponent ? <PendingComponent /> : null
|
||||
|
||||
const routeErrorComponent =
|
||||
route.options.errorComponent ?? router.options.defaultErrorComponent
|
||||
|
||||
const routeOnCatch = route.options.onCatch ?? router.options.defaultOnCatch
|
||||
|
||||
const routeNotFoundComponent = route.isRoot
|
||||
? // If it's the root route, use the globalNotFound option, with fallback to the notFoundRoute's component
|
||||
(route.options.notFoundComponent ??
|
||||
router.options.notFoundRoute?.options.component)
|
||||
: route.options.notFoundComponent
|
||||
|
||||
const ResolvedSuspenseBoundary =
|
||||
// If we're on the root route, allow forcefully wrapping in suspense
|
||||
(!route.isRoot || route.options.wrapInSuspense) &&
|
||||
(route.options.wrapInSuspense ??
|
||||
PendingComponent ??
|
||||
(route.options.errorComponent as any)?.preload)
|
||||
? React.Suspense
|
||||
: SafeFragment
|
||||
|
||||
const ResolvedCatchBoundary = routeErrorComponent
|
||||
? CatchBoundary
|
||||
: SafeFragment
|
||||
|
||||
const ResolvedNotFoundBoundary = routeNotFoundComponent
|
||||
? CatchNotFound
|
||||
: SafeFragment
|
||||
|
||||
const resetKey = useRouterState({
|
||||
select: (s) => s.loadedAt,
|
||||
})
|
||||
|
||||
const parentRouteId = useRouterState({
|
||||
select: (s) => {
|
||||
const index = s.matches.findIndex((d) => d.id === matchId)
|
||||
return s.matches[index - 1]?.routeId as string
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<matchContext.Provider value={matchId}>
|
||||
<ResolvedSuspenseBoundary fallback={pendingElement}>
|
||||
<ResolvedCatchBoundary
|
||||
getResetKey={() => resetKey}
|
||||
errorComponent={routeErrorComponent || ErrorComponent}
|
||||
onCatch={(error, errorInfo) => {
|
||||
// Forward not found errors (we don't want to show the error component for these)
|
||||
if (isNotFound(error)) throw error
|
||||
warning(false, `Error in route match: ${matchId}`)
|
||||
routeOnCatch?.(error, errorInfo)
|
||||
}}
|
||||
>
|
||||
<ResolvedNotFoundBoundary
|
||||
fallback={(error) => {
|
||||
// If the current not found handler doesn't exist or it has a
|
||||
// route ID which doesn't match the current route, rethrow the error
|
||||
if (
|
||||
!routeNotFoundComponent ||
|
||||
(error.routeId && error.routeId !== routeId) ||
|
||||
(!error.routeId && !route.isRoot)
|
||||
)
|
||||
throw error
|
||||
|
||||
return React.createElement(routeNotFoundComponent, error as any)
|
||||
}}
|
||||
>
|
||||
<MatchInner matchId={matchId} />
|
||||
</ResolvedNotFoundBoundary>
|
||||
</ResolvedCatchBoundary>
|
||||
</ResolvedSuspenseBoundary>
|
||||
</matchContext.Provider>
|
||||
{parentRouteId === rootRouteId && router.options.scrollRestoration ? (
|
||||
<>
|
||||
<OnRendered />
|
||||
<ScrollRestoration />
|
||||
</>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
// On Rendered can't happen above the root layout because it actually
|
||||
// renders a dummy dom element to track the rendered state of the app.
|
||||
// We render a script tag with a key that changes based on the current
|
||||
// location state.key. Also, because it's below the root layout, it
|
||||
// allows us to fire onRendered events even after a hydration mismatch
|
||||
// error that occurred above the root layout (like bad head/link tags,
|
||||
// which is common).
|
||||
function OnRendered() {
|
||||
const router = useRouter()
|
||||
|
||||
const prevLocationRef = React.useRef<undefined | ParsedLocation<{}>>(
|
||||
undefined,
|
||||
)
|
||||
|
||||
return (
|
||||
<script
|
||||
key={router.state.resolvedLocation?.state.key}
|
||||
suppressHydrationWarning
|
||||
ref={(el) => {
|
||||
if (
|
||||
el &&
|
||||
(prevLocationRef.current === undefined ||
|
||||
prevLocationRef.current.href !==
|
||||
router.state.resolvedLocation?.href)
|
||||
) {
|
||||
router.emit({
|
||||
type: 'onRendered',
|
||||
...getLocationChangeInfo(router.state),
|
||||
})
|
||||
prevLocationRef.current = router.state.resolvedLocation
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export const MatchInner = React.memo(function MatchInnerImpl({
|
||||
matchId,
|
||||
}: {
|
||||
matchId: string
|
||||
}): any {
|
||||
const router = useRouter()
|
||||
|
||||
const { match, key, routeId } = useRouterState({
|
||||
select: (s) => {
|
||||
const matchIndex = s.matches.findIndex((d) => d.id === matchId)
|
||||
const match = s.matches[matchIndex]!
|
||||
const routeId = match.routeId as string
|
||||
|
||||
const remountFn =
|
||||
(router.routesById[routeId] as AnyRoute).options.remountDeps ??
|
||||
router.options.defaultRemountDeps
|
||||
const remountDeps = remountFn?.({
|
||||
routeId,
|
||||
loaderDeps: match.loaderDeps,
|
||||
params: match._strictParams,
|
||||
search: match._strictSearch,
|
||||
})
|
||||
const key = remountDeps ? JSON.stringify(remountDeps) : undefined
|
||||
|
||||
return {
|
||||
key,
|
||||
routeId,
|
||||
match: pick(match, ['id', 'status', 'error']),
|
||||
}
|
||||
},
|
||||
structuralSharing: true as any,
|
||||
})
|
||||
|
||||
const route = router.routesById[routeId] as AnyRoute
|
||||
|
||||
const out = React.useMemo(() => {
|
||||
const Comp = route.options.component ?? router.options.defaultComponent
|
||||
if (Comp) {
|
||||
return <Comp key={key} />
|
||||
}
|
||||
return <Outlet />
|
||||
}, [key, route.options.component, router.options.defaultComponent])
|
||||
|
||||
const RouteErrorComponent =
|
||||
(route.options.errorComponent ?? router.options.defaultErrorComponent) ||
|
||||
ErrorComponent
|
||||
|
||||
if (match.status === 'notFound') {
|
||||
invariant(isNotFound(match.error), 'Expected a notFound error')
|
||||
return renderRouteNotFound(router, route, match.error)
|
||||
}
|
||||
|
||||
if (match.status === 'redirected') {
|
||||
// Redirects should be handled by the router transition. If we happen to
|
||||
// encounter a redirect here, it's a bug. Let's warn, but render nothing.
|
||||
invariant(isRedirect(match.error), 'Expected a redirect error')
|
||||
|
||||
// warning(
|
||||
// false,
|
||||
// 'Tried to render a redirected route match! This is a weird circumstance, please file an issue!',
|
||||
// )
|
||||
throw router.getMatch(match.id)?.loadPromise
|
||||
}
|
||||
|
||||
if (match.status === 'error') {
|
||||
// If we're on the server, we need to use React's new and super
|
||||
// wonky api for throwing errors from a server side render inside
|
||||
// of a suspense boundary. This is the only way to get
|
||||
// renderToPipeableStream to not hang indefinitely.
|
||||
// We'll serialize the error and rethrow it on the client.
|
||||
if (router.isServer) {
|
||||
return (
|
||||
<RouteErrorComponent
|
||||
error={match.error as any}
|
||||
reset={undefined as any}
|
||||
info={{
|
||||
componentStack: '',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
throw match.error
|
||||
}
|
||||
|
||||
if (match.status === 'pending') {
|
||||
// We're pending, and if we have a minPendingMs, we need to wait for it
|
||||
const pendingMinMs =
|
||||
route.options.pendingMinMs ?? router.options.defaultPendingMinMs
|
||||
|
||||
if (pendingMinMs && !router.getMatch(match.id)?.minPendingPromise) {
|
||||
// Create a promise that will resolve after the minPendingMs
|
||||
if (!router.isServer) {
|
||||
const minPendingPromise = createControlledPromise<void>()
|
||||
|
||||
Promise.resolve().then(() => {
|
||||
router.updateMatch(match.id, (prev) => ({
|
||||
...prev,
|
||||
minPendingPromise,
|
||||
}))
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
minPendingPromise.resolve()
|
||||
|
||||
// We've handled the minPendingPromise, so we can delete it
|
||||
router.updateMatch(match.id, (prev) => ({
|
||||
...prev,
|
||||
minPendingPromise: undefined,
|
||||
}))
|
||||
}, pendingMinMs)
|
||||
}
|
||||
}
|
||||
throw router.getMatch(match.id)?.loadPromise
|
||||
}
|
||||
|
||||
return out
|
||||
})
|
||||
|
||||
export const Outlet = React.memo(function OutletImpl() {
|
||||
const router = useRouter()
|
||||
const matchId = React.useContext(matchContext)
|
||||
const routeId = useRouterState({
|
||||
select: (s) => s.matches.find((d) => d.id === matchId)?.routeId as string,
|
||||
})
|
||||
|
||||
const route = router.routesById[routeId]!
|
||||
|
||||
const parentGlobalNotFound = useRouterState({
|
||||
select: (s) => {
|
||||
const matches = s.matches
|
||||
const parentMatch = matches.find((d) => d.id === matchId)
|
||||
invariant(
|
||||
parentMatch,
|
||||
`Could not find parent match for matchId "${matchId}"`,
|
||||
)
|
||||
return parentMatch.globalNotFound
|
||||
},
|
||||
})
|
||||
|
||||
const childMatchId = useRouterState({
|
||||
select: (s) => {
|
||||
const matches = s.matches
|
||||
const index = matches.findIndex((d) => d.id === matchId)
|
||||
return matches[index + 1]?.id
|
||||
},
|
||||
})
|
||||
|
||||
if (parentGlobalNotFound) {
|
||||
return renderRouteNotFound(router, route, undefined)
|
||||
}
|
||||
|
||||
if (!childMatchId) {
|
||||
return null
|
||||
}
|
||||
|
||||
const nextMatch = <Match matchId={childMatchId} />
|
||||
|
||||
const pendingElement = router.options.defaultPendingComponent ? (
|
||||
<router.options.defaultPendingComponent />
|
||||
) : null
|
||||
|
||||
if (matchId === rootRouteId) {
|
||||
return (
|
||||
<React.Suspense fallback={pendingElement}>{nextMatch}</React.Suspense>
|
||||
)
|
||||
}
|
||||
|
||||
return nextMatch
|
||||
})
|
||||
@@ -0,0 +1 @@
|
||||
module.exports={A:{A:{"1":"A B","2":"K D E F mC"},B:{"1":"0 9 C L M G N O P Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I"},C:{"1":"0 1 2 3 4 5 6 7 8 9 E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC oC pC","2":"nC LC J PB K D qC rC"},D:{"1":"0 1 2 3 4 5 6 7 8 9 G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC","16":"J PB K D E F A B C L M"},E:{"1":"K D E F A B C L M G uC vC wC TC FC GC xC yC zC UC VC HC 0C IC WC XC YC ZC aC 1C JC bC cC dC eC fC 2C KC gC hC iC jC 3C","2":"J PB sC SC tC"},F:{"1":"0 1 2 3 4 5 6 7 8 C G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB wB xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z 8C GC","2":"F 4C 5C","16":"B 6C 7C FC kC"},G:{"1":"E BD CD DD ED FD GD HD ID JD KD LD MD ND OD PD QD RD SD UC VC HC TD IC WC XC YC ZC aC UD JC bC cC dC eC fC VD KC gC hC iC jC","2":"SC 9C lC AD"},H:{"2":"WD"},I:{"1":"I bD cD","2":"LC J XD YD ZD aD lC"},J:{"1":"A","2":"D"},K:{"1":"C H kC GC","2":"A","16":"B FC"},L:{"1":"I"},M:{"1":"EC"},N:{"1":"A B"},O:{"1":"HC"},P:{"1":"1 2 3 4 5 6 7 8 J dD eD fD gD hD TC iD jD kD lD mD IC JC KC nD"},Q:{"1":"oD"},R:{"1":"pD"},S:{"1":"qD rD"}},B:5,C:"FileReaderSync",D:true};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports={C:{"34":0.003,"52":0.009,"59":0.003,"68":0.003,"71":0.003,"72":0.003,"74":0.003,"78":0.01799,"82":0.003,"88":0.003,"89":0.003,"97":0.003,"103":0.009,"104":0.012,"106":0.003,"107":0.003,"111":0.003,"112":0.003,"113":0.03899,"115":0.61779,"118":0.009,"120":0.04199,"121":0.006,"123":0.003,"125":0.003,"127":0.02399,"128":0.07498,"129":0.009,"130":0.012,"131":0.009,"132":0.012,"133":0.02999,"134":0.02999,"135":0.6118,"136":1.89237,"137":0.015,_:"2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 53 54 55 56 57 58 60 61 62 63 64 65 66 67 69 70 73 75 76 77 79 80 81 83 84 85 86 87 90 91 92 93 94 95 96 98 99 100 101 102 105 108 109 110 114 116 117 119 122 124 126 138 139 140 3.5 3.6"},D:{"11":0.02999,"32":0.006,"39":0.003,"40":0.003,"41":0.003,"42":0.012,"43":0.01799,"44":0.003,"45":0.003,"46":0.003,"47":0.003,"48":0.003,"49":0.006,"50":0.003,"51":0.003,"53":0.003,"54":0.003,"55":0.009,"56":0.003,"57":0.003,"58":0.003,"59":0.003,"60":0.006,"61":0.009,"63":0.003,"64":0.003,"66":0.003,"68":0.009,"69":0.006,"70":0.009,"71":0.006,"72":0.003,"73":0.003,"74":0.003,"77":0.003,"79":0.012,"80":0.02099,"81":0.01799,"83":0.003,"84":0.003,"86":0.009,"87":0.006,"88":0.02399,"89":0.003,"90":0.01799,"91":0.006,"94":0.012,"95":0.04199,"98":0.003,"99":0.009,"100":0.003,"101":0.02399,"102":0.006,"103":0.02999,"104":0.009,"105":0.015,"106":0.02999,"108":0.04499,"109":1.74842,"110":0.006,"111":0.01799,"112":0.003,"113":0.006,"114":0.03599,"115":0.006,"116":0.04499,"117":0.003,"118":0.012,"119":0.05098,"120":0.04499,"121":0.02399,"122":0.05698,"123":0.02699,"124":0.02099,"125":0.03899,"126":0.04199,"127":0.03299,"128":0.08097,"129":0.07498,"130":0.06598,"131":0.39587,"132":0.27291,"133":3.85971,"134":7.75242,"135":0.015,_:"4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 33 34 35 36 37 38 52 62 65 67 75 76 78 85 92 93 96 97 107 136 137 138"},F:{"36":0.01799,"38":0.003,"42":0.003,"60":0.003,"79":0.012,"82":0.006,"85":0.009,"86":0.003,"87":0.04499,"88":0.006,"90":0.003,"95":0.06298,"97":0.003,"108":0.003,"112":0.003,"113":0.003,"114":0.003,"115":0.009,"116":0.05698,"117":0.72576,_:"9 11 12 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 37 39 40 41 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 80 81 83 84 89 91 92 93 94 96 98 99 100 101 102 103 104 105 106 107 109 110 111 9.5-9.6 10.0-10.1 10.5 10.6 11.1 11.5 11.6","12.1":0.003},B:{"14":0.003,"15":0.003,"17":0.006,"18":0.01799,"84":0.006,"89":0.009,"90":0.003,"92":0.07498,"100":0.006,"109":0.01799,"114":0.003,"115":0.003,"116":0.012,"120":0.003,"122":0.01799,"123":0.003,"126":0.006,"127":0.003,"128":0.006,"129":0.003,"130":0.015,"131":0.08697,"132":0.15595,"133":0.77674,"134":1.83539,_:"12 13 16 79 80 81 83 85 86 87 88 91 93 94 95 96 97 98 99 101 102 103 104 105 106 107 108 110 111 112 113 117 118 119 121 124 125"},E:{"14":0.006,_:"0 4 5 6 7 8 9 10 11 12 13 15 3.1 3.2 5.1 6.1 7.1 9.1 10.1 11.1 12.1 15.1 15.2-15.3 15.4 15.5 16.0 16.2 16.4 16.5 17.0 18.4","13.1":0.015,"14.1":0.003,"15.6":0.02399,"16.1":0.003,"16.3":0.02699,"16.6":0.10497,"17.1":0.009,"17.2":0.006,"17.3":0.003,"17.4":0.006,"17.5":0.015,"17.6":0.03299,"18.0":0.003,"18.1":0.009,"18.2":0.009,"18.3":0.14395},G:{"8":0,"3.2":0,"4.0-4.1":0,"4.2-4.3":0.00079,"5.0-5.1":0,"6.0-6.1":0.00238,"7.0-7.1":0.00159,"8.1-8.4":0,"9.0-9.2":0.00119,"9.3":0.00556,"10.0-10.2":0.0004,"10.3":0.00913,"11.0-11.2":0.04208,"11.3-11.4":0.00278,"12.0-12.1":0.00159,"12.2-12.5":0.0393,"13.0-13.1":0.00079,"13.2":0.00119,"13.3":0.00159,"13.4-13.7":0.00556,"14.0-14.4":0.0139,"14.5-14.8":0.01667,"15.0-15.1":0.00913,"15.2-15.3":0.00913,"15.4":0.01112,"15.5":0.0127,"15.6-15.8":0.15642,"16.0":0.02223,"16.1":0.04566,"16.2":0.02382,"16.3":0.04129,"16.4":0.00913,"16.5":0.01707,"16.6-16.7":0.18541,"17.0":0.01112,"17.1":0.01985,"17.2":0.01509,"17.3":0.02104,"17.4":0.04208,"17.5":0.0937,"17.6-17.7":0.27195,"18.0":0.07623,"18.1":0.24932,"18.2":0.11156,"18.3":2.33166,"18.4":0.03454},P:{"4":0.07402,"21":0.01057,"22":0.01057,"23":0.01057,"24":0.01057,"25":0.01057,"26":0.03172,"27":0.29608,_:"20 5.0-5.4 8.2 9.2 10.1 11.1-11.2 13.0 14.0 16.0 17.0 18.0 19.0","6.2-6.4":0.01057,"7.2-7.4":0.03172,"12.0":0.01057,"15.0":0.01057},I:{"0":0.24456,"3":0,"4":0,"2.1":0,"2.2":0,"2.3":0,"4.1":0,"4.2-4.3":0.00007,"4.4":0,"4.4.3-4.4.4":0.00027},K:{"0":1.19052,_:"10 11 12 11.1 11.5 12.1"},A:{"9":0.0045,"11":0.0045,_:"6 7 8 10 5.5"},S:{"2.5":0.39211,_:"3.0-3.1"},J:{_:"7 10"},N:{_:"10 11"},R:{_:"0"},M:{"0":0.16105},Q:{"14.9":0.007},O:{"0":0.55316},H:{"0":0.63},L:{"0":68.41058}};
|
||||
@@ -0,0 +1,477 @@
|
||||
import type { Angle, CssColor, Rule, CustomProperty, EnvironmentVariable, Function, Image, LengthValue, MediaQuery, Declaration, Ratio, Resolution, Selector, SupportsCondition, Time, Token, TokenOrValue, UnknownAtRule, Url, Variable, StyleRule, DeclarationBlock, ParsedComponent, Multiplier, StyleSheet, Location2 } from './ast';
|
||||
import { Targets, Features } from './targets';
|
||||
|
||||
export * from './ast';
|
||||
|
||||
export { Targets, Features };
|
||||
|
||||
export interface TransformOptions<C extends CustomAtRules> {
|
||||
/** The filename being transformed. Used for error messages and source maps. */
|
||||
filename: string,
|
||||
/** The source code to transform. */
|
||||
code: Uint8Array,
|
||||
/** Whether to enable minification. */
|
||||
minify?: boolean,
|
||||
/** Whether to output a source map. */
|
||||
sourceMap?: boolean,
|
||||
/** An input source map to extend. */
|
||||
inputSourceMap?: string,
|
||||
/**
|
||||
* An optional project root path, used as the source root in the output source map.
|
||||
* Also used to generate relative paths for sources used in CSS module hashes.
|
||||
*/
|
||||
projectRoot?: string,
|
||||
/** The browser targets for the generated code. */
|
||||
targets?: Targets,
|
||||
/** Features that should always be compiled, even when supported by targets. */
|
||||
include?: number,
|
||||
/** Features that should never be compiled, even when unsupported by targets. */
|
||||
exclude?: number,
|
||||
/** Whether to enable parsing various draft syntax. */
|
||||
drafts?: Drafts,
|
||||
/** Whether to enable various non-standard syntax. */
|
||||
nonStandard?: NonStandard,
|
||||
/** Whether to compile this file as a CSS module. */
|
||||
cssModules?: boolean | CSSModulesConfig,
|
||||
/**
|
||||
* Whether to analyze dependencies (e.g. `@import` and `url()`).
|
||||
* When enabled, `@import` rules are removed, and `url()` dependencies
|
||||
* are replaced with hashed placeholders that can be replaced with the final
|
||||
* urls later (after bundling). Dependencies are returned as part of the result.
|
||||
*/
|
||||
analyzeDependencies?: boolean | DependencyOptions,
|
||||
/**
|
||||
* Replaces user action pseudo classes with class names that can be applied from JavaScript.
|
||||
* This is useful for polyfills, for example.
|
||||
*/
|
||||
pseudoClasses?: PseudoClasses,
|
||||
/**
|
||||
* A list of class names, ids, and custom identifiers (e.g. @keyframes) that are known
|
||||
* to be unused. These will be removed during minification. Note that these are not
|
||||
* selectors but individual names (without any . or # prefixes).
|
||||
*/
|
||||
unusedSymbols?: string[],
|
||||
/**
|
||||
* Whether to ignore invalid rules and declarations rather than erroring.
|
||||
* When enabled, warnings are returned, and the invalid rule or declaration is
|
||||
* omitted from the output code.
|
||||
*/
|
||||
errorRecovery?: boolean,
|
||||
/**
|
||||
* An AST visitor object. This allows custom transforms or analysis to be implemented in JavaScript.
|
||||
* Multiple visitors can be composed into one using the `composeVisitors` function.
|
||||
* For optimal performance, visitors should be as specific as possible about what types of values
|
||||
* they care about so that JavaScript has to be called as little as possible.
|
||||
*/
|
||||
visitor?: Visitor<C>,
|
||||
/**
|
||||
* Defines how to parse custom CSS at-rules. Each at-rule can have a prelude, defined using a CSS
|
||||
* [syntax string](https://drafts.css-houdini.org/css-properties-values-api/#syntax-strings), and
|
||||
* a block body. The body can be a declaration list, rule list, or style block as defined in the
|
||||
* [css spec](https://drafts.csswg.org/css-syntax/#declaration-rule-list).
|
||||
*/
|
||||
customAtRules?: C
|
||||
}
|
||||
|
||||
// This is a hack to make TS still provide autocomplete for `property` vs. just making it `string`.
|
||||
type PropertyStart = '-' | '_' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z';
|
||||
export type ReturnedDeclaration = Declaration | {
|
||||
/** The property name. */
|
||||
property: `${PropertyStart}${string}`,
|
||||
/** The raw string value for the declaration. */
|
||||
raw: string
|
||||
};
|
||||
|
||||
export type ReturnedMediaQuery = MediaQuery | {
|
||||
/** The raw string value for the media query. */
|
||||
raw: string
|
||||
};
|
||||
|
||||
type FindByType<Union, Name> = Union extends { type: Name } ? Union : never;
|
||||
export type ReturnedRule = Rule<ReturnedDeclaration, ReturnedMediaQuery>;
|
||||
type RequiredValue<Rule> = Rule extends { value: object }
|
||||
? Rule['value'] extends StyleRule
|
||||
? Rule & { value: Required<StyleRule> & { declarations: Required<DeclarationBlock> } }
|
||||
: Rule & { value: Required<Rule['value']> }
|
||||
: Rule;
|
||||
type RuleVisitor<R = RequiredValue<Rule>> = ((rule: R) => ReturnedRule | ReturnedRule[] | void);
|
||||
type MappedRuleVisitors = {
|
||||
[Name in Exclude<Rule['type'], 'unknown' | 'custom'>]?: RuleVisitor<RequiredValue<FindByType<Rule, Name>>>;
|
||||
}
|
||||
|
||||
type UnknownVisitors<T> = {
|
||||
[name: string]: RuleVisitor<T>
|
||||
}
|
||||
|
||||
type CustomVisitors<T extends CustomAtRules> = {
|
||||
[Name in keyof T]?: RuleVisitor<CustomAtRule<Name, T[Name]>>
|
||||
};
|
||||
|
||||
type AnyCustomAtRule<C extends CustomAtRules> = {
|
||||
[Key in keyof C]: CustomAtRule<Key, C[Key]>
|
||||
}[keyof C];
|
||||
|
||||
type RuleVisitors<C extends CustomAtRules> = MappedRuleVisitors & {
|
||||
unknown?: UnknownVisitors<UnknownAtRule> | Omit<RuleVisitor<UnknownAtRule>, keyof CallableFunction>,
|
||||
custom?: CustomVisitors<C> | Omit<RuleVisitor<AnyCustomAtRule<C>>, keyof CallableFunction>
|
||||
};
|
||||
|
||||
type PreludeTypes = Exclude<ParsedComponent['type'], 'literal' | 'repeated' | 'token'>;
|
||||
type SyntaxString = `<${PreludeTypes}>` | `<${PreludeTypes}>+` | `<${PreludeTypes}>#` | (string & {});
|
||||
type ComponentTypes = {
|
||||
[Key in PreludeTypes as `<${Key}>`]: FindByType<ParsedComponent, Key>
|
||||
};
|
||||
|
||||
type Repetitions = {
|
||||
[Key in PreludeTypes as `<${Key}>+` | `<${Key}>#`]: {
|
||||
type: "repeated",
|
||||
value: {
|
||||
components: FindByType<ParsedComponent, Key>[],
|
||||
multiplier: Multiplier
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
type MappedPrelude = ComponentTypes & Repetitions;
|
||||
type MappedBody<P extends CustomAtRuleDefinition['body']> = P extends 'style-block' ? 'rule-list' : P;
|
||||
interface CustomAtRule<N, R extends CustomAtRuleDefinition> {
|
||||
name: N,
|
||||
prelude: R['prelude'] extends keyof MappedPrelude ? MappedPrelude[R['prelude']] : ParsedComponent,
|
||||
body: FindByType<CustomAtRuleBody, MappedBody<R['body']>>,
|
||||
loc: Location2
|
||||
}
|
||||
|
||||
type CustomAtRuleBody = {
|
||||
type: 'declaration-list',
|
||||
value: Required<DeclarationBlock>
|
||||
} | {
|
||||
type: 'rule-list',
|
||||
value: RequiredValue<Rule>[]
|
||||
};
|
||||
|
||||
type FindProperty<Union, Name> = Union extends { property: Name } ? Union : never;
|
||||
type DeclarationVisitor<P = Declaration> = ((property: P) => ReturnedDeclaration | ReturnedDeclaration[] | void);
|
||||
type MappedDeclarationVisitors = {
|
||||
[Name in Exclude<Declaration['property'], 'unparsed' | 'custom'>]?: DeclarationVisitor<FindProperty<Declaration, Name> | FindProperty<Declaration, 'unparsed'>>;
|
||||
}
|
||||
|
||||
type CustomPropertyVisitors = {
|
||||
[name: string]: DeclarationVisitor<CustomProperty>
|
||||
}
|
||||
|
||||
type DeclarationVisitors = MappedDeclarationVisitors & {
|
||||
custom?: CustomPropertyVisitors | DeclarationVisitor<CustomProperty>
|
||||
}
|
||||
|
||||
interface RawValue {
|
||||
/** A raw string value which will be parsed like CSS. */
|
||||
raw: string
|
||||
}
|
||||
|
||||
type TokenReturnValue = TokenOrValue | TokenOrValue[] | RawValue | void;
|
||||
type TokenVisitor = (token: Token) => TokenReturnValue;
|
||||
type VisitableTokenTypes = 'ident' | 'at-keyword' | 'hash' | 'id-hash' | 'string' | 'number' | 'percentage' | 'dimension';
|
||||
type TokenVisitors = {
|
||||
[Name in VisitableTokenTypes]?: (token: FindByType<Token, Name>) => TokenReturnValue;
|
||||
}
|
||||
|
||||
type FunctionVisitor = (fn: Function) => TokenReturnValue;
|
||||
type EnvironmentVariableVisitor = (env: EnvironmentVariable) => TokenReturnValue;
|
||||
type EnvironmentVariableVisitors = {
|
||||
[name: string]: EnvironmentVariableVisitor
|
||||
};
|
||||
|
||||
export interface Visitor<C extends CustomAtRules> {
|
||||
StyleSheet?(stylesheet: StyleSheet): StyleSheet<ReturnedDeclaration, ReturnedMediaQuery> | void;
|
||||
StyleSheetExit?(stylesheet: StyleSheet): StyleSheet<ReturnedDeclaration, ReturnedMediaQuery> | void;
|
||||
Rule?: RuleVisitor | RuleVisitors<C>;
|
||||
RuleExit?: RuleVisitor | RuleVisitors<C>;
|
||||
Declaration?: DeclarationVisitor | DeclarationVisitors;
|
||||
DeclarationExit?: DeclarationVisitor | DeclarationVisitors;
|
||||
Url?(url: Url): Url | void;
|
||||
Color?(color: CssColor): CssColor | void;
|
||||
Image?(image: Image): Image | void;
|
||||
ImageExit?(image: Image): Image | void;
|
||||
Length?(length: LengthValue): LengthValue | void;
|
||||
Angle?(angle: Angle): Angle | void;
|
||||
Ratio?(ratio: Ratio): Ratio | void;
|
||||
Resolution?(resolution: Resolution): Resolution | void;
|
||||
Time?(time: Time): Time | void;
|
||||
CustomIdent?(ident: string): string | void;
|
||||
DashedIdent?(ident: string): string | void;
|
||||
MediaQuery?(query: MediaQuery): ReturnedMediaQuery | ReturnedMediaQuery[] | void;
|
||||
MediaQueryExit?(query: MediaQuery): ReturnedMediaQuery | ReturnedMediaQuery[] | void;
|
||||
SupportsCondition?(condition: SupportsCondition): SupportsCondition;
|
||||
SupportsConditionExit?(condition: SupportsCondition): SupportsCondition;
|
||||
Selector?(selector: Selector): Selector | Selector[] | void;
|
||||
Token?: TokenVisitor | TokenVisitors;
|
||||
Function?: FunctionVisitor | { [name: string]: FunctionVisitor };
|
||||
FunctionExit?: FunctionVisitor | { [name: string]: FunctionVisitor };
|
||||
Variable?(variable: Variable): TokenReturnValue;
|
||||
VariableExit?(variable: Variable): TokenReturnValue;
|
||||
EnvironmentVariable?: EnvironmentVariableVisitor | EnvironmentVariableVisitors;
|
||||
EnvironmentVariableExit?: EnvironmentVariableVisitor | EnvironmentVariableVisitors;
|
||||
}
|
||||
|
||||
export interface CustomAtRules {
|
||||
[name: string]: CustomAtRuleDefinition
|
||||
}
|
||||
|
||||
export interface CustomAtRuleDefinition {
|
||||
/**
|
||||
* Defines the syntax for a custom at-rule prelude. The value should be a
|
||||
* CSS [syntax string](https://drafts.css-houdini.org/css-properties-values-api/#syntax-strings)
|
||||
* representing the types of values that are accepted. This property may be omitted or
|
||||
* set to null to indicate that no prelude is accepted.
|
||||
*/
|
||||
prelude?: SyntaxString | null,
|
||||
/**
|
||||
* Defines the type of body contained within the at-rule block.
|
||||
* - declaration-list: A CSS declaration list, as in a style rule.
|
||||
* - rule-list: A list of CSS rules, as supported within a non-nested
|
||||
* at-rule such as `@media` or `@supports`.
|
||||
* - style-block: Both a declaration list and rule list, as accepted within
|
||||
* a nested at-rule within a style rule (e.g. `@media` inside a style rule
|
||||
* with directly nested declarations).
|
||||
*/
|
||||
body?: 'declaration-list' | 'rule-list' | 'style-block' | null
|
||||
}
|
||||
|
||||
export interface DependencyOptions {
|
||||
/** Whether to preserve `@import` rules rather than removing them. */
|
||||
preserveImports?: boolean
|
||||
}
|
||||
|
||||
export type BundleOptions<C extends CustomAtRules> = Omit<TransformOptions<C>, 'code'>;
|
||||
|
||||
export interface BundleAsyncOptions<C extends CustomAtRules> extends BundleOptions<C> {
|
||||
resolver?: Resolver;
|
||||
}
|
||||
|
||||
/** Custom resolver to use when loading CSS files. */
|
||||
export interface Resolver {
|
||||
/** Read the given file and return its contents as a string. */
|
||||
read?: (file: string) => string | Promise<string>;
|
||||
|
||||
/**
|
||||
* Resolve the given CSS import specifier from the provided originating file to a
|
||||
* path which gets passed to `read()`.
|
||||
*/
|
||||
resolve?: (specifier: string, originatingFile: string) => string | Promise<string>;
|
||||
}
|
||||
|
||||
export interface Drafts {
|
||||
/** Whether to enable @custom-media rules. */
|
||||
customMedia?: boolean
|
||||
}
|
||||
|
||||
export interface NonStandard {
|
||||
/** Whether to enable the non-standard >>> and /deep/ selector combinators used by Angular and Vue. */
|
||||
deepSelectorCombinator?: boolean
|
||||
}
|
||||
|
||||
export interface PseudoClasses {
|
||||
hover?: string,
|
||||
active?: string,
|
||||
focus?: string,
|
||||
focusVisible?: string,
|
||||
focusWithin?: string
|
||||
}
|
||||
|
||||
export interface TransformResult {
|
||||
/** The transformed code. */
|
||||
code: Uint8Array,
|
||||
/** The generated source map, if enabled. */
|
||||
map: Uint8Array | void,
|
||||
/** CSS module exports, if enabled. */
|
||||
exports: CSSModuleExports | void,
|
||||
/** CSS module references, if `dashedIdents` is enabled. */
|
||||
references: CSSModuleReferences,
|
||||
/** `@import` and `url()` dependencies, if enabled. */
|
||||
dependencies: Dependency[] | void,
|
||||
/** Warnings that occurred during compilation. */
|
||||
warnings: Warning[]
|
||||
}
|
||||
|
||||
export interface Warning {
|
||||
message: string,
|
||||
type: string,
|
||||
value?: any,
|
||||
loc: ErrorLocation
|
||||
}
|
||||
|
||||
export interface CSSModulesConfig {
|
||||
/** The pattern to use when renaming class names and other identifiers. Default is `[hash]_[local]`. */
|
||||
pattern?: string,
|
||||
/** Whether to rename dashed identifiers, e.g. custom properties. */
|
||||
dashedIdents?: boolean,
|
||||
/** Whether to enable hashing for `@keyframes`. */
|
||||
animation?: boolean,
|
||||
/** Whether to enable hashing for CSS grid identifiers. */
|
||||
grid?: boolean,
|
||||
/** Whether to enable hashing for `@container` names. */
|
||||
container?: boolean,
|
||||
/** Whether to enable hashing for custom identifiers. */
|
||||
customIdents?: boolean,
|
||||
/** Whether to require at least one class or id selector in each rule. */
|
||||
pure?: boolean
|
||||
}
|
||||
|
||||
export type CSSModuleExports = {
|
||||
/** Maps exported (i.e. original) names to local names. */
|
||||
[name: string]: CSSModuleExport
|
||||
};
|
||||
|
||||
export interface CSSModuleExport {
|
||||
/** The local (compiled) name for this export. */
|
||||
name: string,
|
||||
/** Whether the export is referenced in this file. */
|
||||
isReferenced: boolean,
|
||||
/** Other names that are composed by this export. */
|
||||
composes: CSSModuleReference[]
|
||||
}
|
||||
|
||||
export type CSSModuleReferences = {
|
||||
/** Maps placeholder names to references. */
|
||||
[name: string]: DependencyCSSModuleReference,
|
||||
};
|
||||
|
||||
export type CSSModuleReference = LocalCSSModuleReference | GlobalCSSModuleReference | DependencyCSSModuleReference;
|
||||
|
||||
export interface LocalCSSModuleReference {
|
||||
type: 'local',
|
||||
/** The local (compiled) name for the reference. */
|
||||
name: string,
|
||||
}
|
||||
|
||||
export interface GlobalCSSModuleReference {
|
||||
type: 'global',
|
||||
/** The referenced global name. */
|
||||
name: string,
|
||||
}
|
||||
|
||||
export interface DependencyCSSModuleReference {
|
||||
type: 'dependency',
|
||||
/** The name to reference within the dependency. */
|
||||
name: string,
|
||||
/** The dependency specifier for the referenced file. */
|
||||
specifier: string
|
||||
}
|
||||
|
||||
export type Dependency = ImportDependency | UrlDependency;
|
||||
|
||||
export interface ImportDependency {
|
||||
type: 'import',
|
||||
/** The url of the `@import` dependency. */
|
||||
url: string,
|
||||
/** The media query for the `@import` rule. */
|
||||
media: string | null,
|
||||
/** The `supports()` query for the `@import` rule. */
|
||||
supports: string | null,
|
||||
/** The source location where the `@import` rule was found. */
|
||||
loc: SourceLocation,
|
||||
/** The placeholder that the import was replaced with. */
|
||||
placeholder: string
|
||||
}
|
||||
|
||||
export interface UrlDependency {
|
||||
type: 'url',
|
||||
/** The url of the dependency. */
|
||||
url: string,
|
||||
/** The source location where the `url()` was found. */
|
||||
loc: SourceLocation,
|
||||
/** The placeholder that the url was replaced with. */
|
||||
placeholder: string
|
||||
}
|
||||
|
||||
export interface SourceLocation {
|
||||
/** The file path in which the dependency exists. */
|
||||
filePath: string,
|
||||
/** The start location of the dependency. */
|
||||
start: Location,
|
||||
/** The end location (inclusive) of the dependency. */
|
||||
end: Location
|
||||
}
|
||||
|
||||
export interface Location {
|
||||
/** The line number (1-based). */
|
||||
line: number,
|
||||
/** The column number (0-based). */
|
||||
column: number
|
||||
}
|
||||
|
||||
export interface ErrorLocation extends Location {
|
||||
filename: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles a CSS file, including optionally minifying and lowering syntax to the given
|
||||
* targets. A source map may also be generated, but this is not enabled by default.
|
||||
*/
|
||||
export declare function transform<C extends CustomAtRules>(options: TransformOptions<C>): TransformResult;
|
||||
|
||||
export interface TransformAttributeOptions {
|
||||
/** The filename in which the style attribute appeared. Used for error messages and dependencies. */
|
||||
filename?: string,
|
||||
/** The source code to transform. */
|
||||
code: Uint8Array,
|
||||
/** Whether to enable minification. */
|
||||
minify?: boolean,
|
||||
/** The browser targets for the generated code. */
|
||||
targets?: Targets,
|
||||
/**
|
||||
* Whether to analyze `url()` dependencies.
|
||||
* When enabled, `url()` dependencies are replaced with hashed placeholders
|
||||
* that can be replaced with the final urls later (after bundling).
|
||||
* Dependencies are returned as part of the result.
|
||||
*/
|
||||
analyzeDependencies?: boolean,
|
||||
/**
|
||||
* Whether to ignore invalid rules and declarations rather than erroring.
|
||||
* When enabled, warnings are returned, and the invalid rule or declaration is
|
||||
* omitted from the output code.
|
||||
*/
|
||||
errorRecovery?: boolean,
|
||||
/**
|
||||
* An AST visitor object. This allows custom transforms or analysis to be implemented in JavaScript.
|
||||
* Multiple visitors can be composed into one using the `composeVisitors` function.
|
||||
* For optimal performance, visitors should be as specific as possible about what types of values
|
||||
* they care about so that JavaScript has to be called as little as possible.
|
||||
*/
|
||||
visitor?: Visitor<never>
|
||||
}
|
||||
|
||||
export interface TransformAttributeResult {
|
||||
/** The transformed code. */
|
||||
code: Uint8Array,
|
||||
/** `@import` and `url()` dependencies, if enabled. */
|
||||
dependencies: Dependency[] | void,
|
||||
/** Warnings that occurred during compilation. */
|
||||
warnings: Warning[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles a single CSS declaration list, such as an inline style attribute in HTML.
|
||||
*/
|
||||
export declare function transformStyleAttribute(options: TransformAttributeOptions): TransformAttributeResult;
|
||||
|
||||
/**
|
||||
* Converts a browserslist result into targets that can be passed to lightningcss.
|
||||
* @param browserslist the result of calling `browserslist`
|
||||
*/
|
||||
export declare function browserslistToTargets(browserslist: string[]): Targets;
|
||||
|
||||
/**
|
||||
* Bundles a CSS file and its dependencies, inlining @import rules.
|
||||
*/
|
||||
export declare function bundle<C extends CustomAtRules>(options: BundleOptions<C>): TransformResult;
|
||||
|
||||
/**
|
||||
* Bundles a CSS file and its dependencies asynchronously, inlining @import rules.
|
||||
*/
|
||||
export declare function bundleAsync<C extends CustomAtRules>(options: BundleAsyncOptions<C>): Promise<TransformResult>;
|
||||
|
||||
/**
|
||||
* Composes multiple visitor objects into a single one.
|
||||
*/
|
||||
export declare function composeVisitors<C extends CustomAtRules>(visitors: Visitor<C>[]): Visitor<C>;
|
||||
@@ -0,0 +1 @@
|
||||
module.exports={A:{A:{"2":"K D E F A B mC"},B:{"1":"0 9 N O P Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I","2":"C L M","260":"G"},C:{"1":"0 9 UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC oC pC","2":"1 2 3 4 5 6 7 8 nC LC J PB K D E F A B C L M G N O P QB RB SB TB qC rC"},D:{"1":"0 9 mB nB oB pB qB rB sB tB uB vB MC wB NC xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB I PC EC QC RC","2":"1 2 3 4 5 6 7 8 J PB K D E F A B C L M G N O P QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB","194":"lB"},E:{"1":"A B C L M G TC FC GC xC yC zC UC VC HC 0C IC WC XC YC ZC aC 1C JC bC cC dC eC fC 2C KC gC hC iC jC 3C","2":"J PB K D E F sC SC tC uC vC","260":"wC"},F:{"1":"0 ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB pB qB rB sB tB uB vB wB xB yB zB 0B 1B 2B 3B 4B 5B 6B 7B 8B 9B AC BC CC DC Q H R OC S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z","2":"1 2 3 4 5 6 7 8 F B C G N O P QB RB SB TB UB VB WB XB 4C 5C 6C 7C FC kC 8C GC","194":"YB"},G:{"1":"GD HD ID JD KD LD MD ND OD PD QD RD SD UC VC HC TD IC WC XC YC ZC aC UD JC bC cC dC eC fC VD KC gC hC iC jC","2":"E SC 9C lC AD BD CD DD ED","260":"FD"},H:{"2":"WD"},I:{"1":"I","2":"LC J XD YD ZD aD lC bD cD"},J:{"2":"D A"},K:{"1":"H","2":"A B C FC kC GC"},L:{"1":"I"},M:{"1":"EC"},N:{"2":"A B"},O:{"1":"HC"},P:{"1":"1 2 3 4 5 6 7 8 dD eD fD gD hD TC iD jD kD lD mD IC JC KC nD","2":"J"},Q:{"1":"oD"},R:{"1":"pD"},S:{"1":"qD rD"}},B:4,C:"CSS Variables (Custom Properties)",D:true};
|
||||
@@ -0,0 +1,205 @@
|
||||
import {
|
||||
Document,
|
||||
Node,
|
||||
Plugin,
|
||||
ProcessOptions,
|
||||
Root,
|
||||
SourceMap,
|
||||
TransformCallback,
|
||||
Warning,
|
||||
WarningOptions
|
||||
} from './postcss.js'
|
||||
import Processor from './processor.js'
|
||||
|
||||
declare namespace Result {
|
||||
export interface Message {
|
||||
[others: string]: any
|
||||
|
||||
/**
|
||||
* Source PostCSS plugin name.
|
||||
*/
|
||||
plugin?: string
|
||||
|
||||
/**
|
||||
* Message type.
|
||||
*/
|
||||
type: string
|
||||
}
|
||||
|
||||
export interface ResultOptions extends ProcessOptions {
|
||||
/**
|
||||
* The CSS node that was the source of the warning.
|
||||
*/
|
||||
node?: Node
|
||||
|
||||
/**
|
||||
* Name of plugin that created this warning. `Result#warn` will fill it
|
||||
* automatically with `Plugin#postcssPlugin` value.
|
||||
*/
|
||||
plugin?: string
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
export { Result_ as default }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the result of the PostCSS transformations.
|
||||
*
|
||||
* A Result instance is returned by `LazyResult#then`
|
||||
* or `Root#toResult` methods.
|
||||
*
|
||||
* ```js
|
||||
* postcss([autoprefixer]).process(css).then(result => {
|
||||
* console.log(result.css)
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ```js
|
||||
* const result2 = postcss.parse(css).toResult()
|
||||
* ```
|
||||
*/
|
||||
declare class Result_<RootNode = Document | Root> {
|
||||
/**
|
||||
* A CSS string representing of `Result#root`.
|
||||
*
|
||||
* ```js
|
||||
* postcss.parse('a{}').toResult().css //=> "a{}"
|
||||
* ```
|
||||
*/
|
||||
css: string
|
||||
|
||||
/**
|
||||
* Last runned PostCSS plugin.
|
||||
*/
|
||||
lastPlugin: Plugin | TransformCallback
|
||||
|
||||
/**
|
||||
* An instance of `SourceMapGenerator` class from the `source-map` library,
|
||||
* representing changes to the `Result#root` instance.
|
||||
*
|
||||
* ```js
|
||||
* result.map.toJSON() //=> { version: 3, file: 'a.css', … }
|
||||
* ```
|
||||
*
|
||||
* ```js
|
||||
* if (result.map) {
|
||||
* fs.writeFileSync(result.opts.to + '.map', result.map.toString())
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
map: SourceMap
|
||||
|
||||
/**
|
||||
* Contains messages from plugins (e.g., warnings or custom messages).
|
||||
* Each message should have type and plugin properties.
|
||||
*
|
||||
* ```js
|
||||
* AtRule: {
|
||||
* import: (atRule, { result }) {
|
||||
* const importedFile = parseImport(atRule)
|
||||
* result.messages.push({
|
||||
* type: 'dependency',
|
||||
* plugin: 'postcss-import',
|
||||
* file: importedFile,
|
||||
* parent: result.opts.from
|
||||
* })
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
messages: Result.Message[]
|
||||
|
||||
/**
|
||||
* Options from the `Processor#process` or `Root#toResult` call
|
||||
* that produced this Result instance.]
|
||||
*
|
||||
* ```js
|
||||
* root.toResult(opts).opts === opts
|
||||
* ```
|
||||
*/
|
||||
opts: Result.ResultOptions
|
||||
|
||||
/**
|
||||
* The Processor instance used for this transformation.
|
||||
*
|
||||
* ```js
|
||||
* for (const plugin of result.processor.plugins) {
|
||||
* if (plugin.postcssPlugin === 'postcss-bad') {
|
||||
* throw 'postcss-good is incompatible with postcss-bad'
|
||||
* }
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
processor: Processor
|
||||
|
||||
/**
|
||||
* Root node after all transformations.
|
||||
*
|
||||
* ```js
|
||||
* root.toResult().root === root
|
||||
* ```
|
||||
*/
|
||||
root: RootNode
|
||||
|
||||
/**
|
||||
* An alias for the `Result#css` property.
|
||||
* Use it with syntaxes that generate non-CSS output.
|
||||
*
|
||||
* ```js
|
||||
* result.css === result.content
|
||||
* ```
|
||||
*/
|
||||
get content(): string
|
||||
|
||||
/**
|
||||
* @param processor Processor used for this transformation.
|
||||
* @param root Root node after all transformations.
|
||||
* @param opts Options from the `Processor#process` or `Root#toResult`.
|
||||
*/
|
||||
constructor(processor: Processor, root: RootNode, opts: Result.ResultOptions)
|
||||
|
||||
/**
|
||||
* Returns for `Result#css` content.
|
||||
*
|
||||
* ```js
|
||||
* result + '' === result.css
|
||||
* ```
|
||||
*
|
||||
* @return String representing of `Result#root`.
|
||||
*/
|
||||
toString(): string
|
||||
|
||||
/**
|
||||
* Creates an instance of `Warning` and adds it to `Result#messages`.
|
||||
*
|
||||
* ```js
|
||||
* if (decl.important) {
|
||||
* result.warn('Avoid !important', { node: decl, word: '!important' })
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param text Warning message.
|
||||
* @param opts Warning options.
|
||||
* @return Created warning.
|
||||
*/
|
||||
warn(message: string, options?: WarningOptions): Warning
|
||||
|
||||
/**
|
||||
* Returns warnings from plugins. Filters `Warning` instances
|
||||
* from `Result#messages`.
|
||||
*
|
||||
* ```js
|
||||
* result.warnings().forEach(warn => {
|
||||
* console.warn(warn.toString())
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @return Warnings from plugins.
|
||||
*/
|
||||
warnings(): Warning[]
|
||||
}
|
||||
|
||||
declare class Result<RootNode = Document | Root> extends Result_<RootNode> {}
|
||||
|
||||
export = Result
|
||||
@@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
||||
const derived = require("./derived.cjs");
|
||||
const effect = require("./effect.cjs");
|
||||
const store = require("./store.cjs");
|
||||
const scheduler = require("./scheduler.cjs");
|
||||
exports.Derived = derived.Derived;
|
||||
exports.Effect = effect.Effect;
|
||||
exports.Store = store.Store;
|
||||
exports.__depsThatHaveWrittenThisTick = scheduler.__depsThatHaveWrittenThisTick;
|
||||
exports.__derivedToStore = scheduler.__derivedToStore;
|
||||
exports.__flush = scheduler.__flush;
|
||||
exports.__storeToDerived = scheduler.__storeToDerived;
|
||||
exports.batch = scheduler.batch;
|
||||
//# sourceMappingURL=index.cjs.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["PluginPass","constructor","file","key","options","isAsync","_map","Map","opts","cwd","filename","set","val","get","availableHelper","name","versionRange","addHelper","buildCodeFrameError","node","msg","_Error","exports","default","prototype","getModuleName","addImport"],"sources":["../../src/transformation/plugin-pass.ts"],"sourcesContent":["import type * as t from \"@babel/types\";\nimport type File from \"./file/file.ts\";\n\nexport default class PluginPass<Options = object> {\n _map: Map<unknown, unknown> = new Map();\n key: string | undefined | null;\n file: File;\n opts: Partial<Options>;\n\n /**\n * The working directory that Babel's programmatic options are loaded\n * relative to.\n */\n cwd: string;\n\n /** The absolute path of the file being compiled. */\n filename: string | void;\n\n /**\n * Is Babel executed in async mode or not.\n */\n isAsync: boolean;\n\n constructor(\n file: File,\n key: string | null,\n options: Options | undefined,\n isAsync: boolean,\n ) {\n this.key = key;\n this.file = file;\n this.opts = options || {};\n this.cwd = file.opts.cwd;\n this.filename = file.opts.filename;\n this.isAsync = isAsync;\n }\n\n set(key: unknown, val: unknown) {\n this._map.set(key, val);\n }\n\n get(key: unknown): any {\n return this._map.get(key);\n }\n\n availableHelper(name: string, versionRange?: string | null) {\n return this.file.availableHelper(name, versionRange);\n }\n\n addHelper(name: string) {\n return this.file.addHelper(name);\n }\n\n buildCodeFrameError(\n node: t.Node | undefined | null,\n msg: string,\n _Error?: typeof Error,\n ) {\n return this.file.buildCodeFrameError(node, msg, _Error);\n }\n}\n\nif (!process.env.BABEL_8_BREAKING) {\n (PluginPass as any).prototype.getModuleName = function getModuleName(\n this: PluginPass,\n ): string | undefined {\n // @ts-expect-error only exists in Babel 7\n return this.file.getModuleName();\n };\n (PluginPass as any).prototype.addImport = function addImport(\n this: PluginPass,\n ): void {\n // @ts-expect-error only exists in Babel 7\n this.file.addImport();\n };\n}\n"],"mappings":";;;;;;AAGe,MAAMA,UAAU,CAAmB;EAoBhDC,WAAWA,CACTC,IAAU,EACVC,GAAkB,EAClBC,OAA4B,EAC5BC,OAAgB,EAChB;IAAA,KAxBFC,IAAI,GAA0B,IAAIC,GAAG,CAAC,CAAC;IAAA,KACvCJ,GAAG;IAAA,KACHD,IAAI;IAAA,KACJM,IAAI;IAAA,KAMJC,GAAG;IAAA,KAGHC,QAAQ;IAAA,KAKRL,OAAO;IAQL,IAAI,CAACF,GAAG,GAAGA,GAAG;IACd,IAAI,CAACD,IAAI,GAAGA,IAAI;IAChB,IAAI,CAACM,IAAI,GAAGJ,OAAO,IAAI,CAAC,CAAC;IACzB,IAAI,CAACK,GAAG,GAAGP,IAAI,CAACM,IAAI,CAACC,GAAG;IACxB,IAAI,CAACC,QAAQ,GAAGR,IAAI,CAACM,IAAI,CAACE,QAAQ;IAClC,IAAI,CAACL,OAAO,GAAGA,OAAO;EACxB;EAEAM,GAAGA,CAACR,GAAY,EAAES,GAAY,EAAE;IAC9B,IAAI,CAACN,IAAI,CAACK,GAAG,CAACR,GAAG,EAAES,GAAG,CAAC;EACzB;EAEAC,GAAGA,CAACV,GAAY,EAAO;IACrB,OAAO,IAAI,CAACG,IAAI,CAACO,GAAG,CAACV,GAAG,CAAC;EAC3B;EAEAW,eAAeA,CAACC,IAAY,EAAEC,YAA4B,EAAE;IAC1D,OAAO,IAAI,CAACd,IAAI,CAACY,eAAe,CAACC,IAAI,EAAEC,YAAY,CAAC;EACtD;EAEAC,SAASA,CAACF,IAAY,EAAE;IACtB,OAAO,IAAI,CAACb,IAAI,CAACe,SAAS,CAACF,IAAI,CAAC;EAClC;EAEAG,mBAAmBA,CACjBC,IAA+B,EAC/BC,GAAW,EACXC,MAAqB,EACrB;IACA,OAAO,IAAI,CAACnB,IAAI,CAACgB,mBAAmB,CAACC,IAAI,EAAEC,GAAG,EAAEC,MAAM,CAAC;EACzD;AACF;AAACC,OAAA,CAAAC,OAAA,GAAAvB,UAAA;AAEkC;EAChCA,UAAU,CAASwB,SAAS,CAACC,aAAa,GAAG,SAASA,aAAaA,CAAA,EAE9C;IAEpB,OAAO,IAAI,CAACvB,IAAI,CAACuB,aAAa,CAAC,CAAC;EAClC,CAAC;EACAzB,UAAU,CAASwB,SAAS,CAACE,SAAS,GAAG,SAASA,SAASA,CAAA,EAEpD;IAEN,IAAI,CAACxB,IAAI,CAACwB,SAAS,CAAC,CAAC;EACvB,CAAC;AACH;AAAC","ignoreList":[]}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Manage the SVGs drawn on top of the page canvas.
|
||||
* It's important to have them directly on top of the canvas because we want to
|
||||
* be able to use mix-blend-mode for some of them.
|
||||
*/
|
||||
export class DrawLayer {
|
||||
static get _svgFactory(): any;
|
||||
static "__#27@#setBox"(element: any, { x, y, width, height }?: {
|
||||
x?: number | undefined;
|
||||
y?: number | undefined;
|
||||
width?: number | undefined;
|
||||
height?: number | undefined;
|
||||
}): void;
|
||||
constructor({ pageIndex }: {
|
||||
pageIndex: any;
|
||||
});
|
||||
pageIndex: any;
|
||||
setParent(parent: any): void;
|
||||
draw(outlines: any, color: any, opacity: any, isPathUpdatable?: boolean): {
|
||||
id: number;
|
||||
clipPathId: string;
|
||||
};
|
||||
drawOutline(outlines: any): number;
|
||||
finalizeLine(id: any, line: any): void;
|
||||
updateLine(id: any, line: any): void;
|
||||
updatePath(id: any, line: any): void;
|
||||
updateBox(id: any, box: any): void;
|
||||
show(id: any, visible: any): void;
|
||||
rotate(id: any, angle: any): void;
|
||||
changeColor(id: any, color: any): void;
|
||||
changeOpacity(id: any, opacity: any): void;
|
||||
addClass(id: any, className: any): void;
|
||||
removeClass(id: any, className: any): void;
|
||||
getSVGRoot(id: any): any;
|
||||
remove(id: any): void;
|
||||
destroy(): void;
|
||||
#private;
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
# ESLint Plugin Kit
|
||||
|
||||
## Description
|
||||
|
||||
A collection of utilities to help build ESLint plugins.
|
||||
|
||||
## Installation
|
||||
|
||||
For Node.js and compatible runtimes:
|
||||
|
||||
```shell
|
||||
npm install @eslint/plugin-kit
|
||||
# or
|
||||
yarn add @eslint/plugin-kit
|
||||
# or
|
||||
pnpm install @eslint/plugin-kit
|
||||
# or
|
||||
bun install @eslint/plugin-kit
|
||||
```
|
||||
|
||||
For Deno:
|
||||
|
||||
```shell
|
||||
deno add @eslint/plugin-kit
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
This package exports the following utilities:
|
||||
|
||||
- `ConfigCommentParser` - used to parse ESLint configuration comments (i.e., `/* eslint-disable rule */`)
|
||||
- `VisitNodeStep` and `CallMethodStep` - used to help implement `SourceCode#traverse()`
|
||||
- `Directive` - used to help implement `SourceCode#getDisableDirectives()`
|
||||
- `TextSourceCodeBase` - base class to help implement the `SourceCode` interface
|
||||
|
||||
### `ConfigCommentParser`
|
||||
|
||||
To use the `ConfigCommentParser` class, import it from the package and create a new instance, such as:
|
||||
|
||||
```js
|
||||
import { ConfigCommentParser } from "@eslint/plugin-kit";
|
||||
|
||||
// create a new instance
|
||||
const commentParser = new ConfigCommentParser();
|
||||
|
||||
// pass in a comment string without the comment delimiters
|
||||
const directive = commentParser.parseDirective(
|
||||
"eslint-disable prefer-const, semi -- I don't want to use these.",
|
||||
);
|
||||
|
||||
// will be undefined when a directive can't be parsed
|
||||
if (directive) {
|
||||
console.log(directive.label); // "eslint-disable"
|
||||
console.log(directive.value); // "prefer-const, semi"
|
||||
console.log(directive.justification); // "I don't want to use these"
|
||||
}
|
||||
```
|
||||
|
||||
There are different styles of directive values that you'll need to parse separately to get the correct format:
|
||||
|
||||
```js
|
||||
import { ConfigCommentParser } from "@eslint/plugin-kit";
|
||||
|
||||
// create a new instance
|
||||
const commentParser = new ConfigCommentParser();
|
||||
|
||||
// list format
|
||||
const list = commentParser.parseListConfig("prefer-const, semi");
|
||||
console.log(Object.entries(list)); // [["prefer-const", true], ["semi", true]]
|
||||
|
||||
// string format
|
||||
const strings = commentParser.parseStringConfig("foo:off, bar");
|
||||
console.log(Object.entries(strings)); // [["foo", "off"], ["bar", null]]
|
||||
|
||||
// JSON-like config format
|
||||
const jsonLike = commentParser.parseJSONLikeConfig(
|
||||
"semi:[error, never], prefer-const: warn",
|
||||
);
|
||||
console.log(Object.entries(jsonLike.config)); // [["semi", ["error", "never"]], ["prefer-const", "warn"]]
|
||||
```
|
||||
|
||||
### `VisitNodeStep` and `CallMethodStep`
|
||||
|
||||
The `VisitNodeStep` and `CallMethodStep` classes represent steps in the traversal of source code. They implement the correct interfaces to return from the `SourceCode#traverse()` method.
|
||||
|
||||
The `VisitNodeStep` class is the more common of the two, where you are describing a visit to a particular node during the traversal. The constructor accepts three arguments:
|
||||
|
||||
- `target` - the node being visited. This is used to determine the method to call inside of a rule. For instance, if the node's type is `Literal` then ESLint will call a method named `Literal()` on the rule (if present).
|
||||
- `phase` - either 1 for enter or 2 for exit.
|
||||
- `args` - an array of arguments to pass into the visitor method of a rule.
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
import { VisitNodeStep } from "@eslint/plugin-kit";
|
||||
|
||||
class MySourceCode {
|
||||
traverse() {
|
||||
const steps = [];
|
||||
|
||||
for (const { node, parent, phase } of iterator(this.ast)) {
|
||||
steps.push(
|
||||
new VisitNodeStep({
|
||||
target: node,
|
||||
phase: phase === "enter" ? 1 : 2,
|
||||
args: [node, parent],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return steps;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `CallMethodStep` class is less common and is used to tell ESLint to call a specific method on the rule. The constructor accepts two arguments:
|
||||
|
||||
- `target` - the name of the method to call, frequently beginning with `"on"` such as `"onCodePathStart"`.
|
||||
- `args` - an array of arguments to pass to the method.
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
import { VisitNodeStep, CallMethodStep } from "@eslint/plugin-kit";
|
||||
|
||||
class MySourceCode {
|
||||
|
||||
traverse() {
|
||||
|
||||
const steps = [];
|
||||
|
||||
for (const { node, parent, phase } of iterator(this.ast)) {
|
||||
steps.push(
|
||||
new VisitNodeStep({
|
||||
target: node,
|
||||
phase: phase === "enter" ? 1 : 2,
|
||||
args: [node, parent],
|
||||
}),
|
||||
);
|
||||
|
||||
// call a method indicating how many times we've been through the loop
|
||||
steps.push(
|
||||
new CallMethodStep({
|
||||
target: "onIteration",
|
||||
args: [steps.length]
|
||||
});
|
||||
)
|
||||
}
|
||||
|
||||
return steps;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `Directive`
|
||||
|
||||
The `Directive` class represents a disable directive in the source code and implements the `Directive` interface from `@eslint/core`. You can tell ESLint about disable directives using the `SourceCode#getDisableDirectives()` method, where part of the return value is an array of `Directive` objects. Here's an example:
|
||||
|
||||
```js
|
||||
import { Directive, ConfigCommentParser } from "@eslint/plugin-kit";
|
||||
|
||||
class MySourceCode {
|
||||
getDisableDirectives() {
|
||||
const directives = [];
|
||||
const problems = [];
|
||||
const commentParser = new ConfigCommentParser();
|
||||
|
||||
// read in the inline config nodes to check each one
|
||||
this.getInlineConfigNodes().forEach(comment => {
|
||||
// Step 1: Parse the directive
|
||||
const { label, value, justification } =
|
||||
commentParser.parseDirective(comment.value);
|
||||
|
||||
// Step 2: Extract the directive value and create the `Directive` object
|
||||
switch (label) {
|
||||
case "eslint-disable":
|
||||
case "eslint-enable":
|
||||
case "eslint-disable-next-line":
|
||||
case "eslint-disable-line": {
|
||||
const directiveType = label.slice("eslint-".length);
|
||||
|
||||
directives.push(
|
||||
new Directive({
|
||||
type: directiveType,
|
||||
node: comment,
|
||||
value,
|
||||
justification,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// ignore any comments that don't begin with known labels
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
directives,
|
||||
problems,
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `TextSourceCodeBase`
|
||||
|
||||
The `TextSourceCodeBase` class is intended to be a base class that has several of the common members found in `SourceCode` objects already implemented. Those members are:
|
||||
|
||||
- `lines` - an array of text lines that is created automatically when the constructor is called.
|
||||
- `getLoc(node)` - gets the location of a node. Works for nodes that have the ESLint-style `loc` property and nodes that have the Unist-style [`position` property](https://github.com/syntax-tree/unist?tab=readme-ov-file#position). If you're using an AST with a different location format, you'll still need to implement this method yourself.
|
||||
- `getRange(node)` - gets the range of a node within the source text. Works for nodes that have the ESLint-style `range` property and nodes that have the Unist-style [`position` property](https://github.com/syntax-tree/unist?tab=readme-ov-file#position). If you're using an AST with a different range format, you'll still need to implement this method yourself.
|
||||
- `getText(nodeOrToken, charsBefore, charsAfter)` - gets the source text for the given node or token that has range information attached. Optionally, can return additional characters before and after the given node or token. As long as `getRange()` is properly implemented, this method will just work.
|
||||
- `getAncestors(node)` - returns the ancestry of the node. In order for this to work, you must implement the `getParent()` method yourself.
|
||||
|
||||
Here's an example:
|
||||
|
||||
```js
|
||||
import { TextSourceCodeBase } from "@eslint/plugin-kit";
|
||||
|
||||
export class MySourceCode extends TextSourceCodeBase {
|
||||
#parents = new Map();
|
||||
|
||||
constructor({ ast, text }) {
|
||||
super({ ast, text });
|
||||
}
|
||||
|
||||
getParent(node) {
|
||||
return this.#parents.get(node);
|
||||
}
|
||||
|
||||
traverse() {
|
||||
const steps = [];
|
||||
|
||||
for (const { node, parent, phase } of iterator(this.ast)) {
|
||||
//save the parent information
|
||||
this.#parent.set(node, parent);
|
||||
|
||||
steps.push(
|
||||
new VisitNodeStep({
|
||||
target: node,
|
||||
phase: phase === "enter" ? 1 : 2,
|
||||
args: [node, parent],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return steps;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In general, it's safe to collect the parent information during the `traverse()` method as `getParent()` and `getAncestor()` will only be called from rules once the AST has been traversed at least once.
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0
|
||||
|
||||
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
|
||||
<!--sponsorsstart-->
|
||||
|
||||
## Sponsors
|
||||
|
||||
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://eslint.org/donate)
|
||||
to get your logo on our READMEs and [website](https://eslint.org/sponsors).
|
||||
|
||||
<h3>Platinum Sponsors</h3>
|
||||
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="128"></a></p><h3>Gold Sponsors</h3>
|
||||
<p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a> <a href="https://trunk.io/"><img src="https://images.opencollective.com/trunkio/fb92d60/avatar.png" alt="trunk.io" height="96"></a></p><h3>Silver Sponsors</h3>
|
||||
<p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/e6d15e1/logo.png" alt="Vite" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://stackblitz.com"><img src="https://avatars.githubusercontent.com/u/28635252" alt="StackBlitz" height="64"></a></p><h3>Bronze Sponsors</h3>
|
||||
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nolebase.ayaka.io"><img src="https://avatars.githubusercontent.com/u/11081491" alt="Neko" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a> <a href="https://www.lambdatest.com"><img src="https://avatars.githubusercontent.com/u/171592363" alt="LambdaTest" height="32"></a></p>
|
||||
<h3>Technology Sponsors</h3>
|
||||
Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
|
||||
<p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
|
||||
<!--sponsorsend-->
|
||||
@@ -0,0 +1 @@
|
||||
module.exports={C:{"4":0.00801,"52":0.04804,"59":0.02002,"66":0.004,"78":0.004,"82":0.004,"84":0.004,"86":0.004,"88":0.03202,"91":0.02402,"94":0.004,"101":0.00801,"103":0.01601,"106":0.004,"113":0.01201,"114":0.004,"115":0.32424,"118":0.004,"120":0.02802,"122":0.004,"123":0.004,"124":0.004,"125":0.004,"126":0.004,"127":0.004,"128":0.02402,"129":0.004,"130":0.004,"131":0.00801,"132":0.00801,"133":0.00801,"134":0.01201,"135":0.22817,"136":1.01676,"137":0.004,_:"2 3 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 53 54 55 56 57 58 60 61 62 63 64 65 67 68 69 70 71 72 73 74 75 76 77 79 80 81 83 85 87 89 90 92 93 95 96 97 98 99 100 102 104 105 107 108 109 110 111 112 116 117 119 121 138 139 140 3.5 3.6"},D:{"38":0.004,"39":0.004,"41":0.004,"42":0.004,"43":0.004,"44":0.004,"45":0.004,"46":0.004,"47":0.00801,"48":0.004,"49":0.02802,"50":0.004,"51":0.004,"52":0.004,"53":0.004,"54":0.004,"55":0.004,"56":0.004,"57":0.004,"58":0.004,"59":0.004,"60":0.004,"66":0.03603,"74":0.004,"75":0.004,"78":0.004,"79":0.02002,"80":0.004,"81":0.004,"83":0.004,"84":0.004,"85":0.004,"87":0.01601,"88":0.00801,"89":0.004,"90":0.004,"91":0.00801,"92":0.004,"93":0.004,"94":0.01201,"95":0.004,"97":0.004,"98":0.004,"99":0.004,"100":0.004,"101":0.00801,"102":0.00801,"103":0.03202,"104":0.00801,"105":0.004,"106":0.01201,"107":0.00801,"108":0.01601,"109":2.5299,"110":0.02002,"111":0.01601,"112":0.004,"113":0.004,"114":0.00801,"115":0.004,"116":0.05604,"117":0.004,"118":0.004,"119":0.03603,"120":0.04003,"121":0.07606,"122":0.07205,"123":0.03202,"124":0.05204,"125":0.08807,"126":0.05604,"127":0.05604,"128":0.08807,"129":0.04403,"130":0.06405,"131":0.2682,"132":0.34826,"133":7.49762,"134":17.81335,"135":0.01201,_:"4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 40 61 62 63 64 65 67 68 69 70 71 72 73 76 77 86 96 136 137 138"},F:{"87":0.004,"89":0.004,"95":0.03603,"102":0.004,"106":0.004,"114":0.004,"116":0.54841,"117":1.31699,_:"9 11 12 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 60 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 88 90 91 92 93 94 96 97 98 99 100 101 103 104 105 107 108 109 110 111 112 113 115 9.5-9.6 10.0-10.1 10.5 10.6 11.1 11.5 11.6 12.1"},B:{"17":0.004,"18":0.004,"92":0.00801,"109":0.04003,"114":0.00801,"122":0.004,"123":0.004,"126":0.004,"127":0.004,"128":0.004,"129":0.004,"130":0.00801,"131":0.03202,"132":0.03202,"133":0.76858,"134":2.09757,_:"12 13 14 15 16 79 80 81 83 84 85 86 87 88 89 90 91 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 110 111 112 113 115 116 117 118 119 120 121 124 125"},E:{"14":0.004,_:"0 4 5 6 7 8 9 10 11 12 13 15 3.1 3.2 5.1 6.1 7.1 9.1 10.1 15.1 15.2-15.3 15.4","11.1":0.00801,"12.1":0.004,"13.1":0.00801,"14.1":0.00801,"15.5":0.004,"15.6":0.03603,"16.0":0.004,"16.1":0.004,"16.2":0.004,"16.3":0.00801,"16.4":0.004,"16.5":0.00801,"16.6":0.04003,"17.0":0.004,"17.1":0.02402,"17.2":0.00801,"17.3":0.004,"17.4":0.01201,"17.5":0.02402,"17.6":0.06405,"18.0":0.00801,"18.1":0.02802,"18.2":0.01601,"18.3":0.31223,"18.4":0.004},G:{"8":0,"3.2":0,"4.0-4.1":0,"4.2-4.3":0.0011,"5.0-5.1":0,"6.0-6.1":0.0033,"7.0-7.1":0.0022,"8.1-8.4":0,"9.0-9.2":0.00165,"9.3":0.00771,"10.0-10.2":0.00055,"10.3":0.01266,"11.0-11.2":0.05836,"11.3-11.4":0.00385,"12.0-12.1":0.0022,"12.2-12.5":0.0545,"13.0-13.1":0.0011,"13.2":0.00165,"13.3":0.0022,"13.4-13.7":0.00771,"14.0-14.4":0.01927,"14.5-14.8":0.02312,"15.0-15.1":0.01266,"15.2-15.3":0.01266,"15.4":0.01541,"15.5":0.01762,"15.6-15.8":0.21691,"16.0":0.03083,"16.1":0.06331,"16.2":0.03303,"16.3":0.05725,"16.4":0.01266,"16.5":0.02367,"16.6-16.7":0.25709,"17.0":0.01541,"17.1":0.02753,"17.2":0.02092,"17.3":0.02918,"17.4":0.05836,"17.5":0.12992,"17.6-17.7":0.37711,"18.0":0.1057,"18.1":0.34573,"18.2":0.1547,"18.3":3.23323,"18.4":0.0479},P:{"4":0.08244,"20":0.0103,"21":0.02061,"22":0.03091,"23":0.02061,"24":0.04122,"25":0.04122,"26":0.13396,"27":2.37008,_:"5.0-5.4 6.2-6.4 8.2 9.2 10.1 11.1-11.2 12.0 14.0 15.0 16.0 18.0","7.2-7.4":0.11335,"13.0":0.0103,"17.0":0.04122,"19.0":0.0103},I:{"0":0.01197,"3":0,"4":0,"2.1":0,"2.2":0,"2.3":0,"4.1":0,"4.2-4.3":0,"4.4":0,"4.4.3-4.4.4":0.00001},K:{"0":0.13793,_:"10 11 12 11.1 11.5 12.1"},A:{"11":0.09607,_:"6 7 8 9 10 5.5"},S:{_:"2.5 3.0-3.1"},J:{_:"7 10"},N:{_:"10 11"},R:{_:"0"},M:{"0":0.15592},Q:{_:"14.9"},O:{"0":0.01799},H:{"0":0},L:{"0":52.87425}};
|
||||
@@ -0,0 +1,391 @@
|
||||
/**
|
||||
* @fileoverview Comma style - enforces comma styles of two types: last and first
|
||||
* @author Vignesh Anand aka vegetableman
|
||||
* @deprecated in ESLint v8.53.0
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
deprecated: {
|
||||
message: "Formatting rules are being moved out of ESLint core.",
|
||||
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
|
||||
deprecatedSince: "8.53.0",
|
||||
availableUntil: "10.0.0",
|
||||
replacedBy: [
|
||||
{
|
||||
message:
|
||||
"ESLint Stylistic now maintains deprecated stylistic core rules.",
|
||||
url: "https://eslint.style/guide/migration",
|
||||
plugin: {
|
||||
name: "@stylistic/eslint-plugin-js",
|
||||
url: "https://eslint.style/packages/js",
|
||||
},
|
||||
rule: {
|
||||
name: "comma-style",
|
||||
url: "https://eslint.style/rules/js/comma-style",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
type: "layout",
|
||||
|
||||
docs: {
|
||||
description: "Enforce consistent comma style",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/comma-style",
|
||||
},
|
||||
|
||||
fixable: "code",
|
||||
|
||||
schema: [
|
||||
{
|
||||
enum: ["first", "last"],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
exceptions: {
|
||||
type: "object",
|
||||
additionalProperties: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
|
||||
messages: {
|
||||
unexpectedLineBeforeAndAfterComma:
|
||||
"Bad line breaking before and after ','.",
|
||||
expectedCommaFirst: "',' should be placed first.",
|
||||
expectedCommaLast: "',' should be placed last.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const style = context.options[0] || "last",
|
||||
sourceCode = context.sourceCode;
|
||||
const exceptions = {
|
||||
ArrayPattern: true,
|
||||
ArrowFunctionExpression: true,
|
||||
CallExpression: true,
|
||||
FunctionDeclaration: true,
|
||||
FunctionExpression: true,
|
||||
ImportDeclaration: true,
|
||||
ObjectPattern: true,
|
||||
NewExpression: true,
|
||||
};
|
||||
|
||||
if (
|
||||
context.options.length === 2 &&
|
||||
Object.hasOwn(context.options[1], "exceptions")
|
||||
) {
|
||||
const keys = Object.keys(context.options[1].exceptions);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
exceptions[keys[i]] = context.options[1].exceptions[keys[i]];
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Modified text based on the style
|
||||
* @param {string} styleType Style type
|
||||
* @param {string} text Source code text
|
||||
* @returns {string} modified text
|
||||
* @private
|
||||
*/
|
||||
function getReplacedText(styleType, text) {
|
||||
switch (styleType) {
|
||||
case "between":
|
||||
return `,${text.replace(astUtils.LINEBREAK_MATCHER, "")}`;
|
||||
|
||||
case "first":
|
||||
return `${text},`;
|
||||
|
||||
case "last":
|
||||
return `,${text}`;
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the fixer function for a given style.
|
||||
* @param {string} styleType comma style
|
||||
* @param {ASTNode} previousItemToken The token to check.
|
||||
* @param {ASTNode} commaToken The token to check.
|
||||
* @param {ASTNode} currentItemToken The token to check.
|
||||
* @returns {Function} Fixer function
|
||||
* @private
|
||||
*/
|
||||
function getFixerFunction(
|
||||
styleType,
|
||||
previousItemToken,
|
||||
commaToken,
|
||||
currentItemToken,
|
||||
) {
|
||||
const text =
|
||||
sourceCode.text.slice(
|
||||
previousItemToken.range[1],
|
||||
commaToken.range[0],
|
||||
) +
|
||||
sourceCode.text.slice(
|
||||
commaToken.range[1],
|
||||
currentItemToken.range[0],
|
||||
);
|
||||
const range = [
|
||||
previousItemToken.range[1],
|
||||
currentItemToken.range[0],
|
||||
];
|
||||
|
||||
return function (fixer) {
|
||||
return fixer.replaceTextRange(
|
||||
range,
|
||||
getReplacedText(styleType, text),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the spacing around single items in lists.
|
||||
* @param {Token} previousItemToken The last token from the previous item.
|
||||
* @param {Token} commaToken The token representing the comma.
|
||||
* @param {Token} currentItemToken The first token of the current item.
|
||||
* @param {Token} reportItem The item to use when reporting an error.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function validateCommaItemSpacing(
|
||||
previousItemToken,
|
||||
commaToken,
|
||||
currentItemToken,
|
||||
reportItem,
|
||||
) {
|
||||
// if single line
|
||||
if (
|
||||
astUtils.isTokenOnSameLine(commaToken, currentItemToken) &&
|
||||
astUtils.isTokenOnSameLine(previousItemToken, commaToken)
|
||||
) {
|
||||
// do nothing.
|
||||
} else if (
|
||||
!astUtils.isTokenOnSameLine(commaToken, currentItemToken) &&
|
||||
!astUtils.isTokenOnSameLine(previousItemToken, commaToken)
|
||||
) {
|
||||
const comment = sourceCode.getCommentsAfter(commaToken)[0];
|
||||
const styleType =
|
||||
comment &&
|
||||
comment.type === "Block" &&
|
||||
astUtils.isTokenOnSameLine(commaToken, comment)
|
||||
? style
|
||||
: "between";
|
||||
|
||||
// lone comma
|
||||
context.report({
|
||||
node: reportItem,
|
||||
loc: commaToken.loc,
|
||||
messageId: "unexpectedLineBeforeAndAfterComma",
|
||||
fix: getFixerFunction(
|
||||
styleType,
|
||||
previousItemToken,
|
||||
commaToken,
|
||||
currentItemToken,
|
||||
),
|
||||
});
|
||||
} else if (
|
||||
style === "first" &&
|
||||
!astUtils.isTokenOnSameLine(commaToken, currentItemToken)
|
||||
) {
|
||||
context.report({
|
||||
node: reportItem,
|
||||
loc: commaToken.loc,
|
||||
messageId: "expectedCommaFirst",
|
||||
fix: getFixerFunction(
|
||||
style,
|
||||
previousItemToken,
|
||||
commaToken,
|
||||
currentItemToken,
|
||||
),
|
||||
});
|
||||
} else if (
|
||||
style === "last" &&
|
||||
astUtils.isTokenOnSameLine(commaToken, currentItemToken)
|
||||
) {
|
||||
context.report({
|
||||
node: reportItem,
|
||||
loc: commaToken.loc,
|
||||
messageId: "expectedCommaLast",
|
||||
fix: getFixerFunction(
|
||||
style,
|
||||
previousItemToken,
|
||||
commaToken,
|
||||
currentItemToken,
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the comma placement with regards to a declaration/property/element
|
||||
* @param {ASTNode} node The binary expression node to check
|
||||
* @param {string} property The property of the node containing child nodes.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function validateComma(node, property) {
|
||||
const items = node[property],
|
||||
arrayLiteral =
|
||||
node.type === "ArrayExpression" ||
|
||||
node.type === "ArrayPattern";
|
||||
|
||||
if (items.length > 1 || arrayLiteral) {
|
||||
// seed as opening [
|
||||
let previousItemToken = sourceCode.getFirstToken(node);
|
||||
|
||||
items.forEach(item => {
|
||||
const commaToken = item
|
||||
? sourceCode.getTokenBefore(item)
|
||||
: previousItemToken,
|
||||
currentItemToken = item
|
||||
? sourceCode.getFirstToken(item)
|
||||
: sourceCode.getTokenAfter(commaToken),
|
||||
reportItem = item || currentItemToken;
|
||||
|
||||
/*
|
||||
* This works by comparing three token locations:
|
||||
* - previousItemToken is the last token of the previous item
|
||||
* - commaToken is the location of the comma before the current item
|
||||
* - currentItemToken is the first token of the current item
|
||||
*
|
||||
* These values get switched around if item is undefined.
|
||||
* previousItemToken will refer to the last token not belonging
|
||||
* to the current item, which could be a comma or an opening
|
||||
* square bracket. currentItemToken could be a comma.
|
||||
*
|
||||
* All comparisons are done based on these tokens directly, so
|
||||
* they are always valid regardless of an undefined item.
|
||||
*/
|
||||
if (astUtils.isCommaToken(commaToken)) {
|
||||
validateCommaItemSpacing(
|
||||
previousItemToken,
|
||||
commaToken,
|
||||
currentItemToken,
|
||||
reportItem,
|
||||
);
|
||||
}
|
||||
|
||||
if (item) {
|
||||
const tokenAfterItem = sourceCode.getTokenAfter(
|
||||
item,
|
||||
astUtils.isNotClosingParenToken,
|
||||
);
|
||||
|
||||
previousItemToken = tokenAfterItem
|
||||
? sourceCode.getTokenBefore(tokenAfterItem)
|
||||
: sourceCode.ast.tokens.at(-1);
|
||||
} else {
|
||||
previousItemToken = currentItemToken;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Special case for array literals that have empty last items, such
|
||||
* as [ 1, 2, ]. These arrays only have two items show up in the
|
||||
* AST, so we need to look at the token to verify that there's no
|
||||
* dangling comma.
|
||||
*/
|
||||
if (arrayLiteral) {
|
||||
const lastToken = sourceCode.getLastToken(node),
|
||||
nextToLastToken = sourceCode.getTokenBefore(lastToken);
|
||||
|
||||
if (astUtils.isCommaToken(nextToLastToken)) {
|
||||
validateCommaItemSpacing(
|
||||
sourceCode.getTokenBefore(nextToLastToken),
|
||||
nextToLastToken,
|
||||
lastToken,
|
||||
lastToken,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
const nodes = {};
|
||||
|
||||
if (!exceptions.VariableDeclaration) {
|
||||
nodes.VariableDeclaration = function (node) {
|
||||
validateComma(node, "declarations");
|
||||
};
|
||||
}
|
||||
if (!exceptions.ObjectExpression) {
|
||||
nodes.ObjectExpression = function (node) {
|
||||
validateComma(node, "properties");
|
||||
};
|
||||
}
|
||||
if (!exceptions.ObjectPattern) {
|
||||
nodes.ObjectPattern = function (node) {
|
||||
validateComma(node, "properties");
|
||||
};
|
||||
}
|
||||
if (!exceptions.ArrayExpression) {
|
||||
nodes.ArrayExpression = function (node) {
|
||||
validateComma(node, "elements");
|
||||
};
|
||||
}
|
||||
if (!exceptions.ArrayPattern) {
|
||||
nodes.ArrayPattern = function (node) {
|
||||
validateComma(node, "elements");
|
||||
};
|
||||
}
|
||||
if (!exceptions.FunctionDeclaration) {
|
||||
nodes.FunctionDeclaration = function (node) {
|
||||
validateComma(node, "params");
|
||||
};
|
||||
}
|
||||
if (!exceptions.FunctionExpression) {
|
||||
nodes.FunctionExpression = function (node) {
|
||||
validateComma(node, "params");
|
||||
};
|
||||
}
|
||||
if (!exceptions.ArrowFunctionExpression) {
|
||||
nodes.ArrowFunctionExpression = function (node) {
|
||||
validateComma(node, "params");
|
||||
};
|
||||
}
|
||||
if (!exceptions.CallExpression) {
|
||||
nodes.CallExpression = function (node) {
|
||||
validateComma(node, "arguments");
|
||||
};
|
||||
}
|
||||
if (!exceptions.ImportDeclaration) {
|
||||
nodes.ImportDeclaration = function (node) {
|
||||
validateComma(node, "specifiers");
|
||||
};
|
||||
}
|
||||
if (!exceptions.NewExpression) {
|
||||
nodes.NewExpression = function (node) {
|
||||
validateComma(node, "arguments");
|
||||
};
|
||||
}
|
||||
|
||||
return nodes;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
const isProduction: boolean = process.env.NODE_ENV === 'production';
|
||||
const prefix: string = 'Invariant failed';
|
||||
|
||||
/**
|
||||
* `invariant` is used to [assert](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions) that the `condition` is [truthy](https://github.com/getify/You-Dont-Know-JS/blob/bdbe570600d4e1107d0b131787903ca1c9ec8140/up%20%26%20going/ch2.md#truthy--falsy).
|
||||
*
|
||||
* 💥 `invariant` will `throw` an `Error` if the `condition` is [falsey](https://github.com/getify/You-Dont-Know-JS/blob/bdbe570600d4e1107d0b131787903ca1c9ec8140/up%20%26%20going/ch2.md#truthy--falsy)
|
||||
*
|
||||
* 🤏 `message`s are not displayed in production environments to help keep bundles small
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* ```ts
|
||||
* const value: Person | null = { name: 'Alex' };
|
||||
* invariant(value, 'Expected value to be a person');
|
||||
* // type of `value`` has been narrowed to `Person`
|
||||
* ```
|
||||
*/
|
||||
export default function invariant(
|
||||
condition: any,
|
||||
// Not providing an inline default argument for message as the result is smaller
|
||||
/**
|
||||
* Can provide a string, or a function that returns a string for cases where
|
||||
* the message takes a fair amount of effort to compute
|
||||
*/
|
||||
message?: string | (() => string),
|
||||
): asserts condition {
|
||||
if (condition) {
|
||||
return;
|
||||
}
|
||||
// Condition not passed
|
||||
|
||||
// In production we strip the message but still throw
|
||||
if (isProduction) {
|
||||
throw new Error(prefix);
|
||||
}
|
||||
|
||||
// When not in production we allow the message to pass through
|
||||
// *This block will be removed in production builds*
|
||||
|
||||
const provided: string | undefined = typeof message === 'function' ? message() : message;
|
||||
|
||||
// Options:
|
||||
// 1. message provided: `${prefix}: ${provided}`
|
||||
// 2. message not provided: prefix
|
||||
const value: string = provided ? `${prefix}: ${provided}` : prefix;
|
||||
throw new Error(value);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
'use client';
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
||||
t[p] = s[p];
|
||||
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
||||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
||||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
||||
t[p[i]] = s[p[i]];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import clsx from 'clsx';
|
||||
import invariant from 'tiny-invariant';
|
||||
import Page from './Page.js';
|
||||
import { isProvided } from './shared/utils.js';
|
||||
import useDocumentContext from './shared/hooks/useDocumentContext.js';
|
||||
/**
|
||||
* Displays a thumbnail of a page. Does not render the annotation layer or the text layer. Does not register itself as a link target, so the user will not be scrolled to a Thumbnail component when clicked on an internal link (e.g. in Table of Contents). When clicked, attempts to navigate to the page clicked (similarly to a link in Outline).
|
||||
*
|
||||
* Should be placed inside `<Document />`. Alternatively, it can have `pdf` prop passed, which can be obtained from `<Document />`'s `onLoadSuccess` callback function.
|
||||
*/
|
||||
export default function Thumbnail(props) {
|
||||
const documentContext = useDocumentContext();
|
||||
const mergedProps = Object.assign(Object.assign({}, documentContext), props);
|
||||
const { className, linkService, onItemClick, pageIndex: pageIndexProps, pageNumber: pageNumberProps, pdf, } = mergedProps;
|
||||
invariant(pdf, 'Attempted to load a thumbnail, but no document was specified. Wrap <Thumbnail /> in a <Document /> or pass explicit `pdf` prop.');
|
||||
const pageIndex = isProvided(pageNumberProps) ? pageNumberProps - 1 : (pageIndexProps !== null && pageIndexProps !== void 0 ? pageIndexProps : null);
|
||||
const pageNumber = pageNumberProps !== null && pageNumberProps !== void 0 ? pageNumberProps : (isProvided(pageIndexProps) ? pageIndexProps + 1 : null);
|
||||
function onClick(event) {
|
||||
event.preventDefault();
|
||||
if (!isProvided(pageIndex) || !pageNumber) {
|
||||
return;
|
||||
}
|
||||
invariant(onItemClick || linkService, 'Either onItemClick callback or linkService must be defined in order to navigate to an outline item.');
|
||||
if (onItemClick) {
|
||||
onItemClick({
|
||||
pageIndex,
|
||||
pageNumber,
|
||||
});
|
||||
}
|
||||
else if (linkService) {
|
||||
linkService.goToPage(pageNumber);
|
||||
}
|
||||
}
|
||||
const { className: classNameProps, onItemClick: onItemClickProps } = props, pageProps = __rest(props, ["className", "onItemClick"]);
|
||||
return (_jsx("a", { className: clsx('react-pdf__Thumbnail', className), href: pageNumber ? '#' : undefined, onClick: onClick, children: _jsx(Page, Object.assign({}, pageProps, { _className: "react-pdf__Thumbnail__page", _enableRegisterUnregisterPage: false, renderAnnotationLayer: false, renderTextLayer: false })) }));
|
||||
}
|
||||
Reference in New Issue
Block a user