@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
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dialpad/eslint-plugin-dialtone",
3
- "version": "1.11.2",
3
+ "version": "1.12.0-next.1",
4
4
  "description": "dialtone eslint plugin",
5
5
  "keywords": [
6
6
  "Dialpad",