@taiga-ui/prettier-config 0.446.0 → 0.448.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/index.js CHANGED
@@ -32,16 +32,19 @@ module.exports = {
32
32
  },
33
33
  },
34
34
  {
35
- files: ['package.json', 'ng-package.json'],
35
+ files: [
36
+ 'package.json',
37
+ 'ng-package.json',
38
+ 'project.json',
39
+ 'renovate.json',
40
+ 'default.json',
41
+ 'tsconfig*.json',
42
+ ],
36
43
  options: {
37
44
  parser: 'json-stringify',
38
45
  plugins: [
39
46
  require.resolve(
40
- path.resolve(
41
- __dirname,
42
- 'plugins',
43
- 'prettier-plugin-sort-package.js',
44
- ),
47
+ path.resolve(__dirname, 'plugins', 'prettier-plugin-sort.js'),
45
48
  ),
46
49
  ],
47
50
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taiga-ui/prettier-config",
3
- "version": "0.446.0",
3
+ "version": "0.448.0",
4
4
  "description": "Taiga-ui prettier config",
5
5
  "keywords": [
6
6
  "prettier",
@@ -13,20 +13,20 @@
13
13
  "license": "Apache-2.0",
14
14
  "contributors": [
15
15
  {
16
- "name": "Alex Inkin",
17
- "email": "alexander@inkin.ru"
16
+ "email": "alexander@inkin.ru",
17
+ "name": "Alex Inkin"
18
18
  },
19
19
  {
20
- "name": "Maksim Ivanov",
21
- "email": "splincodewd@yandex.ru"
20
+ "email": "splincodewd@yandex.ru",
21
+ "name": "Maksim Ivanov"
22
22
  },
23
23
  {
24
- "name": "Vladimir Potekhin",
25
- "email": "vladimir.potekh@gmail.com"
24
+ "email": "vladimir.potekh@gmail.com",
25
+ "name": "Vladimir Potekhin"
26
26
  },
27
27
  {
28
- "name": "Nikita Barsukov",
29
- "email": "nikita.s.barsukov@gmail.com"
28
+ "email": "nikita.s.barsukov@gmail.com",
29
+ "name": "Nikita Barsukov"
30
30
  }
31
31
  ],
32
32
  "main": "index.js",
@@ -0,0 +1,227 @@
1
+ const prettier = import('prettier');
2
+ const sortPackageJson = import('sort-package-json');
3
+ const {parsers} = require('prettier/parser-babel');
4
+ const {doc} = require('prettier');
5
+
6
+ const {join} = doc.builders;
7
+
8
+ const jsonStringifyParser = parsers['json-stringify'];
9
+
10
+ /**
11
+ * Key order for `compilerOptions` in tsconfig files.
12
+ * Keys listed here appear first (in this order); remaining keys are sorted alphabetically.
13
+ */
14
+ const COMPILER_OPTIONS_KEY_ORDER = ['baseUrl', 'rootDir', 'strict'];
15
+
16
+ /**
17
+ * Top-level key order for tsconfig files.
18
+ * Keys listed here will appear first (in this order); remaining keys keep their original order.
19
+ */
20
+ const TSCONFIG_KEY_ORDER = [
21
+ '$schema',
22
+ 'extends',
23
+ 'compileOnSave',
24
+ 'compilerOptions',
25
+ 'angularCompilerOptions',
26
+ 'files',
27
+ 'include',
28
+ 'exclude',
29
+ 'references',
30
+ ];
31
+
32
+ /**
33
+ * Recursively sorts all plain-object keys alphabetically.
34
+ * Arrays are traversed but their element order is preserved.
35
+ *
36
+ * @param {unknown} value
37
+ * @returns {unknown}
38
+ */
39
+ function sortAlphabetically(value) {
40
+ if (Array.isArray(value)) {
41
+ return value.map(sortAlphabetically);
42
+ }
43
+
44
+ if (typeof value === 'object' && value !== null) {
45
+ /** @type {Record<string, unknown>} */
46
+ const result = {};
47
+
48
+ for (const key of Object.keys(value).sort()) {
49
+ result[key] = sortAlphabetically(
50
+ /** @type {Record<string, unknown>} */ value[key],
51
+ );
52
+ }
53
+
54
+ return result;
55
+ }
56
+
57
+ return value;
58
+ }
59
+
60
+ /**
61
+ * Reorders the top-level keys of a plain object according to `keyOrder`.
62
+ * Keys not listed in `keyOrder` are appended afterward, sorted alphabetically.
63
+ *
64
+ * @param {Record<string, unknown>} obj
65
+ * @param {string[]} keyOrder
66
+ * @returns {Record<string, unknown>}
67
+ */
68
+ function sortKeysByOrder(obj, keyOrder) {
69
+ const result = /** @type {Record<string, unknown>} */ {};
70
+
71
+ for (const key of keyOrder) {
72
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
73
+ result[key] = obj[key];
74
+ }
75
+ }
76
+
77
+ for (const key of Object.keys(obj).sort()) {
78
+ if (!Object.prototype.hasOwnProperty.call(result, key)) {
79
+ result[key] = obj[key];
80
+ }
81
+ }
82
+
83
+ return result;
84
+ }
85
+
86
+ exports.parsers = {
87
+ 'json-stringify': {
88
+ ...jsonStringifyParser,
89
+ /**
90
+ * @param {string} text
91
+ * @param {{ filepath: string | undefined; }} options
92
+ */
93
+ async parse(text, options) {
94
+ const filepath = options.filepath ?? '';
95
+
96
+ if (filepath.endsWith('package-lock.json')) {
97
+ return jsonStringifyParser.parse(text, options);
98
+ }
99
+
100
+ // To avoid parsing errors
101
+ text = await (await prettier).format(text, {filepath: options.filepath});
102
+
103
+ if (jsonStringifyParser.preprocess) {
104
+ text = jsonStringifyParser.preprocess(text, options);
105
+ }
106
+
107
+ const json = JSON.parse(text);
108
+ let sorted;
109
+
110
+ if (/tsconfig[^/\\]*\.json$/.test(filepath)) {
111
+ // For tsconfig files use a dedicated key order instead of sort-package-json,
112
+ // which treats unknown keys as package.json fields and orders them badly.
113
+ sorted = sortKeysByOrder(json, TSCONFIG_KEY_ORDER);
114
+ } else {
115
+ const unsortedScripts = JSON.parse(JSON.stringify(json?.scripts || {}));
116
+
117
+ sorted = (await sortPackageJson).default(json);
118
+
119
+ /**
120
+ * @note: add the scripts field if it's provided
121
+ * the scripts must be unsorted
122
+ */
123
+ if (
124
+ filepath.endsWith('package.json') &&
125
+ json?.hasOwnProperty('scripts')
126
+ ) {
127
+ sorted.scripts = unsortedScripts;
128
+ }
129
+ }
130
+
131
+ // Sort all nested objects alphabetically.
132
+ // Top-level key order is already set above; here we only recurse into values.
133
+ // `scripts` in package.json is intentionally left unsorted.
134
+ for (const key of Object.keys(sorted)) {
135
+ if (key === 'scripts' && filepath.endsWith('package.json')) {
136
+ continue;
137
+ }
138
+
139
+ if (typeof sorted[key] === 'object' && sorted[key] !== null) {
140
+ sorted[key] =
141
+ key === 'compilerOptions'
142
+ ? sortKeysByOrder(
143
+ /** @type {Record<string, unknown>} */ sorted[key],
144
+ COMPILER_OPTIONS_KEY_ORDER,
145
+ )
146
+ : sortAlphabetically(sorted[key]);
147
+ }
148
+ }
149
+
150
+ text = JSON.stringify(sorted);
151
+
152
+ return jsonStringifyParser.parse(text, options);
153
+ },
154
+ },
155
+ };
156
+
157
+ /**
158
+ * Returns true for AST nodes that represent a primitive JSON value (string, number, boolean, null).
159
+ *
160
+ * @param {unknown} node
161
+ * @returns {boolean}
162
+ */
163
+ function isPrimitiveLiteral(node) {
164
+ if (!node || typeof node !== 'object') {
165
+ return false;
166
+ }
167
+
168
+ const {type} = /** @type {{type: string}} */ node;
169
+
170
+ return (
171
+ type === 'StringLiteral' ||
172
+ type === 'NumericLiteral' ||
173
+ type === 'BooleanLiteral' ||
174
+ type === 'NullLiteral' ||
175
+ // Fallback for parsers that produce generic `Literal` nodes
176
+ (type === 'Literal' &&
177
+ /** @type {{value: unknown}} */ node.value !==
178
+ Object(/** @type {{value: unknown}} */ node.value))
179
+ );
180
+ }
181
+
182
+ /**
183
+ * Override the `estree-json` printer (used by both `json` and `json-stringify` parsers).
184
+ * The only change: arrays with 1–2 primitive elements are kept on a single line.
185
+ * Objects are always expanded by the original printer.
186
+ */
187
+ let originalEstreeJsonPrinter;
188
+
189
+ try {
190
+ originalEstreeJsonPrinter =
191
+ /** @type {{printers: Record<string, import('prettier').Printer>}} */ require('prettier/plugins/estree')
192
+ .printers?.['estree-json'];
193
+ } catch {}
194
+
195
+ if (originalEstreeJsonPrinter) {
196
+ exports.printers = {
197
+ 'estree-json': {
198
+ ...originalEstreeJsonPrinter,
199
+ /**
200
+ * @param {import('prettier').AstPath} path
201
+ * @param {import('prettier').ParserOptions} options
202
+ * @param {(path: import('prettier').AstPath) => import('prettier').Doc} print
203
+ * @returns {import('prettier').Doc}
204
+ */
205
+ print(path, options, print) {
206
+ const node = /** @type {{type: string; elements: unknown[]}} */ path.node;
207
+
208
+ if (
209
+ node.type === 'ArrayExpression' &&
210
+ node.elements.length >= 1 &&
211
+ node.elements.length <= 2 &&
212
+ node.elements.every(isPrimitiveLiteral)
213
+ ) {
214
+ const elements = /** @type {import('prettier').Doc[]} */ [];
215
+
216
+ path.each((p) => {
217
+ elements.push(print(p));
218
+ }, 'elements');
219
+
220
+ return ['[', join(', ', elements), ']'];
221
+ }
222
+
223
+ return originalEstreeJsonPrinter.print(path, options, print);
224
+ },
225
+ },
226
+ };
227
+ }
package/project.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "name": "prettier-config",
3
2
  "$schema": "../../node_modules/nx/schemas/project-schema.json",
3
+ "name": "prettier-config",
4
4
  "prefix": "tui",
5
5
  "projectType": "library",
6
6
  "sourceRoot": "projects/prettier-config",
@@ -1,46 +0,0 @@
1
- const prettier = import('prettier');
2
- const sortPackageJson = import('sort-package-json');
3
- const {parsers} = require('prettier/parser-babel');
4
-
5
- const parser = parsers['json-stringify'];
6
-
7
- exports.parsers = {
8
- 'json-stringify': {
9
- ...parser,
10
- /**
11
- * @param {string} text
12
- * @param {{ filepath: string | undefined; }} options
13
- */
14
- async parse(text, options) {
15
- if (options.filepath?.endsWith('package-lock.json')) {
16
- return parser.parse(text, options);
17
- }
18
-
19
- // To avoid parsing errors
20
- text = await (await prettier).format(text, {filepath: options.filepath});
21
-
22
- if (parser.preprocess) {
23
- text = parser.preprocess(text, options);
24
- }
25
-
26
- const json = JSON.parse(text);
27
- const unsortedScripts = JSON.parse(JSON.stringify(json?.scripts || {}));
28
- const sorted = (await sortPackageJson).default(json);
29
-
30
- /**
31
- * @note: add the scripts field if it's provided
32
- * the scripts must be unsorted
33
- */
34
- if (
35
- options.filepath?.endsWith('package.json') &&
36
- json?.hasOwnProperty('scripts')
37
- ) {
38
- sorted.scripts = unsortedScripts;
39
- }
40
-
41
- text = JSON.stringify(sorted);
42
-
43
- return parser.parse(text, options);
44
- },
45
- },
46
- };