update
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import { deepEqual } from './utils'
|
||||
import type { NoInfer, PickOptional } from './utils'
|
||||
import type { SearchMiddleware } from './route'
|
||||
import type { IsRequiredParams } from './link'
|
||||
|
||||
export function retainSearchParams<TSearchSchema extends object>(
|
||||
keys: Array<keyof TSearchSchema> | true,
|
||||
): SearchMiddleware<TSearchSchema> {
|
||||
return ({ search, next }) => {
|
||||
const result = next(search)
|
||||
if (keys === true) {
|
||||
return { ...search, ...result }
|
||||
}
|
||||
// add missing keys from search to result
|
||||
keys.forEach((key) => {
|
||||
if (!(key in result)) {
|
||||
result[key] = search[key]
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
export function stripSearchParams<
|
||||
TSearchSchema,
|
||||
TOptionalProps = PickOptional<NoInfer<TSearchSchema>>,
|
||||
const TValues =
|
||||
| Partial<NoInfer<TOptionalProps>>
|
||||
| Array<keyof TOptionalProps>,
|
||||
const TInput = IsRequiredParams<TSearchSchema> extends never
|
||||
? TValues | true
|
||||
: TValues,
|
||||
>(input: NoInfer<TInput>): SearchMiddleware<TSearchSchema> {
|
||||
return ({ search, next }) => {
|
||||
if (input === true) {
|
||||
return {}
|
||||
}
|
||||
const result = next(search) as Record<string, unknown>
|
||||
if (Array.isArray(input)) {
|
||||
input.forEach((key) => {
|
||||
delete result[key]
|
||||
})
|
||||
} else {
|
||||
Object.entries(input as Record<string, unknown>).forEach(
|
||||
([key, value]) => {
|
||||
if (deepEqual(result[key], value)) {
|
||||
delete result[key]
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
return result as any
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
module.exports={A:{A:{"2":"K D E F A B mC"},B:{"2":"C L M G N O P","33":"0 9 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:{"2":"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:{"33":"0 1 2 3 4 5 6 7 8 9 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 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"},E:{"2":"sC SC","33":"J PB K D E F A B C L M G 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:{"2":"F B C 4C 5C 6C 7C FC kC 8C GC","33":"0 1 2 3 4 5 6 7 8 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"},G:{"33":"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:{"2":"WD"},I:{"33":"LC J I XD YD ZD aD lC bD cD"},J:{"33":"D A"},K:{"2":"A B C FC kC GC","33":"H"},L:{"33":"I"},M:{"2":"EC"},N:{"2":"A B"},O:{"33":"HC"},P:{"33":"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:{"33":"oD"},R:{"33":"pD"},S:{"2":"qD rD"}},B:7,C:"CSS Reflections",D:true};
|
||||
@@ -0,0 +1,16 @@
|
||||
export default function makeCancellablePromise<T>(promise: Promise<T>) {
|
||||
let isCancelled = false;
|
||||
|
||||
const wrappedPromise: typeof promise = new Promise((resolve, reject) => {
|
||||
promise
|
||||
.then((value) => !isCancelled && resolve(value))
|
||||
.catch((error) => !isCancelled && reject(error));
|
||||
});
|
||||
|
||||
return {
|
||||
promise: wrappedPromise,
|
||||
cancel() {
|
||||
isCancelled = true;
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
exports = module.exports = require('./lib/_stream_readable.js');
|
||||
exports.Stream = exports;
|
||||
exports.Readable = exports;
|
||||
exports.Writable = require('./lib/_stream_writable.js');
|
||||
exports.Duplex = require('./lib/_stream_duplex.js');
|
||||
exports.Transform = require('./lib/_stream_transform.js');
|
||||
exports.PassThrough = require('./lib/_stream_passthrough.js');
|
||||
exports.finished = require('./lib/internal/streams/end-of-stream.js');
|
||||
exports.pipeline = require('./lib/internal/streams/pipeline.js');
|
||||
@@ -0,0 +1,611 @@
|
||||
'use strict';
|
||||
|
||||
var levn = require('levn');
|
||||
|
||||
/**
|
||||
* @fileoverview Config Comment Parser
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @typedef {import("@eslint/core").RuleConfig} RuleConfig */
|
||||
/** @typedef {import("@eslint/core").RulesConfig} RulesConfig */
|
||||
/** @typedef {import("./types.ts").StringConfig} StringConfig */
|
||||
/** @typedef {import("./types.ts").BooleanConfig} BooleanConfig */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const directivesPattern = /^([a-z]+(?:-[a-z]+)*)(?:\s|$)/u;
|
||||
const validSeverities = new Set([0, 1, 2, "off", "warn", "error"]);
|
||||
|
||||
/**
|
||||
* Determines if the severity in the rule configuration is valid.
|
||||
* @param {RuleConfig} ruleConfig A rule's configuration.
|
||||
*/
|
||||
function isSeverityValid(ruleConfig) {
|
||||
const severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
|
||||
return validSeverities.has(severity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if all severities in the rules configuration are valid.
|
||||
* @param {RulesConfig} rulesConfig The rules configuration to check.
|
||||
* @returns {boolean} `true` if all severities are valid, otherwise `false`.
|
||||
*/
|
||||
function isEverySeverityValid(rulesConfig) {
|
||||
return Object.values(rulesConfig).every(isSeverityValid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a directive comment.
|
||||
*/
|
||||
class DirectiveComment {
|
||||
/**
|
||||
* The label of the directive, such as "eslint", "eslint-disable", etc.
|
||||
* @type {string}
|
||||
*/
|
||||
label = "";
|
||||
|
||||
/**
|
||||
* The value of the directive (the string after the label).
|
||||
* @type {string}
|
||||
*/
|
||||
value = "";
|
||||
|
||||
/**
|
||||
* The justification of the directive (the string after the --).
|
||||
* @type {string}
|
||||
*/
|
||||
justification = "";
|
||||
|
||||
/**
|
||||
* Creates a new directive comment.
|
||||
* @param {string} label The label of the directive.
|
||||
* @param {string} value The value of the directive.
|
||||
* @param {string} justification The justification of the directive.
|
||||
*/
|
||||
constructor(label, value, justification) {
|
||||
this.label = label;
|
||||
this.value = value;
|
||||
this.justification = justification;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Interface
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Object to parse ESLint configuration comments.
|
||||
*/
|
||||
class ConfigCommentParser {
|
||||
/**
|
||||
* Parses a list of "name:string_value" or/and "name" options divided by comma or
|
||||
* whitespace. Used for "global" comments.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {StringConfig} Result map object of names and string values, or null values if no value was provided.
|
||||
*/
|
||||
parseStringConfig(string) {
|
||||
const items = /** @type {StringConfig} */ ({});
|
||||
|
||||
// Collapse whitespace around `:` and `,` to make parsing easier
|
||||
const trimmedString = string
|
||||
.trim()
|
||||
.replace(/(?<!\s)\s*([:,])\s*/gu, "$1");
|
||||
|
||||
trimmedString.split(/\s|,+/u).forEach(name => {
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
|
||||
// value defaults to null (if not provided), e.g: "foo" => ["foo", null]
|
||||
const [key, value = null] = name.split(":");
|
||||
|
||||
items[key] = value;
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a JSON-like config.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {({ok: true, config: RulesConfig}|{ok: false, error: {message: string}})} Result map object
|
||||
*/
|
||||
parseJSONLikeConfig(string) {
|
||||
// Parses a JSON-like comment by the same way as parsing CLI option.
|
||||
try {
|
||||
const items =
|
||||
/** @type {RulesConfig} */ (levn.parse("Object", string)) || {};
|
||||
|
||||
/*
|
||||
* When the configuration has any invalid severities, it should be completely
|
||||
* ignored. This is because the configuration is not valid and should not be
|
||||
* applied.
|
||||
*
|
||||
* For example, the following configuration is invalid:
|
||||
*
|
||||
* "no-alert: 2 no-console: 2"
|
||||
*
|
||||
* This results in a configuration of { "no-alert": "2 no-console: 2" }, which is
|
||||
* not valid. In this case, the configuration should be ignored.
|
||||
*/
|
||||
if (isEverySeverityValid(items)) {
|
||||
return {
|
||||
ok: true,
|
||||
config: items,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
// levn parsing error: ignore to parse the string by a fallback.
|
||||
}
|
||||
|
||||
/*
|
||||
* Optionator cannot parse commaless notations.
|
||||
* But we are supporting that. So this is a fallback for that.
|
||||
*/
|
||||
const normalizedString = string
|
||||
.replace(/([-a-zA-Z0-9/]+):/gu, '"$1":')
|
||||
.replace(/(\]|[0-9])\s+(?=")/u, "$1,");
|
||||
|
||||
try {
|
||||
const items = JSON.parse(`{${normalizedString}}`);
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
config: items,
|
||||
};
|
||||
} catch (ex) {
|
||||
const errorMessage = ex instanceof Error ? ex.message : String(ex);
|
||||
|
||||
return {
|
||||
ok: false,
|
||||
error: {
|
||||
message: `Failed to parse JSON from '${normalizedString}': ${errorMessage}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a config of values separated by comma.
|
||||
* @param {string} string The string to parse.
|
||||
* @returns {BooleanConfig} Result map of values and true values
|
||||
*/
|
||||
parseListConfig(string) {
|
||||
const items = /** @type {BooleanConfig} */ ({});
|
||||
|
||||
string.split(",").forEach(name => {
|
||||
const trimmedName = name
|
||||
.trim()
|
||||
.replace(
|
||||
/^(?<quote>['"]?)(?<ruleId>.*)\k<quote>$/su,
|
||||
"$<ruleId>",
|
||||
);
|
||||
|
||||
if (trimmedName) {
|
||||
items[trimmedName] = true;
|
||||
}
|
||||
});
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the directive and the justification from a given directive comment and trim them.
|
||||
* @param {string} value The comment text to extract.
|
||||
* @returns {{directivePart: string, justificationPart: string}} The extracted directive and justification.
|
||||
*/
|
||||
#extractDirectiveComment(value) {
|
||||
const match = /\s-{2,}\s/u.exec(value);
|
||||
|
||||
if (!match) {
|
||||
return { directivePart: value.trim(), justificationPart: "" };
|
||||
}
|
||||
|
||||
const directive = value.slice(0, match.index).trim();
|
||||
const justification = value.slice(match.index + match[0].length).trim();
|
||||
|
||||
return { directivePart: directive, justificationPart: justification };
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a directive comment into directive text and value.
|
||||
* @param {string} string The string with the directive to be parsed.
|
||||
* @returns {DirectiveComment|undefined} The parsed directive or `undefined` if the directive is invalid.
|
||||
*/
|
||||
parseDirective(string) {
|
||||
const { directivePart, justificationPart } =
|
||||
this.#extractDirectiveComment(string);
|
||||
const match = directivesPattern.exec(directivePart);
|
||||
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const directiveText = match[1];
|
||||
const directiveValue = directivePart.slice(
|
||||
match.index + directiveText.length,
|
||||
);
|
||||
|
||||
return new DirectiveComment(
|
||||
directiveText,
|
||||
directiveValue.trim(),
|
||||
justificationPart,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fileoverview A collection of helper classes for implementing `SourceCode`.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
/* eslint class-methods-use-this: off -- Required to complete interface. */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Type Definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** @typedef {import("@eslint/core").VisitTraversalStep} VisitTraversalStep */
|
||||
/** @typedef {import("@eslint/core").CallTraversalStep} CallTraversalStep */
|
||||
/** @typedef {import("@eslint/core").TextSourceCode} TextSourceCode */
|
||||
/** @typedef {import("@eslint/core").TraversalStep} TraversalStep */
|
||||
/** @typedef {import("@eslint/core").SourceLocation} SourceLocation */
|
||||
/** @typedef {import("@eslint/core").SourceLocationWithOffset} SourceLocationWithOffset */
|
||||
/** @typedef {import("@eslint/core").SourceRange} SourceRange */
|
||||
/** @typedef {import("@eslint/core").Directive} IDirective */
|
||||
/** @typedef {import("@eslint/core").DirectiveType} DirectiveType */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Determines if a node has ESTree-style loc information.
|
||||
* @param {object} node The node to check.
|
||||
* @returns {node is {loc:SourceLocation}} `true` if the node has ESTree-style loc information, `false` if not.
|
||||
*/
|
||||
function hasESTreeStyleLoc(node) {
|
||||
return "loc" in node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a node has position-style loc information.
|
||||
* @param {object} node The node to check.
|
||||
* @returns {node is {position:SourceLocation}} `true` if the node has position-style range information, `false` if not.
|
||||
*/
|
||||
function hasPosStyleLoc(node) {
|
||||
return "position" in node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a node has ESTree-style range information.
|
||||
* @param {object} node The node to check.
|
||||
* @returns {node is {range:SourceRange}} `true` if the node has ESTree-style range information, `false` if not.
|
||||
*/
|
||||
function hasESTreeStyleRange(node) {
|
||||
return "range" in node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a node has position-style range information.
|
||||
* @param {object} node The node to check.
|
||||
* @returns {node is {position:SourceLocationWithOffset}} `true` if the node has position-style range information, `false` if not.
|
||||
*/
|
||||
function hasPosStyleRange(node) {
|
||||
return "position" in node;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Exports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A class to represent a step in the traversal process where a node is visited.
|
||||
* @implements {VisitTraversalStep}
|
||||
*/
|
||||
class VisitNodeStep {
|
||||
/**
|
||||
* The type of the step.
|
||||
* @type {"visit"}
|
||||
* @readonly
|
||||
*/
|
||||
type = "visit";
|
||||
|
||||
/**
|
||||
* The kind of the step. Represents the same data as the `type` property
|
||||
* but it's a number for performance.
|
||||
* @type {1}
|
||||
* @readonly
|
||||
*/
|
||||
kind = 1;
|
||||
|
||||
/**
|
||||
* The target of the step.
|
||||
* @type {object}
|
||||
*/
|
||||
target;
|
||||
|
||||
/**
|
||||
* The phase of the step.
|
||||
* @type {1|2}
|
||||
*/
|
||||
phase;
|
||||
|
||||
/**
|
||||
* The arguments of the step.
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
args;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the step.
|
||||
* @param {object} options.target The target of the step.
|
||||
* @param {1|2} options.phase The phase of the step.
|
||||
* @param {Array<any>} options.args The arguments of the step.
|
||||
*/
|
||||
constructor({ target, phase, args }) {
|
||||
this.target = target;
|
||||
this.phase = phase;
|
||||
this.args = args;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to represent a step in the traversal process where a
|
||||
* method is called.
|
||||
* @implements {CallTraversalStep}
|
||||
*/
|
||||
class CallMethodStep {
|
||||
/**
|
||||
* The type of the step.
|
||||
* @type {"call"}
|
||||
* @readonly
|
||||
*/
|
||||
type = "call";
|
||||
|
||||
/**
|
||||
* The kind of the step. Represents the same data as the `type` property
|
||||
* but it's a number for performance.
|
||||
* @type {2}
|
||||
* @readonly
|
||||
*/
|
||||
kind = 2;
|
||||
|
||||
/**
|
||||
* The name of the method to call.
|
||||
* @type {string}
|
||||
*/
|
||||
target;
|
||||
|
||||
/**
|
||||
* The arguments to pass to the method.
|
||||
* @type {Array<any>}
|
||||
*/
|
||||
args;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the step.
|
||||
* @param {string} options.target The target of the step.
|
||||
* @param {Array<any>} options.args The arguments of the step.
|
||||
*/
|
||||
constructor({ target, args }) {
|
||||
this.target = target;
|
||||
this.args = args;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to represent a directive comment.
|
||||
* @implements {IDirective}
|
||||
*/
|
||||
class Directive {
|
||||
/**
|
||||
* The type of directive.
|
||||
* @type {DirectiveType}
|
||||
* @readonly
|
||||
*/
|
||||
type;
|
||||
|
||||
/**
|
||||
* The node representing the directive.
|
||||
* @type {unknown}
|
||||
* @readonly
|
||||
*/
|
||||
node;
|
||||
|
||||
/**
|
||||
* Everything after the "eslint-disable" portion of the directive,
|
||||
* but before the "--" that indicates the justification.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
value;
|
||||
|
||||
/**
|
||||
* The justification for the directive.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
justification;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the directive.
|
||||
* @param {"disable"|"enable"|"disable-next-line"|"disable-line"} options.type The type of directive.
|
||||
* @param {unknown} options.node The node representing the directive.
|
||||
* @param {string} options.value The value of the directive.
|
||||
* @param {string} options.justification The justification for the directive.
|
||||
*/
|
||||
constructor({ type, node, value, justification }) {
|
||||
this.type = type;
|
||||
this.node = node;
|
||||
this.value = value;
|
||||
this.justification = justification;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Source Code Base Object
|
||||
* @implements {TextSourceCode}
|
||||
*/
|
||||
class TextSourceCodeBase {
|
||||
/**
|
||||
* The lines of text in the source code.
|
||||
* @type {Array<string>}
|
||||
*/
|
||||
#lines;
|
||||
|
||||
/**
|
||||
* The AST of the source code.
|
||||
* @type {object}
|
||||
*/
|
||||
ast;
|
||||
|
||||
/**
|
||||
* The text of the source code.
|
||||
* @type {string}
|
||||
*/
|
||||
text;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param {Object} options The options for the instance.
|
||||
* @param {string} options.text The source code text.
|
||||
* @param {object} options.ast The root AST node.
|
||||
* @param {RegExp} [options.lineEndingPattern] The pattern to match lineEndings in the source code.
|
||||
*/
|
||||
constructor({ text, ast, lineEndingPattern = /\r?\n/u }) {
|
||||
this.ast = ast;
|
||||
this.text = text;
|
||||
this.#lines = text.split(lineEndingPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the loc information for the given node or token.
|
||||
* @param {object} nodeOrToken The node or token to get the loc information for.
|
||||
* @returns {SourceLocation} The loc information for the node or token.
|
||||
*/
|
||||
getLoc(nodeOrToken) {
|
||||
if (hasESTreeStyleLoc(nodeOrToken)) {
|
||||
return nodeOrToken.loc;
|
||||
}
|
||||
|
||||
if (hasPosStyleLoc(nodeOrToken)) {
|
||||
return nodeOrToken.position;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
"Custom getLoc() method must be implemented in the subclass.",
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the range information for the given node or token.
|
||||
* @param {object} nodeOrToken The node or token to get the range information for.
|
||||
* @returns {SourceRange} The range information for the node or token.
|
||||
*/
|
||||
getRange(nodeOrToken) {
|
||||
if (hasESTreeStyleRange(nodeOrToken)) {
|
||||
return nodeOrToken.range;
|
||||
}
|
||||
|
||||
if (hasPosStyleRange(nodeOrToken)) {
|
||||
return [
|
||||
nodeOrToken.position.start.offset,
|
||||
nodeOrToken.position.end.offset,
|
||||
];
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
"Custom getRange() method must be implemented in the subclass.",
|
||||
);
|
||||
}
|
||||
|
||||
/* eslint-disable no-unused-vars -- Required to complete interface. */
|
||||
/**
|
||||
* Returns the parent of the given node.
|
||||
* @param {object} node The node to get the parent of.
|
||||
* @returns {object|undefined} The parent of the node.
|
||||
*/
|
||||
getParent(node) {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
/* eslint-enable no-unused-vars -- Required to complete interface. */
|
||||
|
||||
/**
|
||||
* Gets all the ancestors of a given node
|
||||
* @param {object} node The node
|
||||
* @returns {Array<object>} All the ancestor nodes in the AST, not including the provided node, starting
|
||||
* from the root node at index 0 and going inwards to the parent node.
|
||||
* @throws {TypeError} When `node` is missing.
|
||||
*/
|
||||
getAncestors(node) {
|
||||
if (!node) {
|
||||
throw new TypeError("Missing required argument: node.");
|
||||
}
|
||||
|
||||
const ancestorsStartingAtParent = [];
|
||||
|
||||
for (
|
||||
let ancestor = this.getParent(node);
|
||||
ancestor;
|
||||
ancestor = this.getParent(ancestor)
|
||||
) {
|
||||
ancestorsStartingAtParent.push(ancestor);
|
||||
}
|
||||
|
||||
return ancestorsStartingAtParent.reverse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source code for the given node.
|
||||
* @param {object} [node] The AST node to get the text for.
|
||||
* @param {number} [beforeCount] The number of characters before the node to retrieve.
|
||||
* @param {number} [afterCount] The number of characters after the node to retrieve.
|
||||
* @returns {string} The text representing the AST node.
|
||||
* @public
|
||||
*/
|
||||
getText(node, beforeCount, afterCount) {
|
||||
if (node) {
|
||||
const range = this.getRange(node);
|
||||
return this.text.slice(
|
||||
Math.max(range[0] - (beforeCount || 0), 0),
|
||||
range[1] + (afterCount || 0),
|
||||
);
|
||||
}
|
||||
return this.text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entire source text split into an array of lines.
|
||||
* @returns {Array<string>} The source text as an array of lines.
|
||||
* @public
|
||||
*/
|
||||
get lines() {
|
||||
return this.#lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse the source code and return the steps that were taken.
|
||||
* @returns {Iterable<TraversalStep>} The steps that were taken while traversing the source code.
|
||||
*/
|
||||
traverse() {
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
exports.CallMethodStep = CallMethodStep;
|
||||
exports.ConfigCommentParser = ConfigCommentParser;
|
||||
exports.Directive = Directive;
|
||||
exports.TextSourceCodeBase = TextSourceCodeBase;
|
||||
exports.VisitNodeStep = VisitNodeStep;
|
||||
@@ -0,0 +1,4 @@
|
||||
const outside = require('./outside')
|
||||
// Determine if version is less than all the versions possible in the range
|
||||
const ltr = (version, range, options) => outside(version, range, '<', options)
|
||||
module.exports = ltr
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @fileoverview Rule to disallow use of the new operator with global non-constructor functions
|
||||
* @author Sosuke Suzuki
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const nonConstructorGlobalFunctionNames = ["Symbol", "BigInt"];
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description:
|
||||
"Disallow `new` operators with global non-constructor functions",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/latest/rules/no-new-native-nonconstructor",
|
||||
},
|
||||
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
noNewNonconstructor:
|
||||
"`{{name}}` cannot be called as a constructor.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
return {
|
||||
"Program:exit"(node) {
|
||||
const globalScope = sourceCode.getScope(node);
|
||||
|
||||
for (const nonConstructorName of nonConstructorGlobalFunctionNames) {
|
||||
const variable = globalScope.set.get(nonConstructorName);
|
||||
|
||||
if (variable && variable.defs.length === 0) {
|
||||
variable.references.forEach(ref => {
|
||||
const idNode = ref.identifier;
|
||||
const parent = idNode.parent;
|
||||
|
||||
if (
|
||||
parent &&
|
||||
parent.type === "NewExpression" &&
|
||||
parent.callee === idNode
|
||||
) {
|
||||
context.report({
|
||||
node: idNode,
|
||||
messageId: "noNewNonconstructor",
|
||||
data: { name: nonConstructorName },
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
module.exports={A:{A:{"2":"K D E F A B mC"},B:{"2":"C L M G N O P","2052":"0 9 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:{"2":"nC LC J PB qC rC","1028":"0 9 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","1060":"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 UB VB WB XB YB"},D:{"2":"1 2 3 4 5 6 J PB K D E F A B C L M G N O P QB","226":"7 8 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","2052":"0 9 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"},E:{"2":"J PB K D sC SC tC uC","772":"L M G 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","804":"E F A B C wC TC FC","1316":"vC"},F:{"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","226":"YB ZB aB bB cB dB eB fB gB","2052":"0 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"},G:{"2":"SC 9C lC AD BD CD","292":"E 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:{"2":"WD"},I:{"1":"I","2":"LC J XD YD ZD aD lC bD cD"},J:{"2":"D A"},K:{"2":"A B C FC kC GC","2052":"H"},L:{"2052":"I"},M:{"1028":"EC"},N:{"2":"A B"},O:{"2052":"HC"},P:{"2":"J dD eD","2052":"1 2 3 4 5 6 7 8 fD gD hD TC iD jD kD lD mD IC JC KC nD"},Q:{"2052":"oD"},R:{"2052":"pD"},S:{"1028":"qD rD"}},B:4,C:"text-decoration styling",D:true};
|
||||
@@ -0,0 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = require('./static.node');
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = require('fs').constants || require('constants')
|
||||
@@ -0,0 +1,16 @@
|
||||
const SemVer = require('../classes/semver')
|
||||
const parse = (version, options, throwErrors = false) => {
|
||||
if (version instanceof SemVer) {
|
||||
return version
|
||||
}
|
||||
try {
|
||||
return new SemVer(version, options)
|
||||
} catch (er) {
|
||||
if (!throwErrors) {
|
||||
return null
|
||||
}
|
||||
throw er
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = parse
|
||||
@@ -0,0 +1,268 @@
|
||||
/**
|
||||
* @fileoverview Rule to require object keys to be sorted
|
||||
* @author Toru Nagashima
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const astUtils = require("./utils/ast-utils"),
|
||||
naturalCompare = require("natural-compare");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Gets the property name of the given `Property` node.
|
||||
*
|
||||
* - If the property's key is an `Identifier` node, this returns the key's name
|
||||
* whether it's a computed property or not.
|
||||
* - If the property has a static name, this returns the static name.
|
||||
* - Otherwise, this returns null.
|
||||
* @param {ASTNode} node The `Property` node to get.
|
||||
* @returns {string|null} The property name or null.
|
||||
* @private
|
||||
*/
|
||||
function getPropertyName(node) {
|
||||
const staticName = astUtils.getStaticPropertyName(node);
|
||||
|
||||
if (staticName !== null) {
|
||||
return staticName;
|
||||
}
|
||||
|
||||
return node.key.name || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions which check that the given 2 names are in specific order.
|
||||
*
|
||||
* Postfix `I` is meant insensitive.
|
||||
* Postfix `N` is meant natural.
|
||||
* @private
|
||||
*/
|
||||
const isValidOrders = {
|
||||
asc(a, b) {
|
||||
return a <= b;
|
||||
},
|
||||
ascI(a, b) {
|
||||
return a.toLowerCase() <= b.toLowerCase();
|
||||
},
|
||||
ascN(a, b) {
|
||||
return naturalCompare(a, b) <= 0;
|
||||
},
|
||||
ascIN(a, b) {
|
||||
return naturalCompare(a.toLowerCase(), b.toLowerCase()) <= 0;
|
||||
},
|
||||
desc(a, b) {
|
||||
return isValidOrders.asc(b, a);
|
||||
},
|
||||
descI(a, b) {
|
||||
return isValidOrders.ascI(b, a);
|
||||
},
|
||||
descN(a, b) {
|
||||
return isValidOrders.ascN(b, a);
|
||||
},
|
||||
descIN(a, b) {
|
||||
return isValidOrders.ascIN(b, a);
|
||||
},
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
defaultOptions: [
|
||||
"asc",
|
||||
{
|
||||
allowLineSeparatedGroups: false,
|
||||
caseSensitive: true,
|
||||
ignoreComputedKeys: false,
|
||||
minKeys: 2,
|
||||
natural: false,
|
||||
},
|
||||
],
|
||||
|
||||
docs: {
|
||||
description: "Require object keys to be sorted",
|
||||
recommended: false,
|
||||
frozen: true,
|
||||
url: "https://eslint.org/docs/latest/rules/sort-keys",
|
||||
},
|
||||
|
||||
schema: [
|
||||
{
|
||||
enum: ["asc", "desc"],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
caseSensitive: {
|
||||
type: "boolean",
|
||||
},
|
||||
natural: {
|
||||
type: "boolean",
|
||||
},
|
||||
minKeys: {
|
||||
type: "integer",
|
||||
minimum: 2,
|
||||
},
|
||||
allowLineSeparatedGroups: {
|
||||
type: "boolean",
|
||||
},
|
||||
ignoreComputedKeys: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
|
||||
messages: {
|
||||
sortKeys:
|
||||
"Expected object keys to be in {{natural}}{{insensitive}}{{order}}ending order. '{{thisName}}' should be before '{{prevName}}'.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const [
|
||||
order,
|
||||
{
|
||||
caseSensitive,
|
||||
natural,
|
||||
minKeys,
|
||||
allowLineSeparatedGroups,
|
||||
ignoreComputedKeys,
|
||||
},
|
||||
] = context.options;
|
||||
const insensitive = !caseSensitive;
|
||||
const isValidOrder =
|
||||
isValidOrders[
|
||||
order + (insensitive ? "I" : "") + (natural ? "N" : "")
|
||||
];
|
||||
|
||||
// The stack to save the previous property's name for each object literals.
|
||||
let stack = null;
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
return {
|
||||
ObjectExpression(node) {
|
||||
stack = {
|
||||
upper: stack,
|
||||
prevNode: null,
|
||||
prevBlankLine: false,
|
||||
prevName: null,
|
||||
numKeys: node.properties.length,
|
||||
};
|
||||
},
|
||||
|
||||
"ObjectExpression:exit"() {
|
||||
stack = stack.upper;
|
||||
},
|
||||
|
||||
SpreadElement(node) {
|
||||
if (node.parent.type === "ObjectExpression") {
|
||||
stack.prevName = null;
|
||||
}
|
||||
},
|
||||
|
||||
Property(node) {
|
||||
if (node.parent.type === "ObjectPattern") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ignoreComputedKeys && node.computed) {
|
||||
stack.prevName = null; // reset sort
|
||||
return;
|
||||
}
|
||||
|
||||
const prevName = stack.prevName;
|
||||
const numKeys = stack.numKeys;
|
||||
const thisName = getPropertyName(node);
|
||||
|
||||
// Get tokens between current node and previous node
|
||||
const tokens =
|
||||
stack.prevNode &&
|
||||
sourceCode.getTokensBetween(stack.prevNode, node, {
|
||||
includeComments: true,
|
||||
});
|
||||
|
||||
let isBlankLineBetweenNodes = stack.prevBlankLine;
|
||||
|
||||
if (tokens) {
|
||||
// check blank line between tokens
|
||||
tokens.forEach((token, index) => {
|
||||
const previousToken = tokens[index - 1];
|
||||
|
||||
if (
|
||||
previousToken &&
|
||||
token.loc.start.line - previousToken.loc.end.line >
|
||||
1
|
||||
) {
|
||||
isBlankLineBetweenNodes = true;
|
||||
}
|
||||
});
|
||||
|
||||
// check blank line between the current node and the last token
|
||||
if (
|
||||
!isBlankLineBetweenNodes &&
|
||||
node.loc.start.line - tokens.at(-1).loc.end.line > 1
|
||||
) {
|
||||
isBlankLineBetweenNodes = true;
|
||||
}
|
||||
|
||||
// check blank line between the first token and the previous node
|
||||
if (
|
||||
!isBlankLineBetweenNodes &&
|
||||
tokens[0].loc.start.line - stack.prevNode.loc.end.line >
|
||||
1
|
||||
) {
|
||||
isBlankLineBetweenNodes = true;
|
||||
}
|
||||
}
|
||||
|
||||
stack.prevNode = node;
|
||||
|
||||
if (thisName !== null) {
|
||||
stack.prevName = thisName;
|
||||
}
|
||||
|
||||
if (allowLineSeparatedGroups && isBlankLineBetweenNodes) {
|
||||
stack.prevBlankLine = thisName === null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
prevName === null ||
|
||||
thisName === null ||
|
||||
numKeys < minKeys
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidOrder(prevName, thisName)) {
|
||||
context.report({
|
||||
node,
|
||||
loc: node.key.loc,
|
||||
messageId: "sortKeys",
|
||||
data: {
|
||||
thisName,
|
||||
prevName,
|
||||
order,
|
||||
insensitive: insensitive ? "insensitive " : "",
|
||||
natural: natural ? "natural " : "",
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* @fileoverview Rule that warns about used warning comments
|
||||
* @author Alexander Schmidt <https://github.com/lxanders>
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const escapeRegExp = require("escape-string-regexp");
|
||||
const astUtils = require("./utils/ast-utils");
|
||||
|
||||
const CHAR_LIMIT = 40;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
defaultOptions: [
|
||||
{
|
||||
location: "start",
|
||||
terms: ["todo", "fixme", "xxx"],
|
||||
},
|
||||
],
|
||||
|
||||
docs: {
|
||||
description: "Disallow specified warning terms in comments",
|
||||
recommended: false,
|
||||
frozen: true,
|
||||
url: "https://eslint.org/docs/latest/rules/no-warning-comments",
|
||||
},
|
||||
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
terms: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
location: {
|
||||
enum: ["start", "anywhere"],
|
||||
},
|
||||
decoration: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "string",
|
||||
pattern: "^\\S$",
|
||||
},
|
||||
minItems: 1,
|
||||
uniqueItems: true,
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
|
||||
messages: {
|
||||
unexpectedComment:
|
||||
"Unexpected '{{matchedTerm}}' comment: '{{comment}}'.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
const [{ decoration, location, terms: warningTerms }] = context.options;
|
||||
const escapedDecoration = escapeRegExp(
|
||||
decoration ? decoration.join("") : "",
|
||||
);
|
||||
const selfConfigRegEx = /\bno-warning-comments\b/u;
|
||||
|
||||
/**
|
||||
* Convert a warning term into a RegExp which will match a comment containing that whole word in the specified
|
||||
* location ("start" or "anywhere"). If the term starts or ends with non word characters, then the match will not
|
||||
* require word boundaries on that side.
|
||||
* @param {string} term A term to convert to a RegExp
|
||||
* @returns {RegExp} The term converted to a RegExp
|
||||
*/
|
||||
function convertToRegExp(term) {
|
||||
const escaped = escapeRegExp(term);
|
||||
|
||||
/*
|
||||
* When matching at the start, ignore leading whitespace, and
|
||||
* there's no need to worry about word boundaries.
|
||||
*
|
||||
* These expressions for the prefix and suffix are designed as follows:
|
||||
* ^ handles any terms at the beginning of a comment.
|
||||
* e.g. terms ["TODO"] matches `//TODO something`
|
||||
* $ handles any terms at the end of a comment
|
||||
* e.g. terms ["TODO"] matches `// something TODO`
|
||||
* \b handles terms preceded/followed by word boundary
|
||||
* e.g. terms: ["!FIX", "FIX!"] matches `// FIX!something` or `// something!FIX`
|
||||
* terms: ["FIX"] matches `// FIX!` or `// !FIX`, but not `// fixed or affix`
|
||||
*
|
||||
* For location start:
|
||||
* [\s]* handles optional leading spaces
|
||||
* e.g. terms ["TODO"] matches `// TODO something`
|
||||
* [\s\*]* (where "\*" is the escaped string of decoration)
|
||||
* handles optional leading spaces or decoration characters (for "start" location only)
|
||||
* e.g. terms ["TODO"] matches `/**** TODO something ... `
|
||||
*/
|
||||
const wordBoundary = "\\b";
|
||||
|
||||
let prefix = "";
|
||||
|
||||
if (location === "start") {
|
||||
prefix = `^[\\s${escapedDecoration}]*`;
|
||||
} else if (/^\w/u.test(term)) {
|
||||
prefix = wordBoundary;
|
||||
}
|
||||
|
||||
const suffix = /\w$/u.test(term) ? wordBoundary : "";
|
||||
const flags = "iu"; // Case-insensitive with Unicode case folding.
|
||||
|
||||
/*
|
||||
* For location "start", the typical regex is:
|
||||
* /^[\s]*ESCAPED_TERM\b/iu.
|
||||
* Or if decoration characters are specified (e.g. "*"), then any of
|
||||
* those characters may appear in any order at the start:
|
||||
* /^[\s\*]*ESCAPED_TERM\b/iu.
|
||||
*
|
||||
* For location "anywhere" the typical regex is
|
||||
* /\bESCAPED_TERM\b/iu
|
||||
*
|
||||
* If it starts or ends with non-word character, the prefix and suffix are empty, respectively.
|
||||
*/
|
||||
return new RegExp(`${prefix}${escaped}${suffix}`, flags);
|
||||
}
|
||||
|
||||
const warningRegExps = warningTerms.map(convertToRegExp);
|
||||
|
||||
/**
|
||||
* Checks the specified comment for matches of the configured warning terms and returns the matches.
|
||||
* @param {string} comment The comment which is checked.
|
||||
* @returns {Array} All matched warning terms for this comment.
|
||||
*/
|
||||
function commentContainsWarningTerm(comment) {
|
||||
const matches = [];
|
||||
|
||||
warningRegExps.forEach((regex, index) => {
|
||||
if (regex.test(comment)) {
|
||||
matches.push(warningTerms[index]);
|
||||
}
|
||||
});
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the specified node for matching warning comments and reports them.
|
||||
* @param {ASTNode} node The AST node being checked.
|
||||
* @returns {void} undefined.
|
||||
*/
|
||||
function checkComment(node) {
|
||||
const comment = node.value;
|
||||
|
||||
if (
|
||||
astUtils.isDirectiveComment(node) &&
|
||||
selfConfigRegEx.test(comment)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matches = commentContainsWarningTerm(comment);
|
||||
|
||||
matches.forEach(matchedTerm => {
|
||||
let commentToDisplay = "";
|
||||
let truncated = false;
|
||||
|
||||
for (const c of comment.trim().split(/\s+/u)) {
|
||||
const tmp = commentToDisplay
|
||||
? `${commentToDisplay} ${c}`
|
||||
: c;
|
||||
|
||||
if (tmp.length <= CHAR_LIMIT) {
|
||||
commentToDisplay = tmp;
|
||||
} else {
|
||||
truncated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
context.report({
|
||||
node,
|
||||
messageId: "unexpectedComment",
|
||||
data: {
|
||||
matchedTerm,
|
||||
comment: `${commentToDisplay}${truncated ? "..." : ""}`,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
Program() {
|
||||
const comments = sourceCode.getAllComments();
|
||||
|
||||
comments
|
||||
.filter(token => token.type !== "Shebang")
|
||||
.forEach(checkComment);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,295 @@
|
||||
declare const _default: {
|
||||
inherit: string;
|
||||
current: string;
|
||||
transparent: string;
|
||||
black: string;
|
||||
white: string;
|
||||
slate: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
gray: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
zinc: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
neutral: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
stone: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
red: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
orange: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
amber: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
yellow: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
lime: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
green: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
emerald: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
teal: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
cyan: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
sky: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
blue: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
indigo: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
violet: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
purple: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
fuchsia: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
pink: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
rose: {
|
||||
'50': string;
|
||||
'100': string;
|
||||
'200': string;
|
||||
'300': string;
|
||||
'400': string;
|
||||
'500': string;
|
||||
'600': string;
|
||||
'700': string;
|
||||
'800': string;
|
||||
'900': string;
|
||||
'950': string;
|
||||
};
|
||||
};
|
||||
|
||||
export { _default as _ };
|
||||
@@ -0,0 +1,132 @@
|
||||
# json-stable-stringify
|
||||
|
||||
This is the same as https://github.com/substack/json-stable-stringify but it doesn't depend on libraries without licenses (jsonify).
|
||||
|
||||
deterministic version of `JSON.stringify()` so you can get a consistent hash
|
||||
from stringified results
|
||||
|
||||
You can also pass in a custom comparison function.
|
||||
|
||||
[](https://ci.testling.com/substack/json-stable-stringify)
|
||||
|
||||
[](http://travis-ci.org/substack/json-stable-stringify)
|
||||
|
||||
# example
|
||||
|
||||
``` js
|
||||
var stringify = require('json-stable-stringify');
|
||||
var obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 };
|
||||
console.log(stringify(obj));
|
||||
```
|
||||
|
||||
output:
|
||||
|
||||
```
|
||||
{"a":3,"b":[{"x":4,"y":5,"z":6},7],"c":8}
|
||||
```
|
||||
|
||||
# methods
|
||||
|
||||
``` js
|
||||
var stringify = require('json-stable-stringify')
|
||||
```
|
||||
|
||||
## var str = stringify(obj, opts)
|
||||
|
||||
Return a deterministic stringified string `str` from the object `obj`.
|
||||
|
||||
## options
|
||||
|
||||
### cmp
|
||||
|
||||
If `opts` is given, you can supply an `opts.cmp` to have a custom comparison
|
||||
function for object keys. Your function `opts.cmp` is called with these
|
||||
parameters:
|
||||
|
||||
``` js
|
||||
opts.cmp({ key: akey, value: avalue }, { key: bkey, value: bvalue })
|
||||
```
|
||||
|
||||
For example, to sort on the object key names in reverse order you could write:
|
||||
|
||||
``` js
|
||||
var stringify = require('json-stable-stringify');
|
||||
|
||||
var obj = { c: 8, b: [{z:6,y:5,x:4},7], a: 3 };
|
||||
var s = stringify(obj, function (a, b) {
|
||||
return a.key < b.key ? 1 : -1;
|
||||
});
|
||||
console.log(s);
|
||||
```
|
||||
|
||||
which results in the output string:
|
||||
|
||||
```
|
||||
{"c":8,"b":[{"z":6,"y":5,"x":4},7],"a":3}
|
||||
```
|
||||
|
||||
Or if you wanted to sort on the object values in reverse order, you could write:
|
||||
|
||||
```
|
||||
var stringify = require('json-stable-stringify');
|
||||
|
||||
var obj = { d: 6, c: 5, b: [{z:3,y:2,x:1},9], a: 10 };
|
||||
var s = stringify(obj, function (a, b) {
|
||||
return a.value < b.value ? 1 : -1;
|
||||
});
|
||||
console.log(s);
|
||||
```
|
||||
|
||||
which outputs:
|
||||
|
||||
```
|
||||
{"d":6,"c":5,"b":[{"z":3,"y":2,"x":1},9],"a":10}
|
||||
```
|
||||
|
||||
### space
|
||||
|
||||
If you specify `opts.space`, it will indent the output for pretty-printing.
|
||||
Valid values are strings (e.g. `{space: \t}`) or a number of spaces
|
||||
(`{space: 3}`).
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
var obj = { b: 1, a: { foo: 'bar', and: [1, 2, 3] } };
|
||||
var s = stringify(obj, { space: ' ' });
|
||||
console.log(s);
|
||||
```
|
||||
|
||||
which outputs:
|
||||
|
||||
```
|
||||
{
|
||||
"a": {
|
||||
"and": [
|
||||
1,
|
||||
2,
|
||||
3
|
||||
],
|
||||
"foo": "bar"
|
||||
},
|
||||
"b": 1
|
||||
}
|
||||
```
|
||||
|
||||
### replacer
|
||||
|
||||
The replacer parameter is a function `opts.replacer(key, value)` that behaves
|
||||
the same as the replacer
|
||||
[from the core JSON object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_native_JSON#The_replacer_parameter).
|
||||
|
||||
# install
|
||||
|
||||
With [npm](https://npmjs.org) do:
|
||||
|
||||
```
|
||||
npm install json-stable-stringify
|
||||
```
|
||||
|
||||
# license
|
||||
|
||||
MIT
|
||||
Reference in New Issue
Block a user