feature: vor und nachteile

This commit is contained in:
Hikyu
2026-05-31 13:54:31 +02:00
parent 552a947a1c
commit e3dad17446
23270 changed files with 3024794 additions and 200 deletions
+18
View File
@@ -0,0 +1,18 @@
The MIT License (MIT)
Copyright (c) 2024-PRESENT Anthony Fu <https://github.com/antfu>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+30
View File
@@ -0,0 +1,30 @@
<img src="https://twoslash.netlify.app/logo.svg" alt="Twoslash Logo" width="150">
# twoslash-protocol
[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![bundle][bundle-src]][bundle-href]
[![JSDocs][jsdocs-src]][jsdocs-href]
[![License][license-src]][license-href]
[📚 Documentation](https://twoslash.netlify.app/)
The protocol for Twoslash interface, a universal layer to support different language services that describe common editor features. This package also includes some common utilities for working with the protocol.
## License
MIT License © [Anthony Fu](https://github.com/antfu
<!-- Badges -->
[npm-version-src]: https://img.shields.io/npm/v/twoslash-protocol?style=flat&colorA=161514&colorB=EAB836
[npm-version-href]: https://npmjs.com/package/twoslash-protocol
[npm-downloads-src]: https://img.shields.io/npm/dm/twoslash-protocol?style=flat&colorA=161514&colorB=E66041
[npm-downloads-href]: https://npmjs.com/package/twoslash-protocol
[bundle-src]: https://img.shields.io/bundlephobia/minzip/twoslash-protocol?style=flat&colorA=161514&colorB=45627B&label=minzip
[bundle-href]: https://bundlephobia.com/result?p=twoslash-protocol
[license-src]: https://img.shields.io/github/license/twoslashes/twoslash.svg?style=flat&colorA=161514&colorB=45627B
[license-href]: https://github.com/twoslashes/twoslash/blob/main/LICENSE
[jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-161514?style=flat&colorA=161514&colorB=EAB836
[jsdocs-href]: https://www.jsdocs.io/package/twoslash-protocol
+96
View File
@@ -0,0 +1,96 @@
'use strict';
function isInRange(index, range, inclusive = true) {
if (inclusive)
return range[0] <= index && index <= range[1];
else
return range[0] < index && index < range[1];
}
function isInRanges(index, ranges, inclusive = true) {
return ranges.find((range) => isInRange(index, range, inclusive));
}
function mergeRanges(ranges) {
ranges.sort((a, b) => a[0] - b[0]);
const merged = [];
for (const range of ranges) {
const last = merged[merged.length - 1];
if (last && last[1] >= range[0])
last[1] = Math.max(last[1], range[1]);
else
merged.push(range);
}
return merged;
}
function splitLines(code, preserveEnding = false) {
const parts = code.split(/(\r?\n)/g);
let index = 0;
const lines = [];
for (let i = 0; i < parts.length; i += 2) {
const line = preserveEnding ? parts[i] + (parts[i + 1] || "") : parts[i];
lines.push([line, index]);
index += parts[i].length;
index += parts[i + 1]?.length || 0;
}
return lines;
}
function createPositionConverter(code) {
const lines = splitLines(code, true).map(([line]) => line);
function indexToPos(index) {
let character = index;
let line = 0;
for (const lineText of lines) {
if (character < lineText.length)
break;
character -= lineText.length;
line++;
}
return { line, character };
}
function posToIndex(line, character) {
let index = 0;
for (let i = 0; i < line; i++)
index += lines[i].length;
index += character;
return index;
}
return {
lines,
indexToPos,
posToIndex
};
}
function removeCodeRanges(code, removals, nodes) {
const ranges = mergeRanges(removals).sort((a, b) => b[0] - a[0]);
let outputCode = code;
for (const remove of ranges) {
const removalLength = remove[1] - remove[0];
outputCode = outputCode.slice(0, remove[0]) + outputCode.slice(remove[1]);
nodes?.forEach((node) => {
if (node.start + node.length <= remove[0])
return void 0;
else if (node.start < remove[1])
node.start = -1;
else
node.start -= removalLength;
});
}
return {
code: outputCode,
removals: ranges,
nodes
};
}
function resolveNodePositions(nodes, options) {
const indexToPos = typeof options === "string" ? createPositionConverter(options).indexToPos : options;
const resolved = nodes.filter((node) => node.start >= 0).sort((a, b) => a.start - b.start || a.type.localeCompare(b.type));
resolved.forEach((node) => Object.assign(node, indexToPos(node.start)));
return resolved;
}
exports.createPositionConverter = createPositionConverter;
exports.isInRange = isInRange;
exports.isInRanges = isInRanges;
exports.mergeRanges = mergeRanges;
exports.removeCodeRanges = removeCodeRanges;
exports.resolveNodePositions = resolveNodePositions;
exports.splitLines = splitLines;
+47
View File
@@ -0,0 +1,47 @@
import { Range, Position, NodeStartLength, NodeWithoutPosition, TwoslashNode } from './types.cjs';
export { CompletionEntry, ErrorLevel, NodeBase, NodeCompletion, NodeError, NodeErrorWithoutPosition, NodeHighlight, NodeHover, NodeQuery, NodeTag, TwoslashGenericFunction, TwoslashGenericResult } from './types.cjs';
declare function isInRange(index: number, range: Range, inclusive?: boolean): boolean;
declare function isInRanges(index: number, ranges: Range[], inclusive?: boolean): Range | undefined;
/**
* Merge overlapping ranges
*/
declare function mergeRanges(ranges: Range[]): Range[];
/**
* Slipt a string into lines, each line preserves the line ending.
*/
declare function splitLines(code: string, preserveEnding?: boolean): [string, number][];
/**
* Creates a converter between index and position in a code block.
*/
declare function createPositionConverter(code: string): {
lines: string[];
indexToPos: (index: number) => Position;
posToIndex: (line: number, character: number) => number;
};
/**
* Remove ranages for a string, and update nodes' `start` property accordingly
*
* Note that items in `nodes` will be mutated
*/
declare function removeCodeRanges<T extends NodeStartLength>(code: string, removals: Range[], nodes: T[]): {
code: string;
removals: Range[];
nodes: T[];
};
declare function removeCodeRanges(code: string, removals: Range[]): {
code: string;
removals: Range[];
nodes: undefined;
};
/**
* - Calculate nodes `line` and `character` properties to match the code
* - Remove nodes that has negative `start` property
* - Sort nodes by `start`
*
* Note that the nodes items will be mutated, clone them beforehand if not desired
*/
declare function resolveNodePositions(nodes: NodeWithoutPosition[], code: string): TwoslashNode[];
declare function resolveNodePositions(nodes: NodeWithoutPosition[], indexToPos: (index: number) => Position): TwoslashNode[];
export { NodeStartLength, NodeWithoutPosition, Position, Range, TwoslashNode, createPositionConverter, isInRange, isInRanges, mergeRanges, removeCodeRanges, resolveNodePositions, splitLines };
+47
View File
@@ -0,0 +1,47 @@
import { Range, Position, NodeStartLength, NodeWithoutPosition, TwoslashNode } from './types.mjs';
export { CompletionEntry, ErrorLevel, NodeBase, NodeCompletion, NodeError, NodeErrorWithoutPosition, NodeHighlight, NodeHover, NodeQuery, NodeTag, TwoslashGenericFunction, TwoslashGenericResult } from './types.mjs';
declare function isInRange(index: number, range: Range, inclusive?: boolean): boolean;
declare function isInRanges(index: number, ranges: Range[], inclusive?: boolean): Range | undefined;
/**
* Merge overlapping ranges
*/
declare function mergeRanges(ranges: Range[]): Range[];
/**
* Slipt a string into lines, each line preserves the line ending.
*/
declare function splitLines(code: string, preserveEnding?: boolean): [string, number][];
/**
* Creates a converter between index and position in a code block.
*/
declare function createPositionConverter(code: string): {
lines: string[];
indexToPos: (index: number) => Position;
posToIndex: (line: number, character: number) => number;
};
/**
* Remove ranages for a string, and update nodes' `start` property accordingly
*
* Note that items in `nodes` will be mutated
*/
declare function removeCodeRanges<T extends NodeStartLength>(code: string, removals: Range[], nodes: T[]): {
code: string;
removals: Range[];
nodes: T[];
};
declare function removeCodeRanges(code: string, removals: Range[]): {
code: string;
removals: Range[];
nodes: undefined;
};
/**
* - Calculate nodes `line` and `character` properties to match the code
* - Remove nodes that has negative `start` property
* - Sort nodes by `start`
*
* Note that the nodes items will be mutated, clone them beforehand if not desired
*/
declare function resolveNodePositions(nodes: NodeWithoutPosition[], code: string): TwoslashNode[];
declare function resolveNodePositions(nodes: NodeWithoutPosition[], indexToPos: (index: number) => Position): TwoslashNode[];
export { NodeStartLength, NodeWithoutPosition, Position, Range, TwoslashNode, createPositionConverter, isInRange, isInRanges, mergeRanges, removeCodeRanges, resolveNodePositions, splitLines };
+47
View File
@@ -0,0 +1,47 @@
import { Range, Position, NodeStartLength, NodeWithoutPosition, TwoslashNode } from './types.js';
export { CompletionEntry, ErrorLevel, NodeBase, NodeCompletion, NodeError, NodeErrorWithoutPosition, NodeHighlight, NodeHover, NodeQuery, NodeTag, TwoslashGenericFunction, TwoslashGenericResult } from './types.js';
declare function isInRange(index: number, range: Range, inclusive?: boolean): boolean;
declare function isInRanges(index: number, ranges: Range[], inclusive?: boolean): Range | undefined;
/**
* Merge overlapping ranges
*/
declare function mergeRanges(ranges: Range[]): Range[];
/**
* Slipt a string into lines, each line preserves the line ending.
*/
declare function splitLines(code: string, preserveEnding?: boolean): [string, number][];
/**
* Creates a converter between index and position in a code block.
*/
declare function createPositionConverter(code: string): {
lines: string[];
indexToPos: (index: number) => Position;
posToIndex: (line: number, character: number) => number;
};
/**
* Remove ranages for a string, and update nodes' `start` property accordingly
*
* Note that items in `nodes` will be mutated
*/
declare function removeCodeRanges<T extends NodeStartLength>(code: string, removals: Range[], nodes: T[]): {
code: string;
removals: Range[];
nodes: T[];
};
declare function removeCodeRanges(code: string, removals: Range[]): {
code: string;
removals: Range[];
nodes: undefined;
};
/**
* - Calculate nodes `line` and `character` properties to match the code
* - Remove nodes that has negative `start` property
* - Sort nodes by `start`
*
* Note that the nodes items will be mutated, clone them beforehand if not desired
*/
declare function resolveNodePositions(nodes: NodeWithoutPosition[], code: string): TwoslashNode[];
declare function resolveNodePositions(nodes: NodeWithoutPosition[], indexToPos: (index: number) => Position): TwoslashNode[];
export { NodeStartLength, NodeWithoutPosition, Position, Range, TwoslashNode, createPositionConverter, isInRange, isInRanges, mergeRanges, removeCodeRanges, resolveNodePositions, splitLines };
+88
View File
@@ -0,0 +1,88 @@
function isInRange(index, range, inclusive = true) {
if (inclusive)
return range[0] <= index && index <= range[1];
else
return range[0] < index && index < range[1];
}
function isInRanges(index, ranges, inclusive = true) {
return ranges.find((range) => isInRange(index, range, inclusive));
}
function mergeRanges(ranges) {
ranges.sort((a, b) => a[0] - b[0]);
const merged = [];
for (const range of ranges) {
const last = merged[merged.length - 1];
if (last && last[1] >= range[0])
last[1] = Math.max(last[1], range[1]);
else
merged.push(range);
}
return merged;
}
function splitLines(code, preserveEnding = false) {
const parts = code.split(/(\r?\n)/g);
let index = 0;
const lines = [];
for (let i = 0; i < parts.length; i += 2) {
const line = preserveEnding ? parts[i] + (parts[i + 1] || "") : parts[i];
lines.push([line, index]);
index += parts[i].length;
index += parts[i + 1]?.length || 0;
}
return lines;
}
function createPositionConverter(code) {
const lines = splitLines(code, true).map(([line]) => line);
function indexToPos(index) {
let character = index;
let line = 0;
for (const lineText of lines) {
if (character < lineText.length)
break;
character -= lineText.length;
line++;
}
return { line, character };
}
function posToIndex(line, character) {
let index = 0;
for (let i = 0; i < line; i++)
index += lines[i].length;
index += character;
return index;
}
return {
lines,
indexToPos,
posToIndex
};
}
function removeCodeRanges(code, removals, nodes) {
const ranges = mergeRanges(removals).sort((a, b) => b[0] - a[0]);
let outputCode = code;
for (const remove of ranges) {
const removalLength = remove[1] - remove[0];
outputCode = outputCode.slice(0, remove[0]) + outputCode.slice(remove[1]);
nodes?.forEach((node) => {
if (node.start + node.length <= remove[0])
return void 0;
else if (node.start < remove[1])
node.start = -1;
else
node.start -= removalLength;
});
}
return {
code: outputCode,
removals: ranges,
nodes
};
}
function resolveNodePositions(nodes, options) {
const indexToPos = typeof options === "string" ? createPositionConverter(options).indexToPos : options;
const resolved = nodes.filter((node) => node.start >= 0).sort((a, b) => a.start - b.start || a.type.localeCompare(b.type));
resolved.forEach((node) => Object.assign(node, indexToPos(node.start)));
return resolved;
}
export { createPositionConverter, isInRange, isInRanges, mergeRanges, removeCodeRanges, resolveNodePositions, splitLines };
+2
View File
@@ -0,0 +1,2 @@
'use strict';
+101
View File
@@ -0,0 +1,101 @@
/**
* Basic node with start and length to represent a range in the code
*/
interface NodeStartLength {
/** 0-indexed position of the node in the file */
start: number;
/** The length of the node */
length: number;
}
interface NodeBase extends NodeStartLength, Position {
}
interface NodeHover extends NodeBase {
type: 'hover';
/** The string content of the node this represents (mainly for debugging) */
target: string;
/** The base LSP response (the type) */
text: string;
/** Attached JSDoc info */
docs?: string;
/** JSDoc tags */
tags?: [name: string, text: string | undefined][];
}
interface NodeHighlight extends NodeBase {
type: 'highlight';
/** The annotation message */
text?: string;
}
interface NodeQuery extends Omit<NodeHover, 'type'> {
type: 'query';
}
interface CompletionEntry {
name: string;
kind?: string;
}
interface NodeCompletion extends NodeBase {
type: 'completion';
/** Results for completions at a particular point */
completions: CompletionEntry[];
completionsPrefix: string;
}
type ErrorLevel = 'warning' | 'error' | 'suggestion' | 'message';
interface NodeError extends NodeBase {
type: 'error';
id?: string;
/**
* Error level
* When not provided, defaults to 'error'
*/
level?: ErrorLevel;
/**
* Error code
*/
code?: number | string;
/**
* Error message
*/
text: string;
/**
* The filename of the file the error is in
*/
filename?: string;
}
interface NodeTag extends NodeBase {
type: 'tag';
/** What was the name of the tag */
name: string;
/** What was the text after the `// @tag: ` string (optional because you could do // @tag on it's own line without the ':') */
text?: string;
}
type TwoslashNode = NodeHighlight | NodeHover | NodeQuery | NodeCompletion | NodeError | NodeTag;
type NodeWithoutPosition = Omit<NodeHighlight, keyof Position> | Omit<NodeHover, keyof Position> | Omit<NodeQuery, keyof Position> | Omit<NodeCompletion, keyof Position> | Omit<NodeError, keyof Position> | Omit<NodeTag, keyof Position>;
type NodeErrorWithoutPosition = Omit<NodeError, keyof Position>;
interface Position {
/**
* 0-indexed line number
*/
line: number;
/**
* 0-indexed column number
*/
character: number;
}
type Range = [start: number, end: number];
interface TwoslashGenericResult {
/**
* The output code, could be TypeScript, but could also be a JS/JSON/d.ts
*/
code: string;
/**
* Extension of the output code
*/
extension?: string;
/**
* Nodes containing various bits of information about the code
*/
nodes: TwoslashNode[];
}
type TwoslashGenericFunction<Options = never> = (code: string, filename?: string, options?: Options) => TwoslashGenericResult;
export type { CompletionEntry, ErrorLevel, NodeBase, NodeCompletion, NodeError, NodeErrorWithoutPosition, NodeHighlight, NodeHover, NodeQuery, NodeStartLength, NodeTag, NodeWithoutPosition, Position, Range, TwoslashGenericFunction, TwoslashGenericResult, TwoslashNode };
+101
View File
@@ -0,0 +1,101 @@
/**
* Basic node with start and length to represent a range in the code
*/
interface NodeStartLength {
/** 0-indexed position of the node in the file */
start: number;
/** The length of the node */
length: number;
}
interface NodeBase extends NodeStartLength, Position {
}
interface NodeHover extends NodeBase {
type: 'hover';
/** The string content of the node this represents (mainly for debugging) */
target: string;
/** The base LSP response (the type) */
text: string;
/** Attached JSDoc info */
docs?: string;
/** JSDoc tags */
tags?: [name: string, text: string | undefined][];
}
interface NodeHighlight extends NodeBase {
type: 'highlight';
/** The annotation message */
text?: string;
}
interface NodeQuery extends Omit<NodeHover, 'type'> {
type: 'query';
}
interface CompletionEntry {
name: string;
kind?: string;
}
interface NodeCompletion extends NodeBase {
type: 'completion';
/** Results for completions at a particular point */
completions: CompletionEntry[];
completionsPrefix: string;
}
type ErrorLevel = 'warning' | 'error' | 'suggestion' | 'message';
interface NodeError extends NodeBase {
type: 'error';
id?: string;
/**
* Error level
* When not provided, defaults to 'error'
*/
level?: ErrorLevel;
/**
* Error code
*/
code?: number | string;
/**
* Error message
*/
text: string;
/**
* The filename of the file the error is in
*/
filename?: string;
}
interface NodeTag extends NodeBase {
type: 'tag';
/** What was the name of the tag */
name: string;
/** What was the text after the `// @tag: ` string (optional because you could do // @tag on it's own line without the ':') */
text?: string;
}
type TwoslashNode = NodeHighlight | NodeHover | NodeQuery | NodeCompletion | NodeError | NodeTag;
type NodeWithoutPosition = Omit<NodeHighlight, keyof Position> | Omit<NodeHover, keyof Position> | Omit<NodeQuery, keyof Position> | Omit<NodeCompletion, keyof Position> | Omit<NodeError, keyof Position> | Omit<NodeTag, keyof Position>;
type NodeErrorWithoutPosition = Omit<NodeError, keyof Position>;
interface Position {
/**
* 0-indexed line number
*/
line: number;
/**
* 0-indexed column number
*/
character: number;
}
type Range = [start: number, end: number];
interface TwoslashGenericResult {
/**
* The output code, could be TypeScript, but could also be a JS/JSON/d.ts
*/
code: string;
/**
* Extension of the output code
*/
extension?: string;
/**
* Nodes containing various bits of information about the code
*/
nodes: TwoslashNode[];
}
type TwoslashGenericFunction<Options = never> = (code: string, filename?: string, options?: Options) => TwoslashGenericResult;
export type { CompletionEntry, ErrorLevel, NodeBase, NodeCompletion, NodeError, NodeErrorWithoutPosition, NodeHighlight, NodeHover, NodeQuery, NodeStartLength, NodeTag, NodeWithoutPosition, Position, Range, TwoslashGenericFunction, TwoslashGenericResult, TwoslashNode };
+101
View File
@@ -0,0 +1,101 @@
/**
* Basic node with start and length to represent a range in the code
*/
interface NodeStartLength {
/** 0-indexed position of the node in the file */
start: number;
/** The length of the node */
length: number;
}
interface NodeBase extends NodeStartLength, Position {
}
interface NodeHover extends NodeBase {
type: 'hover';
/** The string content of the node this represents (mainly for debugging) */
target: string;
/** The base LSP response (the type) */
text: string;
/** Attached JSDoc info */
docs?: string;
/** JSDoc tags */
tags?: [name: string, text: string | undefined][];
}
interface NodeHighlight extends NodeBase {
type: 'highlight';
/** The annotation message */
text?: string;
}
interface NodeQuery extends Omit<NodeHover, 'type'> {
type: 'query';
}
interface CompletionEntry {
name: string;
kind?: string;
}
interface NodeCompletion extends NodeBase {
type: 'completion';
/** Results for completions at a particular point */
completions: CompletionEntry[];
completionsPrefix: string;
}
type ErrorLevel = 'warning' | 'error' | 'suggestion' | 'message';
interface NodeError extends NodeBase {
type: 'error';
id?: string;
/**
* Error level
* When not provided, defaults to 'error'
*/
level?: ErrorLevel;
/**
* Error code
*/
code?: number | string;
/**
* Error message
*/
text: string;
/**
* The filename of the file the error is in
*/
filename?: string;
}
interface NodeTag extends NodeBase {
type: 'tag';
/** What was the name of the tag */
name: string;
/** What was the text after the `// @tag: ` string (optional because you could do // @tag on it's own line without the ':') */
text?: string;
}
type TwoslashNode = NodeHighlight | NodeHover | NodeQuery | NodeCompletion | NodeError | NodeTag;
type NodeWithoutPosition = Omit<NodeHighlight, keyof Position> | Omit<NodeHover, keyof Position> | Omit<NodeQuery, keyof Position> | Omit<NodeCompletion, keyof Position> | Omit<NodeError, keyof Position> | Omit<NodeTag, keyof Position>;
type NodeErrorWithoutPosition = Omit<NodeError, keyof Position>;
interface Position {
/**
* 0-indexed line number
*/
line: number;
/**
* 0-indexed column number
*/
character: number;
}
type Range = [start: number, end: number];
interface TwoslashGenericResult {
/**
* The output code, could be TypeScript, but could also be a JS/JSON/d.ts
*/
code: string;
/**
* Extension of the output code
*/
extension?: string;
/**
* Nodes containing various bits of information about the code
*/
nodes: TwoslashNode[];
}
type TwoslashGenericFunction<Options = never> = (code: string, filename?: string, options?: Options) => TwoslashGenericResult;
export type { CompletionEntry, ErrorLevel, NodeBase, NodeCompletion, NodeError, NodeErrorWithoutPosition, NodeHighlight, NodeHover, NodeQuery, NodeStartLength, NodeTag, NodeWithoutPosition, Position, Range, TwoslashGenericFunction, TwoslashGenericResult, TwoslashNode };
+1
View File
@@ -0,0 +1 @@
+53
View File
@@ -0,0 +1,53 @@
{
"name": "twoslash-protocol",
"type": "module",
"version": "0.2.12",
"description": "The protocol for the Twoslash interface",
"author": "Anthony Fu",
"license": "MIT",
"homepage": "https://github.com/twoslashes/twoslash",
"repository": {
"url": "https://github.com/twoslashes/twoslash",
"type": "git",
"directory": "packages/twoslash-protocol"
},
"bugs": {
"url": "https://github.com/twoslashes/twoslash/issues"
},
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./types": {
"types": "./dist/types.d.mts",
"import": "./dist/types.mjs",
"require": "./dist/types.cjs"
}
},
"main": "dist/index.mjs",
"module": "dist/index.mjs",
"types": "dist/index.d.mts",
"typesVersions": {
"*": {
"./types": [
"./dist/types.d.mts"
],
"*": [
"./dist/index.d.mts"
]
}
},
"files": [
"dist"
],
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"
},
"lint-staged": {
"*": "eslint --fix"
},
"scripts": {
"build": "unbuild"
}
}