• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

alma-oss / spirit-design-system / 28179456061

25 Jun 2026 02:59PM UTC coverage: 86.433% (+0.9%) from 85.576%
28179456061

Pull #2741

github

crishpeen
fix(web): remove unused mixins and variables
Pull Request #2741: refactor(web,web-react)!: switch toggle to composition markup #DS-564

2639 of 3519 branches covered (74.99%)

Branch coverage included in aggregate %.

67 of 79 new or added lines in 4 files covered. (84.81%)

12 existing lines in 6 files now uncovered.

7223 of 7891 relevant lines covered (91.53%)

209.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.02
/packages/codemods/src/transforms/v5/web-react/toggle-margin-y.ts
1
import {
2
  API,
3
  ASTPath,
4
  FileInfo,
5
  JSXAttribute,
6
  JSXMemberExpression,
7
  JSXOpeningElement,
8
  JSXSpreadAttribute,
9
} from 'jscodeshift';
10
import { removeParentheses } from '../../../helpers';
1✔
11

12
const SPIRIT_WEB_REACT_MODULE = /^@alma-oss\/spirit-web-react(\/.*)?$/;
1✔
13
const TOGGLE_COMPONENT = 'Toggle';
1✔
14
const STACK_COMPONENT = 'Stack';
1✔
15
const VERTICAL_MARGIN_PROPS = new Set(['margin', 'marginTop', 'marginBottom', 'marginY']);
1✔
16

17
const isImportedElement = (
1✔
18
  element: JSXOpeningElement,
19
  componentName: string,
20
  namedImports: Set<string>,
21
  namespaceImports: Set<string>,
22
): boolean => {
23
  if (element.name.type === 'JSXIdentifier') {
24!
24
    return namedImports.has(element.name.name);
24✔
25
  }
26

NEW
27
  if (element.name.type !== 'JSXMemberExpression') {
×
NEW
28
    return false;
×
29
  }
30

NEW
31
  const memberExpression = element.name as JSXMemberExpression;
×
NEW
32
  const objectName = memberExpression.object.type === 'JSXIdentifier' ? memberExpression.object.name : undefined;
×
NEW
33
  const propertyName = memberExpression.property.type === 'JSXIdentifier' ? memberExpression.property.name : undefined;
×
34

NEW
35
  return Boolean(objectName && propertyName === componentName && namespaceImports.has(objectName));
×
36
};
37

38
const hasVerticalMarginProp = (attributes: (JSXAttribute | JSXSpreadAttribute)[] | undefined): boolean =>
1✔
39
  Boolean(
8✔
40
    attributes?.some(
41
      (attribute) =>
42
        attribute.type === 'JSXAttribute' &&
20✔
43
        attribute.name.type === 'JSXIdentifier' &&
44
        VERTICAL_MARGIN_PROPS.has(attribute.name.name),
45
    ),
46
  );
47

48
const addMarginYAttribute = (j: API['jscodeshift'], attributes: (JSXAttribute | JSXSpreadAttribute)[] | undefined) => {
1✔
49
  const marginYAttribute = j.jsxAttribute(j.jsxIdentifier('marginY'), j.stringLiteral('space-500'));
4✔
50

51
  if (!attributes) {
4!
NEW
52
    return [marginYAttribute];
×
53
  }
54

55
  const firstSpreadIndex = attributes.findIndex((attribute) => attribute.type === 'JSXSpreadAttribute');
9✔
56

57
  if (firstSpreadIndex === -1) {
4✔
58
    return [...attributes, marginYAttribute];
2✔
59
  }
60

61
  return [...attributes.slice(0, firstSpreadIndex), marginYAttribute, ...attributes.slice(firstSpreadIndex)];
2✔
62
};
63

64
const hasEnabledHasSpacingProp = (attributes: (JSXAttribute | JSXSpreadAttribute)[] | undefined): boolean =>
1✔
65
  Boolean(
4✔
66
    attributes?.some((attribute) => {
67
      if (attribute.type !== 'JSXAttribute' || attribute.name.type !== 'JSXIdentifier') {
4!
NEW
68
        return false;
×
69
      }
70

71
      if (attribute.name.name !== 'hasSpacing') {
4!
NEW
72
        return false;
×
73
      }
74

75
      if (!attribute.value) {
4✔
76
        return true;
2✔
77
      }
78

79
      return attribute.value.type === 'JSXExpressionContainer' && attribute.value.expression.type === 'BooleanLiteral'
2!
80
        ? attribute.value.expression.value
81
        : true;
82
    }),
83
  );
84

85
const isInsideSpacingStack = (
1✔
86
  path: ASTPath<JSXOpeningElement>,
87
  stackNamedImports: Set<string>,
88
  namespaceImports: Set<string>,
89
): boolean => {
90
  let currentPath = path.parentPath;
6✔
91

92
  while (currentPath) {
6✔
93
    if (
52✔
94
      currentPath.node.type === 'JSXElement' &&
68✔
95
      isImportedElement(currentPath.node.openingElement, STACK_COMPONENT, stackNamedImports, namespaceImports) &&
96
      hasEnabledHasSpacingProp(currentPath.node.openingElement.attributes)
97
    ) {
98
      return true;
2✔
99
    }
100

101
    currentPath = currentPath.parentPath;
50✔
102
  }
103

104
  return false;
4✔
105
};
106

107
const transform = (fileInfo: FileInfo, api: API) => {
1✔
108
  const j = api.jscodeshift;
1✔
109
  const root = j(fileInfo.source);
1✔
110
  const toggleNamedImports = new Set<string>();
1✔
111
  const stackNamedImports = new Set<string>();
1✔
112
  const namespaceImports = new Set<string>();
1✔
113

114
  root
1✔
115
    .find(j.ImportDeclaration, {
116
      source: {
117
        value: (value: string) => SPIRIT_WEB_REACT_MODULE.test(value),
2✔
118
      },
119
    })
120
    .forEach((path) => {
121
      path.node.specifiers?.forEach((specifier) => {
1✔
122
        if (specifier.type === 'ImportSpecifier' && specifier.imported.type === 'Identifier') {
3!
123
          if (specifier.imported.name === TOGGLE_COMPONENT) {
3✔
124
            toggleNamedImports.add(specifier.local?.name ?? specifier.imported.name);
1!
125
          }
126

127
          if (specifier.imported.name === STACK_COMPONENT) {
3✔
128
            stackNamedImports.add(specifier.local?.name ?? specifier.imported.name);
1!
129
          }
130
        }
131

132
        if (specifier.type === 'ImportNamespaceSpecifier') {
3!
NEW
133
          if (specifier.local?.name) {
×
NEW
134
            namespaceImports.add(specifier.local.name);
×
135
          }
136
        }
137
      });
138
    });
139

140
  if (toggleNamedImports.size === 0 && namespaceImports.size === 0) {
1!
NEW
141
    return fileInfo.source;
×
142
  }
143

144
  root.find(j.JSXOpeningElement).forEach((path) => {
1✔
145
    if (
12✔
146
      !isImportedElement(path.node, TOGGLE_COMPONENT, toggleNamedImports, namespaceImports) ||
26✔
147
      hasVerticalMarginProp(path.node.attributes) ||
148
      isInsideSpacingStack(path, stackNamedImports, namespaceImports)
149
    ) {
150
      return;
8✔
151
    }
152

153
    path.node.attributes = addMarginYAttribute(j, path.node.attributes);
4✔
154
  });
155

156
  return removeParentheses(root.toSource());
1✔
157
};
158

159
export default transform;
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc