Skip to content

Commit 94af7ca

Browse files
committed
refactor: review suggestions
1 parent e6242d1 commit 94af7ca

5 files changed

Lines changed: 146 additions & 70 deletions

File tree

apps/site/.stylelintrc.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default {
2626
plugins: [
2727
'stylelint-order',
2828
'stylelint-selector-bem-pattern',
29-
'@node-core/ui-components/stylelint.plugin.mjs',
29+
'@node-core/ui-components/stylelint/one-mixin-per-line.mjs',
3030
],
3131
rules: {
3232
// Enforces Element Class Names to be camelCase
@@ -49,6 +49,6 @@ export default {
4949
'import-notation': 'string',
5050
// Allow the `@apply` at rule as its part of Tailwind
5151
'at-rule-no-deprecated': [true, { ignoreAtRules: CUSTOM_AT_RULES }],
52-
'ui-components/one-tailwind-token-per-line': true,
52+
'nodejs/one-mixin-per-line': true,
5353
},
5454
};

packages/ui-components/.stylelintrc.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default {
2626
plugins: [
2727
'stylelint-order',
2828
'stylelint-selector-bem-pattern',
29-
'./stylelint.plugin.mjs',
29+
'./stylelint/one-mixin-per-line.mjs',
3030
],
3131
rules: {
3232
// Enforces Element Class Names to be camelCase
@@ -49,6 +49,6 @@ export default {
4949
'import-notation': 'string',
5050
// Allow the `@apply` at rule as its part of Tailwind
5151
'at-rule-no-deprecated': [true, { ignoreAtRules: CUSTOM_AT_RULES }],
52-
'ui-components/one-tailwind-token-per-line': true,
52+
'nodejs/one-mixin-per-line': true,
5353
},
5454
};
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import {
2+
indentClassNames,
3+
cleanClassNames,
4+
applyIndentation,
5+
} from '../utils.mjs';
6+
7+
describe('cleanClassNames', () => {
8+
it('removes newlines and extra spaces', () => {
9+
const input = ' text-xl \r font-bold \n\n text-center ';
10+
const expected = 'text-xl font-bold text-center';
11+
12+
expect(cleanClassNames(input)).toBe(expected);
13+
});
14+
15+
it('trims leading and trailing spaces', () => {
16+
const input = ' mt-4 ';
17+
const expected = 'mt-4';
18+
19+
expect(cleanClassNames(input)).toBe(expected);
20+
});
21+
22+
it('returns empty string when input is empty', () => {
23+
expect(cleanClassNames('')).toBe('');
24+
});
25+
});
26+
27+
describe('applyIndentation', () => {
28+
it('adds indentation to each class name', () => {
29+
const input = 'text-xl font-bold text-center';
30+
const indent = ' ';
31+
const expected = ['text-xl', ' font-bold', ' text-center'].join('\n');
32+
33+
expect(applyIndentation(input, indent)).toBe(expected);
34+
});
35+
});
36+
37+
describe('indentClassNames', () => {
38+
it('returns null if rule is missing required properties', () => {
39+
expect(indentClassNames(null)).toBeNull();
40+
expect(indentClassNames({})).toBeNull();
41+
expect(indentClassNames({ params: 'foo' })).toBeNull();
42+
expect(indentClassNames({ params: 'foo', raws: {} })).toBeNull();
43+
});
44+
45+
it('cleans and indents class names correctly', () => {
46+
const rule = {
47+
params: ' text-xl \n font-bold \n text-center ',
48+
raws: {
49+
before: ' ',
50+
},
51+
};
52+
53+
const result = indentClassNames({ ...rule });
54+
const expectedParams = ['text-xl', ' font-bold', ' text-center'].join(
55+
'\n'
56+
);
57+
58+
expect(result).toEqual({
59+
...rule,
60+
params: expectedParams,
61+
});
62+
});
63+
64+
it('returns the same rule object with modified params', () => {
65+
const rule = {
66+
params: 'p-4 mb-2',
67+
raws: { before: ' \n' },
68+
};
69+
70+
const result = indentClassNames(rule);
71+
72+
expect(result).toBe(rule);
73+
expect(result.params).toBe('p-4\n mb-2');
74+
});
75+
});
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import stylelint from 'stylelint';
2+
3+
import { indentClassNames } from './utils.mjs';
4+
5+
const {
6+
createPlugin,
7+
utils: { report, ruleMessages },
8+
} = stylelint;
9+
10+
const name = 'nodejs/one-mixin-per-line';
11+
12+
const messages = ruleMessages(name, {
13+
className: tokens =>
14+
`Each line should contain only one Tailwind token; "${tokens}"`,
15+
spacing: tokens =>
16+
`Each class used with @apply should be indented by 2 spaces on a new line; ${tokens}`,
17+
});
18+
19+
const meta = {
20+
url: 'https://github.com/nodejs/nodejs.org/blob/main/COLLABORATOR_GUIDE.md#styling-a-component',
21+
fixable: true,
22+
};
23+
24+
/** @type {import('stylelint').Rule} */
25+
const rule = () => (root, result) => {
26+
root.walkAtRules('apply', rule => {
27+
if (!rule.params.includes(' ')) {
28+
// If there are no spaces in the params, we don't need to check anything
29+
return;
30+
}
31+
32+
// Since we use 2 spaces for indentation, each line in the apply rule
33+
// should be indented with two extra whitespaces.
34+
const classes = rule.params.split(`${rule.raws.before} `);
35+
const classNames = classes.join('');
36+
37+
// Check if the params contain any spaces
38+
if (classNames.includes(' ')) {
39+
if (classNames.includes('\n')) {
40+
return report({
41+
ruleName: name,
42+
result: result,
43+
message: messages.spacing(JSON.stringify(rule.params)),
44+
node: rule,
45+
fix: indentClassNames(rule),
46+
});
47+
}
48+
49+
return report({
50+
ruleName: name,
51+
result,
52+
message: messages.className(rule.params),
53+
node: rule,
54+
fix: indentClassNames(rule),
55+
});
56+
}
57+
});
58+
};
59+
60+
rule.ruleName = name;
61+
rule.messages = messages;
62+
rule.meta = meta;
63+
64+
export default createPlugin(name, rule);
Lines changed: 3 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,3 @@
1-
import stylelint from 'stylelint';
2-
3-
const {
4-
createPlugin,
5-
utils: { report, ruleMessages },
6-
} = stylelint;
7-
8-
const name = 'ui-components/one-tailwind-token-per-line';
9-
10-
const messages = ruleMessages(name, {
11-
className: tokens =>
12-
`Each line should contain only one Tailwind token; "${tokens}"`,
13-
spacing: tokens =>
14-
`Each class used with @apply should be indented by 2 spaces on a new line; ${tokens}`,
15-
});
16-
17-
const meta = {
18-
url: 'https://github.com/nodejs/nodejs.org/blob/main/COLLABORATOR_GUIDE.md#styling-a-component',
19-
fixable: true,
20-
};
21-
221
/**
232
* Adjusts the class names in the rule by cleaning and adding proper indentation.
243
*
@@ -28,7 +7,7 @@ const meta = {
287
* @param {string} rule.raws.before - The raw string before to the @apply rule.
298
* @returns {Object|null} The modified rule with properly formatted class names, or null if the rule is invalid.
309
*/
31-
const indentClassNames = rule => {
10+
export const indentClassNames = rule => {
3211
// Ensure that the rule contains necessary properties
3312
if (!rule || !rule.params || !rule.raws || !rule.raws.before) {
3413
return null;
@@ -51,7 +30,7 @@ const indentClassNames = rule => {
5130
* @param {string} params - The class names string to be cleaned.
5231
* @returns {string} The cleaned class names string.
5332
*/
54-
const cleanClassNames = params => {
33+
export const cleanClassNames = params => {
5534
return params
5635
.replace(/[\n\r]+/g, '') // Remove new lines
5736
.replace(/\s+/g, ' ') // Replace multiple spaces with a single space
@@ -65,52 +44,10 @@ const cleanClassNames = params => {
6544
* @param {string} indent - The string used for indentation.
6645
* @returns {string} The class names string with applied indentation.
6746
*/
68-
const applyIndentation = (classes, indent) => {
47+
export const applyIndentation = (classes, indent) => {
6948
return classes
7049
.split(' ') // Split into an array of class names
7150
.map(className => indent + className) // Add indentation to each class
7251
.join('\n') // Join with new lines
7352
.trim(); // Remove extra space at the end
7453
};
75-
76-
/** @type {import('stylelint').Rule} */
77-
const rule = () => (root, result) => {
78-
root.walkAtRules('apply', rule => {
79-
if (!rule.params.includes(' ')) {
80-
// If there are no spaces in the params, we don't need to check anything
81-
return;
82-
}
83-
84-
// Since we use 2 spaces for indentation, each line in the apply rule
85-
// should be indented with two extra whitespaces.
86-
const classes = rule.params.split(`${rule.raws.before} `);
87-
const classNames = classes.join('');
88-
89-
// Check if the params contain any spaces
90-
if (classNames.includes(' ')) {
91-
if (classNames.includes('\n')) {
92-
return report({
93-
ruleName: name,
94-
result: result,
95-
message: messages.spacing(JSON.stringify(rule.params)),
96-
node: rule,
97-
fix: indentClassNames(rule),
98-
});
99-
}
100-
101-
return report({
102-
ruleName: name,
103-
result,
104-
message: messages.className(rule.params),
105-
node: rule,
106-
fix: indentClassNames(rule),
107-
});
108-
}
109-
});
110-
};
111-
112-
rule.ruleName = name;
113-
rule.messages = messages;
114-
rule.meta = meta;
115-
116-
export default createPlugin(name, rule);

0 commit comments

Comments
 (0)