@deslop/coding-standards 0.1.1249 → 0.1.1250
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lint.js +299 -8
- package/package.json +1 -1
package/dist/lint.js
CHANGED
|
@@ -2307,6 +2307,19 @@ const succeed = (success) => new SuccessImpl(success);
|
|
|
2307
2307
|
const fromOption$1 = /*#__PURE__*/ dual(2, (self, onNone) => isNone$1(self) ? fail(onNone()) : succeed(self.value));
|
|
2308
2308
|
// ../../node_modules/.pnpm/effect@4.1.2/node_modules/effect/dist/Order.js
|
|
2309
2309
|
/**
|
|
2310
|
+
* Defines comparison functions for ordered values.
|
|
2311
|
+
*
|
|
2312
|
+
* An `Order<A>` compares two `A` values and returns whether the first is less
|
|
2313
|
+
* than, equal to, or greater than the second. Orders are used for sorting,
|
|
2314
|
+
* choosing minimum or maximum values, checking ranges, and building ordered data
|
|
2315
|
+
* structures. This module includes built-in orders, constructors for custom
|
|
2316
|
+
* orders, tools for reversing and combining comparisons, tuple and struct
|
|
2317
|
+
* helpers, comparison predicates, clamping, and reducer support.
|
|
2318
|
+
*
|
|
2319
|
+
* @stability stable
|
|
2320
|
+
* @since 2.0.0
|
|
2321
|
+
*/
|
|
2322
|
+
/**
|
|
2310
2323
|
* Creates a new `Order` instance from a comparison function.
|
|
2311
2324
|
*
|
|
2312
2325
|
* **When to use**
|
|
@@ -2374,6 +2387,76 @@ function make$4(compare) {
|
|
|
2374
2387
|
* @since 4.0.0
|
|
2375
2388
|
*/
|
|
2376
2389
|
const String$2 = /*#__PURE__*/ make$4((self, that) => self < that ? -1 : 1);
|
|
2390
|
+
/**
|
|
2391
|
+
* Order instance for numbers that compares them numerically.
|
|
2392
|
+
*
|
|
2393
|
+
* **When to use**
|
|
2394
|
+
*
|
|
2395
|
+
* Use when you need numeric ordering for numbers.
|
|
2396
|
+
*
|
|
2397
|
+
* **Details**
|
|
2398
|
+
*
|
|
2399
|
+
* `0` is considered equal to `-0`. All `NaN` values are considered equal to
|
|
2400
|
+
* each other, and any `NaN` is considered less than any non-`NaN` number. All
|
|
2401
|
+
* other values use standard numeric comparison.
|
|
2402
|
+
*
|
|
2403
|
+
* **Example** (Ordering numbers)
|
|
2404
|
+
*
|
|
2405
|
+
* ```ts import.meta.vitest
|
|
2406
|
+
* import { Order } from "effect"
|
|
2407
|
+
*
|
|
2408
|
+
* Order.Number(1, 1) // => 0
|
|
2409
|
+
* Order.Number(1, 2) // => -1
|
|
2410
|
+
* Order.Number(2, 1) // => 1
|
|
2411
|
+
*
|
|
2412
|
+
* Order.Number(0, -0) // => 0
|
|
2413
|
+
* Order.Number(NaN, 1) // => -1
|
|
2414
|
+
* ```
|
|
2415
|
+
*
|
|
2416
|
+
* @see {@link mapInput} to compare objects by a number property
|
|
2417
|
+
* @see {@link BigInt} for bigint comparisons
|
|
2418
|
+
* @stability stable
|
|
2419
|
+
* @category instances
|
|
2420
|
+
* @since 4.0.0
|
|
2421
|
+
*/
|
|
2422
|
+
const Number$2 = /*#__PURE__*/ make$4((self, that) => {
|
|
2423
|
+
if (globalThis.Number.isNaN(self) && globalThis.Number.isNaN(that)) return 0;
|
|
2424
|
+
if (globalThis.Number.isNaN(self)) return -1;
|
|
2425
|
+
if (globalThis.Number.isNaN(that)) return 1;
|
|
2426
|
+
return self < that ? -1 : 1;
|
|
2427
|
+
});
|
|
2428
|
+
/**
|
|
2429
|
+
* Returns the maximum of two values according to the given order. If they are equal, returns the first argument.
|
|
2430
|
+
*
|
|
2431
|
+
* **When to use**
|
|
2432
|
+
*
|
|
2433
|
+
* Use when you need to select the larger of two values according to an
|
|
2434
|
+
* `Order`.
|
|
2435
|
+
*
|
|
2436
|
+
* **Details**
|
|
2437
|
+
*
|
|
2438
|
+
* Returns the value that compares as greater than or equal to the other value.
|
|
2439
|
+
* If values are equal, the first argument is returned.
|
|
2440
|
+
*
|
|
2441
|
+
* **Example** (Selecting the maximum value)
|
|
2442
|
+
*
|
|
2443
|
+
* ```ts import.meta.vitest
|
|
2444
|
+
* import { Order } from "effect"
|
|
2445
|
+
*
|
|
2446
|
+
* const maxNumber = Order.max(Order.Number)
|
|
2447
|
+
*
|
|
2448
|
+
* maxNumber(1, 2) // => 2
|
|
2449
|
+
* maxNumber(2, 1) // => 2
|
|
2450
|
+
* maxNumber(1, 1) // => 1
|
|
2451
|
+
* ```
|
|
2452
|
+
*
|
|
2453
|
+
* @see {@link min} for the minimum of two values
|
|
2454
|
+
* @see {@link clamp} to clamp a value between min and max
|
|
2455
|
+
* @stability stable
|
|
2456
|
+
* @category comparisons
|
|
2457
|
+
* @since 2.0.0
|
|
2458
|
+
*/
|
|
2459
|
+
const max$1 = (O) => dual(2, (self, that) => self === that || O(self, that) > -1 ? self : that);
|
|
2377
2460
|
// ../../node_modules/.pnpm/effect@4.1.2/node_modules/effect/dist/Option.js
|
|
2378
2461
|
/**
|
|
2379
2462
|
* Creates an `Option` representing the absence of a value.
|
|
@@ -4565,6 +4648,33 @@ const filter = /*#__PURE__*/ dual(2, (self, predicate) => {
|
|
|
4565
4648
|
return out;
|
|
4566
4649
|
});
|
|
4567
4650
|
/**
|
|
4651
|
+
* Folds an iterable from left to right into a single value.
|
|
4652
|
+
*
|
|
4653
|
+
* **When to use**
|
|
4654
|
+
*
|
|
4655
|
+
* Use to combine all elements into one accumulated value from left to right.
|
|
4656
|
+
*
|
|
4657
|
+
* **Details**
|
|
4658
|
+
*
|
|
4659
|
+
* The function receives `(accumulator, element, index)`.
|
|
4660
|
+
*
|
|
4661
|
+
* **Example** (Summing an array)
|
|
4662
|
+
*
|
|
4663
|
+
* ```ts import.meta.vitest
|
|
4664
|
+
* import { Array } from "effect"
|
|
4665
|
+
*
|
|
4666
|
+
* Array.reduce([1, 2, 3], 0, (acc, n) => acc + n) // => 6
|
|
4667
|
+
* ```
|
|
4668
|
+
*
|
|
4669
|
+
* @see {@link reduceRight} — fold from right to left
|
|
4670
|
+
* @see {@link scan} — fold keeping intermediate values
|
|
4671
|
+
*
|
|
4672
|
+
* @stability stable
|
|
4673
|
+
* @category folding
|
|
4674
|
+
* @since 2.0.0
|
|
4675
|
+
*/
|
|
4676
|
+
const reduce = /*#__PURE__*/ dual(3, (self, b, f) => fromIterable(self).reduce((b, a, i) => f(b, a, i), b));
|
|
4677
|
+
/**
|
|
4568
4678
|
* Checks whether all elements satisfy the predicate. Supports refinements for
|
|
4569
4679
|
* type narrowing.
|
|
4570
4680
|
*
|
|
@@ -4832,6 +4942,28 @@ const TaggedError = TaggedError$1;
|
|
|
4832
4942
|
*/
|
|
4833
4943
|
const Number$1 = globalThis.Number;
|
|
4834
4944
|
/**
|
|
4945
|
+
* Returns the maximum between two `number`s.
|
|
4946
|
+
*
|
|
4947
|
+
* **When to use**
|
|
4948
|
+
*
|
|
4949
|
+
* Use to select the larger of two numbers.
|
|
4950
|
+
*
|
|
4951
|
+
* **Example** (Finding the maximum)
|
|
4952
|
+
*
|
|
4953
|
+
* ```ts import.meta.vitest
|
|
4954
|
+
* import { Number } from "effect"
|
|
4955
|
+
*
|
|
4956
|
+
* Number.max(2, 3) // => 3
|
|
4957
|
+
* ```
|
|
4958
|
+
*
|
|
4959
|
+
* @see {@link min} for selecting the smaller value
|
|
4960
|
+
*
|
|
4961
|
+
* @stability stable
|
|
4962
|
+
* @category math
|
|
4963
|
+
* @since 2.0.0
|
|
4964
|
+
*/
|
|
4965
|
+
const max = /*#__PURE__*/ max$1(Number$2);
|
|
4966
|
+
/**
|
|
4835
4967
|
* Parses a `number` from a `string` safely using the `Number()` function.
|
|
4836
4968
|
* The following special string values are supported: "NaN", "Infinity", "-Infinity".
|
|
4837
4969
|
*
|
|
@@ -4904,6 +5036,28 @@ const Order = String$2;
|
|
|
4904
5036
|
*/
|
|
4905
5037
|
const toUpperCase = (self) => self.toUpperCase();
|
|
4906
5038
|
/**
|
|
5039
|
+
* Replaces matches in a string using `String.prototype.replace`.
|
|
5040
|
+
*
|
|
5041
|
+
* **Details**
|
|
5042
|
+
*
|
|
5043
|
+
* String search values and non-global regular expressions replace the first
|
|
5044
|
+
* match; global regular expressions replace every match.
|
|
5045
|
+
*
|
|
5046
|
+
* **Example** (Replacing a substring)
|
|
5047
|
+
*
|
|
5048
|
+
* ```ts import.meta.vitest
|
|
5049
|
+
* import { pipe, String } from "effect"
|
|
5050
|
+
*
|
|
5051
|
+
* pipe("abc", String.replace("b", "d")) // => "adc"
|
|
5052
|
+
* pipe("hello world", String.replace("world", "Effect")) // => "hello Effect"
|
|
5053
|
+
* ```
|
|
5054
|
+
*
|
|
5055
|
+
* @stability stable
|
|
5056
|
+
* @category transforming
|
|
5057
|
+
* @since 2.0.0
|
|
5058
|
+
*/
|
|
5059
|
+
const replace = (searchValue, replaceValue) => (self) => self.replace(searchValue, replaceValue);
|
|
5060
|
+
/**
|
|
4907
5061
|
* Removes whitespace from both ends of a string.
|
|
4908
5062
|
*
|
|
4909
5063
|
* **Example** (Trimming whitespace)
|
|
@@ -7863,14 +8017,14 @@ const PRIMITIVES = {
|
|
|
7863
8017
|
textarea: "Textarea"
|
|
7864
8018
|
};
|
|
7865
8019
|
const CONTROL_STYLE = /(?:^|:)(?:hover|focus|focus-visible|active):|(?:^|:)(?:rounded|shadow|ring)(?:-|$)|(?:^|:)p[blrtxy]?-(?!0$)|(?:^|:)bg-(?!transparent$)|(?:^|:)border(?:-[blrtxy])?$|(?:^|:)border-(?!0$|[blrtxy]-0$)/u;
|
|
7866
|
-
function classStrings(node) {
|
|
8020
|
+
function classStrings$1(node) {
|
|
7867
8021
|
if (node.type === "Literal") return filter([node.value], isString);
|
|
7868
8022
|
if (node.type === "TemplateLiteral") return map(node.quasis, (quasi) => quasi.value.raw);
|
|
7869
|
-
if (node.type === "JSXExpressionContainer") return classStrings(node.expression);
|
|
7870
|
-
if (node.type === "CallExpression") return flatMap(node.arguments, classStrings);
|
|
7871
|
-
if (node.type === "ConditionalExpression") return flatMap([node.consequent, node.alternate], classStrings);
|
|
7872
|
-
if (node.type === "LogicalExpression") return classStrings(node.right);
|
|
7873
|
-
if (node.type === "ArrayExpression") return flatMap(filter(node.elements, isNotNull), classStrings);
|
|
8023
|
+
if (node.type === "JSXExpressionContainer") return classStrings$1(node.expression);
|
|
8024
|
+
if (node.type === "CallExpression") return flatMap(node.arguments, classStrings$1);
|
|
8025
|
+
if (node.type === "ConditionalExpression") return flatMap([node.consequent, node.alternate], classStrings$1);
|
|
8026
|
+
if (node.type === "LogicalExpression") return classStrings$1(node.right);
|
|
8027
|
+
if (node.type === "ArrayExpression") return flatMap(filter(node.elements, isNotNull), classStrings$1);
|
|
7874
8028
|
return empty$2();
|
|
7875
8029
|
}
|
|
7876
8030
|
const noNativeControl = defineRule({
|
|
@@ -7880,7 +8034,7 @@ const noNativeControl = defineRule({
|
|
|
7880
8034
|
map$1(get$3(PRIMITIVES, name), (primitive) => {
|
|
7881
8035
|
const styled = pipe(node.attributes, findFirst((attribute) => attribute.type === "JSXAttribute" && attribute.name.type === "JSXIdentifier" && attribute.name.name === "className"), map$1((attribute) => {
|
|
7882
8036
|
if (attribute.type !== "JSXAttribute" || attribute.value === null) return empty$2();
|
|
7883
|
-
return classStrings(attribute.value);
|
|
8037
|
+
return classStrings$1(attribute.value);
|
|
7884
8038
|
}), exists((values) => some(values, (value) => some(split(value, /\s+/u), matches(CONTROL_STYLE)))));
|
|
7885
8039
|
if (name !== "select" && !styled) return;
|
|
7886
8040
|
context.report({
|
|
@@ -8304,6 +8458,139 @@ const noPollingTest = defineRule({
|
|
|
8304
8458
|
},
|
|
8305
8459
|
meta: { type: "problem" }
|
|
8306
8460
|
});
|
|
8461
|
+
// src/rules/no-primitive-restyle.ts
|
|
8462
|
+
const UI_MODULES = ["@deslop/components-web/ui/", "#components/ui/"];
|
|
8463
|
+
const PLACEMENT_PREFIXES = [
|
|
8464
|
+
"m-",
|
|
8465
|
+
"mx-",
|
|
8466
|
+
"my-",
|
|
8467
|
+
"mt-",
|
|
8468
|
+
"mr-",
|
|
8469
|
+
"mb-",
|
|
8470
|
+
"ml-",
|
|
8471
|
+
"ms-",
|
|
8472
|
+
"me-",
|
|
8473
|
+
"w-",
|
|
8474
|
+
"h-",
|
|
8475
|
+
"size-",
|
|
8476
|
+
"min-w-",
|
|
8477
|
+
"min-h-",
|
|
8478
|
+
"max-w-",
|
|
8479
|
+
"max-h-",
|
|
8480
|
+
"basis-",
|
|
8481
|
+
"order-",
|
|
8482
|
+
"col-span-",
|
|
8483
|
+
"col-start-",
|
|
8484
|
+
"col-end-",
|
|
8485
|
+
"row-span-",
|
|
8486
|
+
"row-start-",
|
|
8487
|
+
"row-end-",
|
|
8488
|
+
"self-",
|
|
8489
|
+
"justify-self-",
|
|
8490
|
+
"place-self-",
|
|
8491
|
+
"inset-",
|
|
8492
|
+
"inset-x-",
|
|
8493
|
+
"inset-y-",
|
|
8494
|
+
"top-",
|
|
8495
|
+
"right-",
|
|
8496
|
+
"bottom-",
|
|
8497
|
+
"left-",
|
|
8498
|
+
"start-",
|
|
8499
|
+
"end-",
|
|
8500
|
+
"z-",
|
|
8501
|
+
"translate-",
|
|
8502
|
+
"pointer-events-"
|
|
8503
|
+
];
|
|
8504
|
+
const PLACEMENT_EXACT = [
|
|
8505
|
+
"flex-1",
|
|
8506
|
+
"flex-auto",
|
|
8507
|
+
"flex-none",
|
|
8508
|
+
"grow",
|
|
8509
|
+
"grow-0",
|
|
8510
|
+
"shrink",
|
|
8511
|
+
"shrink-0",
|
|
8512
|
+
"relative",
|
|
8513
|
+
"absolute",
|
|
8514
|
+
"fixed",
|
|
8515
|
+
"sticky",
|
|
8516
|
+
"hidden",
|
|
8517
|
+
"block",
|
|
8518
|
+
"flex",
|
|
8519
|
+
"inline-flex",
|
|
8520
|
+
"grid",
|
|
8521
|
+
"sr-only"
|
|
8522
|
+
];
|
|
8523
|
+
const RESTYLE = "A shadcn component keeps its shipped look: className only places it (margin, size, position, flex or grid placement). Pick a variant or change the composition instead of restyling.";
|
|
8524
|
+
function uiImport(program) {
|
|
8525
|
+
return flatMap(program.body, (statement) => {
|
|
8526
|
+
if (statement.type !== "ImportDeclaration") return empty$2();
|
|
8527
|
+
if (!some(UI_MODULES, (prefix) => startsWith(prefix)(statement.source.value))) return empty$2();
|
|
8528
|
+
return map(statement.specifiers, (specifier) => specifier.local.name);
|
|
8529
|
+
});
|
|
8530
|
+
}
|
|
8531
|
+
function classStrings(node) {
|
|
8532
|
+
if (node.type === "Literal") return filter([node.value], isString);
|
|
8533
|
+
if (node.type === "TemplateLiteral") return map(node.quasis, (quasi) => quasi.value.raw);
|
|
8534
|
+
if (node.type === "JSXExpressionContainer") return classStrings(node.expression);
|
|
8535
|
+
if (node.type === "CallExpression" && node.callee.type === "Identifier" && node.callee.name === "cn") return flatMap(node.arguments, (argument) => classStrings(argument));
|
|
8536
|
+
return empty$2();
|
|
8537
|
+
}
|
|
8538
|
+
function utility(token) {
|
|
8539
|
+
const scanned = reduce(split("")(token), {
|
|
8540
|
+
depth: 0,
|
|
8541
|
+
end: 0,
|
|
8542
|
+
index: 0
|
|
8543
|
+
}, (state, character) => {
|
|
8544
|
+
const index = state.index + 1;
|
|
8545
|
+
if (character === "[") return {
|
|
8546
|
+
depth: state.depth + 1,
|
|
8547
|
+
end: state.end,
|
|
8548
|
+
index
|
|
8549
|
+
};
|
|
8550
|
+
if (character === "]") return {
|
|
8551
|
+
depth: max(0, state.depth - 1),
|
|
8552
|
+
end: state.end,
|
|
8553
|
+
index
|
|
8554
|
+
};
|
|
8555
|
+
if (character === ":" && state.depth === 0) return {
|
|
8556
|
+
depth: state.depth,
|
|
8557
|
+
end: index,
|
|
8558
|
+
index
|
|
8559
|
+
};
|
|
8560
|
+
return {
|
|
8561
|
+
depth: state.depth,
|
|
8562
|
+
end: state.end,
|
|
8563
|
+
index
|
|
8564
|
+
};
|
|
8565
|
+
});
|
|
8566
|
+
return pipe(token, slice(scanned.end), replaceAll(/^!|!$/gu, ""), replace(/^-/u, ""));
|
|
8567
|
+
}
|
|
8568
|
+
function places(token) {
|
|
8569
|
+
const name = utility(token);
|
|
8570
|
+
return contains(PLACEMENT_EXACT, name) || some(PLACEMENT_PREFIXES, (prefix) => startsWith(prefix)(name));
|
|
8571
|
+
}
|
|
8572
|
+
function restyled(attribute) {
|
|
8573
|
+
if (attribute.value === null) return false;
|
|
8574
|
+
return pipe(classStrings(attribute.value), flatMap((value) => split(value, /\s+/u)), filter(isNonEmpty), some((token) => !places(token)));
|
|
8575
|
+
}
|
|
8576
|
+
const noPrimitiveRestyle = defineRule({
|
|
8577
|
+
create: (context) => {
|
|
8578
|
+
const file = { primitives: empty$2() };
|
|
8579
|
+
return {
|
|
8580
|
+
JSXOpeningElement: (node) => {
|
|
8581
|
+
if (node.name.type !== "JSXIdentifier" || !contains(file.primitives, node.name.name)) return;
|
|
8582
|
+
pipe(findFirst(node.attributes, (attribute) => attribute.type === "JSXAttribute" && attribute.name.type === "JSXIdentifier" && attribute.name.name === "className"), filter$1((attribute) => attribute.type === "JSXAttribute" && restyled(attribute)), map$1((attribute) => context.report({
|
|
8583
|
+
message: RESTYLE,
|
|
8584
|
+
node: attribute
|
|
8585
|
+
})));
|
|
8586
|
+
},
|
|
8587
|
+
Program: (node) => {
|
|
8588
|
+
file.primitives = uiImport(node);
|
|
8589
|
+
}
|
|
8590
|
+
};
|
|
8591
|
+
},
|
|
8592
|
+
meta: { type: "problem" }
|
|
8593
|
+
});
|
|
8307
8594
|
// src/rules/no-property-alias.ts
|
|
8308
8595
|
const FUNCTIONS = [
|
|
8309
8596
|
"ArrowFunctionExpression",
|
|
@@ -10409,6 +10696,7 @@ const RULES = {
|
|
|
10409
10696
|
"no-option-value-access": noOptionValueAccess,
|
|
10410
10697
|
"no-pipe-method": noPipeMethod,
|
|
10411
10698
|
"no-polling-test": noPollingTest,
|
|
10699
|
+
"no-primitive-restyle": noPrimitiveRestyle,
|
|
10412
10700
|
"no-property-alias": noPropertyAlias,
|
|
10413
10701
|
"no-redundant-state-type": noRedundantStateType,
|
|
10414
10702
|
"no-redundant-use-ref-null-type": noRedundantUseRefNullType,
|
|
@@ -11315,7 +11603,10 @@ const lint = {
|
|
|
11315
11603
|
"typescript/no-confusing-void-expression": ["error", { ignoreVoidReturningFunctions: true }],
|
|
11316
11604
|
"typescript/no-deprecated": "error",
|
|
11317
11605
|
"typescript/no-duplicate-type-constituents": "error",
|
|
11318
|
-
"typescript/no-floating-promises": "error",
|
|
11606
|
+
"typescript/no-floating-promises": ["error", { allowForKnownSafeCalls: [{
|
|
11607
|
+
from: "file",
|
|
11608
|
+
name: "navigate"
|
|
11609
|
+
}] }],
|
|
11319
11610
|
"typescript/no-for-in-array": "error",
|
|
11320
11611
|
"typescript/no-generated-empty-object-type": "error",
|
|
11321
11612
|
"typescript/no-misused-promises": ["error", { checksVoidReturn: { attributes: false } }],
|