Skip to content

Commit

Permalink
fix(refactor): complete migrate to stylelint v16 (#263)
Browse files Browse the repository at this point in the history
> [!NOTE]
>
> Поехало форматирование, т.к. в репе нет prettier конфига и всё форматировалось по настройкам моего IDE.
>
> В другом PR добавлю `.prettierrc`.

В PR #238 не до конца мигрировал конфиги. Это выяснилось при попытке починить линты в VKCOM/VKUI#6606.

Поэтому по рекомендациям https://stylelint.io/migration-guide/to-16 делаем следующие изменения:

- добавляем в `package.json` поля `"type": "module"`, `"exports": "./index.js"` и `"module": "index.js"`;
- в `typescript.config.js` задаём `module` и `moduleResolution"  как `NodeNext`. ⚠️ после этого в `*.ts` относительных импортах используем расширение `.js`;
- заменяем `module.exports` на `exports default`;
- `jest.config.js` тоже переписываем в ESM, а также задаём `moduleNameMapper`, чтобы резолвились относительные импорты с `.js`;
  • Loading branch information
inomdzhon authored Feb 20, 2024
1 parent 46f64ba commit a96f896
Show file tree
Hide file tree
Showing 15 changed files with 192 additions and 234 deletions.
3 changes: 1 addition & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
module.exports = {
export default {
plugins: ["./dist/stylelint-selector-bem-pattern", "./dist/stylelint-vkui", "./dist/stylelint-logical-shorthands"],
rules: {
"max-nesting-depth": [0, { ignoreAtRules: ["supports"] }],
indentation: 2,
"selector-max-id": 0,
"selector-max-type": 0,
"selector-max-universal": 0,
Expand Down
16 changes: 11 additions & 5 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
module.exports = {
preset: "jest-preset-stylelint",
import fs from 'node:fs';
import process from 'node:process';

export default {
preset: 'jest-preset-stylelint',
transform: {
"^.+\\.(t|j)sx?$": "@swc/jest",
'^.+\\.(t|j)sx?$': '@swc/jest',
},
testEnvironment: "node",
testEnvironment: 'node',
// см. https://jestjs.io/ru/docs/ecmascript-modules
extensionsToTreatAsEsm: [".ts"],
extensionsToTreatAsEsm: ['.ts'],
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},
};
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
"name": "@vkontakte/stylelint-config",
"version": "4.0.1",
"description": "stylelint config from VK",
"type": "module",
"main": "index.js",
"exports": "./index.js",
"engines": {
"node": ">=20",
"yarn": "^1.21.1"
Expand Down
116 changes: 49 additions & 67 deletions src/stylelint-logical-shorthands/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
import stylelint, { Rule } from "stylelint";
import valueParser from "postcss-value-parser";
import postcss from "postcss";
import {
messageReportBorder,
messageReportBorderRadius,
messageReportSimple,
} from "./messageReport";
import stylelint, { Rule } from 'stylelint';
import valueParser from 'postcss-value-parser';
import postcss from 'postcss';
import { messageReportBorder, messageReportBorderRadius, messageReportSimple } from './messageReport.js';

function ignoreCommentAndSpaceNodes(valueNode: valueParser.Node): boolean {
return valueNode.type !== "comment" && valueNode.type !== "space";
return valueNode.type !== 'comment' && valueNode.type !== 'space';
}

/**
* Собирает сообщение в зависимости от свойства
*/
export function messageReport(prop: string) {
if (prop === "border-radius") {
if (prop === 'border-radius') {
return messageReportBorderRadius(prop);
} else if (prop.startsWith("border")) {
} else if (prop.startsWith('border')) {
return messageReportBorder(prop);
}

Expand All @@ -33,8 +29,8 @@ export function messageReport(prop: string) {
* ```
*/
function logicalProp(prop: string, type: string) {
if (prop.startsWith("border")) {
return prop.replace("-", `-${type}-`);
if (prop.startsWith('border')) {
return prop.replace('-', `-${type}-`);
}

return `${prop}-${type}`;
Expand All @@ -44,42 +40,33 @@ function logicalProp(prop: string, type: string) {
* Превращает свойства из физических в логические
*/
function fixSimple(node: postcss.Declaration, valueNodes: valueParser.Node[]) {
let blockValue = "";
let inlineValue = "";
let blockValue = '';
let inlineValue = '';

switch (valueNodes.length) {
case 2:
blockValue = valueParser.stringify(valueNodes[0]);
inlineValue = valueParser.stringify(valueNodes[1]);
break;
case 3:
blockValue =
valueParser.stringify(valueNodes[0]) +
" " +
valueParser.stringify(valueNodes[2]);
blockValue = valueParser.stringify(valueNodes[0]) + ' ' + valueParser.stringify(valueNodes[2]);
inlineValue = valueParser.stringify(valueNodes[1]);
break;
case 4:
blockValue =
valueParser.stringify(valueNodes[0]) +
" " +
valueParser.stringify(valueNodes[2]);
inlineValue =
valueParser.stringify(valueNodes[3]) +
" " +
valueParser.stringify(valueNodes[1]);
blockValue = valueParser.stringify(valueNodes[0]) + ' ' + valueParser.stringify(valueNodes[2]);
inlineValue = valueParser.stringify(valueNodes[3]) + ' ' + valueParser.stringify(valueNodes[1]);
break;
default:
return;
}

node.after({
prop: logicalProp(node.prop, "inline"),
prop: logicalProp(node.prop, 'inline'),
value: inlineValue,
important: node.important,
});
node.after({
prop: logicalProp(node.prop, "block"),
prop: logicalProp(node.prop, 'block'),
value: blockValue,
important: node.important,
});
Expand All @@ -89,49 +76,44 @@ function fixSimple(node: postcss.Declaration, valueNodes: valueParser.Node[]) {
/**
* Превращает свойства из физических в логические для border radius
*/
function fixBorderRadius(
node: postcss.Declaration,
valueNodes: valueParser.Node[]
) {
let startStartValue = "";
let startEndValue = "";
let endEndValue = "";
let endStartValue = "";

let firstStartStartValue = "";
let firstStartEndValue = "";
let firstEndEndValue = "";
let firstEndStartValue = "";

const indexDiv = valueNodes.findIndex(
(valueNode) => valueNode.type === "div"
);
function fixBorderRadius(node: postcss.Declaration, valueNodes: valueParser.Node[]) {
let startStartValue = '';
let startEndValue = '';
let endEndValue = '';
let endStartValue = '';

let firstStartStartValue = '';
let firstStartEndValue = '';
let firstEndEndValue = '';
let firstEndStartValue = '';

const indexDiv = valueNodes.findIndex(valueNode => valueNode.type === 'div');

switch (indexDiv) {
case 1:
const v = valueParser.stringify(valueNodes[0]) + " ";
const v = valueParser.stringify(valueNodes[0]) + ' ';
firstStartStartValue = v;
firstStartEndValue = v;
firstEndEndValue = v;
firstEndStartValue = v;
break;
case 2:
firstStartStartValue = valueParser.stringify(valueNodes[0]) + " ";
firstStartEndValue = valueParser.stringify(valueNodes[1]) + " ";
firstEndEndValue = valueParser.stringify(valueNodes[0]) + " ";
firstEndStartValue = valueParser.stringify(valueNodes[1]) + " ";
firstStartStartValue = valueParser.stringify(valueNodes[0]) + ' ';
firstStartEndValue = valueParser.stringify(valueNodes[1]) + ' ';
firstEndEndValue = valueParser.stringify(valueNodes[0]) + ' ';
firstEndStartValue = valueParser.stringify(valueNodes[1]) + ' ';
break;
case 3:
firstStartStartValue = valueParser.stringify(valueNodes[0]) + " ";
firstStartEndValue = valueParser.stringify(valueNodes[1]) + " ";
firstEndEndValue = valueParser.stringify(valueNodes[2]) + " ";
firstEndStartValue = valueParser.stringify(valueNodes[1]) + " ";
firstStartStartValue = valueParser.stringify(valueNodes[0]) + ' ';
firstStartEndValue = valueParser.stringify(valueNodes[1]) + ' ';
firstEndEndValue = valueParser.stringify(valueNodes[2]) + ' ';
firstEndStartValue = valueParser.stringify(valueNodes[1]) + ' ';
break;
case 4:
firstStartStartValue = valueParser.stringify(valueNodes[0]) + " ";
firstStartEndValue = valueParser.stringify(valueNodes[1]) + " ";
firstEndEndValue = valueParser.stringify(valueNodes[2]) + " ";
firstEndStartValue = valueParser.stringify(valueNodes[3]) + " ";
firstStartStartValue = valueParser.stringify(valueNodes[0]) + ' ';
firstStartEndValue = valueParser.stringify(valueNodes[1]) + ' ';
firstEndEndValue = valueParser.stringify(valueNodes[2]) + ' ';
firstEndStartValue = valueParser.stringify(valueNodes[3]) + ' ';
break;
}

Expand Down Expand Up @@ -164,22 +146,22 @@ function fixBorderRadius(
}

node.after({
prop: "border-end-start-radius",
prop: 'border-end-start-radius',
value: firstEndStartValue + endStartValue,
important: node.important,
});
node.after({
prop: "border-end-end-radius",
prop: 'border-end-end-radius',
value: firstEndEndValue + endEndValue,
important: node.important,
});
node.after({
prop: "border-start-end-radius",
prop: 'border-start-end-radius',
value: firstStartEndValue + startEndValue,
important: node.important,
});
node.after({
prop: "border-start-start-radius",
prop: 'border-start-start-radius',
value: firstStartStartValue + startStartValue,
important: node.important,
});
Expand All @@ -190,25 +172,25 @@ function fixBorderRadius(
* Превращает свойства из физических в логические
*/
function fix(node: postcss.Declaration, valueNodes: valueParser.Node[]) {
if (node.prop === "border-radius") {
if (node.prop === 'border-radius') {
fixBorderRadius(node, valueNodes);
return;
}

fixSimple(node, valueNodes);
}

export const ruleName = "plugin/logical-shorthands";
export const ruleName = 'plugin/logical-shorthands';
const messages = stylelint.utils.ruleMessages(ruleName, {});
const meta = {
url: "https://github.com/VKCOM/stylelint-config/tree/master/src/stylelint-logical-shorthands",
url: 'https://github.com/VKCOM/stylelint-config/tree/master/src/stylelint-logical-shorthands',
};

const ruleFunction: Rule = (_, __, context) => {
return (root, result) => {
root.walkDecls(
/^(inset|margin|padding|scroll-padding|scroll-margin|border-(width|style|color)|border-radius)$/,
(node) => {
node => {
const parsedValue = valueParser(node.value);
const valueNodes = parsedValue.nodes.filter(ignoreCommentAndSpaceNodes);

Expand Down
Loading

0 comments on commit a96f896

Please sign in to comment.