tsl-dx 0.6.1 → 0.7.1
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/index.d.ts +48 -2
- package/dist/index.js +85 -26
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -39,9 +39,55 @@ declare const noDuplicateExports: (options?: "off" | undefined) => tsl.Rule<unkn
|
|
|
39
39
|
declare const noDuplicateImports: (options?: "off" | undefined) => tsl.Rule<unknown>;
|
|
40
40
|
//#endregion
|
|
41
41
|
//#region src/rules/no-multiline-template-expression-without-auto-dedent.d.ts
|
|
42
|
-
|
|
42
|
+
type noMultilineTemplateExpressionWithoutAutoDedentOptions = {
|
|
43
|
+
dedentTagNames?: string[];
|
|
44
|
+
dedentTagImportCallback?: (name: string) => string;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Rule to enforce the use of a dedent tag for multiline template expressions.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* // Incorrect
|
|
53
|
+
* const message = `
|
|
54
|
+
* Hello
|
|
55
|
+
* World
|
|
56
|
+
* `;
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* ```ts
|
|
60
|
+
* // Correct
|
|
61
|
+
* import dedent from "dedent";
|
|
62
|
+
* const message = dedent`
|
|
63
|
+
* Hello
|
|
64
|
+
* World
|
|
65
|
+
* `;
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
declare const noMultilineTemplateExpressionWithoutAutoDedent: (options?: "off" | noMultilineTemplateExpressionWithoutAutoDedentOptions | undefined) => tsl.Rule<unknown>;
|
|
43
69
|
//#endregion
|
|
44
70
|
//#region src/rules/nullish.d.ts
|
|
45
|
-
|
|
71
|
+
type nullishOptions = {
|
|
72
|
+
runtimeLibrary?: string;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Rule to enforce the use of `unit` instead of `undefined` and loose equality for nullish checks.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
*
|
|
79
|
+
* ```ts
|
|
80
|
+
* // Incorrect
|
|
81
|
+
* let x = undefined;
|
|
82
|
+
* if (x === undefined) { }
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* ```ts
|
|
86
|
+
* // Correct
|
|
87
|
+
* let x = unit;
|
|
88
|
+
* if (x == null) { }
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
declare const nullish: (options?: "off" | nullishOptions | undefined) => tsl.Rule<unknown>;
|
|
46
92
|
//#endregion
|
|
47
93
|
export { noDuplicateExports, noDuplicateImports, noMultilineTemplateExpressionWithoutAutoDedent, nullish };
|
package/dist/index.js
CHANGED
|
@@ -170,6 +170,9 @@ const dual = function(arity, body) {
|
|
|
170
170
|
* Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`.
|
|
171
171
|
* The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`.
|
|
172
172
|
*
|
|
173
|
+
* @param self - The first function to apply (or the composed function in data-last style).
|
|
174
|
+
* @param bc - The second function to apply.
|
|
175
|
+
* @returns A composed function that applies both functions in sequence.
|
|
173
176
|
* @example
|
|
174
177
|
* ```ts
|
|
175
178
|
* import * as assert from "node:assert"
|
|
@@ -277,26 +280,85 @@ function getLine(node) {
|
|
|
277
280
|
|
|
278
281
|
//#endregion
|
|
279
282
|
//#region src/rules/no-multiline-template-expression-without-auto-dedent.ts
|
|
280
|
-
const messages$1 = {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
283
|
+
const messages$1 = {
|
|
284
|
+
useDedentTag: () => "Use a dedent tag to auto-dedent this template expression's content.",
|
|
285
|
+
addDedentTag: (p) => `Add a/an '${p.name}' tag to this template expression to auto-dedent its content.`
|
|
286
|
+
};
|
|
287
|
+
/**
|
|
288
|
+
* Rule to enforce the use of a dedent tag for multiline template expressions.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
*
|
|
292
|
+
* ```ts
|
|
293
|
+
* // Incorrect
|
|
294
|
+
* const message = `
|
|
295
|
+
* Hello
|
|
296
|
+
* World
|
|
297
|
+
* `;
|
|
298
|
+
* ```
|
|
299
|
+
*
|
|
300
|
+
* ```ts
|
|
301
|
+
* // Correct
|
|
302
|
+
* import dedent from "dedent";
|
|
303
|
+
* const message = dedent`
|
|
304
|
+
* Hello
|
|
305
|
+
* World
|
|
306
|
+
* `;
|
|
307
|
+
* ```
|
|
308
|
+
*/
|
|
309
|
+
const noMultilineTemplateExpressionWithoutAutoDedent = defineRule((options) => {
|
|
310
|
+
const dedentTagNames = options?.dedentTagNames ?? ["dedent"];
|
|
311
|
+
const dedentTagImportCallback = options?.dedentTagImportCallback ?? ((name) => `import ${name} from "dedent";\n`);
|
|
312
|
+
return {
|
|
313
|
+
name: "dx/no-multiline-template-expression-without-auto-dedent",
|
|
314
|
+
visitor: { NoSubstitutionTemplateLiteral(ctx, node) {
|
|
315
|
+
if (node.parent.kind === SyntaxKind.TaggedTemplateExpression) return;
|
|
316
|
+
const [startLine, endLine] = getLine(node);
|
|
317
|
+
if (startLine !== endLine) ctx.report({
|
|
318
|
+
node,
|
|
319
|
+
message: messages$1.useDedentTag(),
|
|
320
|
+
suggestions: dedentTagNames.map((name) => {
|
|
321
|
+
return {
|
|
322
|
+
message: messages$1.addDedentTag({ name }),
|
|
323
|
+
changes: [{
|
|
324
|
+
start: 0,
|
|
325
|
+
end: 0,
|
|
326
|
+
newText: dedentTagImportCallback(name)
|
|
327
|
+
}, {
|
|
328
|
+
node,
|
|
329
|
+
newText: `${name}${node.getFullText()}`
|
|
330
|
+
}]
|
|
331
|
+
};
|
|
332
|
+
})
|
|
333
|
+
});
|
|
334
|
+
} }
|
|
335
|
+
};
|
|
336
|
+
});
|
|
292
337
|
|
|
293
338
|
//#endregion
|
|
294
339
|
//#region src/rules/nullish.ts
|
|
295
340
|
const messages = {
|
|
296
341
|
useUnitForUndefined: "Use 'unit' instead of 'undefined'.",
|
|
297
|
-
useLooseNullishComparison: (p) => `Use '${p.op}' for nullish comparison
|
|
342
|
+
useLooseNullishComparison: (p) => `Use '${p.op}' for nullish comparison.`,
|
|
343
|
+
replaceWithExpression: (p) => `Replace with '${p.expr}'.`
|
|
298
344
|
};
|
|
299
|
-
|
|
345
|
+
/**
|
|
346
|
+
* Rule to enforce the use of `unit` instead of `undefined` and loose equality for nullish checks.
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
*
|
|
350
|
+
* ```ts
|
|
351
|
+
* // Incorrect
|
|
352
|
+
* let x = undefined;
|
|
353
|
+
* if (x === undefined) { }
|
|
354
|
+
* ```
|
|
355
|
+
*
|
|
356
|
+
* ```ts
|
|
357
|
+
* // Correct
|
|
358
|
+
* let x = unit;
|
|
359
|
+
* if (x == null) { }
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
300
362
|
const nullish = defineRule((options) => ({
|
|
301
363
|
name: "dx/nullish",
|
|
302
364
|
createData(ctx) {
|
|
@@ -304,44 +366,41 @@ const nullish = defineRule((options) => ({
|
|
|
304
366
|
},
|
|
305
367
|
visitor: {
|
|
306
368
|
Identifier(ctx, node) {
|
|
307
|
-
if (node.getSourceFile().isDeclarationFile) return;
|
|
308
369
|
if (node.parent.kind === SyntaxKind.BinaryExpression || node.text !== "undefined") return;
|
|
309
370
|
ctx.report({
|
|
310
371
|
node,
|
|
311
372
|
message: messages.useUnitForUndefined,
|
|
312
373
|
suggestions: [{
|
|
313
|
-
message:
|
|
374
|
+
message: messages.replaceWithExpression({ expr: "unit" }),
|
|
314
375
|
changes: [{
|
|
315
|
-
node,
|
|
316
|
-
newText: "unit"
|
|
317
|
-
}, {
|
|
318
376
|
start: 0,
|
|
319
377
|
end: 0,
|
|
320
378
|
newText: `import { unit } from '${ctx.data.runtimeLibrary}';\n`
|
|
379
|
+
}, {
|
|
380
|
+
node,
|
|
381
|
+
newText: "unit"
|
|
321
382
|
}]
|
|
322
383
|
}]
|
|
323
384
|
});
|
|
324
385
|
},
|
|
325
386
|
UndefinedKeyword(ctx, node) {
|
|
326
|
-
if (node.getSourceFile().isDeclarationFile) return;
|
|
327
387
|
ctx.report({
|
|
328
388
|
node,
|
|
329
389
|
message: messages.useUnitForUndefined,
|
|
330
390
|
suggestions: [{
|
|
331
|
-
message:
|
|
391
|
+
message: messages.replaceWithExpression({ expr: "unit" }),
|
|
332
392
|
changes: [{
|
|
333
|
-
node,
|
|
334
|
-
newText: "unit"
|
|
335
|
-
}, {
|
|
336
393
|
start: 0,
|
|
337
394
|
end: 0,
|
|
338
395
|
newText: `import type { unit } from '${ctx.data.runtimeLibrary}';\n`
|
|
396
|
+
}, {
|
|
397
|
+
node,
|
|
398
|
+
newText: "unit"
|
|
339
399
|
}]
|
|
340
400
|
}]
|
|
341
401
|
});
|
|
342
402
|
},
|
|
343
403
|
BinaryExpression(ctx, node) {
|
|
344
|
-
if (node.getSourceFile().isDeclarationFile) return;
|
|
345
404
|
const newOperatorText = match(node.operatorToken.kind).with(SyntaxKind.EqualsEqualsEqualsToken, () => "==").with(SyntaxKind.ExclamationEqualsEqualsToken, () => "!=").otherwise(() => null);
|
|
346
405
|
if (newOperatorText == null) return;
|
|
347
406
|
const offendingChild = [node.left, node.right].find((n) => {
|
|
@@ -356,7 +415,7 @@ const nullish = defineRule((options) => ({
|
|
|
356
415
|
message: messages.useLooseNullishComparison({ op: newOperatorText }),
|
|
357
416
|
node,
|
|
358
417
|
suggestions: [{
|
|
359
|
-
message:
|
|
418
|
+
message: messages.replaceWithExpression({ expr: offendingChild === node.left ? `null ${newOperatorText} ${node.right.getText()}` : `${node.left.getText()} ${newOperatorText} null` }),
|
|
360
419
|
changes: [{
|
|
361
420
|
node: node.operatorToken,
|
|
362
421
|
newText: newOperatorText
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tsl-dx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "A tsl plugin for better JavaScript/TypeScript DX.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tsl",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"dedent": "^1.7.1",
|
|
28
28
|
"tsdown": "^0.20.3",
|
|
29
|
-
"tsl": "^1.0.
|
|
29
|
+
"tsl": "^1.0.29",
|
|
30
30
|
"vitest": "^4.0.18",
|
|
31
31
|
"@local/configs": "0.0.0",
|
|
32
32
|
"@local/eff": "0.2.9"
|