Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion apps/site/.stylelintrc.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ const ONLY_ALLOW_CAMEL_CASE_SELECTORS = [

export default {
extends: ['stylelint-config-standard'],
plugins: ['stylelint-order', 'stylelint-selector-bem-pattern'],
plugins: [
'stylelint-order',
'stylelint-selector-bem-pattern',
'@node-core/ui-components/stylelint/one-mixin-per-line.mjs',
],
rules: {
// Enforces Element Class Names to be camelCase
'selector-class-pattern': ONLY_ALLOW_CAMEL_CASE_SELECTORS,
Expand All @@ -45,5 +49,6 @@ export default {
'import-notation': 'string',
// Allow the `@apply` at rule as its part of Tailwind
'at-rule-no-deprecated': [true, { ignoreAtRules: CUSTOM_AT_RULES }],
'nodejs/one-mixin-per-line': true,
},
};
22 changes: 11 additions & 11 deletions apps/site/layouts/layouts.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,14 @@

&:nth-of-type(2) {
@apply flex
min-w-0
max-w-full
flex-[1_1]
flex-col
items-center
gap-4
md:max-w-2xl
lg:max-w-3xl;
min-w-0
max-w-full
flex-[1_1]
flex-col
items-center
gap-4
md:max-w-2xl
lg:max-w-3xl;

> div {
@apply w-full
Expand All @@ -154,9 +154,9 @@

> p {
@apply text-center
text-sm
text-neutral-800
dark:text-neutral-200;
text-sm
text-neutral-800
dark:text-neutral-200;
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions apps/site/styles/effects.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

& img {
@apply h-auto
w-24
md:w-48;
w-24
md:w-48;
}
}
7 changes: 6 additions & 1 deletion packages/ui-components/.stylelintrc.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ const ONLY_ALLOW_CAMEL_CASE_SELECTORS = [

export default {
extends: ['stylelint-config-standard'],
plugins: ['stylelint-order', 'stylelint-selector-bem-pattern'],
plugins: [
'stylelint-order',
'stylelint-selector-bem-pattern',
'./stylelint/one-mixin-per-line.mjs',
],
rules: {
// Enforces Element Class Names to be camelCase
'selector-class-pattern': ONLY_ALLOW_CAMEL_CASE_SELECTORS,
Expand All @@ -45,6 +49,7 @@ export default {
'import-notation': 'string',
// Allow the `@apply` at rule as its part of Tailwind
'at-rule-no-deprecated': [true, { ignoreAtRules: CUSTOM_AT_RULES }],
'nodejs/one-mixin-per-line': true,
// We need complex `:not()` for headings with anchor
'selector-not-notation': null,
},
Expand Down
20 changes: 18 additions & 2 deletions packages/ui-components/Common/Blockquote/index.module.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
@reference "../../styles/index.css";

.wrapper {
@apply flex max-w-2xl flex-col items-start gap-4 self-stretch border-l-2 border-green-600 py-2 pl-5 text-lg font-semibold text-neutral-900 dark:border-green-400 dark:text-white;
@apply flex
max-w-2xl
flex-col
items-start
gap-4
self-stretch
border-l-2
border-green-600
py-2
pl-5
text-lg
font-semibold
text-neutral-900
dark:border-green-400
dark:text-white;

& cite {
@apply font-regular text-base not-italic;
@apply font-regular
text-base
not-italic;

&::before {
@apply content-['—_'];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,41 @@
@reference "../../../styles/index.css";

.item {
@apply flex max-w-fit items-center gap-5 truncate text-sm font-medium;
@apply flex
max-w-fit
items-center
gap-5
truncate
text-sm
font-medium;

&:last-child {
@apply w-full;
}

a {
@apply shrink grow;
@apply shrink
grow;
}

&,
> a,
> a:hover {
@apply text-neutral-800 motion-safe:transition-colors dark:text-neutral-200;
@apply text-neutral-800
motion-safe:transition-colors
dark:text-neutral-200;
}

&.visuallyHidden {
@apply hidden;
}

.separator {
@apply size-4 max-w-fit shrink-0 grow text-neutral-600 dark:text-neutral-400;
@apply size-4
max-w-fit
shrink-0
grow
text-neutral-600
dark:text-neutral-400;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
@reference "../../../styles/index.css";

.link {
@apply max-w-fit truncate;
@apply max-w-fit
truncate;

&.active {
@apply rounded bg-green-600 px-2 py-1 font-semibold text-white motion-safe:transition-colors dark:text-white;
@apply rounded
bg-green-600
px-2
py-1
font-semibold
text-white
motion-safe:transition-colors
dark:text-white;

&:hover {
@apply bg-green-700 text-white;
@apply bg-green-700
text-white;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
@reference "../../../styles/index.css";

.list {
@apply xs:w-full flex w-screen gap-5 px-6;
@apply xs:w-full
flex
w-screen
gap-5
px-6;
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@

> div {
@apply max-h-80
w-48 overflow-y-auto;
w-48
overflow-y-auto;
}
}

Expand All @@ -47,5 +48,6 @@
}

.currentDropDown {
@apply bg-green-600 text-white;
@apply bg-green-600
text-white;
}
2 changes: 1 addition & 1 deletion packages/ui-components/Common/Tabs/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

.tabSecondaryLabel {
@apply text-green-800
dark:text-green-600;
dark:text-green-600;
}
}
}
Expand Down
75 changes: 75 additions & 0 deletions packages/ui-components/stylelint/__tests__/index.test.mjs
Comment thread
avivkeller marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {
indentClassNames,
cleanClassNames,
applyIndentation,
} from '../utils.mjs';

describe('cleanClassNames', () => {
it('removes newlines and extra spaces', () => {
const input = ' text-xl \r font-bold \n\n text-center ';
const expected = 'text-xl font-bold text-center';

expect(cleanClassNames(input)).toBe(expected);
});

it('trims leading and trailing spaces', () => {
const input = ' mt-4 ';
const expected = 'mt-4';

expect(cleanClassNames(input)).toBe(expected);
});

it('returns empty string when input is empty', () => {
expect(cleanClassNames('')).toBe('');
});
});

describe('applyIndentation', () => {
it('adds indentation to each class name', () => {
const input = 'text-xl font-bold text-center';
const indent = ' ';
const expected = ['text-xl', ' font-bold', ' text-center'].join('\n');

expect(applyIndentation(input, indent)).toBe(expected);
});
});

describe('indentClassNames', () => {
it('returns null if rule is missing required properties', () => {
expect(indentClassNames(null)).toBeNull();
expect(indentClassNames({})).toBeNull();
expect(indentClassNames({ params: 'foo' })).toBeNull();
expect(indentClassNames({ params: 'foo', raws: {} })).toBeNull();
});

it('cleans and indents class names correctly', () => {
const rule = {
params: ' text-xl \n font-bold \n text-center ',
raws: {
before: ' ',
},
};

const result = indentClassNames({ ...rule });
const expectedParams = ['text-xl', ' font-bold', ' text-center'].join(
'\n'
);

expect(result).toEqual({
...rule,
params: expectedParams,
});
});

it('returns the same rule object with modified params', () => {
const rule = {
params: 'p-4 mb-2',
raws: { before: ' \n' },
};

const result = indentClassNames(rule);

expect(result).toBe(rule);
expect(result.params).toBe('p-4\n mb-2');
});
});
64 changes: 64 additions & 0 deletions packages/ui-components/stylelint/one-mixin-per-line.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import stylelint from 'stylelint';

import { indentClassNames } from './utils.mjs';

const {
createPlugin,
utils: { report, ruleMessages },
} = stylelint;

const name = 'nodejs/one-mixin-per-line';

const messages = ruleMessages(name, {
className: tokens =>
`Each line should contain only one Tailwind token; "${tokens}"`,
Comment thread
canerakdas marked this conversation as resolved.
Outdated
spacing: tokens =>
`Each class used with @apply should be indented by 2 spaces on a new line; ${tokens}`,
Comment thread
canerakdas marked this conversation as resolved.
Outdated
});

const meta = {
url: 'https://github.com/nodejs/nodejs.org/blob/main/COLLABORATOR_GUIDE.md#styling-a-component',
fixable: true,
};

/** @type {import('stylelint').Rule} */
const rule = () => (root, result) => {
root.walkAtRules('apply', rule => {
if (!rule.params.includes(' ')) {
// If there are no spaces in the params, we don't need to check anything
return;
}

// Since we use 2 spaces for indentation, each line in the apply rule
// should be indented with two extra whitespaces.
const classes = rule.params.split(`${rule.raws.before} `);
const classNames = classes.join('');

// Check if the params contain any spaces
if (classNames.includes(' ')) {
if (classNames.includes('\n')) {
return report({
ruleName: name,
result: result,
message: messages.spacing(JSON.stringify(rule.params)),
node: rule,
fix: indentClassNames(rule),
});
}

return report({
ruleName: name,
result,
message: messages.className(rule.params),
node: rule,
fix: indentClassNames(rule),
});
}
});
};

rule.ruleName = name;
rule.messages = messages;
rule.meta = meta;

export default createPlugin(name, rule);
Loading
Loading