@taiga-ui/eslint-plugin-experience-next 0.255.0 → 0.256.0
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/eslint.config.cjs.js +115 -1
- package/eslint.config.esm.js +115 -1
- package/package.json +3 -3
- package/plugin/index.d.ts +15 -0
- package/plugin/no-deep-imports.d.ts +3 -0
package/eslint.config.cjs.js
CHANGED
|
@@ -14,6 +14,7 @@ var unicorn = require('eslint-plugin-unicorn');
|
|
|
14
14
|
var unusedImports = require('eslint-plugin-unused-imports');
|
|
15
15
|
var globals = require('globals');
|
|
16
16
|
var tseslint = require('typescript-eslint');
|
|
17
|
+
var path = require('node:path');
|
|
17
18
|
|
|
18
19
|
function getDefaultExportFromCjs (x) {
|
|
19
20
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
@@ -348,6 +349,118 @@ var src = {
|
|
|
348
349
|
|
|
349
350
|
var eslint = /*@__PURE__*/getDefaultExportFromCjs(src);
|
|
350
351
|
|
|
352
|
+
const MESSAGE_ID = 'no-deep-imports';
|
|
353
|
+
const ERROR_MESSAGE = 'Deep imports of Taiga UI packages are prohibited';
|
|
354
|
+
const DEFAULT_OPTIONS = {
|
|
355
|
+
currentProject: '',
|
|
356
|
+
deepImport: String.raw`(?<=^@taiga-ui/[\w-]+)(/.+)$`,
|
|
357
|
+
ignoreImports: [],
|
|
358
|
+
importDeclaration: '^@taiga-ui*',
|
|
359
|
+
projectName: String.raw`(?<=^@taiga-ui/)([-\w]+)`
|
|
360
|
+
};
|
|
361
|
+
const config = {
|
|
362
|
+
create(context) {
|
|
363
|
+
const {
|
|
364
|
+
currentProject,
|
|
365
|
+
deepImport,
|
|
366
|
+
ignoreImports,
|
|
367
|
+
importDeclaration,
|
|
368
|
+
projectName
|
|
369
|
+
} = {
|
|
370
|
+
...DEFAULT_OPTIONS,
|
|
371
|
+
...(context.options[0] || {})
|
|
372
|
+
};
|
|
373
|
+
const isDeepImport = source => !!source.match(new RegExp(deepImport, 'g'))?.length;
|
|
374
|
+
const isInsideTheSameEntryPoint = source => {
|
|
375
|
+
const filePath = path.relative(context.getCwd(), context.getFilename()).replaceAll(/\\+/g, '/');
|
|
376
|
+
const [currentFileProjectName] = currentProject && new RegExp(currentProject, 'g').exec(filePath) || [];
|
|
377
|
+
const [importSourceProjectName] = source.match(new RegExp(projectName, 'g')) || [];
|
|
378
|
+
return Boolean(currentFileProjectName && importSourceProjectName && currentFileProjectName === importSourceProjectName);
|
|
379
|
+
};
|
|
380
|
+
const shouldIgnore = source => ignoreImports.some(p => source.match(new RegExp(p, 'g')));
|
|
381
|
+
return {
|
|
382
|
+
[`ImportDeclaration[source.value=/${importDeclaration}/]`]({
|
|
383
|
+
source: sourceNode
|
|
384
|
+
}) {
|
|
385
|
+
const importSource = sourceNode?.value || '';
|
|
386
|
+
if (!isDeepImport(importSource) || isInsideTheSameEntryPoint(importSource) || shouldIgnore(importSource)) {
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
context.report({
|
|
390
|
+
fix: fixer => {
|
|
391
|
+
const [start, end] = sourceNode.range;
|
|
392
|
+
return fixer.replaceTextRange([start + 1, end - 1],
|
|
393
|
+
// keeps quotes
|
|
394
|
+
importSource.replaceAll(new RegExp(deepImport, 'g'), ''));
|
|
395
|
+
},
|
|
396
|
+
messageId: MESSAGE_ID,
|
|
397
|
+
node: sourceNode
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
},
|
|
402
|
+
meta: {
|
|
403
|
+
docs: {
|
|
404
|
+
description: ERROR_MESSAGE
|
|
405
|
+
},
|
|
406
|
+
fixable: 'code',
|
|
407
|
+
messages: {
|
|
408
|
+
[MESSAGE_ID]: ERROR_MESSAGE
|
|
409
|
+
},
|
|
410
|
+
schema: [{
|
|
411
|
+
additionalProperties: false,
|
|
412
|
+
properties: {
|
|
413
|
+
currentProject: {
|
|
414
|
+
description: 'RegExp string to pick out current project name of processed file',
|
|
415
|
+
type: 'string'
|
|
416
|
+
},
|
|
417
|
+
deepImport: {
|
|
418
|
+
description: 'RegExp string to pick out deep import part',
|
|
419
|
+
type: 'string'
|
|
420
|
+
},
|
|
421
|
+
ignoreImports: {
|
|
422
|
+
description: 'RegExp string to exclude import declarations which is selected by importDeclaration-option',
|
|
423
|
+
items: {
|
|
424
|
+
type: 'string'
|
|
425
|
+
},
|
|
426
|
+
type: 'array'
|
|
427
|
+
},
|
|
428
|
+
importDeclaration: {
|
|
429
|
+
description: 'RegExp string to detect import declarations for which this rule should be applied',
|
|
430
|
+
type: 'string'
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
type: 'object'
|
|
434
|
+
}],
|
|
435
|
+
type: 'problem'
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
const plugin = {
|
|
440
|
+
configs: {},
|
|
441
|
+
meta: {
|
|
442
|
+
name: '@taiga-ui/experience'
|
|
443
|
+
},
|
|
444
|
+
rules: {
|
|
445
|
+
'no-deep-imports': config
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
// https://eslint.org/docs/latest/extend/plugins
|
|
449
|
+
// assign configs here so we can reference `plugin`
|
|
450
|
+
Object.assign(plugin.configs, {
|
|
451
|
+
recommended: [{
|
|
452
|
+
plugins: {
|
|
453
|
+
'@taiga-ui/experience': plugin
|
|
454
|
+
},
|
|
455
|
+
rules: {
|
|
456
|
+
'@taiga-ui/experience/no-deep-imports': ['error', {
|
|
457
|
+
currentProject: String.raw`(?<=projects/)([-\w]+)`,
|
|
458
|
+
ignoreImports: [String.raw`\?raw`, '@taiga-ui/testing/cypress', '@taiga-ui/testing/setup-jest']
|
|
459
|
+
}]
|
|
460
|
+
}
|
|
461
|
+
}]
|
|
462
|
+
});
|
|
463
|
+
|
|
351
464
|
let angularVersion = 16;
|
|
352
465
|
const tsconfig = projectJsonExist('tsconfig.eslint.json') || projectJsonExist('tsconfig.json');
|
|
353
466
|
const parserOptions = tsconfig ? {
|
|
@@ -366,11 +479,12 @@ try {
|
|
|
366
479
|
} catch {}
|
|
367
480
|
var eslint_config = tseslint.config(progress.configs['recommended-ci'], require('eslint-plugin-de-morgan').configs.recommended, require('eslint-plugin-import').flatConfigs.recommended, require('eslint-plugin-import').flatConfigs.typescript, require('eslint-plugin-promise').configs['flat/recommended'], {
|
|
368
481
|
ignores: ['*/icons/all.ts', '**/tests-report/**', '**/snapshots/**', '**/test-results/**', '**/.nx/**', '404.html', '*.jpg', '*.svg', '*.less', '*.scss', '*.txt', '*.png', '*.jpg', '*.webmanifest', '*.pdf', '*.mp3', '*.ogv', '*.mp4', '*.ico', '*.xml', '*.md', 'LICENSE', 'jest.preset.js', '*.config.js', 'node_modules', 'dist', '**/node_modules/**', '**/*@dasherize__/**', '**/coverage/**', 'eslintrc.js', '.eslintrc.js', '**/*.d.ts', '**/dist/**', '**/docs/**', '**/bin/**', '.cache/**', '.git/**', '.idea/**']
|
|
369
|
-
}, eslint.configs.recommended, tseslint.configs.recommended, require('eslint-config-prettier'), {
|
|
482
|
+
}, eslint.configs.recommended, plugin.configs.recommended, tseslint.configs.recommended, require('eslint-config-prettier'), {
|
|
370
483
|
files: ['**/*.ts', '**/*.js'],
|
|
371
484
|
plugins: {
|
|
372
485
|
'@stylistic': stylistic,
|
|
373
486
|
'@stylistic/ts': stylisticTs,
|
|
487
|
+
'@taiga-ui/experience': plugin,
|
|
374
488
|
'decorator-position': require('eslint-plugin-decorator-position'),
|
|
375
489
|
perfectionist: require('eslint-plugin-perfectionist'),
|
|
376
490
|
prettier,
|
package/eslint.config.esm.js
CHANGED
|
@@ -12,6 +12,7 @@ import unicorn from 'eslint-plugin-unicorn';
|
|
|
12
12
|
import unusedImports from 'eslint-plugin-unused-imports';
|
|
13
13
|
import globals from 'globals';
|
|
14
14
|
import tseslint from 'typescript-eslint';
|
|
15
|
+
import path from 'node:path';
|
|
15
16
|
|
|
16
17
|
function getDefaultExportFromCjs (x) {
|
|
17
18
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
@@ -346,6 +347,118 @@ var src = {
|
|
|
346
347
|
|
|
347
348
|
var eslint = /*@__PURE__*/getDefaultExportFromCjs(src);
|
|
348
349
|
|
|
350
|
+
const MESSAGE_ID = 'no-deep-imports';
|
|
351
|
+
const ERROR_MESSAGE = 'Deep imports of Taiga UI packages are prohibited';
|
|
352
|
+
const DEFAULT_OPTIONS = {
|
|
353
|
+
currentProject: '',
|
|
354
|
+
deepImport: String.raw`(?<=^@taiga-ui/[\w-]+)(/.+)$`,
|
|
355
|
+
ignoreImports: [],
|
|
356
|
+
importDeclaration: '^@taiga-ui*',
|
|
357
|
+
projectName: String.raw`(?<=^@taiga-ui/)([-\w]+)`
|
|
358
|
+
};
|
|
359
|
+
const config = {
|
|
360
|
+
create(context) {
|
|
361
|
+
const {
|
|
362
|
+
currentProject,
|
|
363
|
+
deepImport,
|
|
364
|
+
ignoreImports,
|
|
365
|
+
importDeclaration,
|
|
366
|
+
projectName
|
|
367
|
+
} = {
|
|
368
|
+
...DEFAULT_OPTIONS,
|
|
369
|
+
...(context.options[0] || {})
|
|
370
|
+
};
|
|
371
|
+
const isDeepImport = source => !!source.match(new RegExp(deepImport, 'g'))?.length;
|
|
372
|
+
const isInsideTheSameEntryPoint = source => {
|
|
373
|
+
const filePath = path.relative(context.getCwd(), context.getFilename()).replaceAll(/\\+/g, '/');
|
|
374
|
+
const [currentFileProjectName] = currentProject && new RegExp(currentProject, 'g').exec(filePath) || [];
|
|
375
|
+
const [importSourceProjectName] = source.match(new RegExp(projectName, 'g')) || [];
|
|
376
|
+
return Boolean(currentFileProjectName && importSourceProjectName && currentFileProjectName === importSourceProjectName);
|
|
377
|
+
};
|
|
378
|
+
const shouldIgnore = source => ignoreImports.some(p => source.match(new RegExp(p, 'g')));
|
|
379
|
+
return {
|
|
380
|
+
[`ImportDeclaration[source.value=/${importDeclaration}/]`]({
|
|
381
|
+
source: sourceNode
|
|
382
|
+
}) {
|
|
383
|
+
const importSource = sourceNode?.value || '';
|
|
384
|
+
if (!isDeepImport(importSource) || isInsideTheSameEntryPoint(importSource) || shouldIgnore(importSource)) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
context.report({
|
|
388
|
+
fix: fixer => {
|
|
389
|
+
const [start, end] = sourceNode.range;
|
|
390
|
+
return fixer.replaceTextRange([start + 1, end - 1],
|
|
391
|
+
// keeps quotes
|
|
392
|
+
importSource.replaceAll(new RegExp(deepImport, 'g'), ''));
|
|
393
|
+
},
|
|
394
|
+
messageId: MESSAGE_ID,
|
|
395
|
+
node: sourceNode
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
},
|
|
400
|
+
meta: {
|
|
401
|
+
docs: {
|
|
402
|
+
description: ERROR_MESSAGE
|
|
403
|
+
},
|
|
404
|
+
fixable: 'code',
|
|
405
|
+
messages: {
|
|
406
|
+
[MESSAGE_ID]: ERROR_MESSAGE
|
|
407
|
+
},
|
|
408
|
+
schema: [{
|
|
409
|
+
additionalProperties: false,
|
|
410
|
+
properties: {
|
|
411
|
+
currentProject: {
|
|
412
|
+
description: 'RegExp string to pick out current project name of processed file',
|
|
413
|
+
type: 'string'
|
|
414
|
+
},
|
|
415
|
+
deepImport: {
|
|
416
|
+
description: 'RegExp string to pick out deep import part',
|
|
417
|
+
type: 'string'
|
|
418
|
+
},
|
|
419
|
+
ignoreImports: {
|
|
420
|
+
description: 'RegExp string to exclude import declarations which is selected by importDeclaration-option',
|
|
421
|
+
items: {
|
|
422
|
+
type: 'string'
|
|
423
|
+
},
|
|
424
|
+
type: 'array'
|
|
425
|
+
},
|
|
426
|
+
importDeclaration: {
|
|
427
|
+
description: 'RegExp string to detect import declarations for which this rule should be applied',
|
|
428
|
+
type: 'string'
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
type: 'object'
|
|
432
|
+
}],
|
|
433
|
+
type: 'problem'
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
const plugin = {
|
|
438
|
+
configs: {},
|
|
439
|
+
meta: {
|
|
440
|
+
name: '@taiga-ui/experience'
|
|
441
|
+
},
|
|
442
|
+
rules: {
|
|
443
|
+
'no-deep-imports': config
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
// https://eslint.org/docs/latest/extend/plugins
|
|
447
|
+
// assign configs here so we can reference `plugin`
|
|
448
|
+
Object.assign(plugin.configs, {
|
|
449
|
+
recommended: [{
|
|
450
|
+
plugins: {
|
|
451
|
+
'@taiga-ui/experience': plugin
|
|
452
|
+
},
|
|
453
|
+
rules: {
|
|
454
|
+
'@taiga-ui/experience/no-deep-imports': ['error', {
|
|
455
|
+
currentProject: String.raw`(?<=projects/)([-\w]+)`,
|
|
456
|
+
ignoreImports: [String.raw`\?raw`, '@taiga-ui/testing/cypress', '@taiga-ui/testing/setup-jest']
|
|
457
|
+
}]
|
|
458
|
+
}
|
|
459
|
+
}]
|
|
460
|
+
});
|
|
461
|
+
|
|
349
462
|
let angularVersion = 16;
|
|
350
463
|
const tsconfig = projectJsonExist('tsconfig.eslint.json') || projectJsonExist('tsconfig.json');
|
|
351
464
|
const parserOptions = tsconfig ? {
|
|
@@ -364,11 +477,12 @@ try {
|
|
|
364
477
|
} catch {}
|
|
365
478
|
var eslint_config = tseslint.config(progress.configs['recommended-ci'], require('eslint-plugin-de-morgan').configs.recommended, require('eslint-plugin-import').flatConfigs.recommended, require('eslint-plugin-import').flatConfigs.typescript, require('eslint-plugin-promise').configs['flat/recommended'], {
|
|
366
479
|
ignores: ['*/icons/all.ts', '**/tests-report/**', '**/snapshots/**', '**/test-results/**', '**/.nx/**', '404.html', '*.jpg', '*.svg', '*.less', '*.scss', '*.txt', '*.png', '*.jpg', '*.webmanifest', '*.pdf', '*.mp3', '*.ogv', '*.mp4', '*.ico', '*.xml', '*.md', 'LICENSE', 'jest.preset.js', '*.config.js', 'node_modules', 'dist', '**/node_modules/**', '**/*@dasherize__/**', '**/coverage/**', 'eslintrc.js', '.eslintrc.js', '**/*.d.ts', '**/dist/**', '**/docs/**', '**/bin/**', '.cache/**', '.git/**', '.idea/**']
|
|
367
|
-
}, eslint.configs.recommended, tseslint.configs.recommended, require('eslint-config-prettier'), {
|
|
480
|
+
}, eslint.configs.recommended, plugin.configs.recommended, tseslint.configs.recommended, require('eslint-config-prettier'), {
|
|
368
481
|
files: ['**/*.ts', '**/*.js'],
|
|
369
482
|
plugins: {
|
|
370
483
|
'@stylistic': stylistic,
|
|
371
484
|
'@stylistic/ts': stylisticTs,
|
|
485
|
+
'@taiga-ui/experience': plugin,
|
|
372
486
|
'decorator-position': require('eslint-plugin-decorator-position'),
|
|
373
487
|
perfectionist: require('eslint-plugin-perfectionist'),
|
|
374
488
|
prettier,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taiga-ui/eslint-plugin-experience-next",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.256.0",
|
|
4
4
|
"description": "An ESLint plugin to enforce a consistent code styles across taiga-ui projects",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./eslint.config.cjs.js",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"@smarttools/eslint-plugin-rxjs": ">=1.0.18",
|
|
10
10
|
"@stylistic/eslint-plugin": ">=4.0.1",
|
|
11
11
|
"@stylistic/eslint-plugin-ts": ">=4.0.1",
|
|
12
|
-
"@typescript-eslint/eslint-plugin": ">=8.
|
|
12
|
+
"@typescript-eslint/eslint-plugin": ">=8.25.0",
|
|
13
13
|
"angular-eslint": ">=19.1.0",
|
|
14
14
|
"eslint": ">=9.21.0",
|
|
15
15
|
"eslint-config-prettier": ">=10.0.1",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"eslint-plugin-unicorn": ">=57.0.0",
|
|
28
28
|
"eslint-plugin-unused-imports": ">=4.1.4",
|
|
29
29
|
"globals": ">=16.0.0",
|
|
30
|
-
"typescript-eslint": ">=8.
|
|
30
|
+
"typescript-eslint": ">=8.25.0"
|
|
31
31
|
},
|
|
32
32
|
"publishConfig": {
|
|
33
33
|
"access": "public"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
declare const plugin: {
|
|
3
|
+
configs: {
|
|
4
|
+
readonly recommended: {
|
|
5
|
+
readonly rules: Readonly<Linter.RulesRecord>;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
meta: {
|
|
9
|
+
name: string;
|
|
10
|
+
};
|
|
11
|
+
rules: {
|
|
12
|
+
'no-deep-imports': import("eslint").Rule.RuleModule;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export default plugin;
|