@vijayhardaha/dev-config 2.2.0 → 2.3.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.
Files changed (45) hide show
  1. package/README.md +39 -0
  2. package/package.json +17 -20
  3. package/src/__tests__/config-constants.test.js +111 -0
  4. package/src/{index.test.js → __tests__/index.test.js} +1 -1
  5. package/src/commitlint/{index.test.js → __tests__/index.test.js} +5 -5
  6. package/src/commitlint/index.js +3 -1
  7. package/src/config-constants.js +172 -0
  8. package/src/eslint/{index.test.js → __tests__/index.test.js} +3 -3
  9. package/src/eslint/{next.test.js → __tests__/next.test.js} +3 -3
  10. package/src/eslint/{react.test.js → __tests__/react.test.js} +3 -3
  11. package/src/eslint/{typescript.test.js → __tests__/typescript.test.js} +3 -3
  12. package/src/eslint/lib/{build-config.test.js → __tests__/build-config.test.js} +11 -11
  13. package/src/eslint/lib/{files.test.js → __tests__/files.test.js} +2 -2
  14. package/src/eslint/lib/{ignores.test.js → __tests__/ignores.test.js} +3 -3
  15. package/src/eslint/lib/{index.test.js → __tests__/index.test.js} +2 -2
  16. package/src/eslint/lib/{language-options.test.js → __tests__/language-options.test.js} +2 -2
  17. package/src/eslint/lib/{rules.test.js → __tests__/rules.test.js} +1 -1
  18. package/src/eslint/lib/{setup.test.js → __tests__/setup.test.js} +1 -1
  19. package/src/eslint/lib/build-config.js +11 -110
  20. package/src/eslint/lib/files.js +3 -1
  21. package/src/eslint/lib/plugin-helpers/__tests__/enabled-plugins.test.js +49 -0
  22. package/src/eslint/lib/plugin-helpers/__tests__/fixup.test.js +48 -0
  23. package/src/eslint/lib/plugin-helpers/__tests__/flatten.test.js +51 -0
  24. package/src/eslint/lib/plugin-helpers/__tests__/parser.test.js +78 -0
  25. package/src/eslint/lib/plugin-helpers/__tests__/strip.test.js +70 -0
  26. package/src/eslint/lib/plugin-helpers/enabled-plugins.js +26 -0
  27. package/src/eslint/lib/plugin-helpers/fixup.js +34 -0
  28. package/src/eslint/lib/plugin-helpers/flatten.js +31 -0
  29. package/src/eslint/lib/plugin-helpers/index.js +18 -0
  30. package/src/eslint/lib/plugin-helpers/parser.js +33 -0
  31. package/src/eslint/lib/plugin-helpers/strip.js +45 -0
  32. package/src/gulp-smacss/{index.test.js → __tests__/index.test.js} +2 -2
  33. package/src/gulp-smacss/index.js +5 -0
  34. package/src/jsconfig/{index.test.js → __tests__/index.test.js} +3 -3
  35. package/src/lib/__tests__/config-utils.test.js +145 -0
  36. package/src/lib/__tests__/validators.test.js +229 -0
  37. package/src/lib/config-utils.js +187 -0
  38. package/src/lib/validators.js +225 -0
  39. package/src/next-sitemap/{index.test.js → __tests__/index.test.js} +31 -5
  40. package/src/next-sitemap/index.js +22 -8
  41. package/src/prettier/{index.test.js → __tests__/index.test.js} +4 -4
  42. package/src/prettier/index.js +11 -47
  43. package/src/stylelint/{index.test.js → __tests__/index.test.js} +5 -5
  44. package/src/stylelint/index.js +4 -2
  45. package/src/tsconfig/{index.test.js → __tests__/index.test.js} +5 -5
@@ -0,0 +1,225 @@
1
+ /**
2
+ * =====================================================================
3
+ * Configuration Validators
4
+ * =====================================================================
5
+ * Purpose: Centralized validation functions for all configuration builders.
6
+ * Ensures consistent error handling and helpful error messages.
7
+ * Usage: Import validators and use in createConfig functions
8
+ * =====================================================================
9
+ */
10
+
11
+ /**
12
+ * Validates that a URL is properly formatted.
13
+ *
14
+ * @param {string} url - URL to validate.
15
+ * @param {string} [fieldName] - Field name for error message.
16
+ *
17
+ * @throws {TypeError} If url is not a string.
18
+ * @throws {Error} If url is empty.
19
+ * @throws {Error} If url is not a valid URL.
20
+ */
21
+ export function validateUrl(url, fieldName = 'URL') {
22
+ if (typeof url !== 'string') {
23
+ throw new TypeError(`${fieldName} must be a string, got ${typeof url}`);
24
+ }
25
+
26
+ if (url.trim().length === 0) {
27
+ throw new Error(`${fieldName} cannot be empty`);
28
+ }
29
+
30
+ try {
31
+ new URL(url);
32
+ } catch {
33
+ throw new Error(`Invalid ${fieldName}: "${url}" is not a valid URL`);
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Validates that a value is an array.
39
+ *
40
+ * @param {unknown} value - Value to validate.
41
+ * @param {string} [fieldName] - Field name for error message.
42
+ *
43
+ * @throws {TypeError} If value is not an array.
44
+ */
45
+ export function validateArray(value, fieldName = 'Array') {
46
+ if (!Array.isArray(value)) {
47
+ throw new TypeError(`${fieldName} must be an array, got ${typeof value}`);
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Validates that an array is not empty.
53
+ *
54
+ * @param {unknown[]} array - Array to validate.
55
+ * @param {string} [fieldName] - Field name for error message.
56
+ *
57
+ * @throws {TypeError} If array is not an array.
58
+ * @throws {Error} If array is empty.
59
+ */
60
+ export function validateNonEmptyArray(array, fieldName = 'Array') {
61
+ validateArray(array, fieldName);
62
+
63
+ if (array.length === 0) {
64
+ throw new Error(`${fieldName} cannot be empty`);
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Validates that a value is an object.
70
+ *
71
+ * @param {unknown} value - Value to validate.
72
+ * @param {string} [fieldName] - Field name for error message.
73
+ *
74
+ * @throws {TypeError} If value is not an object or is null.
75
+ */
76
+ export function validateObject(value, fieldName = 'Object') {
77
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
78
+ throw new TypeError(`${fieldName} must be an object, got ${typeof value}`);
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Validates that a value is a string.
84
+ *
85
+ * @param {unknown} value - Value to validate.
86
+ * @param {string} [fieldName] - Field name for error message.
87
+ *
88
+ * @throws {TypeError} If value is not a string.
89
+ */
90
+ export function validateString(value, fieldName = 'String') {
91
+ if (typeof value !== 'string') {
92
+ throw new TypeError(`${fieldName} must be a string, got ${typeof value}`);
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Validates that a string is not empty.
98
+ *
99
+ * @param {unknown} value - Value to validate.
100
+ * @param {string} [fieldName] - Field name for error message.
101
+ *
102
+ * @throws {TypeError} If value is not a string.
103
+ * @throws {Error} If value is empty.
104
+ */
105
+ export function validateNonEmptyString(value, fieldName = 'String') {
106
+ validateString(value, fieldName);
107
+
108
+ if (value.trim().length === 0) {
109
+ throw new Error(`${fieldName} cannot be empty`);
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Validates that a value is a boolean.
115
+ *
116
+ * @param {unknown} value - Value to validate.
117
+ * @param {string} [fieldName] - Field name for error message.
118
+ *
119
+ * @throws {TypeError} If value is not a boolean.
120
+ */
121
+ export function validateBoolean(value, fieldName = 'Boolean') {
122
+ if (typeof value !== 'boolean') {
123
+ throw new TypeError(`${fieldName} must be a boolean, got ${typeof value}`);
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Validates that a value is a number.
129
+ *
130
+ * @param {unknown} value - Value to validate.
131
+ * @param {string} [fieldName] - Field name for error message.
132
+ *
133
+ * @throws {TypeError} If value is not a number.
134
+ * @throws {Error} If value is NaN or Infinity.
135
+ */
136
+ export function validateNumber(value, fieldName = 'Number') {
137
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
138
+ throw new TypeError(`${fieldName} must be a valid number, got ${typeof value}`);
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Validates that a number is within a specific range.
144
+ *
145
+ * @param {unknown} value - Value to validate.
146
+ * @param {number} min - Minimum allowed value (inclusive).
147
+ * @param {number} max - Maximum allowed value (inclusive).
148
+ * @param {string} [fieldName] - Field name for error message.
149
+ *
150
+ * @throws {TypeError} If value is not a valid number.
151
+ * @throws {Error} If value is outside the range.
152
+ */
153
+ export function validateNumberInRange(value, min, max, fieldName = 'Number') {
154
+ validateNumber(value, fieldName);
155
+
156
+ if (value < min || value > max) {
157
+ throw new Error(`${fieldName} must be between ${min} and ${max}, got ${value}`);
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Validates that all array items are strings.
163
+ *
164
+ * @param {unknown[]} array - Array to validate.
165
+ * @param {string} [fieldName] - Field name for error message.
166
+ *
167
+ * @throws {TypeError} If array is not an array.
168
+ * @throws {TypeError} If any item is not a string.
169
+ */
170
+ export function validateStringArray(array, fieldName = 'Array') {
171
+ validateArray(array, fieldName);
172
+
173
+ for (let i = 0; i < array.length; i++) {
174
+ if (typeof array[i] !== 'string') {
175
+ throw new TypeError(`${fieldName}[${i}] must be a string, got ${typeof array[i]}`);
176
+ }
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Validates that an object has specific required keys.
182
+ *
183
+ * @param {unknown} obj - Object to validate.
184
+ * @param {string[]} requiredKeys - Keys that must exist.
185
+ * @param {string} [fieldName] - Field name for error message.
186
+ *
187
+ * @throws {TypeError} If obj is not an object.
188
+ * @throws {Error} If any required key is missing.
189
+ */
190
+ export function validateObjectKeys(obj, requiredKeys, fieldName = 'Object') {
191
+ validateObject(obj, fieldName);
192
+
193
+ for (const key of requiredKeys) {
194
+ if (!(key in obj)) {
195
+ throw new Error(`${fieldName} is missing required key: "${key}"`);
196
+ }
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Validates configuration rules object.
202
+ *
203
+ * @param {unknown} rules - Rules object to validate.
204
+ * @param {string} [fieldName] - Field name for error message.
205
+ *
206
+ * @throws {TypeError} If rules is not an object.
207
+ */
208
+ export function validateRules(rules, fieldName = 'Rules') {
209
+ if (typeof rules !== 'object' || rules === null || Array.isArray(rules)) {
210
+ throw new TypeError(`${fieldName} must be an object, got ${typeof rules}`);
211
+ }
212
+ }
213
+
214
+ /**
215
+ * Validates file patterns array.
216
+ *
217
+ * @param {unknown} patterns - File patterns to validate.
218
+ * @param {string} [fieldName] - Field name for error message.
219
+ *
220
+ * @throws {TypeError} If patterns is not an array.
221
+ * @throws {TypeError} If any pattern is not a string.
222
+ */
223
+ export function validateFilePatterns(patterns, fieldName = 'File patterns') {
224
+ validateStringArray(patterns, fieldName);
225
+ }
@@ -5,7 +5,7 @@ describe('next-sitemap/index.js', () => {
5
5
  // Test that the module exports the createSitemapConfig function.
6
6
  it('should export createSitemapConfig function', async () => {
7
7
  // Dynamically import the module to test its exports.
8
- const module = await import('./index.js');
8
+ const module = await import('../index.js');
9
9
 
10
10
  // Verify that createSitemapConfig is a function.
11
11
  expect(typeof module.createSitemapConfig).toBe('function');
@@ -14,7 +14,7 @@ describe('next-sitemap/index.js', () => {
14
14
  // Test that the module exports a default config object.
15
15
  it('should export default config object', async () => {
16
16
  // Dynamically import the module to test its exports.
17
- const module = await import('./index.js');
17
+ const module = await import('../index.js');
18
18
 
19
19
  // Verify that the default export is an object.
20
20
  expect(typeof module.default).toBe('object');
@@ -23,7 +23,7 @@ describe('next-sitemap/index.js', () => {
23
23
  // Test that createSitemapConfig returns config with provided siteUrl.
24
24
  it('should return config with siteUrl', async () => {
25
25
  // Dynamically import the module to test its function.
26
- const module = await import('./index.js');
26
+ const module = await import('../index.js');
27
27
 
28
28
  // Call createSitemapConfig with a siteUrl parameter.
29
29
  const config = module.createSitemapConfig({ siteUrl: 'https://example.com' });
@@ -35,7 +35,7 @@ describe('next-sitemap/index.js', () => {
35
35
  // Test that createSitemapConfig returns config with default values when no params provided.
36
36
  it('should return config with default values', async () => {
37
37
  // Dynamically import the module to test its function.
38
- const module = await import('./index.js');
38
+ const module = await import('../index.js');
39
39
 
40
40
  // Call createSitemapConfig without parameters to get defaults.
41
41
  const config = module.createSitemapConfig();
@@ -48,7 +48,7 @@ describe('next-sitemap/index.js', () => {
48
48
  // Test that generateRobotsTxt is enabled by default in the config.
49
49
  it('should have generateRobotsTxt enabled', async () => {
50
50
  // Dynamically import the module to test its function.
51
- const module = await import('./index.js');
51
+ const module = await import('../index.js');
52
52
 
53
53
  // Call createSitemapConfig to get default config.
54
54
  const config = module.createSitemapConfig();
@@ -56,4 +56,30 @@ describe('next-sitemap/index.js', () => {
56
56
  // Verify that generateRobotsTxt is enabled by default.
57
57
  expect(config.generateRobotsTxt).toBe(true);
58
58
  });
59
+
60
+ // Test that transformRobotsTxt removes the Host header from generated robots.txt.
61
+ it('should remove Host header in transformRobotsTxt', async () => {
62
+ // Dynamically import the module to test its function.
63
+ const module = await import('../index.js');
64
+
65
+ // Call createSitemapConfig with a test siteUrl.
66
+ const config = module.createSitemapConfig({ siteUrl: 'https://example.com' });
67
+
68
+ // Verify that robotsTxtOptions has the transformRobotsTxt function.
69
+ expect(typeof config.robotsTxtOptions.transformRobotsTxt).toBe('function');
70
+
71
+ // Mock a robots.txt output with the Host header that next-sitemap generates.
72
+ const mockRobotsTxt = `# Host\nHost: https://example.com\n\nUser-agent: *\nAllow: /\n`;
73
+
74
+ // Call the transformRobotsTxt function with mock data.
75
+ const transformed = await config.robotsTxtOptions.transformRobotsTxt(config, mockRobotsTxt);
76
+
77
+ // Verify that the Host header has been removed from the output.
78
+ expect(transformed).not.toContain('# Host');
79
+ expect(transformed).not.toContain('Host: https://example.com');
80
+
81
+ // Verify that the rest of the robots.txt content is preserved.
82
+ expect(transformed).toContain('User-agent: *');
83
+ expect(transformed).toContain('Allow: /');
84
+ });
59
85
  });
@@ -8,6 +8,9 @@
8
8
  * =====================================================================
9
9
  */
10
10
 
11
+ import { SITEMAP } from '../config-constants.js';
12
+ import { validateUrl, validateStringArray, validateNonEmptyString } from '../lib/validators.js';
13
+
11
14
  /**
12
15
  * Creates a sitemap configuration object for next-sitemap.
13
16
  *
@@ -17,9 +20,20 @@
17
20
  * @param {string[]} [options.exclude] - Paths to exclude from sitemap.
18
21
  *
19
22
  * @returns {import('next-sitemap').IConfig} Sitemap configuration object.
23
+ *
24
+ * @throws {Error} If required parameters are invalid.
20
25
  */
21
26
  export function createSitemapConfig(options = {}) {
22
- const { siteUrl = 'https://example.com', outDir = './public', exclude = ['/404', '/500'] } = options;
27
+ const {
28
+ siteUrl = SITEMAP.DEFAULTS.SITE_URL,
29
+ outDir = SITEMAP.DEFAULTS.OUTPUT_DIR,
30
+ exclude = SITEMAP.DEFAULTS.EXCLUDE_PATHS,
31
+ } = options;
32
+
33
+ // ---- Validation ----
34
+ validateUrl(siteUrl, 'siteUrl');
35
+ validateNonEmptyString(outDir, 'outDir');
36
+ validateStringArray(exclude, 'exclude');
23
37
 
24
38
  // ---- Last Modified ----
25
39
  // Use current timestamp for all sitemap entries
@@ -28,13 +42,13 @@ export function createSitemapConfig(options = {}) {
28
42
  return {
29
43
  // ---- Basic Settings ----
30
44
  siteUrl,
31
- sitemapBaseFileName: 'sitemap',
32
- trailingSlash: false,
45
+ sitemapBaseFileName: SITEMAP.DEFAULTS.SITEMAP_FILENAME,
46
+ trailingSlash: SITEMAP.DEFAULTS.TRAILING_SLASH,
33
47
 
34
48
  // ---- Output Settings ----
35
49
  outDir,
36
- changefreq: 'weekly',
37
- priority: 0.7,
50
+ changefreq: SITEMAP.DEFAULTS.CHANGE_FREQUENCY,
51
+ priority: SITEMAP.DEFAULTS.PRIORITY,
38
52
  exclude,
39
53
 
40
54
  // ---- Transform Function ----
@@ -44,13 +58,13 @@ export function createSitemapConfig(options = {}) {
44
58
  },
45
59
 
46
60
  // ---- Robots.txt Generation ----
47
- generateRobotsTxt: true,
61
+ generateRobotsTxt: SITEMAP.DEFAULTS.GENERATE_ROBOTS_TXT,
48
62
  robotsTxtOptions: {
49
- policies: [{ userAgent: '*', allow: '/' }],
63
+ policies: [{ userAgent: SITEMAP.ROBOTS_TXT.USER_AGENT, allow: SITEMAP.ROBOTS_TXT.ALLOW }],
50
64
  // ---- Custom Robots.txt Transform ----
51
65
  // Remove the default Host header from generated robots.txt
52
66
  transformRobotsTxt: async (_config, robotsTxt) => {
53
- const hostHeader = `# Host\nHost: ${siteUrl}\n\n`;
67
+ const hostHeader = `${SITEMAP.HEADERS.HOST}\nHost: ${siteUrl}\n\n`;
54
68
  return robotsTxt.replace(hostHeader, '');
55
69
  },
56
70
  },
@@ -5,7 +5,7 @@ describe('prettier/index.js', () => {
5
5
  // Test that the module exports a default config object.
6
6
  it('should export default config object', async () => {
7
7
  // Dynamically import the rules module to test its function.
8
- const module = await import('./index.js');
8
+ const module = await import('../index.js');
9
9
 
10
10
  // Verify default export is an object.
11
11
  expect(typeof module.default).toBe('object');
@@ -14,7 +14,7 @@ describe('prettier/index.js', () => {
14
14
  // Test that the config has the correct Prettier properties.
15
15
  it('should have correct Prettier configuration properties', async () => {
16
16
  // Dynamically import the rules module to test its function.
17
- const module = await import('./index.js');
17
+ const module = await import('../index.js');
18
18
  const config = module.default;
19
19
 
20
20
  // Verify basic formatting options.
@@ -29,7 +29,7 @@ describe('prettier/index.js', () => {
29
29
  // Test that the config has overrides for different file types.
30
30
  it('should have overrides for different file types', async () => {
31
31
  // Dynamically import the rules module to test its function.
32
- const module = await import('./index.js');
32
+ const module = await import('../index.js');
33
33
  const config = module.default;
34
34
 
35
35
  // Verify overrides array exists and has entries.
@@ -39,7 +39,7 @@ describe('prettier/index.js', () => {
39
39
 
40
40
  // Test that XML-like extensions are matched as normal file globs.
41
41
  it('should use XML glob patterns that match normal files', async () => {
42
- const module = await import('./index.js');
42
+ const module = await import('../index.js');
43
43
  const xmlOverride = module.default.overrides.find((override) => override.options?.xmlWhitespaceSensitivity);
44
44
 
45
45
  expect(xmlOverride.files).toEqual(['**/*.xml', '**/*.xsd', '**/*.xsl', '**/*.xslt']);
@@ -9,72 +9,36 @@
9
9
  * =====================================================================
10
10
  */
11
11
 
12
+ import { PRETTIER } from '../config-constants.js';
13
+
12
14
  /** @type {import("prettier").Config} */
13
15
  const config = {
14
16
  // ---- Basic Settings ----
15
- // Maximum line width before wrapping
16
- printWidth: 120,
17
- // Number of spaces per indentation
18
- tabWidth: 2,
19
- // Use spaces instead of tabs
20
- useTabs: false,
21
- // Add semicolons at the end of statements
22
- semi: true,
23
- // Use single quotes for strings
24
- singleQuote: false,
25
- // Handle line endings automatically
26
- endOfLine: 'auto',
27
- // Always include parentheses around arrow function parameters
28
- arrowParens: 'always',
29
- // Trailing commas in multi-line structures
30
- trailingComma: 'es5',
31
- // Add spaces between object braces
32
- bracketSpacing: true,
33
- // Do not put single-line objects on a single line
34
- bracketSameLine: false,
35
- // Preserve prose wrapping in Markdown files
36
- proseWrap: 'preserve',
37
- // Experimental operator position at start
38
- experimentalOperatorPosition: 'start',
39
- // Collapse object literals
40
- objectWrap: 'collapse',
41
- // Ensures that whitespace in XML is preserved as-is
42
- xmlWhitespaceSensitivity: 'preserve',
17
+ ...PRETTIER.BASE,
43
18
 
44
19
  // ---- Plugins ----
45
- plugins: ['@prettier/plugin-xml'],
20
+ plugins: [PRETTIER.PLUGINS.XML],
46
21
 
47
22
  // ---- Overrides ----
48
23
  // Different formatting rules for different file types
49
24
  overrides: [
50
25
  // ---- Backend Languages ----
51
- // Use 4-space indentation for Python and PHP
52
- { files: ['*.py', '*.php'], options: { tabWidth: 4, useTabs: false } },
26
+ { files: PRETTIER.FILE_PATTERNS.BACKEND, options: PRETTIER.OVERRIDES.BACKEND },
53
27
 
54
28
  // ---- JavaScript/TypeScript ----
55
- // Use 2-space indentation and single quotes for JS/TS
56
- { files: ['*.js', '*.ts', '*.mjs', '*.cjs', '*.jsx', '*.tsx'], options: { tabWidth: 2, singleQuote: true } },
29
+ { files: PRETTIER.FILE_PATTERNS.JAVASCRIPT, options: PRETTIER.OVERRIDES.JAVASCRIPT },
57
30
 
58
31
  // ---- Stylesheet Languages ----
59
- // Use 2-space indentation for CSS/SCSS/SASS
60
- { files: ['*.css', '*.scss', '*.sass'], options: { tabWidth: 2 } },
32
+ { files: PRETTIER.FILE_PATTERNS.STYLESHEETS, options: PRETTIER.OVERRIDES.STYLESHEETS },
61
33
 
62
34
  // ---- Data & Documentation ----
63
- // Use 2-space indentation and no trailing commas for JSON/YAML/Markdown
64
- {
65
- files: ['*.json', '*.jsonc', '*.yml', '*.yaml', '*.md', '*.mdx'],
66
- options: { tabWidth: 2, trailingComma: 'none' },
67
- },
35
+ { files: PRETTIER.FILE_PATTERNS.DATA_AND_DOCS, options: PRETTIER.OVERRIDES.DATA_AND_DOCS },
36
+
68
37
  // ---- YAML ----
69
- // Use yaml parser with 2-space indentation
70
- { files: ['*.yml', '*.yaml'], options: { parser: 'yaml', tabWidth: 2 } },
38
+ { files: PRETTIER.FILE_PATTERNS.YAML, options: PRETTIER.OVERRIDES.YAML },
71
39
 
72
40
  // ---- XML ----
73
- // Use 2-space indentation for XML files
74
- {
75
- files: ['**/*.xml', '**/*.xsd', '**/*.xsl', '**/*.xslt'],
76
- options: { tabWidth: 2, xmlWhitespaceSensitivity: 'preserve' },
77
- },
41
+ { files: PRETTIER.FILE_PATTERNS.XML, options: PRETTIER.OVERRIDES.XML },
78
42
  ],
79
43
  };
80
44
 
@@ -5,7 +5,7 @@ describe('stylelint/index.js', () => {
5
5
  // Test that the module exports a default configuration object.
6
6
  it('should export default config object', async () => {
7
7
  // Dynamically import the index.js module to test its exports.
8
- const module = await import('./index.js');
8
+ const module = await import('../index.js');
9
9
 
10
10
  // Verify that the default export is an object (Stylelint config).
11
11
  expect(typeof module.default).toBe('object');
@@ -14,7 +14,7 @@ describe('stylelint/index.js', () => {
14
14
  // Test that the config has an extends array (inherits from base configs).
15
15
  it('should have extends property', async () => {
16
16
  // Dynamically import the index.js module to test its exports.
17
- const module = await import('./index.js');
17
+ const module = await import('../index.js');
18
18
 
19
19
  // Verify that extends is an array (list of config files to extend).
20
20
  expect(Array.isArray(module.default.extends)).toBe(true);
@@ -23,7 +23,7 @@ describe('stylelint/index.js', () => {
23
23
  // Test that the config has a plugins array (contains Stylelint plugins).
24
24
  it('should have plugins property', async () => {
25
25
  // Dynamically import the index.js module to test its exports.
26
- const module = await import('./index.js');
26
+ const module = await import('../index.js');
27
27
 
28
28
  // Verify that plugins is an array (list of Stylelint plugins).
29
29
  expect(Array.isArray(module.default.plugins)).toBe(true);
@@ -32,7 +32,7 @@ describe('stylelint/index.js', () => {
32
32
  // Test that the config has a rules object (contains Stylelint rules).
33
33
  it('should have rules property', async () => {
34
34
  // Dynamically import the index.js module to test its exports.
35
- const module = await import('./index.js');
35
+ const module = await import('../index.js');
36
36
 
37
37
  // Verify that rules is an object (key-value pairs of rule configurations).
38
38
  expect(typeof module.default.rules).toBe('object');
@@ -41,7 +41,7 @@ describe('stylelint/index.js', () => {
41
41
  // Test that specific rules are disabled (set to null).
42
42
  it('should have disabled rules', async () => {
43
43
  // Dynamically import the index.js module to test its exports.
44
- const module = await import('./index.js');
44
+ const module = await import('../index.js');
45
45
 
46
46
  // Verify that selector-class-pattern rule is disabled (null).
47
47
  expect(module.default.rules['selector-class-pattern']).toBeNull();
@@ -9,15 +9,17 @@
9
9
  * =====================================================================
10
10
  */
11
11
 
12
+ import { STYLELINT } from '../config-constants.js';
13
+
12
14
  /** @type {import("stylelint").Config} */
13
15
  const config = {
14
16
  // ---- Extends ----
15
17
  // Use standard SCSS configuration and property sort order
16
- extends: ['stylelint-config-standard-scss', 'stylelint-config-property-sort-order-smacss'],
18
+ ...STYLELINT.DEFAULTS,
17
19
 
18
20
  // ---- Plugins ----
19
21
  // Use stylelint-order for property sorting
20
- plugins: ['stylelint-order'],
22
+ plugins: [STYLELINT.PLUGINS.ORDER],
21
23
 
22
24
  // ---- Rules ----
23
25
  // Disable specific rules that are too strict or conflict with team style
@@ -5,7 +5,7 @@ describe('tsconfig/index.json', () => {
5
5
  // Test that the tsconfig file is valid JSON and exports an object.
6
6
  it('should be a valid JSON file', async () => {
7
7
  // Dynamically import the JSON file with JSON assertion.
8
- const module = await import('./index.json', { assert: { type: 'json' } });
8
+ const module = await import('../index.json', { assert: { type: 'json' } });
9
9
 
10
10
  // Verify that the default export is an object (valid JSON object).
11
11
  expect(typeof module.default).toBe('object');
@@ -14,7 +14,7 @@ describe('tsconfig/index.json', () => {
14
14
  // Test that the tsconfig contains compilerOptions.
15
15
  it('should have compilerOptions', async () => {
16
16
  // Dynamically import the JSON file with JSON assertion.
17
- const module = await import('./index.json', { assert: { type: 'json' } });
17
+ const module = await import('../index.json', { assert: { type: 'json' } });
18
18
 
19
19
  // Verify that compilerOptions property exists on the config object.
20
20
  expect(module.default.compilerOptions).toBeDefined();
@@ -26,7 +26,7 @@ describe('tsconfig/index.json', () => {
26
26
  // Test that the tsconfig has the correct ECMAScript target.
27
27
  it('should have correct target', async () => {
28
28
  // Dynamically import the JSON file with JSON assertion.
29
- const module = await import('./index.json', { assert: { type: 'json' } });
29
+ const module = await import('../index.json', { assert: { type: 'json' } });
30
30
 
31
31
  // Verify that the target is set to ES2024 (modern JavaScript).
32
32
  expect(module.default.compilerOptions.target).toBe('ES2024');
@@ -35,7 +35,7 @@ describe('tsconfig/index.json', () => {
35
35
  // Test that the tsconfig has JSX configured for React.
36
36
  it('should have jsx configured', async () => {
37
37
  // Dynamically import the JSON file with JSON assertion.
38
- const module = await import('./index.json', { assert: { type: 'json' } });
38
+ const module = await import('../index.json', { assert: { type: 'json' } });
39
39
 
40
40
  // Verify that JSX is configured to use react-jsx preset.
41
41
  expect(module.default.compilerOptions.jsx).toBe('react-jsx');
@@ -44,7 +44,7 @@ describe('tsconfig/index.json', () => {
44
44
  // Test that the tsconfig has strict mode enabled.
45
45
  it('should have strict mode enabled', async () => {
46
46
  // Dynamically import the JSON file with JSON assertion.
47
- const module = await import('./index.json', { assert: { type: 'json' } });
47
+ const module = await import('../index.json', { assert: { type: 'json' } });
48
48
 
49
49
  // Verify that strict type checking options are enabled.
50
50
  expect(module.default.compilerOptions.strict).toBe(true);