@dialpad/eslint-plugin-dialtone 1.11.2 → 1.12.0-next.1
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.
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Detects usage of deprecated xxl/xxxl headline sizes which have been renamed to 2xl/3xl.
|
|
3
|
+
* @author Dialtone Team
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
// ------------------------------------------------------------------------------
|
|
8
|
+
// Rule Definition
|
|
9
|
+
// ------------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
const SIZE_MAP = {
|
|
12
|
+
xxxl: '3xl',
|
|
13
|
+
xxl: '2xl',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
module.exports = {
|
|
17
|
+
meta: {
|
|
18
|
+
type: 'suggestion',
|
|
19
|
+
docs: {
|
|
20
|
+
description: 'Headline sizes xxl/xxxl have been renamed to 2xl/3xl.',
|
|
21
|
+
recommended: false,
|
|
22
|
+
url: 'https://github.com/dialpad/dialtone/blob/staging/packages/eslint-plugin-dialtone/docs/rules/deprecated-headline-sizes.md',
|
|
23
|
+
},
|
|
24
|
+
fixable: 'code',
|
|
25
|
+
schema: [],
|
|
26
|
+
messages: {
|
|
27
|
+
deprecatedSize: 'Headline size "{{oldSize}}" has been renamed to "{{newSize}}". Update size="{{oldSize}}" to size="{{newSize}}".',
|
|
28
|
+
deprecatedClass: 'CSS class "{{oldClass}}" has been renamed to "{{newClass}}". Update to use the new class name.',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
create(context) {
|
|
33
|
+
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
|
34
|
+
return sourceCode.parserServices.defineTemplateBodyVisitor({
|
|
35
|
+
VAttribute(node) {
|
|
36
|
+
// Check size prop (e.g., size="xxl" or size="xxxl")
|
|
37
|
+
if (node.key.name === 'size' && node.value && node.value.value) {
|
|
38
|
+
const sizeValue = node.value.value;
|
|
39
|
+
if (SIZE_MAP[sizeValue]) {
|
|
40
|
+
context.report({
|
|
41
|
+
node,
|
|
42
|
+
messageId: 'deprecatedSize',
|
|
43
|
+
data: {
|
|
44
|
+
oldSize: sizeValue,
|
|
45
|
+
newSize: SIZE_MAP[sizeValue],
|
|
46
|
+
},
|
|
47
|
+
fix(fixer) {
|
|
48
|
+
return fixer.replaceText(node.value, `"${SIZE_MAP[sizeValue]}"`);
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Check class attributes for deprecated d-text-headline--xxl/xxxl classes
|
|
55
|
+
// Note: We only flag d-text-headline-- (current system), NOT d-headline-- (legacy system)
|
|
56
|
+
if (node.key.name === 'class' && node.value && node.value.value) {
|
|
57
|
+
const classValue = node.value.value;
|
|
58
|
+
// Match d-text-headline--xxl or d-text-headline--xxxl (but NOT d-headline--xxl)
|
|
59
|
+
const match = classValue.match(/\bd-text-headline--(xxx?l)\b/);
|
|
60
|
+
if (match && SIZE_MAP[match[1]]) {
|
|
61
|
+
const oldClass = `d-text-headline--${match[1]}`;
|
|
62
|
+
const newClass = `d-text-headline--${SIZE_MAP[match[1]]}`;
|
|
63
|
+
context.report({
|
|
64
|
+
node,
|
|
65
|
+
messageId: 'deprecatedClass',
|
|
66
|
+
data: { oldClass, newClass },
|
|
67
|
+
fix(fixer) {
|
|
68
|
+
const newValue = classValue.replace(oldClass, newClass);
|
|
69
|
+
return fixer.replaceText(node.value, `"${newValue}"`);
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
},
|
|
77
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Detects usage of pixel-based utility classes (d-h16, d-p8, d-m8, etc.)
|
|
3
|
+
* which should be replaced with token-stop-based equivalents (d-h-25, d-p-100, d-m-100).
|
|
4
|
+
* @author Joshua Hynes
|
|
5
|
+
*/
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
//------------------------------------------------------------------------------
|
|
9
|
+
// Rule Definition
|
|
10
|
+
//------------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
// Pixel values that have token-stop equivalents
|
|
13
|
+
// MUST STAY IN SYNC with WIDTH_HEIGHTS_LAYOUT, MARGIN_SIZES_SPACING, MARGIN_SIZES_LAYOUT,
|
|
14
|
+
// and NEGATIVE_SPACING_MAP in dialtone-css/postcss/constants.cjs
|
|
15
|
+
// Sizing: layout stops (16px+)
|
|
16
|
+
const SIZING_PIXELS = '16|32|48|64|80|96|112|128|160|192|224|256|288|320|352|384|416|448|480|512|544|576|608|640|672|704|736|768|800|832|864|896|928|960|992|1024';
|
|
17
|
+
// Spacing: spacing stops (0-64px) + layout stops for margin/padding (96, 128)
|
|
18
|
+
const SPACING_PIXELS = '0|1|2|4|6|8|10|12|14|16|20|24|32|48|64|96|128';
|
|
19
|
+
// Negative spacing
|
|
20
|
+
const NEGATIVE_PIXELS = '1|2|4|6|8|10|12|14|16|24|32|48|64';
|
|
21
|
+
|
|
22
|
+
// Build patterns for each category
|
|
23
|
+
// Sizing: d-h16, d-w64, d-hmn96, d-hmx128, d-wmn32, d-wmx512
|
|
24
|
+
const SIZING_PATTERN = `d-(?:h|w|hmn|hmx|wmn|wmx)(?:${SIZING_PIXELS})\\b`;
|
|
25
|
+
// Margin: d-m8, d-mt16, d-mr8, d-mb8, d-ml8, d-mx8, d-my8
|
|
26
|
+
const MARGIN_PATTERN = `d-m(?:t|r|b|l|x|y)?(?:${SPACING_PIXELS})\\b`;
|
|
27
|
+
// Negative margin: d-mtn8, d-mrn8, d-mbn8, d-mln8, d-mxn8, d-myn8, d-mn8
|
|
28
|
+
const NEGATIVE_MARGIN_PATTERN = `d-m(?:t|r|b|l|x|y)?n(?:${NEGATIVE_PIXELS})\\b`;
|
|
29
|
+
// Padding: d-p8, d-pt16, d-pr8, d-pb8, d-pl8, d-px8, d-py8
|
|
30
|
+
const PADDING_PATTERN = `d-p(?:t|r|b|l|x|y)?(?:${SPACING_PIXELS})\\b`;
|
|
31
|
+
// Gap: d-g8, d-rg8, d-cg8
|
|
32
|
+
const GAP_PATTERN = `d-(?:g|rg|cg)(?:${SPACING_PIXELS})\\b`;
|
|
33
|
+
// Position: d-t8, d-r8, d-b8, d-l8, d-x8, d-y8, d-all8
|
|
34
|
+
const POSITION_PATTERN = `d-(?:t|r|b|l|x|y|all)(?:${SPACING_PIXELS})\\b`;
|
|
35
|
+
// Negative position: d-tn8, d-rn8, d-bn8, d-ln8, d-xn8, d-yn8, d-alln8
|
|
36
|
+
const NEGATIVE_POSITION_PATTERN = `d-(?:t|r|b|l|x|y|all)n(?:${NEGATIVE_PIXELS})\\b`;
|
|
37
|
+
|
|
38
|
+
const COMBINED_PATTERN = new RegExp(
|
|
39
|
+
`(?:${SIZING_PATTERN}|${NEGATIVE_MARGIN_PATTERN}|${MARGIN_PATTERN}|${PADDING_PATTERN}|${GAP_PATTERN}|${NEGATIVE_POSITION_PATTERN}|${POSITION_PATTERN})`
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
meta: {
|
|
44
|
+
type: 'suggestion',
|
|
45
|
+
docs: {
|
|
46
|
+
description: "Pixel-based utility classes (d-h16, d-p8, d-m8) are deprecated. Use token-stop-based equivalents (d-h-25, d-p-100, d-m-100).",
|
|
47
|
+
recommended: false,
|
|
48
|
+
url: 'https://github.com/dialpad/dialtone/blob/staging/packages/eslint-plugin-dialtone/docs/rules/deprecated-pixel-utility-classes.md',
|
|
49
|
+
},
|
|
50
|
+
fixable: null,
|
|
51
|
+
schema: [],
|
|
52
|
+
messages: {
|
|
53
|
+
deprecatedPixelClass: `Pixel-based utility classes are deprecated. Use token-stop-based equivalents instead (e.g. d-h16 → d-h-25, d-p8 → d-p-100). Run the "utility-class-to-token-stops" migration helper to update automatically.`,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
create (context) {
|
|
58
|
+
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
|
59
|
+
return sourceCode.parserServices.defineTemplateBodyVisitor({
|
|
60
|
+
VAttribute (node) {
|
|
61
|
+
if (node.key.name === 'class') {
|
|
62
|
+
const classes = node.value.value;
|
|
63
|
+
if (COMBINED_PATTERN.test(classes)) {
|
|
64
|
+
context.report({
|
|
65
|
+
node,
|
|
66
|
+
messageId: 'deprecatedPixelClass',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
};
|